OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 | 6 |
7 #if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && \ | 7 #if defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && \ |
8 !defined(TARGET_ARCH_DBC) && !defined(HOST_OS_FUCHSIA) | 8 !defined(TARGET_ARCH_DBC) && !defined(HOST_OS_FUCHSIA) |
9 | 9 |
10 #include "vm/malloc_hooks.h" | 10 #include "vm/malloc_hooks.h" |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 Mutex* mutex_; | 124 Mutex* mutex_; |
125 ThreadId* owner_; | 125 ThreadId* owner_; |
126 }; | 126 }; |
127 | 127 |
128 // AllocationInfo contains all information related to a given allocation | 128 // AllocationInfo contains all information related to a given allocation |
129 // including: | 129 // including: |
130 // -Allocation size in bytes | 130 // -Allocation size in bytes |
131 // -Stack trace corresponding to the location of allocation, if applicable | 131 // -Stack trace corresponding to the location of allocation, if applicable |
132 class AllocationInfo { | 132 class AllocationInfo { |
133 public: | 133 public: |
134 AllocationInfo(uword address, intptr_t allocation_size) | 134 explicit AllocationInfo(intptr_t allocation_size) |
135 : sample_(NULL), address_(address), allocation_size_(allocation_size) { | 135 : sample_(NULL), allocation_size_(allocation_size) { |
136 // Stack trace collection is disabled when we are in the process of creating | 136 // Stack trace collection is disabled when we are in the process of creating |
137 // the first OSThread in order to prevent deadlocks. | 137 // the first OSThread in order to prevent deadlocks. |
138 if (MallocHooksState::ProfilingEnabled() && | 138 if (MallocHooksState::ProfilingEnabled() && |
139 MallocHooksState::stack_trace_collection_enabled()) { | 139 MallocHooksState::stack_trace_collection_enabled()) { |
140 sample_ = Profiler::SampleNativeAllocation(kSkipCount, address, | 140 sample_ = Profiler::SampleNativeAllocation(kSkipCount); |
141 allocation_size); | |
142 ASSERT(sample_->native_allocation_address() == address_); | |
143 } | 141 } |
144 } | 142 } |
145 | 143 |
146 Sample* sample() const { return sample_; } | 144 Sample* sample() const { return sample_; } |
147 intptr_t allocation_size() const { return allocation_size_; } | 145 intptr_t allocation_size() const { return allocation_size_; } |
148 | 146 |
149 private: | 147 private: |
150 // Note: sample_ is not owned by AllocationInfo, but by the SampleBuffer | |
151 // created by the profiler. As such, this is only here to track if the sample | |
152 // is still associated with a native allocation, and its fields are never | |
153 // accessed from this class. | |
154 Sample* sample_; | 148 Sample* sample_; |
155 uword address_; | |
156 intptr_t allocation_size_; | 149 intptr_t allocation_size_; |
157 | 150 |
158 // The number of frames that are generated by the malloc hooks and collection | 151 // The number of frames that are generated by the malloc hooks and collection |
159 // of the stack trace. These frames are ignored when collecting the stack | 152 // of the stack trace. These frames are ignored when collecting the stack |
160 // trace for a memory allocation. If this number is incorrect, some tests in | 153 // trace for a memory allocation. If this number is incorrect, some tests in |
161 // malloc_hook_tests.cc might fail, particularily | 154 // malloc_hook_tests.cc might fail, particularily |
162 // StackTraceMallocHookLengthTest. If this value is updated, please make sure | 155 // StackTraceMallocHookLengthTest. If this value is updated, please make sure |
163 // that the MallocHooks test cases pass on all platforms. | 156 // that the MallocHooks test cases pass on all platforms. |
164 static const intptr_t kSkipCount = 6; | 157 static const intptr_t kSkipCount = 5; |
165 }; | 158 }; |
166 | 159 |
167 | 160 |
168 // Custom key/value trait specifically for address/size pairs. Unlike | 161 // Custom key/value trait specifically for address/size pairs. Unlike |
169 // RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry. | 162 // RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry. |
170 class AddressKeyValueTrait : public AllStatic { | 163 class AddressKeyValueTrait : public AllStatic { |
171 public: | 164 public: |
172 typedef const void* Key; | 165 typedef const void* Key; |
173 typedef AllocationInfo* Value; | 166 typedef AllocationInfo* Value; |
174 | 167 |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 if (MallocHooksState::IsLockHeldByCurrentThread() || | 409 if (MallocHooksState::IsLockHeldByCurrentThread() || |
417 !MallocHooksState::IsOriginalProcess()) { | 410 !MallocHooksState::IsOriginalProcess()) { |
418 return; | 411 return; |
419 } | 412 } |
420 | 413 |
421 MallocLocker ml(MallocHooksState::malloc_hook_mutex(), | 414 MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
422 MallocHooksState::malloc_hook_mutex_owner()); | 415 MallocHooksState::malloc_hook_mutex_owner()); |
423 // Now that we hold the lock, check to make sure everything is still active. | 416 // Now that we hold the lock, check to make sure everything is still active. |
424 if ((ptr != NULL) && MallocHooksState::Active()) { | 417 if ((ptr != NULL) && MallocHooksState::Active()) { |
425 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size); | 418 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size); |
426 MallocHooksState::address_map()->Insert( | 419 MallocHooksState::address_map()->Insert(ptr, new AllocationInfo(size)); |
427 ptr, new AllocationInfo(reinterpret_cast<uword>(ptr), size)); | |
428 } | 420 } |
429 } | 421 } |
430 | 422 |
431 | 423 |
432 void MallocHooksState::RecordFreeHook(const void* ptr) { | 424 void MallocHooksState::RecordFreeHook(const void* ptr) { |
433 if (MallocHooksState::IsLockHeldByCurrentThread() || | 425 if (MallocHooksState::IsLockHeldByCurrentThread() || |
434 !MallocHooksState::IsOriginalProcess()) { | 426 !MallocHooksState::IsOriginalProcess()) { |
435 return; | 427 return; |
436 } | 428 } |
437 | 429 |
438 MallocLocker ml(MallocHooksState::malloc_hook_mutex(), | 430 MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
439 MallocHooksState::malloc_hook_mutex_owner()); | 431 MallocHooksState::malloc_hook_mutex_owner()); |
440 // Now that we hold the lock, check to make sure everything is still active. | 432 // Now that we hold the lock, check to make sure everything is still active. |
441 if ((ptr != NULL) && MallocHooksState::Active()) { | 433 if ((ptr != NULL) && MallocHooksState::Active()) { |
442 AllocationInfo* allocation_info = NULL; | 434 AllocationInfo* allocation_info = NULL; |
443 if (MallocHooksState::address_map()->Lookup(ptr, &allocation_info)) { | 435 if (MallocHooksState::address_map()->Lookup(ptr, &allocation_info)) { |
444 MallocHooksState::DecrementHeapAllocatedMemoryInBytes( | 436 MallocHooksState::DecrementHeapAllocatedMemoryInBytes( |
445 allocation_info->allocation_size()); | 437 allocation_info->allocation_size()); |
446 ASSERT(MallocHooksState::address_map()->Remove(ptr)); | 438 MallocHooksState::address_map()->Remove(ptr); |
447 delete allocation_info; | 439 delete allocation_info; |
448 } | 440 } |
449 } | 441 } |
450 } | 442 } |
451 | 443 |
452 } // namespace dart | 444 } // namespace dart |
453 | 445 |
454 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && | 446 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && |
455 // !defined(TARGET_ARCH_DBC) && !defined(HOST_OS_FUCHSIA) | 447 // !defined(TARGET_ARCH_DBC) && !defined(HOST_OS_FUCHSIA) |
OLD | NEW |