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

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

Issue 2678313003: Fix for issue 28638 - flakiness on dartkp-dart-precompiled caused by MallocHooks (Closed)
Patch Set: Address self review comments. Created 3 years, 10 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_unsupported.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 8
9 #include "vm/malloc_hooks.h" 9 #include "vm/malloc_hooks.h"
10 10
11 #include "gperftools/malloc_hook.h" 11 #include "gperftools/malloc_hook.h"
12 12
13 #include "platform/assert.h" 13 #include "platform/assert.h"
14 #include "vm/hash_map.h" 14 #include "vm/hash_map.h"
15 #include "vm/json_stream.h"
15 #include "vm/lockers.h" 16 #include "vm/lockers.h"
16 17
17 namespace dart { 18 namespace dart {
18 19
19 // A locker-type class to automatically grab and release the 20 // A locker-type class to automatically grab and release the
20 // in_malloc_hook_flag_. 21 // in_malloc_hook_flag_.
21 class MallocHookScope { 22 class MallocHookScope {
22 public: 23 public:
23 static void InitMallocHookFlag() { 24 static void InitMallocHookFlag() {
24 ASSERT(in_malloc_hook_flag_ == kUnsetThreadLocalKey); 25 ASSERT(in_malloc_hook_flag_ == kUnsetThreadLocalKey);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 if (pair == NULL) { 96 if (pair == NULL) {
96 return false; 97 return false;
97 } else { 98 } else {
98 *value = pair->value; 99 *value = pair->value;
99 return true; 100 return true;
100 } 101 }
101 } 102 }
102 }; 103 };
103 104
104 105
105 class MallocHooksState { 106 class MallocHooksState : public AllStatic {
106 public: 107 public:
107 static void RecordAllocHook(const void* ptr, size_t size); 108 static void RecordAllocHook(const void* ptr, size_t size);
108 static void RecordFreeHook(const void* ptr); 109 static void RecordFreeHook(const void* ptr);
109 110
110 static bool initialized() { return initialized_; } 111 static bool Active() { return active_; }
111 static void Init() { 112 static void Init() {
112 address_map_ = new AddressMap(); 113 address_map_ = new AddressMap();
113 initialized_ = true; 114 active_ = true;
114 original_pid_ = OS::ProcessId(); 115 original_pid_ = OS::ProcessId();
115 } 116 }
116 117
117 static bool IsOriginalProcess() { 118 static bool IsOriginalProcess() {
118 ASSERT(original_pid_ != kInvalidPid); 119 ASSERT(original_pid_ != kInvalidPid);
119 return original_pid_ == OS::ProcessId(); 120 return original_pid_ == OS::ProcessId();
120 } 121 }
121 122
122 static Mutex* malloc_hook_mutex() { return malloc_hook_mutex_; } 123 static Mutex* malloc_hook_mutex() { return malloc_hook_mutex_; }
123 124
124 static intptr_t allocation_count() { return allocation_count_; } 125 static intptr_t allocation_count() { return allocation_count_; }
125 126
126 static intptr_t heap_allocated_memory_in_bytes() { 127 static intptr_t heap_allocated_memory_in_bytes() {
127 return heap_allocated_memory_in_bytes_; 128 return heap_allocated_memory_in_bytes_;
128 } 129 }
129 130
130 static void IncrementHeapAllocatedMemoryInBytes(intptr_t size) { 131 static void IncrementHeapAllocatedMemoryInBytes(intptr_t size) {
132 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
131 ASSERT(size >= 0); 133 ASSERT(size >= 0);
132 heap_allocated_memory_in_bytes_ += size; 134 heap_allocated_memory_in_bytes_ += size;
133 ++allocation_count_; 135 ++allocation_count_;
134 } 136 }
135 137
136 static void DecrementHeapAllocatedMemoryInBytes(intptr_t size) { 138 static void DecrementHeapAllocatedMemoryInBytes(intptr_t size) {
139 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
137 ASSERT(size >= 0); 140 ASSERT(size >= 0);
138 ASSERT(heap_allocated_memory_in_bytes_ >= size); 141 ASSERT(heap_allocated_memory_in_bytes_ >= size);
139 heap_allocated_memory_in_bytes_ -= size; 142 heap_allocated_memory_in_bytes_ -= size;
140 --allocation_count_; 143 --allocation_count_;
141 ASSERT(allocation_count_ >= 0); 144 ASSERT(allocation_count_ >= 0);
142 } 145 }
143 146
144 static AddressMap* address_map() { return address_map_; } 147 static AddressMap* address_map() { return address_map_; }
145 148
146 static void ResetStats() { 149 static void ResetStats() {
150 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
147 allocation_count_ = 0; 151 allocation_count_ = 0;
148 heap_allocated_memory_in_bytes_ = 0; 152 heap_allocated_memory_in_bytes_ = 0;
149 address_map_->Clear(); 153 address_map_->Clear();
150 } 154 }
151 155
152 static void TearDown() { 156 static void TearDown() {
153 initialized_ = false; 157 ASSERT(malloc_hook_mutex()->IsOwnedByCurrentThread());
158 active_ = false;
154 original_pid_ = kInvalidPid; 159 original_pid_ = kInvalidPid;
155 ResetStats(); 160 ResetStats();
156 delete address_map_; 161 delete address_map_;
157 } 162 }
158 163
159 private: 164 private:
160 static bool initialized_; 165 static bool active_;
161 static intptr_t original_pid_; 166 static intptr_t original_pid_;
162 static Mutex* malloc_hook_mutex_; 167 static Mutex* malloc_hook_mutex_;
163 static intptr_t allocation_count_; 168 static intptr_t allocation_count_;
164 static intptr_t heap_allocated_memory_in_bytes_; 169 static intptr_t heap_allocated_memory_in_bytes_;
165 static AddressMap* address_map_; 170 static AddressMap* address_map_;
166 171
167 static const intptr_t kInvalidPid = -1; 172 static const intptr_t kInvalidPid = -1;
168
169 DISALLOW_ALLOCATION();
170 DISALLOW_COPY_AND_ASSIGN(MallocHooksState);
171 }; 173 };
172 174
173 175
174 // MallocHooks state / locks. 176 // MallocHooks state / locks.
175 ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey; 177 ThreadLocalKey MallocHookScope::in_malloc_hook_flag_ = kUnsetThreadLocalKey;
176 bool MallocHooksState::initialized_ = false; 178 bool MallocHooksState::active_ = false;
177 intptr_t MallocHooksState::original_pid_ = MallocHooksState::kInvalidPid; 179 intptr_t MallocHooksState::original_pid_ = MallocHooksState::kInvalidPid;
178 Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex(); 180 Mutex* MallocHooksState::malloc_hook_mutex_ = new Mutex();
179 181
180 // Memory allocation state information. 182 // Memory allocation state information.
181 intptr_t MallocHooksState::allocation_count_ = 0; 183 intptr_t MallocHooksState::allocation_count_ = 0;
182 intptr_t MallocHooksState::heap_allocated_memory_in_bytes_ = 0; 184 intptr_t MallocHooksState::heap_allocated_memory_in_bytes_ = 0;
183 AddressMap* MallocHooksState::address_map_ = NULL; 185 AddressMap* MallocHooksState::address_map_ = NULL;
184 186
185 187
186 void MallocHooks::InitOnce() { 188 void MallocHooks::InitOnce() {
187 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 189 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
188 ASSERT(!MallocHooksState::initialized()); 190 ASSERT(!MallocHooksState::Active());
189 191
190 MallocHookScope::InitMallocHookFlag(); 192 MallocHookScope::InitMallocHookFlag();
191 MallocHooksState::Init(); 193 MallocHooksState::Init();
192 194
193 // Register malloc hooks. 195 // Register malloc hooks.
194 bool success = false; 196 bool success = false;
195 success = MallocHook::AddNewHook(&MallocHooksState::RecordAllocHook); 197 success = MallocHook::AddNewHook(&MallocHooksState::RecordAllocHook);
196 ASSERT(success); 198 ASSERT(success);
197 success = MallocHook::AddDeleteHook(&MallocHooksState::RecordFreeHook); 199 success = MallocHook::AddDeleteHook(&MallocHooksState::RecordFreeHook);
198 ASSERT(success); 200 ASSERT(success);
199 } 201 }
200 202
201 203
202 void MallocHooks::TearDown() { 204 void MallocHooks::TearDown() {
203 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 205 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
204 ASSERT(MallocHooksState::initialized()); 206 ASSERT(MallocHooksState::Active());
205 207
206 // Remove malloc hooks. 208 // Remove malloc hooks.
207 bool success = false; 209 bool success = false;
208 success = MallocHook::RemoveNewHook(&MallocHooksState::RecordAllocHook); 210 success = MallocHook::RemoveNewHook(&MallocHooksState::RecordAllocHook);
209 ASSERT(success); 211 ASSERT(success);
210 success = MallocHook::RemoveDeleteHook(&MallocHooksState::RecordFreeHook); 212 success = MallocHook::RemoveDeleteHook(&MallocHooksState::RecordFreeHook);
211 ASSERT(success); 213 ASSERT(success);
212 214
213 MallocHooksState::TearDown(); 215 MallocHooksState::TearDown();
214 MallocHookScope::DestroyMallocHookFlag(); 216 MallocHookScope::DestroyMallocHookFlag();
215 } 217 }
216 218
217 219
218 void MallocHooks::ResetStats() { 220 void MallocHooks::ResetStats() {
219 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 221 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
220 ASSERT(MallocHooksState::initialized()); 222 if (MallocHooksState::Active()) {
221 223 MallocHooksState::ResetStats();
222 MallocHooksState::ResetStats(); 224 }
223 } 225 }
224 226
225 227
226 bool MallocHooks::Initialized() { 228 bool MallocHooks::Active() {
227 return MallocHooksState::initialized(); 229 ASSERT(MallocHooksState::malloc_hook_mutex()->IsOwnedByCurrentThread());
230 return MallocHooksState::Active();
228 } 231 }
229 232
230 233
234 void MallocHooks::PrintToJSONObject(JSONObject* jsobj) {
235 intptr_t allocated_memory = 0;
236 intptr_t allocation_count = 0;
237 bool add_usage = false;
238 // AddProperty may call malloc which would result in an attempt
239 // to acquire the lock recursively so we extract the values first
240 // and then add the JSON properties.
241 {
242 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
243 if (Active()) {
244 allocated_memory = MallocHooksState::heap_allocated_memory_in_bytes();
245 allocation_count = MallocHooksState::allocation_count();
246 add_usage = true;
247 }
248 }
249 if (add_usage) {
250 jsobj->AddProperty("_heapAllocatedMemoryUsage", allocated_memory);
251 jsobj->AddProperty("_heapAllocationCount", allocation_count);
252 }
253 }
254
255
231 intptr_t MallocHooks::allocation_count() { 256 intptr_t MallocHooks::allocation_count() {
232 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 257 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
233 return MallocHooksState::allocation_count(); 258 return MallocHooksState::allocation_count();
234 } 259 }
235 260
236 261
237 intptr_t MallocHooks::heap_allocated_memory_in_bytes() { 262 intptr_t MallocHooks::heap_allocated_memory_in_bytes() {
238 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 263 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
239 return MallocHooksState::heap_allocated_memory_in_bytes(); 264 return MallocHooksState::heap_allocated_memory_in_bytes();
240 } 265 }
241 266
242 267
243 void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) { 268 void MallocHooksState::RecordAllocHook(const void* ptr, size_t size) {
244 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { 269 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) {
245 return; 270 return;
246 } 271 }
247 272
248 // Set the malloc hook flag before grabbing the mutex to avoid calling hooks 273 // Set the malloc hook flag before grabbing the mutex to avoid calling hooks
249 // again. 274 // again.
250 MallocHookScope mhs; 275 MallocHookScope mhs;
251 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 276 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
252 ASSERT(MallocHooksState::initialized()); 277 if ((ptr != NULL) && MallocHooksState::Active()) {
253
254 if (ptr != NULL) {
255 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size); 278 MallocHooksState::IncrementHeapAllocatedMemoryInBytes(size);
256 MallocHooksState::address_map()->Insert(ptr, size); 279 MallocHooksState::address_map()->Insert(ptr, size);
257 } 280 }
258 } 281 }
259 282
260 283
261 void MallocHooksState::RecordFreeHook(const void* ptr) { 284 void MallocHooksState::RecordFreeHook(const void* ptr) {
262 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) { 285 if (MallocHookScope::IsInHook() || !MallocHooksState::IsOriginalProcess()) {
263 return; 286 return;
264 } 287 }
265 288
266 // Set the malloc hook flag before grabbing the mutex to avoid calling hooks 289 // Set the malloc hook flag before grabbing the mutex to avoid calling hooks
267 // again. 290 // again.
268 MallocHookScope mhs; 291 MallocHookScope mhs;
269 MutexLocker ml(MallocHooksState::malloc_hook_mutex()); 292 MutexLocker ml(MallocHooksState::malloc_hook_mutex());
270 ASSERT(MallocHooksState::initialized()); 293 if ((ptr != NULL) && MallocHooksState::Active()) {
271
272 if (ptr != NULL) {
273 intptr_t size = 0; 294 intptr_t size = 0;
274 if (MallocHooksState::address_map()->Lookup(ptr, &size)) { 295 if (MallocHooksState::address_map()->Lookup(ptr, &size)) {
275 MallocHooksState::DecrementHeapAllocatedMemoryInBytes(size); 296 MallocHooksState::DecrementHeapAllocatedMemoryInBytes(size);
276 MallocHooksState::address_map()->Remove(ptr); 297 MallocHooksState::address_map()->Remove(ptr);
277 } 298 }
278 } 299 }
279 } 300 }
280 301
281 } // namespace dart 302 } // namespace dart
282 303
283 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT) 304 #endif // defined(DART_USE_TCMALLOC) && !defined(PRODUCT)
OLDNEW
« no previous file with comments | « runtime/vm/malloc_hooks.h ('k') | runtime/vm/malloc_hooks_unsupported.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698