| Index: runtime/vm/malloc_hooks.cc
|
| diff --git a/runtime/vm/malloc_hooks.cc b/runtime/vm/malloc_hooks.cc
|
| index 849f8d5d56928ed4bb812cf0128808426c730578..9e5c6587c3065498c8a757de121770e315e1b03d 100644
|
| --- a/runtime/vm/malloc_hooks.cc
|
| +++ b/runtime/vm/malloc_hooks.cc
|
| @@ -12,6 +12,7 @@
|
|
|
| #include "platform/assert.h"
|
| #include "vm/hash_map.h"
|
| +#include "vm/json_stream.h"
|
| #include "vm/lockers.h"
|
|
|
| namespace dart {
|
| @@ -102,15 +103,15 @@ class AddressMap : public MallocDirectChainedHashMap<AddressKeyValueTrait> {
|
| };
|
|
|
|
|
| -class MallocHooksState {
|
| +class MallocHooksState : public AllStatic {
|
| public:
|
| static void RecordAllocHook(const void* ptr, size_t size);
|
| static void RecordFreeHook(const void* ptr);
|
|
|
| - static bool initialized() { return initialized_; }
|
| + static bool Active() { return active_; }
|
| static void Init() {
|
| address_map_ = new AddressMap();
|
| - initialized_ = true;
|
| + active_ = true;
|
| original_pid_ = OS::ProcessId();
|
| }
|
|
|
| @@ -128,12 +129,14 @@ class MallocHooksState {
|
| }
|
|
|
| static void IncrementHeapAllocatedMemoryInBytes(intptr_t size) {
|
| + ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
|
| ASSERT(size >= 0);
|
| heap_allocated_memory_in_bytes_ += size;
|
| ++allocation_count_;
|
| }
|
|
|
| static void DecrementHeapAllocatedMemoryInBytes(intptr_t size) {
|
| + ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
|
| ASSERT(size >= 0);
|
| ASSERT(heap_allocated_memory_in_bytes_ >= size);
|
| heap_allocated_memory_in_bytes_ -= size;
|
| @@ -144,20 +147,22 @@ class MallocHooksState {
|
| static AddressMap* address_map() { return address_map_; }
|
|
|
| static void ResetStats() {
|
| + ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
|
| allocation_count_ = 0;
|
| heap_allocated_memory_in_bytes_ = 0;
|
| address_map_->Clear();
|
| }
|
|
|
| static void TearDown() {
|
| - initialized_ = false;
|
| + ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
|
| + active_ = false;
|
| original_pid_ = kInvalidPid;
|
| ResetStats();
|
| delete address_map_;
|
| }
|
|
|
| private:
|
| - static bool initialized_;
|
| + static bool active_;
|
| static intptr_t original_pid_;
|
| static Mutex* malloc_hook_mutex_;
|
| static intptr_t allocation_count_;
|
| @@ -165,15 +170,12 @@ class MallocHooksState {
|
| static AddressMap* address_map_;
|
|
|
| static const intptr_t kInvalidPid = -1;
|
| -
|
| - DISALLOW_ALLOCATION();
|
| - DISALLOW_COPY_AND_ASSIGN(MallocHooksState);
|
| };
|
|
|
|
|
| // MallocHooks state / locks.
|
| ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey;
|
| -bool MallocHooksState::initialized_ = false;
|
| +bool MallocHooksState::active_ = false;
|
| intptr_t MallocHooksState::original_pid_ = MallocHooksState::kInvalidPid;
|
| Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex();
|
|
|
| @@ -185,7 +187,7 @@ AddressMap* MallocHooksState::address_map_ = NULL;
|
|
|
| void MallocHooks::InitOnce() {
|
| MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(!MallocHooksState::initialized());
|
| + ASSERT(!MallocHooksState::Active());
|
|
|
| MallocHookScope::InitMallocHookFlag();
|
| MallocHooksState::Init();
|
| @@ -201,7 +203,7 @@ void MallocHooks::InitOnce() {
|
|
|
| void MallocHooks::TearDown() {
|
| MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(MallocHooksState::initialized());
|
| + ASSERT(MallocHooksState::Active());
|
|
|
| // Remove malloc hooks.
|
| bool success = false;
|
| @@ -217,14 +219,37 @@ void MallocHooks::TearDown() {
|
|
|
| void MallocHooks::ResetStats() {
|
| MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(MallocHooksState::initialized());
|
| + if (MallocHooksState::Active()) {
|
| + MallocHooksState::ResetStats();
|
| + }
|
| +}
|
| +
|
|
|
| - MallocHooksState::ResetStats();
|
| +bool MallocHooks::Active() {
|
| + ASSERT(MallocHooksState::malloc_hook_mutex()->IsOwnedByCurrentThread());
|
| + return MallocHooksState::Active();
|
| }
|
|
|
|
|
| -bool MallocHooks::Initialized() {
|
| - return MallocHooksState::initialized();
|
| +void MallocHooks::PrintToJSONObject(JSONObject* jsobj) {
|
| + intptr_t allocated_memory = 0;
|
| + intptr_t allocation_count = 0;
|
| + bool add_usage = false;
|
| + // AddProperty may call malloc which would result in an attempt
|
| + // to acquire the lock recursively so we extract the values first
|
| + // and then add the JSON properties.
|
| + {
|
| + MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| + if (Active()) {
|
| + allocated_memory = MallocHooksState::heap_allocated_memory_in_bytes();
|
| + allocation_count = MallocHooksState::allocation_count();
|
| + add_usage = true;
|
| + }
|
| + }
|
| + if (add_usage) {
|
| + jsobj->AddProperty("_heapAllocatedMemoryUsage", allocated_memory);
|
| + jsobj->AddProperty("_heapAllocationCount", allocation_count);
|
| + }
|
| }
|
|
|
|
|
| @@ -249,9 +274,7 @@ void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) {
|
| // again.
|
| MallocHookScope mhs;
|
| MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(MallocHooksState::initialized());
|
| -
|
| - if (ptr != NULL) {
|
| + if ((ptr != NULL) && MallocHooksState::Active()) {
|
| MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size);
|
| MallocHooksState::address_map()->Insert(ptr, size);
|
| }
|
| @@ -267,9 +290,7 @@ void MallocHooksState::RecordFreeHook(const void* ptr) {
|
| // again.
|
| MallocHookScope mhs;
|
| MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(MallocHooksState::initialized());
|
| -
|
| - if (ptr != NULL) {
|
| + if ((ptr != NULL) && MallocHooksState::Active()) {
|
| intptr_t size = 0;
|
| if (MallocHooksState::address_map()->Lookup(ptr, &size)) {
|
| MallocHooksState::DecrementHeapAllocatedMemoryInBytes(size);
|
|
|