Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(158)

Side by Side Diff: runtime/vm/malloc_hooks.cc

Issue 2647793005: Revert "Reintroducing MallocHooks changes with fix for infinite loop in MallocHooks on Platform::Ex… (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/malloc_hooks.h ('k') | runtime/vm/malloc_hooks_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #if defined(DART_USE_TCMALLOC)
6
7 #if defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
8 6
9 #include "vm/malloc_hooks.h" 7 #include "vm/malloc_hooks.h"
10 8
11 #include "gperftools/malloc_hook.h"
12
13 #include "platform/assert.h"
14 #include "vm/hash_map.h"
15 #include "vm/lockers.h"
16
17 namespace dart { 9 namespace dart {
18 10
19 // A locker-type class to automatically grab and release the 11 void MallocHooks::Init() {
20 // in_malloc_hook_flag_. 12 // TODO(bkonyi): Implement
21 class MallocHookScope {
22 public:
23 static void InitMallocHookFlag() {
24 ASSERT(in_malloc_hook_flag_ == kUnsetThreadLocalKey);
25 in_malloc_hook_flag_ = OSThread::CreateThreadLocal();
26 OSThread::SetThreadLocal(in_malloc_hook_flag_, 0);
27 }
28
29 static void DestroyMallocHookFlag() {
30 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
31 OSThread::DeleteThreadLocal(in_malloc_hook_flag_);
32 in_malloc_hook_flag_ = kUnsetThreadLocalKey;
33 }
34
35 MallocHookScope() {
36 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
37 OSThread::SetThreadLocal(in_malloc_hook_flag_, 1);
38 }
39
40 ~MallocHookScope() {
41 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
42 OSThread::SetThreadLocal(in_malloc_hook_flag_, 0);
43 }
44
45 static bool IsInHook() {
46 ASSERT(in_malloc_hook_flag_ != kUnsetThreadLocalKey);
47 return OSThread::GetThreadLocal(in_malloc_hook_flag_);
48 }
49
50 private:
51 static ThreadLocalKey in_malloc_hook_flag_;
52
53 DISALLOW_ALLOCATION();
54 DISALLOW_COPY_AND_ASSIGN(MallocHookScope);
55 };
56
57
58 // Custom key/value trait specifically for address/size pairs. Unlike
59 // RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry.
60 class AddressKeyValueTrait {
61 public:
62 typedef const void* Key;
63 typedef intptr_t Value;
64
65 struct Pair {
66 Key key;
67 Value value;
68 Pair() : key(NULL), value(-1) {}
69 Pair(const Key key, const Value& value) : key(key), value(value) {}
70 Pair(const Pair& other) : key(other.key), value(other.value) {}
71 };
72
73 static Key KeyOf(Pair kv) { return kv.key; }
74 static Value ValueOf(Pair kv) { return kv.value; }
75 static intptr_t Hashcode(Key key) { return reinterpret_cast<intptr_t>(key); }
76 static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; }
77 };
78
79
80 // Map class that will be used to store mappings between ptr -> allocation size.
81 class AddressMap : public MallocDirectChainedHashMap<AddressKeyValueTrait> {
82 public:
83 typedef AddressKeyValueTrait::Key Key;
84 typedef AddressKeyValueTrait::Value Value;
85 typedef AddressKeyValueTrait::Pair Pair;
86
87 inline void Insert(const Key& key, const Value& value) {
88 Pair pair(key, value);
89 MallocDirectChainedHashMap<AddressKeyValueTrait>::Insert(pair);
90 }
91
92 inline bool Lookup(const Key& key, Value* value) {
93 ASSERT(value != NULL);
94 Pair* pair = MallocDirectChainedHashMap<AddressKeyValueTrait>::Lookup(key);
95 if (pair == NULL) {
96 return false;
97 } else {
98 *value = pair->value;
99 return true;
100 }
101 }
102 };
103
104
105 class MallocHooksState {
106 public:
107 static void RecordAllocHook(const void* ptr, size_t size);
108 static void RecordFreeHook(const void* ptr);
109
110 static bool initialized() { return initialized_; }
111 static void Init() {
112 address_map_ = new AddressMap();
113 initialized_ = true;
114 }
115
116 static Mutex* malloc_hook_mutex() { return malloc_hook_mutex_; }
117
118 static intptr_t allocation_count() { return allocation_count_; }
119
120 static intptr_t heap_allocated_memory_in_bytes() {
121 return heap_allocated_memory_in_bytes_;
122 }
123
124 static void IncrementHeapAllocatedMemoryInBytes(intptr_t size) {
125 ASSERT(size >= 0);
126 heap_allocated_memory_in_bytes_ += size;
127 ++allocation_count_;
128 }
129
130 static void DecrementHeapAllocatedMemoryInBytes(intptr_t size) {
131 ASSERT(size >= 0);
132 ASSERT(heap_allocated_memory_in_bytes_ >= size);
133 heap_allocated_memory_in_bytes_ -= size;
134 --allocation_count_;
135 ASSERT(allocation_count_ >= 0);
136 }
137
138 static AddressMap* address_map() { return address_map_; }
139
140 static void ResetStats() {
141 allocation_count_ = 0;
142 heap_allocated_memory_in_bytes_ = 0;
143 address_map_->Clear();
144 }
145
146 static void TearDown() {
147 initialized_ = false;
148 ResetStats();
149 delete address_map_;
150 }
151
152 private:
153 static bool initialized_;
154 static Mutex* malloc_hook_mutex_;
155 static intptr_t allocation_count_;
156 static intptr_t heap_allocated_memory_in_bytes_;
157 static AddressMap* address_map_;
158
159 private:
160 DISALLOW_ALLOCATION();
161 DISALLOW_COPY_AND_ASSIGN(MallocHooksState);
162 };
163
164
165 // MallocHooks state / locks.
166 ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey;
167 bool MallocHooksState::initialized_ = false;
168 Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex();
169
170 // Memory allocation state information.
171 intptr_t MallocHooksState::allocation_count_ = 0;
172 intptr_t MallocHooksState::heap_allocated_memory_in_bytes_ = 0;
173 AddressMap* MallocHooksState::address_map_ = NULL;
174
175
176 void MallocHooks::InitOnce() {
177 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
178 ASSERT(!MallocHooksState::initialized());
179
180 MallocHookScope::InitMallocHookFlag();
181 MallocHooksState::Init();
182
183 // Register malloc hooks.
184 bool success = false;
185 success = MallocHook::AddNewHook(&MallocHooksState::RecordAllocHook);
186 ASSERT(success);
187 success = MallocHook::AddDeleteHook(&MallocHooksState::RecordFreeHook);
188 ASSERT(success);
189 }
190
191
192 void MallocHooks::TearDown() {
193 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
194 ASSERT(MallocHooksState::initialized());
195
196 // Remove malloc hooks.
197 bool success = false;
198 success = MallocHook::RemoveNewHook(&MallocHooksState::RecordAllocHook);
199 ASSERT(success);
200 success = MallocHook::RemoveDeleteHook(&MallocHooksState::RecordFreeHook);
201 ASSERT(success);
202
203 MallocHooksState::TearDown();
204 MallocHookScope::DestroyMallocHookFlag();
205 }
206
207
208 void MallocHooks::ResetStats() {
209 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
210 ASSERT(MallocHooksState::initialized());
211
212 MallocHooksState::ResetStats();
213 }
214
215
216 intptr_t MallocHooks::allocation_count() {
217 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
218 return MallocHooksState::allocation_count();
219 }
220
221
222 intptr_t MallocHooks::heap_allocated_memory_in_bytes() {
223 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
224 return MallocHooksState::heap_allocated_memory_in_bytes();
225 }
226
227
228 void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) {
229 if (MallocHookScope::IsInHook()) {
230 return;
231 }
232
233 // Set the malloc hook flag before grabbing the mutex to avoid calling hooks
234 // again.
235 MallocHookScope mhs;
236 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
237 ASSERT(MallocHooksState::initialized());
238
239 if (ptr != NULL) {
240 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size);
241 MallocHooksState::address_map()->Insert(ptr, size);
242 }
243 }
244
245
246 void MallocHooksState::RecordFreeHook(const void* ptr) {
247 if (MallocHookScope::IsInHook()) {
248 return;
249 }
250
251 // Set the malloc hook flag before grabbing the mutex to avoid calling hooks
252 // again.
253 MallocHookScope mhs;
254 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
255 ASSERT(MallocHooksState::initialized());
256
257 if (ptr != NULL) {
258 intptr_t size = 0;
259 if (MallocHooksState::address_map()->Lookup(ptr, &size)) {
260 MallocHooksState::DecrementHeapAllocatedMemoryInBytes(size);
261 MallocHooksState::address_map()->Remove(ptr);
262 }
263 }
264 } 13 }
265 14
266 } // namespace dart 15 } // namespace dart
267 16
268 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) 17 #endif // defined(DART_USE_TCMALLOC)
OLDNEW
« no previous file with comments | « runtime/vm/malloc_hooks.h ('k') | runtime/vm/malloc_hooks_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698