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

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

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