| Index: runtime/vm/malloc_hooks.cc
|
| diff --git a/runtime/vm/malloc_hooks.cc b/runtime/vm/malloc_hooks.cc
|
| index c7c09d7f2d57a0c9f308ec7ad597bf4814ae6ae8..65edca7bff776d8d8c571b97c1e3e95c0e199a2c 100644
|
| --- a/runtime/vm/malloc_hooks.cc
|
| +++ b/runtime/vm/malloc_hooks.cc
|
| @@ -2,263 +2,16 @@
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| -#include "platform/globals.h"
|
| -
|
| -#if defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
|
| +#if defined(DART_USE_TCMALLOC)
|
|
|
| #include "vm/malloc_hooks.h"
|
|
|
| -#include "gperftools/malloc_hook.h"
|
| -
|
| -#include "platform/assert.h"
|
| -#include "vm/hash_map.h"
|
| -#include "vm/lockers.h"
|
| -
|
| namespace dart {
|
|
|
| -// A locker-type class to automatically grab and release the
|
| -// in_malloc_hook_flag_.
|
| -class MallocHookScope {
|
| - public:
|
| - static void InitMallocHookFlag() {
|
| - ASSERT(in_malloc_hook_flag_ == kUnsetThreadLocalKey);
|
| - in_malloc_hook_flag_ = OSThread::CreateThreadLocal();
|
| - OSThread::SetThreadLocal(in_malloc_hook_flag_, 0);
|
| - }
|
| -
|
| - static void DestroyMallocHookFlag() {
|
| - ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
|
| - OSThread::DeleteThreadLocal(in_malloc_hook_flag_);
|
| - in_malloc_hook_flag_ = kUnsetThreadLocalKey;
|
| - }
|
| -
|
| - MallocHookScope() {
|
| - ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
|
| - OSThread::SetThreadLocal(in_malloc_hook_flag_, 1);
|
| - }
|
| -
|
| - ~MallocHookScope() {
|
| - ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
|
| - OSThread::SetThreadLocal(in_malloc_hook_flag_, 0);
|
| - }
|
| -
|
| - static bool IsInHook() {
|
| - ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
|
| - return OSThread::GetThreadLocal(in_malloc_hook_flag_);
|
| - }
|
| -
|
| - private:
|
| - static ThreadLocalKey in_malloc_hook_flag_;
|
| -
|
| - DISALLOW_ALLOCATION();
|
| - DISALLOW_COPY_AND_ASSIGN(MallocHookScope);
|
| -};
|
| -
|
| -
|
| -// Custom key/value trait specifically for address/size pairs. Unlike
|
| -// RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry.
|
| -class AddressKeyValueTrait {
|
| - public:
|
| - typedef const void* Key;
|
| - typedef intptr_t Value;
|
| -
|
| - struct Pair {
|
| - Key key;
|
| - Value value;
|
| - Pair() : key(NULL), value(-1) {}
|
| - Pair(const Key key, const Value& value) : key(key), value(value) {}
|
| - Pair(const Pair& other) : key(other.key), value(other.value) {}
|
| - };
|
| -
|
| - static Key KeyOf(Pair kv) { return kv.key; }
|
| - static Value ValueOf(Pair kv) { return kv.value; }
|
| - static intptr_t Hashcode(Key key) { return reinterpret_cast<intptr_t>(key); }
|
| - static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; }
|
| -};
|
| -
|
| -
|
| -// Map class that will be used to store mappings between ptr -> allocation size.
|
| -class AddressMap : public MallocDirectChainedHashMap<AddressKeyValueTrait> {
|
| - public:
|
| - typedef AddressKeyValueTrait::Key Key;
|
| - typedef AddressKeyValueTrait::Value Value;
|
| - typedef AddressKeyValueTrait::Pair Pair;
|
| -
|
| - inline void Insert(const Key& key, const Value& value) {
|
| - Pair pair(key, value);
|
| - MallocDirectChainedHashMap<AddressKeyValueTrait>::Insert(pair);
|
| - }
|
| -
|
| - inline bool Lookup(const Key& key, Value* value) {
|
| - ASSERT(value != NULL);
|
| - Pair* pair = MallocDirectChainedHashMap<AddressKeyValueTrait>::Lookup(key);
|
| - if (pair == NULL) {
|
| - return false;
|
| - } else {
|
| - *value = pair->value;
|
| - return true;
|
| - }
|
| - }
|
| -};
|
| -
|
| -
|
| -class MallocHooksState {
|
| - public:
|
| - static void RecordAllocHook(const void* ptr, size_t size);
|
| - static void RecordFreeHook(const void* ptr);
|
| -
|
| - static bool initialized() { return initialized_; }
|
| - static void set_initialized() { initialized_ = true; }
|
| -
|
| - static Mutex* malloc_hook_mutex() { return malloc_hook_mutex_; }
|
| -
|
| - static intptr_t allocation_count() { return allocation_count_; }
|
| -
|
| - static intptr_t heap_allocated_memory_in_bytes() {
|
| - return heap_allocated_memory_in_bytes_;
|
| - }
|
| -
|
| - static void IncrementHeapAllocatedMemoryInBytes(intptr_t size) {
|
| - ASSERT(size >= 0);
|
| - heap_allocated_memory_in_bytes_ += size;
|
| - ++allocation_count_;
|
| - }
|
| -
|
| - static void DecrementHeapAllocatedMemoryInBytes(intptr_t size) {
|
| - ASSERT(size >= 0);
|
| - ASSERT(heap_allocated_memory_in_bytes_ >= size);
|
| - heap_allocated_memory_in_bytes_ -= size;
|
| - --allocation_count_;
|
| - ASSERT(allocation_count_ >= 0);
|
| - }
|
| -
|
| - static AddressMap* address_map() { return &address_map_; }
|
| -
|
| - static void ResetStats() {
|
| - allocation_count_ = 0;
|
| - heap_allocated_memory_in_bytes_ = 0;
|
| - address_map_.Clear();
|
| - }
|
| -
|
| - static void Reset() {
|
| - initialized_ = false;
|
| - ResetStats();
|
| - }
|
| -
|
| - private:
|
| - static bool initialized_;
|
| - static Mutex* malloc_hook_mutex_;
|
| - static intptr_t allocation_count_;
|
| - static intptr_t heap_allocated_memory_in_bytes_;
|
| - static AddressMap address_map_;
|
| -
|
| - private:
|
| - DISALLOW_ALLOCATION();
|
| - DISALLOW_COPY_AND_ASSIGN(MallocHooksState);
|
| -};
|
| -
|
| -
|
| -// MallocHooks state / locks.
|
| -ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey;
|
| -bool MallocHooksState::initialized_ = false;
|
| -Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex();
|
| -
|
| -// Memory allocation state information.
|
| -intptr_t MallocHooksState::allocation_count_ = 0;
|
| -intptr_t MallocHooksState::heap_allocated_memory_in_bytes_ = 0;
|
| -AddressMap MallocHooksState::address_map_;
|
| -
|
| -
|
| -void MallocHooks::InitOnce() {
|
| - MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(!MallocHooksState::initialized());
|
| -
|
| - MallocHookScope::InitMallocHookFlag();
|
| - MallocHooksState::set_initialized();
|
| -
|
| - // Register malloc hooks.
|
| - bool success = false;
|
| - success = MallocHook::AddNewHook(&MallocHooksState::RecordAllocHook);
|
| - ASSERT(success);
|
| - success = MallocHook::AddDeleteHook(&MallocHooksState::RecordFreeHook);
|
| - ASSERT(success);
|
| -}
|
| -
|
| -
|
| -void MallocHooks::TearDown() {
|
| - MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(MallocHooksState::initialized());
|
| -
|
| - // Remove malloc hooks.
|
| - bool success = false;
|
| - success = MallocHook::RemoveNewHook(&MallocHooksState::RecordAllocHook);
|
| - ASSERT(success);
|
| - success = MallocHook::RemoveDeleteHook(&MallocHooksState::RecordFreeHook);
|
| - ASSERT(success);
|
| -
|
| - MallocHooksState::Reset();
|
| - MallocHookScope::DestroyMallocHookFlag();
|
| -}
|
| -
|
| -
|
| -void MallocHooks::ResetStats() {
|
| - MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(MallocHooksState::initialized());
|
| -
|
| - MallocHooksState::ResetStats();
|
| -}
|
| -
|
| -
|
| -intptr_t MallocHooks::allocation_count() {
|
| - MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - return MallocHooksState::allocation_count();
|
| -}
|
| -
|
| -
|
| -intptr_t MallocHooks::heap_allocated_memory_in_bytes() {
|
| - MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - return MallocHooksState::heap_allocated_memory_in_bytes();
|
| -}
|
| -
|
| -
|
| -void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) {
|
| - if (MallocHookScope::IsInHook()) {
|
| - return;
|
| - }
|
| -
|
| - // Set the malloc hook flag before grabbing the mutex to avoid calling hooks
|
| - // again.
|
| - MallocHookScope mhs;
|
| - MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(MallocHooksState::initialized());
|
| -
|
| - if (ptr != NULL) {
|
| - MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size);
|
| - MallocHooksState::address_map()->Insert(ptr, size);
|
| - }
|
| -}
|
| -
|
| -
|
| -void MallocHooksState::RecordFreeHook(const void* ptr) {
|
| - if (MallocHookScope::IsInHook()) {
|
| - return;
|
| - }
|
| -
|
| - // Set the malloc hook flag before grabbing the mutex to avoid calling hooks
|
| - // again.
|
| - MallocHookScope mhs;
|
| - MutexLocker ml(MallocHooksState::malloc_hook_mutex());
|
| - ASSERT(MallocHooksState::initialized());
|
| -
|
| - if (ptr != NULL) {
|
| - intptr_t size = 0;
|
| - if (MallocHooksState::address_map()->Lookup(ptr, &size)) {
|
| - MallocHooksState::DecrementHeapAllocatedMemoryInBytes(size);
|
| - MallocHooksState::address_map()->Remove(ptr);
|
| - }
|
| - }
|
| +void MallocHooks::Init() {
|
| + // TODO(bkonyi): Implement
|
| }
|
|
|
| } // namespace dart
|
|
|
| -#endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
|
| +#endif // defined(DART_USE_TCMALLOC)
|
|
|