OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 12 matching lines...) Expand all Loading... |
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 */ | 29 */ |
30 | 30 |
31 #include "platform/heap/Heap.h" | 31 #include "platform/heap/Heap.h" |
32 | 32 |
| 33 #include "base/debug/alias.h" |
33 #include "base/sys_info.h" | 34 #include "base/sys_info.h" |
34 #include "platform/Histogram.h" | 35 #include "platform/Histogram.h" |
35 #include "platform/ScriptForbiddenScope.h" | 36 #include "platform/ScriptForbiddenScope.h" |
36 #include "platform/TraceEvent.h" | 37 #include "platform/TraceEvent.h" |
37 #include "platform/heap/BlinkGCMemoryDumpProvider.h" | 38 #include "platform/heap/BlinkGCMemoryDumpProvider.h" |
38 #include "platform/heap/CallbackStack.h" | 39 #include "platform/heap/CallbackStack.h" |
39 #include "platform/heap/MarkingVisitor.h" | 40 #include "platform/heap/MarkingVisitor.h" |
40 #include "platform/heap/PageMemory.h" | 41 #include "platform/heap/PageMemory.h" |
41 #include "platform/heap/PagePool.h" | 42 #include "platform/heap/PagePool.h" |
42 #include "platform/heap/SafePoint.h" | 43 #include "platform/heap/SafePoint.h" |
(...skipping 15 matching lines...) Expand all Loading... |
58 class ParkThreadsScope final { | 59 class ParkThreadsScope final { |
59 STACK_ALLOCATED(); | 60 STACK_ALLOCATED(); |
60 public: | 61 public: |
61 ParkThreadsScope() | 62 ParkThreadsScope() |
62 : m_shouldResumeThreads(false) | 63 : m_shouldResumeThreads(false) |
63 { | 64 { |
64 } | 65 } |
65 | 66 |
66 bool parkThreads(ThreadState* state) | 67 bool parkThreads(ThreadState* state) |
67 { | 68 { |
68 TRACE_EVENT0("blink_gc", "ThreadHeap::ParkThreadsScope"); | 69 TRACE_EVENT0("blink_gc", "Heap::ParkThreadsScope"); |
69 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); | 70 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); |
70 if (state->isMainThread()) | 71 if (state->isMainThread()) |
71 TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting"); | 72 TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting"); |
72 | 73 |
73 // TODO(haraken): In an unlikely coincidence that two threads decide | 74 // TODO(haraken): In an unlikely coincidence that two threads decide |
74 // to collect garbage at the same time, avoid doing two GCs in | 75 // to collect garbage at the same time, avoid doing two GCs in |
75 // a row and return false. | 76 // a row and return false. |
76 double startTime = WTF::currentTimeMS(); | 77 double startTime = WTF::currentTimeMS(); |
77 | 78 |
78 m_shouldResumeThreads = ThreadState::stopThreads(); | 79 m_shouldResumeThreads = ThreadState::stopThreads(); |
(...skipping 12 matching lines...) Expand all Loading... |
91 // Only cleanup if we parked all threads in which case the GC happened | 92 // Only cleanup if we parked all threads in which case the GC happened |
92 // and we need to resume the other threads. | 93 // and we need to resume the other threads. |
93 if (m_shouldResumeThreads) | 94 if (m_shouldResumeThreads) |
94 ThreadState::resumeThreads(); | 95 ThreadState::resumeThreads(); |
95 } | 96 } |
96 | 97 |
97 private: | 98 private: |
98 bool m_shouldResumeThreads; | 99 bool m_shouldResumeThreads; |
99 }; | 100 }; |
100 | 101 |
101 void ThreadHeap::flushHeapDoesNotContainCache() | 102 void Heap::flushHeapDoesNotContainCache() |
102 { | 103 { |
103 s_heapDoesNotContainCache->flush(); | 104 s_heapDoesNotContainCache->flush(); |
104 } | 105 } |
105 | 106 |
106 void ProcessHeap::init() | 107 void ProcessHeap::init() |
107 { | 108 { |
108 s_totalAllocatedSpace = 0; | 109 s_totalAllocatedSpace = 0; |
109 s_totalAllocatedObjectSize = 0; | 110 s_totalAllocatedObjectSize = 0; |
110 s_totalMarkedObjectSize = 0; | 111 s_totalMarkedObjectSize = 0; |
111 s_isLowEndDevice = base::SysInfo::IsLowEndDevice(); | 112 s_isLowEndDevice = base::SysInfo::IsLowEndDevice(); |
112 } | 113 } |
113 | 114 |
114 void ProcessHeap::resetHeapCounters() | 115 void ProcessHeap::resetHeapCounters() |
115 { | 116 { |
116 s_totalAllocatedObjectSize = 0; | 117 s_totalAllocatedObjectSize = 0; |
117 s_totalMarkedObjectSize = 0; | 118 s_totalMarkedObjectSize = 0; |
118 } | 119 } |
119 | 120 |
120 void ThreadHeap::init() | 121 void Heap::init() |
121 { | 122 { |
122 ThreadState::init(); | 123 ThreadState::init(); |
123 ProcessHeap::init(); | 124 ProcessHeap::init(); |
124 s_markingStack = new CallbackStack(); | 125 s_markingStack = new CallbackStack(); |
125 s_postMarkingCallbackStack = new CallbackStack(); | 126 s_postMarkingCallbackStack = new CallbackStack(); |
126 s_globalWeakCallbackStack = new CallbackStack(); | 127 s_globalWeakCallbackStack = new CallbackStack(); |
127 // Use smallest supported block size for ephemerons. | 128 // Use smallest supported block size for ephemerons. |
128 s_ephemeronStack = new CallbackStack(CallbackStack::kMinimalBlockSize); | 129 s_ephemeronStack = new CallbackStack(CallbackStack::kMinimalBlockSize); |
129 s_heapDoesNotContainCache = new HeapDoesNotContainCache(); | 130 s_heapDoesNotContainCache = new HeapDoesNotContainCache(); |
130 s_freePagePool = new FreePagePool(); | 131 s_freePagePool = new FreePagePool(); |
131 s_orphanedPagePool = new OrphanedPagePool(); | 132 s_orphanedPagePool = new OrphanedPagePool(); |
132 s_lastGCReason = BlinkGC::NumberOfGCReason; | 133 s_lastGCReason = BlinkGC::NumberOfGCReason; |
133 | 134 |
134 GCInfoTable::init(); | 135 GCInfoTable::init(); |
135 | 136 |
136 if (Platform::current() && Platform::current()->currentThread()) | 137 if (Platform::current() && Platform::current()->currentThread()) |
137 Platform::current()->registerMemoryDumpProvider(BlinkGCMemoryDumpProvide
r::instance(), "BlinkGC"); | 138 Platform::current()->registerMemoryDumpProvider(BlinkGCMemoryDumpProvide
r::instance(), "BlinkGC"); |
138 } | 139 } |
139 | 140 |
140 void ThreadHeap::shutdown() | 141 void Heap::shutdown() |
141 { | 142 { |
142 ASSERT(s_markingStack); | 143 ASSERT(s_markingStack); |
143 | 144 |
144 if (Platform::current() && Platform::current()->currentThread()) | 145 if (Platform::current() && Platform::current()->currentThread()) |
145 Platform::current()->unregisterMemoryDumpProvider(BlinkGCMemoryDumpProvi
der::instance()); | 146 Platform::current()->unregisterMemoryDumpProvider(BlinkGCMemoryDumpProvi
der::instance()); |
146 | 147 |
147 // The main thread must be the last thread that gets detached. | 148 // The main thread must be the last thread that gets detached. |
148 RELEASE_ASSERT(ThreadState::attachedThreads().size() == 0); | 149 RELEASE_ASSERT(ThreadState::attachedThreads().size() == 0); |
149 | 150 |
150 delete s_heapDoesNotContainCache; | 151 delete s_heapDoesNotContainCache; |
151 s_heapDoesNotContainCache = nullptr; | 152 s_heapDoesNotContainCache = nullptr; |
152 delete s_freePagePool; | 153 delete s_freePagePool; |
153 s_freePagePool = nullptr; | 154 s_freePagePool = nullptr; |
154 delete s_orphanedPagePool; | 155 delete s_orphanedPagePool; |
155 s_orphanedPagePool = nullptr; | 156 s_orphanedPagePool = nullptr; |
156 delete s_globalWeakCallbackStack; | 157 delete s_globalWeakCallbackStack; |
157 s_globalWeakCallbackStack = nullptr; | 158 s_globalWeakCallbackStack = nullptr; |
158 delete s_postMarkingCallbackStack; | 159 delete s_postMarkingCallbackStack; |
159 s_postMarkingCallbackStack = nullptr; | 160 s_postMarkingCallbackStack = nullptr; |
160 delete s_markingStack; | 161 delete s_markingStack; |
161 s_markingStack = nullptr; | 162 s_markingStack = nullptr; |
162 delete s_ephemeronStack; | 163 delete s_ephemeronStack; |
163 s_ephemeronStack = nullptr; | 164 s_ephemeronStack = nullptr; |
164 GCInfoTable::shutdown(); | 165 GCInfoTable::shutdown(); |
165 ThreadState::shutdown(); | 166 ThreadState::shutdown(); |
166 ASSERT(ThreadHeap::heapStats().allocatedSpace() == 0); | 167 ASSERT(Heap::heapStats().allocatedSpace() == 0); |
167 } | 168 } |
168 | 169 |
169 CrossThreadPersistentRegion& ProcessHeap::crossThreadPersistentRegion() | 170 CrossThreadPersistentRegion& ProcessHeap::crossThreadPersistentRegion() |
170 { | 171 { |
171 DEFINE_THREAD_SAFE_STATIC_LOCAL(CrossThreadPersistentRegion, persistentRegio
n, new CrossThreadPersistentRegion()); | 172 DEFINE_THREAD_SAFE_STATIC_LOCAL(CrossThreadPersistentRegion, persistentRegio
n, new CrossThreadPersistentRegion()); |
172 return persistentRegion; | 173 return persistentRegion; |
173 } | 174 } |
174 | 175 |
175 bool ProcessHeap::s_isLowEndDevice = false; | 176 bool ProcessHeap::s_isLowEndDevice = false; |
176 size_t ProcessHeap::s_totalAllocatedSpace = 0; | 177 size_t ProcessHeap::s_totalAllocatedSpace = 0; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 ProcessHeap::increaseTotalAllocatedSpace(delta); | 239 ProcessHeap::increaseTotalAllocatedSpace(delta); |
239 } | 240 } |
240 | 241 |
241 void ThreadHeapStats::decreaseAllocatedSpace(size_t delta) | 242 void ThreadHeapStats::decreaseAllocatedSpace(size_t delta) |
242 { | 243 { |
243 atomicSubtract(&m_allocatedSpace, static_cast<long>(delta)); | 244 atomicSubtract(&m_allocatedSpace, static_cast<long>(delta)); |
244 ProcessHeap::decreaseTotalAllocatedSpace(delta); | 245 ProcessHeap::decreaseTotalAllocatedSpace(delta); |
245 } | 246 } |
246 | 247 |
247 #if ENABLE(ASSERT) | 248 #if ENABLE(ASSERT) |
248 BasePage* ThreadHeap::findPageFromAddress(Address address) | 249 BasePage* Heap::findPageFromAddress(Address address) |
249 { | 250 { |
250 MutexLocker lock(ThreadState::threadAttachMutex()); | 251 MutexLocker lock(ThreadState::threadAttachMutex()); |
251 for (ThreadState* state : ThreadState::attachedThreads()) { | 252 for (ThreadState* state : ThreadState::attachedThreads()) { |
252 if (BasePage* page = state->findPageFromAddress(address)) | 253 if (BasePage* page = state->findPageFromAddress(address)) |
253 return page; | 254 return page; |
254 } | 255 } |
255 return nullptr; | 256 return nullptr; |
256 } | 257 } |
257 #endif | 258 #endif |
258 | 259 |
259 Address ThreadHeap::checkAndMarkPointer(Visitor* visitor, Address address) | 260 Address Heap::checkAndMarkPointer(Visitor* visitor, Address address) |
260 { | 261 { |
261 ASSERT(ThreadState::current()->isInGC()); | 262 ASSERT(ThreadState::current()->isInGC()); |
262 | 263 |
263 #if !ENABLE(ASSERT) | 264 #if !ENABLE(ASSERT) |
264 if (s_heapDoesNotContainCache->lookup(address)) | 265 if (s_heapDoesNotContainCache->lookup(address)) |
265 return nullptr; | 266 return nullptr; |
266 #endif | 267 #endif |
267 | 268 |
268 if (BasePage* page = lookup(address)) { | 269 if (BasePage* page = lookup(address)) { |
269 ASSERT(page->contains(address)); | 270 ASSERT(page->contains(address)); |
270 ASSERT(!page->orphaned()); | 271 ASSERT(!page->orphaned()); |
271 ASSERT(!s_heapDoesNotContainCache->lookup(address)); | 272 ASSERT(!s_heapDoesNotContainCache->lookup(address)); |
272 page->checkAndMarkPointer(visitor, address); | 273 page->checkAndMarkPointer(visitor, address); |
273 return address; | 274 return address; |
274 } | 275 } |
275 | 276 |
276 #if !ENABLE(ASSERT) | 277 #if !ENABLE(ASSERT) |
277 s_heapDoesNotContainCache->addEntry(address); | 278 s_heapDoesNotContainCache->addEntry(address); |
278 #else | 279 #else |
279 if (!s_heapDoesNotContainCache->lookup(address)) | 280 if (!s_heapDoesNotContainCache->lookup(address)) |
280 s_heapDoesNotContainCache->addEntry(address); | 281 s_heapDoesNotContainCache->addEntry(address); |
281 #endif | 282 #endif |
282 return nullptr; | 283 return nullptr; |
283 } | 284 } |
284 | 285 |
285 void ThreadHeap::pushTraceCallback(void* object, TraceCallback callback) | 286 void Heap::pushTraceCallback(void* object, TraceCallback callback) |
286 { | 287 { |
287 ASSERT(ThreadState::current()->isInGC()); | 288 ASSERT(ThreadState::current()->isInGC()); |
288 | 289 |
289 // Trace should never reach an orphaned page. | 290 // Trace should never reach an orphaned page. |
290 ASSERT(!ThreadHeap::getOrphanedPagePool()->contains(object)); | 291 ASSERT(!Heap::getOrphanedPagePool()->contains(object)); |
291 CallbackStack::Item* slot = s_markingStack->allocateEntry(); | 292 CallbackStack::Item* slot = s_markingStack->allocateEntry(); |
292 *slot = CallbackStack::Item(object, callback); | 293 *slot = CallbackStack::Item(object, callback); |
293 } | 294 } |
294 | 295 |
295 bool ThreadHeap::popAndInvokeTraceCallback(Visitor* visitor) | 296 bool Heap::popAndInvokeTraceCallback(Visitor* visitor) |
296 { | 297 { |
297 CallbackStack::Item* item = s_markingStack->pop(); | 298 CallbackStack::Item* item = s_markingStack->pop(); |
298 if (!item) | 299 if (!item) |
299 return false; | 300 return false; |
300 item->call(visitor); | 301 item->call(visitor); |
301 return true; | 302 return true; |
302 } | 303 } |
303 | 304 |
304 void ThreadHeap::pushPostMarkingCallback(void* object, TraceCallback callback) | 305 void Heap::pushPostMarkingCallback(void* object, TraceCallback callback) |
305 { | 306 { |
306 ASSERT(ThreadState::current()->isInGC()); | 307 ASSERT(ThreadState::current()->isInGC()); |
307 | 308 |
308 // Trace should never reach an orphaned page. | 309 // Trace should never reach an orphaned page. |
309 ASSERT(!ThreadHeap::getOrphanedPagePool()->contains(object)); | 310 ASSERT(!Heap::getOrphanedPagePool()->contains(object)); |
310 CallbackStack::Item* slot = s_postMarkingCallbackStack->allocateEntry(); | 311 CallbackStack::Item* slot = s_postMarkingCallbackStack->allocateEntry(); |
311 *slot = CallbackStack::Item(object, callback); | 312 *slot = CallbackStack::Item(object, callback); |
312 } | 313 } |
313 | 314 |
314 bool ThreadHeap::popAndInvokePostMarkingCallback(Visitor* visitor) | 315 bool Heap::popAndInvokePostMarkingCallback(Visitor* visitor) |
315 { | 316 { |
316 if (CallbackStack::Item* item = s_postMarkingCallbackStack->pop()) { | 317 if (CallbackStack::Item* item = s_postMarkingCallbackStack->pop()) { |
317 item->call(visitor); | 318 item->call(visitor); |
318 return true; | 319 return true; |
319 } | 320 } |
320 return false; | 321 return false; |
321 } | 322 } |
322 | 323 |
323 void ThreadHeap::pushGlobalWeakCallback(void** cell, WeakCallback callback) | 324 void Heap::pushGlobalWeakCallback(void** cell, WeakCallback callback) |
324 { | 325 { |
325 ASSERT(ThreadState::current()->isInGC()); | 326 ASSERT(ThreadState::current()->isInGC()); |
326 | 327 |
327 // Trace should never reach an orphaned page. | 328 // Trace should never reach an orphaned page. |
328 ASSERT(!ThreadHeap::getOrphanedPagePool()->contains(cell)); | 329 ASSERT(!Heap::getOrphanedPagePool()->contains(cell)); |
329 CallbackStack::Item* slot = s_globalWeakCallbackStack->allocateEntry(); | 330 CallbackStack::Item* slot = s_globalWeakCallbackStack->allocateEntry(); |
330 *slot = CallbackStack::Item(cell, callback); | 331 *slot = CallbackStack::Item(cell, callback); |
331 } | 332 } |
332 | 333 |
333 void ThreadHeap::pushThreadLocalWeakCallback(void* closure, void* object, WeakCa
llback callback) | 334 void Heap::pushThreadLocalWeakCallback(void* closure, void* object, WeakCallback
callback) |
334 { | 335 { |
335 ASSERT(ThreadState::current()->isInGC()); | 336 ASSERT(ThreadState::current()->isInGC()); |
336 | 337 |
337 // Trace should never reach an orphaned page. | 338 // Trace should never reach an orphaned page. |
338 ASSERT(!ThreadHeap::getOrphanedPagePool()->contains(object)); | 339 ASSERT(!Heap::getOrphanedPagePool()->contains(object)); |
339 ThreadState* state = pageFromObject(object)->arena()->getThreadState(); | 340 ThreadState* state = pageFromObject(object)->arena()->getThreadState(); |
340 state->pushThreadLocalWeakCallback(closure, callback); | 341 state->pushThreadLocalWeakCallback(closure, callback); |
341 } | 342 } |
342 | 343 |
343 bool ThreadHeap::popAndInvokeGlobalWeakCallback(Visitor* visitor) | 344 bool Heap::popAndInvokeGlobalWeakCallback(Visitor* visitor) |
344 { | 345 { |
345 if (CallbackStack::Item* item = s_globalWeakCallbackStack->pop()) { | 346 if (CallbackStack::Item* item = s_globalWeakCallbackStack->pop()) { |
346 item->call(visitor); | 347 item->call(visitor); |
347 return true; | 348 return true; |
348 } | 349 } |
349 return false; | 350 return false; |
350 } | 351 } |
351 | 352 |
352 void ThreadHeap::registerWeakTable(void* table, EphemeronCallback iterationCallb
ack, EphemeronCallback iterationDoneCallback) | 353 void Heap::registerWeakTable(void* table, EphemeronCallback iterationCallback, E
phemeronCallback iterationDoneCallback) |
353 { | 354 { |
354 ASSERT(ThreadState::current()->isInGC()); | 355 ASSERT(ThreadState::current()->isInGC()); |
355 | 356 |
356 // Trace should never reach an orphaned page. | 357 // Trace should never reach an orphaned page. |
357 ASSERT(!ThreadHeap::getOrphanedPagePool()->contains(table)); | 358 ASSERT(!Heap::getOrphanedPagePool()->contains(table)); |
358 CallbackStack::Item* slot = s_ephemeronStack->allocateEntry(); | 359 CallbackStack::Item* slot = s_ephemeronStack->allocateEntry(); |
359 *slot = CallbackStack::Item(table, iterationCallback); | 360 *slot = CallbackStack::Item(table, iterationCallback); |
360 | 361 |
361 // Register a post-marking callback to tell the tables that | 362 // Register a post-marking callback to tell the tables that |
362 // ephemeron iteration is complete. | 363 // ephemeron iteration is complete. |
363 pushPostMarkingCallback(table, iterationDoneCallback); | 364 pushPostMarkingCallback(table, iterationDoneCallback); |
364 } | 365 } |
365 | 366 |
366 #if ENABLE(ASSERT) | 367 #if ENABLE(ASSERT) |
367 bool ThreadHeap::weakTableRegistered(const void* table) | 368 bool Heap::weakTableRegistered(const void* table) |
368 { | 369 { |
369 ASSERT(s_ephemeronStack); | 370 ASSERT(s_ephemeronStack); |
370 return s_ephemeronStack->hasCallbackForObject(table); | 371 return s_ephemeronStack->hasCallbackForObject(table); |
371 } | 372 } |
372 #endif | 373 #endif |
373 | 374 |
374 void ThreadHeap::decommitCallbackStacks() | 375 void Heap::decommitCallbackStacks() |
375 { | 376 { |
376 s_markingStack->decommit(); | 377 s_markingStack->decommit(); |
377 s_postMarkingCallbackStack->decommit(); | 378 s_postMarkingCallbackStack->decommit(); |
378 s_globalWeakCallbackStack->decommit(); | 379 s_globalWeakCallbackStack->decommit(); |
379 s_ephemeronStack->decommit(); | 380 s_ephemeronStack->decommit(); |
380 } | 381 } |
381 | 382 |
382 void ThreadHeap::preGC() | 383 void Heap::preGC() |
383 { | 384 { |
384 ASSERT(!ThreadState::current()->isInGC()); | 385 ASSERT(!ThreadState::current()->isInGC()); |
385 for (ThreadState* state : ThreadState::attachedThreads()) | 386 for (ThreadState* state : ThreadState::attachedThreads()) |
386 state->preGC(); | 387 state->preGC(); |
387 } | 388 } |
388 | 389 |
389 void ThreadHeap::postGC(BlinkGC::GCType gcType) | 390 void Heap::postGC(BlinkGC::GCType gcType) |
390 { | 391 { |
391 ASSERT(ThreadState::current()->isInGC()); | 392 ASSERT(ThreadState::current()->isInGC()); |
392 for (ThreadState* state : ThreadState::attachedThreads()) | 393 for (ThreadState* state : ThreadState::attachedThreads()) |
393 state->postGC(gcType); | 394 state->postGC(gcType); |
394 } | 395 } |
395 | 396 |
396 const char* ThreadHeap::gcReasonString(BlinkGC::GCReason reason) | 397 const char* Heap::gcReasonString(BlinkGC::GCReason reason) |
397 { | 398 { |
398 switch (reason) { | 399 switch (reason) { |
399 case BlinkGC::IdleGC: | 400 case BlinkGC::IdleGC: |
400 return "IdleGC"; | 401 return "IdleGC"; |
401 case BlinkGC::PreciseGC: | 402 case BlinkGC::PreciseGC: |
402 return "PreciseGC"; | 403 return "PreciseGC"; |
403 case BlinkGC::ConservativeGC: | 404 case BlinkGC::ConservativeGC: |
404 return "ConservativeGC"; | 405 return "ConservativeGC"; |
405 case BlinkGC::ForcedGC: | 406 case BlinkGC::ForcedGC: |
406 return "ForcedGC"; | 407 return "ForcedGC"; |
407 case BlinkGC::MemoryPressureGC: | 408 case BlinkGC::MemoryPressureGC: |
408 return "MemoryPressureGC"; | 409 return "MemoryPressureGC"; |
409 case BlinkGC::PageNavigationGC: | 410 case BlinkGC::PageNavigationGC: |
410 return "PageNavigationGC"; | 411 return "PageNavigationGC"; |
411 default: | 412 default: |
412 ASSERT_NOT_REACHED(); | 413 ASSERT_NOT_REACHED(); |
413 } | 414 } |
414 return "<Unknown>"; | 415 return "<Unknown>"; |
415 } | 416 } |
416 | 417 |
417 void ThreadHeap::collectGarbage(BlinkGC::StackState stackState, BlinkGC::GCType
gcType, BlinkGC::GCReason reason) | 418 void Heap::collectGarbage(BlinkGC::StackState stackState, BlinkGC::GCType gcType
, BlinkGC::GCReason reason) |
418 { | 419 { |
419 ASSERT(gcType != BlinkGC::ThreadTerminationGC); | 420 ASSERT(gcType != BlinkGC::ThreadTerminationGC); |
420 | 421 |
421 ThreadState* state = ThreadState::current(); | 422 ThreadState* state = ThreadState::current(); |
422 // Nested collectGarbage() invocations aren't supported. | 423 // Nested collectGarbage() invocations aren't supported. |
423 RELEASE_ASSERT(!state->isGCForbidden()); | 424 RELEASE_ASSERT(!state->isGCForbidden()); |
424 state->completeSweep(); | 425 state->completeSweep(); |
425 | 426 |
| 427 size_t debugAllocatedObjectSize = Heap::heapStats().allocatedObjectSize(); |
| 428 base::debug::Alias(&debugAllocatedObjectSize); |
| 429 size_t debugWrapperCount = Heap::heapStats().wrapperCount(); |
| 430 base::debug::Alias(&debugWrapperCount); |
| 431 |
426 OwnPtr<Visitor> visitor = Visitor::create(state, gcType); | 432 OwnPtr<Visitor> visitor = Visitor::create(state, gcType); |
427 | 433 |
428 SafePointScope safePointScope(stackState, state); | 434 SafePointScope safePointScope(stackState, state); |
429 | 435 |
430 // Resume all parked threads upon leaving this scope. | 436 // Resume all parked threads upon leaving this scope. |
431 ParkThreadsScope parkThreadsScope; | 437 ParkThreadsScope parkThreadsScope; |
432 | 438 |
433 // Try to park the other threads. If we're unable to, bail out of the GC. | 439 // Try to park the other threads. If we're unable to, bail out of the GC. |
434 if (!parkThreadsScope.parkThreads(state)) | 440 if (!parkThreadsScope.parkThreads(state)) |
435 return; | 441 return; |
436 | 442 |
437 ScriptForbiddenIfMainThreadScope scriptForbidden; | 443 ScriptForbiddenIfMainThreadScope scriptForbidden; |
438 | 444 |
439 TRACE_EVENT2("blink_gc,devtools.timeline", "BlinkGCMarking", | 445 TRACE_EVENT2("blink_gc,devtools.timeline", "Heap::collectGarbage", |
440 "lazySweeping", gcType == BlinkGC::GCWithoutSweep, | 446 "lazySweeping", gcType == BlinkGC::GCWithoutSweep, |
441 "gcReason", gcReasonString(reason)); | 447 "gcReason", gcReasonString(reason)); |
442 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); | 448 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); |
443 double startTime = WTF::currentTimeMS(); | 449 double startTime = WTF::currentTimeMS(); |
444 | 450 |
445 if (gcType == BlinkGC::TakeSnapshot) | 451 if (gcType == BlinkGC::TakeSnapshot) |
446 BlinkGCMemoryDumpProvider::instance()->clearProcessDumpForCurrentGC(); | 452 BlinkGCMemoryDumpProvider::instance()->clearProcessDumpForCurrentGC(); |
447 | 453 |
448 // Disallow allocation during garbage collection (but not during the | 454 // Disallow allocation during garbage collection (but not during the |
449 // finalization that happens when the visitorScope is torn down). | 455 // finalization that happens when the visitorScope is torn down). |
450 ThreadState::NoAllocationScope noAllocationScope(state); | 456 ThreadState::NoAllocationScope noAllocationScope(state); |
451 | 457 |
452 preGC(); | 458 preGC(); |
453 | 459 |
454 StackFrameDepthScope stackDepthScope; | 460 StackFrameDepthScope stackDepthScope; |
455 | 461 |
456 size_t totalObjectSize = ThreadHeap::heapStats().allocatedObjectSize() + Thr
eadHeap::heapStats().markedObjectSize(); | 462 size_t totalObjectSize = Heap::heapStats().allocatedObjectSize() + Heap::hea
pStats().markedObjectSize(); |
457 if (gcType != BlinkGC::TakeSnapshot) | 463 if (gcType != BlinkGC::TakeSnapshot) |
458 ThreadHeap::resetHeapCounters(); | 464 Heap::resetHeapCounters(); |
459 | 465 |
460 // 1. Trace persistent roots. | 466 // 1. Trace persistent roots. |
461 ThreadState::visitPersistentRoots(visitor.get()); | 467 ThreadState::visitPersistentRoots(visitor.get()); |
462 | 468 |
463 // 2. Trace objects reachable from the stack. We do this independent of the | 469 // 2. Trace objects reachable from the stack. We do this independent of the |
464 // given stackState since other threads might have a different stack state. | 470 // given stackState since other threads might have a different stack state. |
465 ThreadState::visitStackRoots(visitor.get()); | 471 ThreadState::visitStackRoots(visitor.get()); |
466 | 472 |
467 // 3. Transitive closure to trace objects including ephemerons. | 473 // 3. Transitive closure to trace objects including ephemerons. |
468 processMarkingStack(visitor.get()); | 474 processMarkingStack(visitor.get()); |
469 | 475 |
470 postMarkingProcessing(visitor.get()); | 476 postMarkingProcessing(visitor.get()); |
471 globalWeakProcessing(visitor.get()); | 477 globalWeakProcessing(visitor.get()); |
472 | 478 |
473 // Now we can delete all orphaned pages because there are no dangling | 479 // Now we can delete all orphaned pages because there are no dangling |
474 // pointers to the orphaned pages. (If we have such dangling pointers, | 480 // pointers to the orphaned pages. (If we have such dangling pointers, |
475 // we should have crashed during marking before getting here.) | 481 // we should have crashed during marking before getting here.) |
476 getOrphanedPagePool()->decommitOrphanedPages(); | 482 getOrphanedPagePool()->decommitOrphanedPages(); |
477 | 483 |
478 double markingTimeInMilliseconds = WTF::currentTimeMS() - startTime; | 484 double markingTimeInMilliseconds = WTF::currentTimeMS() - startTime; |
479 ThreadHeap::heapStats().setEstimatedMarkingTimePerByte(totalObjectSize ? (ma
rkingTimeInMilliseconds / 1000 / totalObjectSize) : 0); | 485 Heap::heapStats().setEstimatedMarkingTimePerByte(totalObjectSize ? (markingT
imeInMilliseconds / 1000 / totalObjectSize) : 0); |
480 | 486 |
481 #if PRINT_HEAP_STATS | 487 #if PRINT_HEAP_STATS |
482 dataLogF("ThreadHeap::collectGarbage (gcReason=%s, lazySweeping=%d, time=%.1
lfms)\n", gcReasonString(reason), gcType == BlinkGC::GCWithoutSweep, markingTime
InMilliseconds); | 488 dataLogF("Heap::collectGarbage (gcReason=%s, lazySweeping=%d, time=%.1lfms)\
n", gcReasonString(reason), gcType == BlinkGC::GCWithoutSweep, markingTimeInMill
iseconds); |
483 #endif | 489 #endif |
484 | 490 |
485 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, markingTimeHistogram,
new CustomCountHistogram("BlinkGC.CollectGarbage", 0, 10 * 1000, 50)); | 491 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, markingTimeHistogram,
new CustomCountHistogram("BlinkGC.CollectGarbage", 0, 10 * 1000, 50)); |
486 markingTimeHistogram.count(markingTimeInMilliseconds); | 492 markingTimeHistogram.count(markingTimeInMilliseconds); |
487 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, totalObjectSpaceHistog
ram, new CustomCountHistogram("BlinkGC.TotalObjectSpace", 0, 4 * 1024 * 1024, 50
)); | 493 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, totalObjectSpaceHistog
ram, new CustomCountHistogram("BlinkGC.TotalObjectSpace", 0, 4 * 1024 * 1024, 50
)); |
488 totalObjectSpaceHistogram.count(ProcessHeap::totalAllocatedObjectSize() / 10
24); | 494 totalObjectSpaceHistogram.count(ProcessHeap::totalAllocatedObjectSize() / 10
24); |
489 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, totalAllocatedSpaceHis
togram, new CustomCountHistogram("BlinkGC.TotalAllocatedSpace", 0, 4 * 1024 * 10
24, 50)); | 495 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, totalAllocatedSpaceHis
togram, new CustomCountHistogram("BlinkGC.TotalAllocatedSpace", 0, 4 * 1024 * 10
24, 50)); |
490 totalAllocatedSpaceHistogram.count(ProcessHeap::totalAllocatedSpace() / 1024
); | 496 totalAllocatedSpaceHistogram.count(ProcessHeap::totalAllocatedSpace() / 1024
); |
491 DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, gcReasonHistogram, new
EnumerationHistogram("BlinkGC.GCReason", BlinkGC::NumberOfGCReason)); | 497 DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, gcReasonHistogram, new
EnumerationHistogram("BlinkGC.GCReason", BlinkGC::NumberOfGCReason)); |
492 gcReasonHistogram.count(reason); | 498 gcReasonHistogram.count(reason); |
493 | 499 |
494 s_lastGCReason = reason; | 500 s_lastGCReason = reason; |
495 | 501 |
496 ThreadHeap::reportMemoryUsageHistogram(); | 502 Heap::reportMemoryUsageHistogram(); |
497 WTF::Partitions::reportMemoryUsageHistogram(); | 503 WTF::Partitions::reportMemoryUsageHistogram(); |
498 | 504 |
499 postGC(gcType); | 505 postGC(gcType); |
500 ThreadHeap::decommitCallbackStacks(); | 506 Heap::decommitCallbackStacks(); |
501 } | 507 } |
502 | 508 |
503 void ThreadHeap::collectGarbageForTerminatingThread(ThreadState* state) | 509 void Heap::collectGarbageForTerminatingThread(ThreadState* state) |
504 { | 510 { |
505 { | 511 { |
506 // A thread-specific termination GC must not allow other global GCs to g
o | 512 // A thread-specific termination GC must not allow other global GCs to g
o |
507 // ahead while it is running, hence the termination GC does not enter a | 513 // ahead while it is running, hence the termination GC does not enter a |
508 // safepoint. VisitorScope will not enter also a safepoint scope for | 514 // safepoint. VisitorScope will not enter also a safepoint scope for |
509 // ThreadTerminationGC. | 515 // ThreadTerminationGC. |
510 OwnPtr<Visitor> visitor = Visitor::create(state, BlinkGC::ThreadTerminat
ionGC); | 516 OwnPtr<Visitor> visitor = Visitor::create(state, BlinkGC::ThreadTerminat
ionGC); |
511 | 517 |
512 ThreadState::NoAllocationScope noAllocationScope(state); | 518 ThreadState::NoAllocationScope noAllocationScope(state); |
513 | 519 |
(...skipping 12 matching lines...) Expand all Loading... |
526 state->visitPersistents(visitor.get()); | 532 state->visitPersistents(visitor.get()); |
527 | 533 |
528 // 2. Trace objects reachable from the thread's persistent roots | 534 // 2. Trace objects reachable from the thread's persistent roots |
529 // including ephemerons. | 535 // including ephemerons. |
530 processMarkingStack(visitor.get()); | 536 processMarkingStack(visitor.get()); |
531 | 537 |
532 postMarkingProcessing(visitor.get()); | 538 postMarkingProcessing(visitor.get()); |
533 globalWeakProcessing(visitor.get()); | 539 globalWeakProcessing(visitor.get()); |
534 | 540 |
535 state->postGC(BlinkGC::GCWithSweep); | 541 state->postGC(BlinkGC::GCWithSweep); |
536 ThreadHeap::decommitCallbackStacks(); | 542 Heap::decommitCallbackStacks(); |
537 } | 543 } |
538 state->preSweep(); | 544 state->preSweep(); |
539 } | 545 } |
540 | 546 |
541 void ThreadHeap::processMarkingStack(Visitor* visitor) | 547 void Heap::processMarkingStack(Visitor* visitor) |
542 { | 548 { |
543 // Ephemeron fixed point loop. | 549 // Ephemeron fixed point loop. |
544 do { | 550 do { |
545 { | 551 { |
546 // Iteratively mark all objects that are reachable from the objects | 552 // Iteratively mark all objects that are reachable from the objects |
547 // currently pushed onto the marking stack. | 553 // currently pushed onto the marking stack. |
548 TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThrea
ded"); | 554 TRACE_EVENT0("blink_gc", "Heap::processMarkingStackSingleThreaded"); |
549 while (popAndInvokeTraceCallback(visitor)) { } | 555 while (popAndInvokeTraceCallback(visitor)) { } |
550 } | 556 } |
551 | 557 |
552 { | 558 { |
553 // Mark any strong pointers that have now become reachable in | 559 // Mark any strong pointers that have now become reachable in |
554 // ephemeron maps. | 560 // ephemeron maps. |
555 TRACE_EVENT0("blink_gc", "ThreadHeap::processEphemeronStack"); | 561 TRACE_EVENT0("blink_gc", "Heap::processEphemeronStack"); |
556 s_ephemeronStack->invokeEphemeronCallbacks(visitor); | 562 s_ephemeronStack->invokeEphemeronCallbacks(visitor); |
557 } | 563 } |
558 | 564 |
559 // Rerun loop if ephemeron processing queued more objects for tracing. | 565 // Rerun loop if ephemeron processing queued more objects for tracing. |
560 } while (!s_markingStack->isEmpty()); | 566 } while (!s_markingStack->isEmpty()); |
561 } | 567 } |
562 | 568 |
563 void ThreadHeap::postMarkingProcessing(Visitor* visitor) | 569 void Heap::postMarkingProcessing(Visitor* visitor) |
564 { | 570 { |
565 TRACE_EVENT0("blink_gc", "ThreadHeap::postMarkingProcessing"); | 571 TRACE_EVENT0("blink_gc", "Heap::postMarkingProcessing"); |
566 // Call post-marking callbacks including: | 572 // Call post-marking callbacks including: |
567 // 1. the ephemeronIterationDone callbacks on weak tables to do cleanup | 573 // 1. the ephemeronIterationDone callbacks on weak tables to do cleanup |
568 // (specifically to clear the queued bits for weak hash tables), and | 574 // (specifically to clear the queued bits for weak hash tables), and |
569 // 2. the markNoTracing callbacks on collection backings to mark them | 575 // 2. the markNoTracing callbacks on collection backings to mark them |
570 // if they are only reachable from their front objects. | 576 // if they are only reachable from their front objects. |
571 while (popAndInvokePostMarkingCallback(visitor)) { } | 577 while (popAndInvokePostMarkingCallback(visitor)) { } |
572 | 578 |
573 // Post-marking callbacks should not trace any objects and | 579 // Post-marking callbacks should not trace any objects and |
574 // therefore the marking stack should be empty after the | 580 // therefore the marking stack should be empty after the |
575 // post-marking callbacks. | 581 // post-marking callbacks. |
576 ASSERT(s_markingStack->isEmpty()); | 582 ASSERT(s_markingStack->isEmpty()); |
577 } | 583 } |
578 | 584 |
579 void ThreadHeap::globalWeakProcessing(Visitor* visitor) | 585 void Heap::globalWeakProcessing(Visitor* visitor) |
580 { | 586 { |
581 TRACE_EVENT0("blink_gc", "ThreadHeap::globalWeakProcessing"); | 587 TRACE_EVENT0("blink_gc", "Heap::globalWeakProcessing"); |
582 double startTime = WTF::currentTimeMS(); | 588 double startTime = WTF::currentTimeMS(); |
583 | 589 |
584 // Call weak callbacks on objects that may now be pointing to dead objects. | 590 // Call weak callbacks on objects that may now be pointing to dead objects. |
585 while (popAndInvokeGlobalWeakCallback(visitor)) { } | 591 while (popAndInvokeGlobalWeakCallback(visitor)) { } |
586 | 592 |
587 // It is not permitted to trace pointers of live objects in the weak | 593 // It is not permitted to trace pointers of live objects in the weak |
588 // callback phase, so the marking stack should still be empty here. | 594 // callback phase, so the marking stack should still be empty here. |
589 ASSERT(s_markingStack->isEmpty()); | 595 ASSERT(s_markingStack->isEmpty()); |
590 | 596 |
591 double timeForGlobalWeakProcessing = WTF::currentTimeMS() - startTime; | 597 double timeForGlobalWeakProcessing = WTF::currentTimeMS() - startTime; |
592 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, globalWeakTimeHistogra
m, new CustomCountHistogram("BlinkGC.TimeForGlobalWeakProcessing", 1, 10 * 1000,
50)); | 598 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, globalWeakTimeHistogra
m, new CustomCountHistogram("BlinkGC.TimeForGlobalWeakProcessing", 1, 10 * 1000,
50)); |
593 globalWeakTimeHistogram.count(timeForGlobalWeakProcessing); | 599 globalWeakTimeHistogram.count(timeForGlobalWeakProcessing); |
594 } | 600 } |
595 | 601 |
596 void ThreadHeap::collectAllGarbage() | 602 void Heap::collectAllGarbage() |
597 { | 603 { |
598 // We need to run multiple GCs to collect a chain of persistent handles. | 604 // We need to run multiple GCs to collect a chain of persistent handles. |
599 size_t previousLiveObjects = 0; | 605 size_t previousLiveObjects = 0; |
600 for (int i = 0; i < 5; ++i) { | 606 for (int i = 0; i < 5; ++i) { |
601 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, Bli
nkGC::ForcedGC); | 607 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, Bli
nkGC::ForcedGC); |
602 size_t liveObjects = ThreadHeap::heapStats().markedObjectSize(); | 608 size_t liveObjects = Heap::heapStats().markedObjectSize(); |
603 if (liveObjects == previousLiveObjects) | 609 if (liveObjects == previousLiveObjects) |
604 break; | 610 break; |
605 previousLiveObjects = liveObjects; | 611 previousLiveObjects = liveObjects; |
606 } | 612 } |
607 } | 613 } |
608 | 614 |
609 void ThreadHeap::reportMemoryUsageHistogram() | 615 void Heap::reportMemoryUsageHistogram() |
610 { | 616 { |
611 static size_t supportedMaxSizeInMB = 4 * 1024; | 617 static size_t supportedMaxSizeInMB = 4 * 1024; |
612 static size_t observedMaxSizeInMB = 0; | 618 static size_t observedMaxSizeInMB = 0; |
613 | 619 |
614 // We only report the memory in the main thread. | 620 // We only report the memory in the main thread. |
615 if (!isMainThread()) | 621 if (!isMainThread()) |
616 return; | 622 return; |
617 // +1 is for rounding up the sizeInMB. | 623 // +1 is for rounding up the sizeInMB. |
618 size_t sizeInMB = ThreadHeap::heapStats().allocatedSpace() / 1024 / 1024 + 1
; | 624 size_t sizeInMB = Heap::heapStats().allocatedSpace() / 1024 / 1024 + 1; |
619 if (sizeInMB >= supportedMaxSizeInMB) | 625 if (sizeInMB >= supportedMaxSizeInMB) |
620 sizeInMB = supportedMaxSizeInMB - 1; | 626 sizeInMB = supportedMaxSizeInMB - 1; |
621 if (sizeInMB > observedMaxSizeInMB) { | 627 if (sizeInMB > observedMaxSizeInMB) { |
622 // Send a UseCounter only when we see the highest memory usage | 628 // Send a UseCounter only when we see the highest memory usage |
623 // we've ever seen. | 629 // we've ever seen. |
624 DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, commitedSizeHistog
ram, new EnumerationHistogram("BlinkGC.CommittedSize", supportedMaxSizeInMB)); | 630 DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, commitedSizeHistog
ram, new EnumerationHistogram("BlinkGC.CommittedSize", supportedMaxSizeInMB)); |
625 commitedSizeHistogram.count(sizeInMB); | 631 commitedSizeHistogram.count(sizeInMB); |
626 observedMaxSizeInMB = sizeInMB; | 632 observedMaxSizeInMB = sizeInMB; |
627 } | 633 } |
628 } | 634 } |
629 | 635 |
630 void ThreadHeap::reportMemoryUsageForTracing() | 636 void Heap::reportMemoryUsageForTracing() |
631 { | 637 { |
632 #if PRINT_HEAP_STATS | 638 #if PRINT_HEAP_STATS |
633 // dataLogF("allocatedSpace=%ldMB, allocatedObjectSize=%ldMB, markedObjectSi
ze=%ldMB, partitionAllocSize=%ldMB, wrapperCount=%ld, collectedWrapperCount=%ld\
n", ThreadHeap::allocatedSpace() / 1024 / 1024, ThreadHeap::allocatedObjectSize(
) / 1024 / 1024, ThreadHeap::markedObjectSize() / 1024 / 1024, WTF::Partitions::
totalSizeOfCommittedPages() / 1024 / 1024, ThreadHeap::wrapperCount(), ThreadHea
p::collectedWrapperCount()); | 639 // dataLogF("allocatedSpace=%ldMB, allocatedObjectSize=%ldMB, markedObjectSi
ze=%ldMB, partitionAllocSize=%ldMB, wrapperCount=%ld, collectedWrapperCount=%ld\
n", Heap::allocatedSpace() / 1024 / 1024, Heap::allocatedObjectSize() / 1024 / 1
024, Heap::markedObjectSize() / 1024 / 1024, WTF::Partitions::totalSizeOfCommitt
edPages() / 1024 / 1024, Heap::wrapperCount(), Heap::collectedWrapperCount()); |
634 #endif | 640 #endif |
635 | 641 |
636 bool gcTracingEnabled; | 642 bool gcTracingEnabled; |
637 TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink_gc", &gcTracingEnabled); | 643 TRACE_EVENT_CATEGORY_GROUP_ENABLED("blink_gc", &gcTracingEnabled); |
638 if (!gcTracingEnabled) | 644 if (!gcTracingEnabled) |
639 return; | 645 return; |
640 | 646 |
641 // These values are divided by 1024 to avoid overflow in practical cases (TR
ACE_COUNTER values are 32-bit ints). | 647 // These values are divided by 1024 to avoid overflow in practical cases (TR
ACE_COUNTER values are 32-bit ints). |
642 // They are capped to INT_MAX just in case. | 648 // They are capped to INT_MAX just in case. |
643 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::allocated
ObjectSizeKB", std::min(ThreadHeap::heapStats().allocatedObjectSize() / 1024, st
atic_cast<size_t>(INT_MAX))); | 649 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::allocatedObject
SizeKB", std::min(Heap::heapStats().allocatedObjectSize() / 1024, static_cast<si
ze_t>(INT_MAX))); |
644 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::markedObj
ectSizeKB", std::min(ThreadHeap::heapStats().markedObjectSize() / 1024, static_c
ast<size_t>(INT_MAX))); | 650 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::markedObjectSiz
eKB", std::min(Heap::heapStats().markedObjectSize() / 1024, static_cast<size_t>(
INT_MAX))); |
645 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::markedObj
ectSizeAtLastCompleteSweepKB", std::min(ThreadHeap::heapStats().markedObjectSize
AtLastCompleteSweep() / 1024, static_cast<size_t>(INT_MAX))); | 651 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::markedObjectSiz
eAtLastCompleteSweepKB", std::min(Heap::heapStats().markedObjectSizeAtLastComple
teSweep() / 1024, static_cast<size_t>(INT_MAX))); |
646 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::allocated
SpaceKB", std::min(ThreadHeap::heapStats().allocatedSpace() / 1024, static_cast<
size_t>(INT_MAX))); | 652 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::allocatedSpaceK
B", std::min(Heap::heapStats().allocatedSpace() / 1024, static_cast<size_t>(INT_
MAX))); |
647 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::objectSiz
eAtLastGCKB", std::min(ThreadHeap::heapStats().objectSizeAtLastGC() / 1024, stat
ic_cast<size_t>(INT_MAX))); | 653 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::objectSizeAtLas
tGCKB", std::min(Heap::heapStats().objectSizeAtLastGC() / 1024, static_cast<size
_t>(INT_MAX))); |
648 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::wrapperCo
unt", std::min(ThreadHeap::heapStats().wrapperCount(), static_cast<size_t>(INT_M
AX))); | 654 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::wrapperCount",
std::min(Heap::heapStats().wrapperCount(), static_cast<size_t>(INT_MAX))); |
649 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::heapStats
().wrapperCountAtLastGC", std::min(ThreadHeap::heapStats().wrapperCountAtLastGC(
), static_cast<size_t>(INT_MAX))); | 655 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::heapStats().wra
pperCountAtLastGC", std::min(Heap::heapStats().wrapperCountAtLastGC(), static_ca
st<size_t>(INT_MAX))); |
650 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::collected
WrapperCount", std::min(ThreadHeap::heapStats().collectedWrapperCount(), static_
cast<size_t>(INT_MAX))); | 656 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::collectedWrappe
rCount", std::min(Heap::heapStats().collectedWrapperCount(), static_cast<size_t>
(INT_MAX))); |
651 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "ThreadHeap::partition
AllocSizeAtLastGCKB", std::min(ThreadHeap::heapStats().partitionAllocSizeAtLastG
C() / 1024, static_cast<size_t>(INT_MAX))); | 657 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Heap::partitionAllocS
izeAtLastGCKB", std::min(Heap::heapStats().partitionAllocSizeAtLastGC() / 1024,
static_cast<size_t>(INT_MAX))); |
652 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Partitions::totalSize
OfCommittedPagesKB", std::min(WTF::Partitions::totalSizeOfCommittedPages() / 102
4, static_cast<size_t>(INT_MAX))); | 658 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), "Partitions::totalSize
OfCommittedPagesKB", std::min(WTF::Partitions::totalSizeOfCommittedPages() / 102
4, static_cast<size_t>(INT_MAX))); |
653 } | 659 } |
654 | 660 |
655 size_t ThreadHeap::objectPayloadSizeForTesting() | 661 size_t Heap::objectPayloadSizeForTesting() |
656 { | 662 { |
657 size_t objectPayloadSize = 0; | 663 size_t objectPayloadSize = 0; |
658 for (ThreadState* state : ThreadState::attachedThreads()) { | 664 for (ThreadState* state : ThreadState::attachedThreads()) { |
659 state->setGCState(ThreadState::GCRunning); | 665 state->setGCState(ThreadState::GCRunning); |
660 state->makeConsistentForGC(); | 666 state->makeConsistentForGC(); |
661 objectPayloadSize += state->objectPayloadSizeForTesting(); | 667 objectPayloadSize += state->objectPayloadSizeForTesting(); |
662 state->setGCState(ThreadState::EagerSweepScheduled); | 668 state->setGCState(ThreadState::EagerSweepScheduled); |
663 state->setGCState(ThreadState::Sweeping); | 669 state->setGCState(ThreadState::Sweeping); |
664 state->setGCState(ThreadState::NoGCScheduled); | 670 state->setGCState(ThreadState::NoGCScheduled); |
665 } | 671 } |
666 return objectPayloadSize; | 672 return objectPayloadSize; |
667 } | 673 } |
668 | 674 |
669 RegionTree* ThreadHeap::getRegionTree() | 675 RegionTree* Heap::getRegionTree() |
670 { | 676 { |
671 DEFINE_THREAD_SAFE_STATIC_LOCAL(RegionTree, tree, new RegionTree); | 677 DEFINE_THREAD_SAFE_STATIC_LOCAL(RegionTree, tree, new RegionTree); |
672 return &tree; | 678 return &tree; |
673 } | 679 } |
674 | 680 |
675 BasePage* ThreadHeap::lookup(Address address) | 681 BasePage* Heap::lookup(Address address) |
676 { | 682 { |
677 ASSERT(ThreadState::current()->isInGC()); | 683 ASSERT(ThreadState::current()->isInGC()); |
678 if (PageMemoryRegion* region = ThreadHeap::getRegionTree()->lookup(address))
{ | 684 if (PageMemoryRegion* region = Heap::getRegionTree()->lookup(address)) { |
679 BasePage* page = region->pageFromAddress(address); | 685 BasePage* page = region->pageFromAddress(address); |
680 return page && !page->orphaned() ? page : nullptr; | 686 return page && !page->orphaned() ? page : nullptr; |
681 } | 687 } |
682 return nullptr; | 688 return nullptr; |
683 } | 689 } |
684 | 690 |
685 void ThreadHeap::resetHeapCounters() | 691 void Heap::resetHeapCounters() |
686 { | 692 { |
687 ASSERT(ThreadState::current()->isInGC()); | 693 ASSERT(ThreadState::current()->isInGC()); |
688 | 694 |
689 ThreadHeap::reportMemoryUsageForTracing(); | 695 Heap::reportMemoryUsageForTracing(); |
690 | 696 |
691 ProcessHeap::resetHeapCounters(); | 697 ProcessHeap::resetHeapCounters(); |
692 ThreadHeap::heapStats().reset(); | 698 Heap::heapStats().reset(); |
693 for (ThreadState* state : ThreadState::attachedThreads()) | 699 for (ThreadState* state : ThreadState::attachedThreads()) |
694 state->resetHeapCounters(); | 700 state->resetHeapCounters(); |
695 } | 701 } |
696 | 702 |
697 ThreadHeapStats& ThreadHeap::heapStats() | 703 // TODO(keishi): Make this a member of ThreadHeap. |
| 704 ThreadHeapStats& Heap::heapStats() |
698 { | 705 { |
699 DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadHeapStats, stats, new ThreadHeapStats(
)); | 706 DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadHeapStats, stats, new ThreadHeapStats(
)); |
700 return stats; | 707 return stats; |
701 } | 708 } |
702 | 709 |
703 CallbackStack* ThreadHeap::s_markingStack; | 710 CallbackStack* Heap::s_markingStack; |
704 CallbackStack* ThreadHeap::s_postMarkingCallbackStack; | 711 CallbackStack* Heap::s_postMarkingCallbackStack; |
705 CallbackStack* ThreadHeap::s_globalWeakCallbackStack; | 712 CallbackStack* Heap::s_globalWeakCallbackStack; |
706 CallbackStack* ThreadHeap::s_ephemeronStack; | 713 CallbackStack* Heap::s_ephemeronStack; |
707 HeapDoesNotContainCache* ThreadHeap::s_heapDoesNotContainCache; | 714 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; |
708 FreePagePool* ThreadHeap::s_freePagePool; | 715 FreePagePool* Heap::s_freePagePool; |
709 OrphanedPagePool* ThreadHeap::s_orphanedPagePool; | 716 OrphanedPagePool* Heap::s_orphanedPagePool; |
710 | 717 |
711 BlinkGC::GCReason ThreadHeap::s_lastGCReason = BlinkGC::NumberOfGCReason; | 718 BlinkGC::GCReason Heap::s_lastGCReason = BlinkGC::NumberOfGCReason; |
712 | 719 |
713 } // namespace blink | 720 } // namespace blink |
OLD | NEW |