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

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

Issue 2713803003: Revert "Updated MallocHooks to collect stack traces when memory is allocated." (Closed)
Patch Set: Created 3 years, 9 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 #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)
9 8
10 #include "vm/malloc_hooks.h" 9 #include "vm/malloc_hooks.h"
11 10
12 #include "gperftools/malloc_hook.h" 11 #include "gperftools/malloc_hook.h"
13 12
14 #include "platform/assert.h" 13 #include "platform/assert.h"
15 #include "vm/hash_map.h" 14 #include "vm/hash_map.h"
16 #include "vm/json_stream.h" 15 #include "vm/json_stream.h"
17 #include "vm/lockers.h" 16 #include "vm/lockers.h"
18 #include "vm/profiler.h"
19 17
20 namespace dart { 18 namespace dart {
21 19
22 class AddressMap;
23
24 // MallocHooksState contains all of the state related to the configuration of
25 // the malloc hooks, allocation information, and locks.
26 class MallocHooksState : public AllStatic {
27 public:
28 static void RecordAllocHook(const void* ptr, size_t size);
29 static void RecordFreeHook(const void* ptr);
30
31 static bool Active() {
32 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
33 return active_;
34 }
35 static void Init();
36
37 static bool ProfilingEnabled() { return (OSThread::TryCurrent() != NULL); }
38
39 static bool stack_trace_collection_enabled() {
40 return stack_trace_collection_enabled_;
41 }
42
43 static void set_stack_trace_collection_enabled(bool enabled) {
44 stack_trace_collection_enabled_ = enabled;
45 }
46
47 static bool IsOriginalProcess() {
48 ASSERT(original_pid_ != kInvalidPid);
49 return original_pid_ == OS::ProcessId();
50 }
51
52 static Mutex* malloc_hook_mutex() { return malloc_hook_mutex_; }
53
54 static intptr_t allocation_count() { return allocation_count_; }
55
56 static intptr_t heap_allocated_memory_in_bytes() {
57 return heap_allocated_memory_in_bytes_;
58 }
59
60 static void IncrementHeapAllocatedMemoryInBytes(intptr_t size) {
61 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
62 ASSERT(size >= 0);
63 heap_allocated_memory_in_bytes_ += size;
64 ++allocation_count_;
65 }
66
67 static void DecrementHeapAllocatedMemoryInBytes(intptr_t size) {
68 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
69 ASSERT(size >= 0);
70 ASSERT(heap_allocated_memory_in_bytes_ >= size);
71 heap_allocated_memory_in_bytes_ -= size;
72 --allocation_count_;
73 ASSERT(allocation_count_ >= 0);
74 }
75
76 static AddressMap* address_map() { return address_map_; }
77
78 static void ResetStats();
79 static void TearDown();
80
81 private:
82 static Mutex* malloc_hook_mutex_;
83
84 // Variables protected by malloc_hook_mutex_.
85 static bool active_;
86 static bool stack_trace_collection_enabled_;
87 static intptr_t allocation_count_;
88 static intptr_t heap_allocated_memory_in_bytes_;
89 static AddressMap* address_map_;
90 // End protected variables.
91
92 static intptr_t original_pid_;
93 static const intptr_t kInvalidPid = -1;
94 };
95
96 // A locker-type class to automatically grab and release the 20 // A locker-type class to automatically grab and release the
97 // in_malloc_hook_flag_. 21 // in_malloc_hook_flag_.
98 class MallocHookScope { 22 class MallocHookScope {
99 public: 23 public:
100 static void InitMallocHookFlag() { 24 static void InitMallocHookFlag() {
101 MutexLocker ml(malloc_hook_scope_mutex_); 25 MutexLocker ml(malloc_hook_scope_mutex_);
102 ASSERT(in_malloc_hook_flag_ == kUnsetThreadLocalKey); 26 ASSERT(in_malloc_hook_flag_ == kUnsetThreadLocalKey);
103 in_malloc_hook_flag_ = OSThread::CreateThreadLocal(); 27 in_malloc_hook_flag_ = OSThread::CreateThreadLocal();
104 OSThread::SetThreadLocal(in_malloc_hook_flag_, 0); 28 OSThread::SetThreadLocal(in_malloc_hook_flag_, 0);
105 } 29 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 } 62 }
139 63
140 private: 64 private:
141 static Mutex* malloc_hook_scope_mutex_; 65 static Mutex* malloc_hook_scope_mutex_;
142 static ThreadLocalKey in_malloc_hook_flag_; 66 static ThreadLocalKey in_malloc_hook_flag_;
143 67
144 DISALLOW_ALLOCATION(); 68 DISALLOW_ALLOCATION();
145 DISALLOW_COPY_AND_ASSIGN(MallocHookScope); 69 DISALLOW_COPY_AND_ASSIGN(MallocHookScope);
146 }; 70 };
147 71
148 // AllocationInfo contains all information related to a given allocation
149 // including:
150 // -Allocation size in bytes
151 // -Stack trace corresponding to the location of allocation, if applicable
152 class AllocationInfo {
153 public:
154 explicit AllocationInfo(intptr_t allocation_size)
155 : sample_(NULL), allocation_size_(allocation_size) {
156 // Stack trace collection is disabled when we are in the process of creating
157 // the first OSThread in order to prevent deadlocks.
158 if (MallocHooksState::ProfilingEnabled() &&
159 MallocHooksState::stack_trace_collection_enabled()) {
160 sample_ = Profiler::SampleNativeAllocation(kSkipCount);
161 }
162 }
163
164 Sample* sample() const { return sample_; }
165 intptr_t allocation_size() const { return allocation_size_; }
166
167 private:
168 Sample* sample_;
169 intptr_t allocation_size_;
170
171 // The number of frames that are generated by the malloc hooks and collection
172 // of the stack trace. These frames are ignored when collecting the stack
173 // trace for a memory allocation. If this number is incorrect, some tests in
174 // malloc_hook_tests.cc might fail, particularily
175 // StackTraceMallocHookLengthTest. If this value is updated, please make sure
176 // that the MallocHooks test cases pass on all platforms.
177 static const intptr_t kSkipCount = 5;
178 };
179
180 72
181 // Custom key/value trait specifically for address/size pairs. Unlike 73 // Custom key/value trait specifically for address/size pairs. Unlike
182 // RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry. 74 // RawPointerKeyValueTrait, the default value is -1 as 0 can be a valid entry.
183 class AddressKeyValueTrait : public AllStatic { 75 class AddressKeyValueTrait {
184 public: 76 public:
185 typedef const void* Key; 77 typedef const void* Key;
186 typedef AllocationInfo* Value; 78 typedef intptr_t Value;
187 79
188 struct Pair { 80 struct Pair {
189 Key key; 81 Key key;
190 Value value; 82 Value value;
191 Pair() : key(NULL), value(NULL) {} 83 Pair() : key(NULL), value(-1) {}
192 Pair(const Key key, const Value& value) : key(key), value(value) {} 84 Pair(const Key key, const Value& value) : key(key), value(value) {}
193 Pair(const Pair& other) : key(other.key), value(other.value) {} 85 Pair(const Pair& other) : key(other.key), value(other.value) {}
194 }; 86 };
195 87
196 static Key KeyOf(Pair kv) { return kv.key; } 88 static Key KeyOf(Pair kv) { return kv.key; }
197 static Value ValueOf(Pair kv) { return kv.value; } 89 static Value ValueOf(Pair kv) { return kv.value; }
198 static intptr_t Hashcode(Key key) { return reinterpret_cast<intptr_t>(key); } 90 static intptr_t Hashcode(Key key) { return reinterpret_cast<intptr_t>(key); }
199 static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; } 91 static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; }
200 }; 92 };
201 93
202 94
203 // Map class that will be used to store mappings between ptr -> allocation size. 95 // Map class that will be used to store mappings between ptr -> allocation size.
204 class AddressMap : public MallocDirectChainedHashMap<AddressKeyValueTrait> { 96 class AddressMap : public MallocDirectChainedHashMap<AddressKeyValueTrait> {
205 public: 97 public:
206 typedef AddressKeyValueTrait::Key Key; 98 typedef AddressKeyValueTrait::Key Key;
207 typedef AddressKeyValueTrait::Value Value; 99 typedef AddressKeyValueTrait::Value Value;
208 typedef AddressKeyValueTrait::Pair Pair; 100 typedef AddressKeyValueTrait::Pair Pair;
209 101
210 virtual ~AddressMap() { Clear(); } 102 inline void Insert(const Key& key, const Value& value) {
211
212 void Insert(const Key& key, const Value& value) {
213 Pair pair(key, value); 103 Pair pair(key, value);
214 MallocDirectChainedHashMap<AddressKeyValueTrait>::Insert(pair); 104 MallocDirectChainedHashMap<AddressKeyValueTrait>::Insert(pair);
215 } 105 }
216 106
217 bool Lookup(const Key& key, Value* value) { 107 inline bool Lookup(const Key& key, Value* value) {
218 ASSERT(value != NULL); 108 ASSERT(value != NULL);
219 Pair* pair = MallocDirectChainedHashMap<AddressKeyValueTrait>::Lookup(key); 109 Pair* pair = MallocDirectChainedHashMap<AddressKeyValueTrait>::Lookup(key);
220 if (pair == NULL) { 110 if (pair == NULL) {
221 return false; 111 return false;
222 } else { 112 } else {
223 *value = pair->value; 113 *value = pair->value;
224 return true; 114 return true;
225 } 115 }
226 } 116 }
227
228 void Clear() {
229 Iterator iter = GetIterator();
230 Pair* result = iter.Next();
231 while (result != NULL) {
232 delete result->value;
233 result->value = NULL;
234 result = iter.Next();
235 }
236 MallocDirectChainedHashMap<AddressKeyValueTrait>::Clear();
237 }
238 }; 117 };
239 118
240 119
120 class MallocHooksState : public AllStatic {
121 public:
122 static void RecordAllocHook(const void* ptr, size_t size);
123 static void RecordFreeHook(const void* ptr);
124
125 static bool Active() { return active_; }
126 static void Init() {
127 address_map_ = new AddressMap();
128 active_ = true;
129 original_pid_ = OS::ProcessId();
130 }
131
132 static bool IsOriginalProcess() {
133 ASSERT(original_pid_ != kInvalidPid);
134 return original_pid_ == OS::ProcessId();
135 }
136
137 static Mutex* malloc_hook_mutex() { return malloc_hook_mutex_; }
138
139 static intptr_t allocation_count() { return allocation_count_; }
140
141 static intptr_t heap_allocated_memory_in_bytes() {
142 return heap_allocated_memory_in_bytes_;
143 }
144
145 static void IncrementHeapAllocatedMemoryInBytes(intptr_t size) {
146 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
147 ASSERT(size >= 0);
148 heap_allocated_memory_in_bytes_ += size;
149 ++allocation_count_;
150 }
151
152 static void DecrementHeapAllocatedMemoryInBytes(intptr_t size) {
153 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
154 ASSERT(size >= 0);
155 ASSERT(heap_allocated_memory_in_bytes_ >= size);
156 heap_allocated_memory_in_bytes_ -= size;
157 --allocation_count_;
158 ASSERT(allocation_count_ >= 0);
159 }
160
161 static AddressMap* address_map() { return address_map_; }
162
163 static void ResetStats() {
164 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
165 allocation_count_ = 0;
166 heap_allocated_memory_in_bytes_ = 0;
167 address_map_->Clear();
168 }
169
170 static void TearDown() {
171 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
172 active_ = false;
173 original_pid_ = kInvalidPid;
174 ResetStats();
175 delete address_map_;
176 }
177
178 private:
179 static bool active_;
180 static intptr_t original_pid_;
181 static Mutex* malloc_hook_mutex_;
182 static intptr_t allocation_count_;
183 static intptr_t heap_allocated_memory_in_bytes_;
184 static AddressMap* address_map_;
185
186 static const intptr_t kInvalidPid = -1;
187 };
188
189
241 // MallocHookScope state. 190 // MallocHookScope state.
242 Mutex* MallocHookScope::malloc_hook_scope_mutex_ = new Mutex(); 191 Mutex* MallocHookScope::malloc_hook_scope_mutex_ = new Mutex();
243 ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey; 192 ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey;
244 193
245 // MallocHooks state / locks. 194 // MallocHooks state / locks.
246 bool MallocHooksState::active_ = false; 195 bool MallocHooksState::active_ = false;
247 bool MallocHooksState::stack_trace_collection_enabled_ = false;
248 intptr_t MallocHooksState::original_pid_ = MallocHooksState::kInvalidPid; 196 intptr_t MallocHooksState::original_pid_ = MallocHooksState::kInvalidPid;
249 Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex(); 197 Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex();
250 198
251 // Memory allocation state information. 199 // Memory allocation state information.
252 intptr_t MallocHooksState::allocation_count_ = 0; 200 intptr_t MallocHooksState::allocation_count_ = 0;
253 intptr_t MallocHooksState::heap_allocated_memory_in_bytes_ = 0; 201 intptr_t MallocHooksState::heap_allocated_memory_in_bytes_ = 0;
254 AddressMap* MallocHooksState::address_map_ = NULL; 202 AddressMap* MallocHooksState::address_map_ = NULL;
255 203
256 204
257 void MallocHooksState::Init() {
258 address_map_ = new AddressMap();
259 active_ = true;
260 #if defined(DEBUG)
261 stack_trace_collection_enabled_ = true;
262 #else
263 stack_trace_collection_enabled_ = false;
264 #endif // defined(DEBUG)
265 original_pid_ = OS::ProcessId();
266 }
267
268
269 void MallocHooksState::ResetStats() {
270 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
271 allocation_count_ = 0;
272 heap_allocated_memory_in_bytes_ = 0;
273 address_map_->Clear();
274 }
275
276
277 void MallocHooksState::TearDown() {
278 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
279 active_ = false;
280 original_pid_ = kInvalidPid;
281 ResetStats();
282 delete address_map_;
283 address_map_ = NULL;
284 }
285
286
287 void MallocHooks::InitOnce() { 205 void MallocHooks::InitOnce() {
288 if (!FLAG_enable_malloc_hooks) { 206 if (!FLAG_enable_malloc_hooks) {
289 return; 207 return;
290 } 208 }
291 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 209 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
292 ASSERT(!MallocHooksState::Active()); 210 ASSERT(!MallocHooksState::Active());
293 211
294 MallocHookScope::InitMallocHookFlag(); 212 MallocHookScope::InitMallocHookFlag();
295 MallocHooksState::Init(); 213 MallocHooksState::Init();
296 214
(...skipping 18 matching lines...) Expand all
315 success = MallocHook::RemoveNewHook(&MallocHooksState::RecordAllocHook); 233 success = MallocHook::RemoveNewHook(&MallocHooksState::RecordAllocHook);
316 ASSERT(success); 234 ASSERT(success);
317 success = MallocHook::RemoveDeleteHook(&MallocHooksState::RecordFreeHook); 235 success = MallocHook::RemoveDeleteHook(&MallocHooksState::RecordFreeHook);
318 ASSERT(success); 236 ASSERT(success);
319 237
320 MallocHooksState::TearDown(); 238 MallocHooksState::TearDown();
321 MallocHookScope::DestroyMallocHookFlag(); 239 MallocHookScope::DestroyMallocHookFlag();
322 } 240 }
323 241
324 242
325 bool MallocHooks::ProfilingEnabled() {
326 return MallocHooksState::ProfilingEnabled();
327 }
328
329
330 bool MallocHooks::stack_trace_collection_enabled() {
331 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
332 return MallocHooksState::stack_trace_collection_enabled();
333 }
334
335
336 void MallocHooks::set_stack_trace_collection_enabled(bool enabled) {
337 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
338 MallocHooksState::set_stack_trace_collection_enabled(enabled);
339 }
340
341
342 void MallocHooks::ResetStats() { 243 void MallocHooks::ResetStats() {
343 if (!FLAG_enable_malloc_hooks) { 244 if (!FLAG_enable_malloc_hooks) {
344 return; 245 return;
345 } 246 }
346 // Set the malloc hook flag before completing the reset since ResetStats()
347 // frees memory.
348 MallocHookScope mhs;
349 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 247 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
350 if (MallocHooksState::Active()) { 248 if (MallocHooksState::Active()) {
351 MallocHooksState::ResetStats(); 249 MallocHooksState::ResetStats();
352 } 250 }
353 } 251 }
354 252
355 253
356 bool MallocHooks::Active() { 254 bool MallocHooks::Active() {
357 if (!FLAG_enable_malloc_hooks) { 255 if (!FLAG_enable_malloc_hooks) {
358 return false; 256 return false;
359 } 257 }
360 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 258 ASSERT(MallocHooksState::malloc_hook_mutex()->IsOwnedByCurrentThread());
361 return MallocHooksState::Active(); 259 return MallocHooksState::Active();
362 } 260 }
363 261
364 262
365 void MallocHooks::PrintToJSONObject(JSONObject* jsobj) { 263 void MallocHooks::PrintToJSONObject(JSONObject* jsobj) {
366 if (!FLAG_enable_malloc_hooks) { 264 if (!FLAG_enable_malloc_hooks) {
367 return; 265 return;
368 } 266 }
369 intptr_t allocated_memory = 0; 267 intptr_t allocated_memory = 0;
370 intptr_t allocation_count = 0; 268 intptr_t allocation_count = 0;
371 bool add_usage = false; 269 bool add_usage = false;
372 // AddProperty may call malloc which would result in an attempt 270 // AddProperty may call malloc which would result in an attempt
373 // to acquire the lock recursively so we extract the values first 271 // to acquire the lock recursively so we extract the values first
374 // and then add the JSON properties. 272 // and then add the JSON properties.
375 { 273 {
376 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 274 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
377 if (MallocHooksState::Active()) { 275 if (Active()) {
378 allocated_memory = MallocHooksState::heap_allocated_memory_in_bytes(); 276 allocated_memory = MallocHooksState::heap_allocated_memory_in_bytes();
379 allocation_count = MallocHooksState::allocation_count(); 277 allocation_count = MallocHooksState::allocation_count();
380 add_usage = true; 278 add_usage = true;
381 } 279 }
382 } 280 }
383 if (add_usage) { 281 if (add_usage) {
384 jsobj->AddProperty("_heapAllocatedMemoryUsage", allocated_memory); 282 jsobj->AddProperty("_heapAllocatedMemoryUsage", allocated_memory);
385 jsobj->AddProperty("_heapAllocationCount", allocation_count); 283 jsobj->AddProperty("_heapAllocationCount", allocation_count);
386 } 284 }
387 } 285 }
(...skipping 10 matching lines...) Expand all
398 296
399 intptr_t MallocHooks::heap_allocated_memory_in_bytes() { 297 intptr_t MallocHooks::heap_allocated_memory_in_bytes() {
400 if (!FLAG_enable_malloc_hooks) { 298 if (!FLAG_enable_malloc_hooks) {
401 return 0; 299 return 0;
402 } 300 }
403 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 301 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
404 return MallocHooksState::heap_allocated_memory_in_bytes(); 302 return MallocHooksState::heap_allocated_memory_in_bytes();
405 } 303 }
406 304
407 305
408 Sample* MallocHooks::GetSample(const void* ptr) {
409 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
410 ASSERT(MallocHooksState::Active());
411
412 if (ptr != NULL) {
413 AllocationInfo* allocation_info = NULL;
414 if (MallocHooksState::address_map()->Lookup(ptr, &allocation_info)) {
415 ASSERT(allocation_info != NULL);
416 return allocation_info->sample();
417 }
418 }
419 return NULL;
420 }
421
422
423 void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) { 306 void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) {
424 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { 307 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) {
425 return; 308 return;
426 } 309 }
427 310
428 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 311 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
429 // Now that we hold the lock, check to make sure everything is still active. 312 // Now that we hold the lock, check to make sure everything is still active.
430 if ((ptr != NULL) && MallocHooksState::Active()) { 313 if ((ptr != NULL) && MallocHooksState::Active()) {
431 // Set the malloc hook flag to avoid calling hooks again if memory is 314 // Set the malloc hook flag to avoid calling hooks again if memory is
432 // allocated/freed below. 315 // allocated/freed below.
433 MallocHookScope mhs; 316 MallocHookScope mhs;
434 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size); 317 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size);
435 MallocHooksState::address_map()->Insert(ptr, new AllocationInfo(size)); 318 MallocHooksState::address_map()->Insert(ptr, size);
436 } 319 }
437 } 320 }
438 321
439 322
440 void MallocHooksState::RecordFreeHook(const void* ptr) { 323 void MallocHooksState::RecordFreeHook(const void* ptr) {
441 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { 324 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) {
442 return; 325 return;
443 } 326 }
444 327
445 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 328 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
446 // Now that we hold the lock, check to make sure everything is still active. 329 // Now that we hold the lock, check to make sure everything is still active.
447 if ((ptr != NULL) && MallocHooksState::Active()) { 330 if ((ptr != NULL) && MallocHooksState::Active()) {
448 AllocationInfo* allocation_info = NULL; 331 // Set the malloc hook flag to avoid calling hooks again if memory is
449 if (MallocHooksState::address_map()->Lookup(ptr, &allocation_info)) { 332 // allocated/freed below.
450 MallocHooksState::DecrementHeapAllocatedMemoryInBytes( 333 MallocHookScope mhs;
451 allocation_info->allocation_size()); 334 intptr_t size = 0;
335 if (MallocHooksState::address_map()->Lookup(ptr, &size)) {
336 MallocHooksState::DecrementHeapAllocatedMemoryInBytes(size);
452 MallocHooksState::address_map()->Remove(ptr); 337 MallocHooksState::address_map()->Remove(ptr);
453 delete allocation_info;
454 } 338 }
455 } 339 }
456 } 340 }
457 341
458 } // namespace dart 342 } // namespace dart
459 343
460 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) && 344 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
461 // !defined(TARGET_ARCH_DBC) && !defined(TARGET_OS_FUCHSIA)
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