| 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(TARGET_OS_FUCHSIA) | 8 !defined(TARGET_ARCH_DBC) && !defined(TARGET_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 explicit AllocationInfo(intptr_t allocation_size) | 134 AllocationInfo(uword address, intptr_t allocation_size) |
| 135 : sample_(NULL), allocation_size_(allocation_size) { | 135 : sample_(NULL), address_(address), 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); | 140 sample_ = Profiler::SampleNativeAllocation(kSkipCount, address, |
| 141 allocation_size); |
| 142 ASSERT(sample_->native_allocation_address() == address_); |
| 141 } | 143 } |
| 142 } | 144 } |
| 143 | 145 |
| 144 Sample* sample() const { return sample_; } | 146 Sample* sample() const { return sample_; } |
| 145 intptr_t allocation_size() const { return allocation_size_; } | 147 intptr_t allocation_size() const { return allocation_size_; } |
| 146 | 148 |
| 147 private: | 149 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. |
| 148 Sample* sample_; | 154 Sample* sample_; |
| 155 uword address_; |
| 149 intptr_t allocation_size_; | 156 intptr_t allocation_size_; |
| 150 | 157 |
| 151 // The number of frames that are generated by the malloc hooks and collection | 158 // The number of frames that are generated by the malloc hooks and collection |
| 152 // of the stack trace. These frames are ignored when collecting the stack | 159 // of the stack trace. These frames are ignored when collecting the stack |
| 153 // trace for a memory allocation. If this number is incorrect, some tests in | 160 // trace for a memory allocation. If this number is incorrect, some tests in |
| 154 // malloc_hook_tests.cc might fail, particularily | 161 // malloc_hook_tests.cc might fail, particularily |
| 155 // StackTraceMallocHookLengthTest. If this value is updated, please make sure | 162 // StackTraceMallocHookLengthTest. If this value is updated, please make sure |
| 156 // that the MallocHooks test cases pass on all platforms. | 163 // that the MallocHooks test cases pass on all platforms. |
| 157 static const intptr_t kSkipCount = 5; | 164 static const intptr_t kSkipCount = 6; |
| 158 }; | 165 }; |
| 159 | 166 |
| 160 | 167 |
| 161 // Custom key/value trait specifically for address/size pairs. Unlike | 168 // Custom key/value trait specifically for address/size pairs. Unlike |
| 162 // RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry. | 169 // RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry. |
| 163 class AddressKeyValueTrait : public AllStatic { | 170 class AddressKeyValueTrait : public AllStatic { |
| 164 public: | 171 public: |
| 165 typedef const void* Key; | 172 typedef const void* Key; |
| 166 typedef AllocationInfo* Value; | 173 typedef AllocationInfo* Value; |
| 167 | 174 |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 AllocationInfo* allocation_info = NULL; | 405 AllocationInfo* allocation_info = NULL; |
| 399 if (MallocHooksState::address_map()->Lookup(ptr, &allocation_info)) { | 406 if (MallocHooksState::address_map()->Lookup(ptr, &allocation_info)) { |
| 400 ASSERT(allocation_info != NULL); | 407 ASSERT(allocation_info != NULL); |
| 401 return allocation_info->sample(); | 408 return allocation_info->sample(); |
| 402 } | 409 } |
| 403 } | 410 } |
| 404 return NULL; | 411 return NULL; |
| 405 } | 412 } |
| 406 | 413 |
| 407 | 414 |
| 415 bool MallocHooks::NativeAllocationFreed(const void* ptr) { |
| 416 Sample* sample = GetSample(ptr); |
| 417 return (sample == NULL); |
| 418 } |
| 419 |
| 420 |
| 408 void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) { | 421 void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) { |
| 409 if (MallocHooksState::IsLockHeldByCurrentThread() || | 422 if (MallocHooksState::IsLockHeldByCurrentThread() || |
| 410 !MallocHooksState::IsOriginalProcess()) { | 423 !MallocHooksState::IsOriginalProcess()) { |
| 411 return; | 424 return; |
| 412 } | 425 } |
| 413 | 426 |
| 414 MallocLocker ml(MallocHooksState::malloc_hook_mutex(), | 427 MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
| 415 MallocHooksState::malloc_hook_mutex_owner()); | 428 MallocHooksState::malloc_hook_mutex_owner()); |
| 416 // Now that we hold the lock, check to make sure everything is still active. | 429 // Now that we hold the lock, check to make sure everything is still active. |
| 417 if ((ptr != NULL) && MallocHooksState::Active()) { | 430 if ((ptr != NULL) && MallocHooksState::Active()) { |
| 418 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size); | 431 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size); |
| 419 MallocHooksState::address_map()->Insert(ptr, new AllocationInfo(size)); | 432 MallocHooksState::address_map()->Insert( |
| 433 ptr, new AllocationInfo(reinterpret_cast<uword>(ptr), size)); |
| 420 } | 434 } |
| 421 } | 435 } |
| 422 | 436 |
| 423 | 437 |
| 424 void MallocHooksState::RecordFreeHook(const void* ptr) { | 438 void MallocHooksState::RecordFreeHook(const void* ptr) { |
| 425 if (MallocHooksState::IsLockHeldByCurrentThread() || | 439 if (MallocHooksState::IsLockHeldByCurrentThread() || |
| 426 !MallocHooksState::IsOriginalProcess()) { | 440 !MallocHooksState::IsOriginalProcess()) { |
| 427 return; | 441 return; |
| 428 } | 442 } |
| 429 | 443 |
| 430 MallocLocker ml(MallocHooksState::malloc_hook_mutex(), | 444 MallocLocker ml(MallocHooksState::malloc_hook_mutex(), |
| 431 MallocHooksState::malloc_hook_mutex_owner()); | 445 MallocHooksState::malloc_hook_mutex_owner()); |
| 432 // Now that we hold the lock, check to make sure everything is still active. | 446 // Now that we hold the lock, check to make sure everything is still active. |
| 433 if ((ptr != NULL) && MallocHooksState::Active()) { | 447 if ((ptr != NULL) && MallocHooksState::Active()) { |
| 434 AllocationInfo* allocation_info = NULL; | 448 AllocationInfo* allocation_info = NULL; |
| 435 if (MallocHooksState::address_map()->Lookup(ptr, &allocation_info)) { | 449 if (MallocHooksState::address_map()->Lookup(ptr, &allocation_info)) { |
| 436 MallocHooksState::DecrementHeapAllocatedMemoryInBytes( | 450 MallocHooksState::DecrementHeapAllocatedMemoryInBytes( |
| 437 allocation_info->allocation_size()); | 451 allocation_info->allocation_size()); |
| 438 MallocHooksState::address_map()->Remove(ptr); | 452 MallocHooksState::address_map()->Remove(ptr); |
| 439 delete allocation_info; | 453 delete allocation_info; |
| 440 } | 454 } |
| 441 } | 455 } |
| 442 } | 456 } |
| 443 | 457 |
| 444 } // namespace dart | 458 } // namespace dart |
| 445 | 459 |
| 446 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && | 460 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && |
| 447 // !defined(TARGET_ARCH_DBC) && !defined(TARGET_OS_FUCHSIA) | 461 // !defined(TARGET_ARCH_DBC) && !defined(TARGET_OS_FUCHSIA) |
| OLD | NEW |