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

Side by Side Diff: third_party/WebKit/Source/platform/heap/ThreadState.cpp

Issue 2619493003: Replace ASSERTs in platform/heap/ with DCHECKs
Patch Set: temp Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 m_invalidateDeadObjectsInWrappersMarkingDeque(nullptr), 170 m_invalidateDeadObjectsInWrappersMarkingDeque(nullptr),
171 #if defined(ADDRESS_SANITIZER) 171 #if defined(ADDRESS_SANITIZER)
172 m_asanFakeStack(__asan_get_current_fake_stack()), 172 m_asanFakeStack(__asan_get_current_fake_stack()),
173 #endif 173 #endif
174 #if defined(LEAK_SANITIZER) 174 #if defined(LEAK_SANITIZER)
175 m_disabledStaticPersistentsRegistration(0), 175 m_disabledStaticPersistentsRegistration(0),
176 #endif 176 #endif
177 m_allocatedObjectSize(0), 177 m_allocatedObjectSize(0),
178 m_markedObjectSize(0), 178 m_markedObjectSize(0),
179 m_reportedMemoryToV8(0) { 179 m_reportedMemoryToV8(0) {
180 ASSERT(checkThread()); 180 DCHECK(checkThread());
181 ASSERT(!**s_threadSpecific); 181 DCHECK(!**s_threadSpecific);
182 **s_threadSpecific = this; 182 **s_threadSpecific = this;
183 183
184 switch (m_threadHeapMode) { 184 switch (m_threadHeapMode) {
185 case BlinkGC::MainThreadHeapMode: 185 case BlinkGC::MainThreadHeapMode:
186 if (isMainThread()) { 186 if (isMainThread()) {
187 s_mainThreadStackStart = 187 s_mainThreadStackStart =
188 reinterpret_cast<uintptr_t>(m_startOfStack) - sizeof(void*); 188 reinterpret_cast<uintptr_t>(m_startOfStack) - sizeof(void*);
189 size_t underestimatedStackSize = 189 size_t underestimatedStackSize =
190 StackFrameDepth::getUnderestimatedStackSize(); 190 StackFrameDepth::getUnderestimatedStackSize();
191 if (underestimatedStackSize > sizeof(void*)) 191 if (underestimatedStackSize > sizeof(void*))
192 s_mainThreadUnderestimatedStackSize = 192 s_mainThreadUnderestimatedStackSize =
193 underestimatedStackSize - sizeof(void*); 193 underestimatedStackSize - sizeof(void*);
194 m_heap = new ThreadHeap(); 194 m_heap = new ThreadHeap();
195 } else { 195 } else {
196 m_heap = &ThreadState::mainThreadState()->heap(); 196 m_heap = &ThreadState::mainThreadState()->heap();
197 } 197 }
198 break; 198 break;
199 case BlinkGC::PerThreadHeapMode: 199 case BlinkGC::PerThreadHeapMode:
200 m_heap = new ThreadHeap(); 200 m_heap = new ThreadHeap();
201 break; 201 break;
202 } 202 }
203 ASSERT(m_heap); 203 DCHECK(m_heap);
204 m_heap->attach(this); 204 m_heap->attach(this);
205 205
206 for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex; 206 for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex;
207 arenaIndex++) 207 arenaIndex++)
208 m_arenas[arenaIndex] = new NormalPageArena(this, arenaIndex); 208 m_arenas[arenaIndex] = new NormalPageArena(this, arenaIndex);
209 m_arenas[BlinkGC::LargeObjectArenaIndex] = 209 m_arenas[BlinkGC::LargeObjectArenaIndex] =
210 new LargeObjectArena(this, BlinkGC::LargeObjectArenaIndex); 210 new LargeObjectArena(this, BlinkGC::LargeObjectArenaIndex);
211 211
212 m_likelyToBePromptlyFreed = 212 m_likelyToBePromptlyFreed =
213 wrapArrayUnique(new int[likelyToBePromptlyFreedArraySize]); 213 wrapArrayUnique(new int[likelyToBePromptlyFreedArraySize]);
214 clearArenaAges(); 214 clearArenaAges();
215 } 215 }
216 216
217 ThreadState::~ThreadState() { 217 ThreadState::~ThreadState() {
218 ASSERT(checkThread()); 218 DCHECK(checkThread());
219 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 219 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
220 delete m_arenas[i]; 220 delete m_arenas[i];
221 221
222 **s_threadSpecific = nullptr; 222 **s_threadSpecific = nullptr;
223 if (isMainThread()) { 223 if (isMainThread()) {
224 s_mainThreadStackStart = 0; 224 s_mainThreadStackStart = 0;
225 s_mainThreadUnderestimatedStackSize = 0; 225 s_mainThreadUnderestimatedStackSize = 0;
226 } 226 }
227 } 227 }
228 228
229 #if OS(WIN) && COMPILER(MSVC) 229 #if OS(WIN) && COMPILER(MSVC)
230 size_t ThreadState::threadStackSize() { 230 size_t ThreadState::threadStackSize() {
231 if (m_threadStackSize) 231 if (m_threadStackSize)
232 return m_threadStackSize; 232 return m_threadStackSize;
233 233
234 // Notice that we cannot use the TIB's StackLimit for the stack end, as it 234 // Notice that we cannot use the TIB's StackLimit for the stack end, as it
235 // tracks the end of the committed range. We're after the end of the reserved 235 // tracks the end of the committed range. We're after the end of the reserved
236 // stack area (most of which will be uncommitted, most times.) 236 // stack area (most of which will be uncommitted, most times.)
237 MEMORY_BASIC_INFORMATION stackInfo; 237 MEMORY_BASIC_INFORMATION stackInfo;
238 memset(&stackInfo, 0, sizeof(MEMORY_BASIC_INFORMATION)); 238 memset(&stackInfo, 0, sizeof(MEMORY_BASIC_INFORMATION));
239 size_t resultSize = 239 size_t resultSize =
240 VirtualQuery(&stackInfo, &stackInfo, sizeof(MEMORY_BASIC_INFORMATION)); 240 VirtualQuery(&stackInfo, &stackInfo, sizeof(MEMORY_BASIC_INFORMATION));
241 DCHECK_GE(resultSize, sizeof(MEMORY_BASIC_INFORMATION)); 241 DCHECK_GE(resultSize, sizeof(MEMORY_BASIC_INFORMATION));
242 Address stackEnd = reinterpret_cast<Address>(stackInfo.AllocationBase); 242 Address stackEnd = reinterpret_cast<Address>(stackInfo.AllocationBase);
243 243
244 Address stackStart = 244 Address stackStart =
245 reinterpret_cast<Address>(StackFrameDepth::getStackStart()); 245 reinterpret_cast<Address>(StackFrameDepth::getStackStart());
246 RELEASE_ASSERT(stackStart && stackStart > stackEnd); 246 CHECK(stackStart && stackStart > stackEnd);
247 m_threadStackSize = static_cast<size_t>(stackStart - stackEnd); 247 m_threadStackSize = static_cast<size_t>(stackStart - stackEnd);
248 // When the third last page of the reserved stack is accessed as a 248 // When the third last page of the reserved stack is accessed as a
249 // guard page, the second last page will be committed (along with removing 249 // guard page, the second last page will be committed (along with removing
250 // the guard bit on the third last) _and_ a stack overflow exception 250 // the guard bit on the third last) _and_ a stack overflow exception
251 // is raised. 251 // is raised.
252 // 252 //
253 // We have zero interest in running into stack overflow exceptions while 253 // We have zero interest in running into stack overflow exceptions while
254 // marking objects, so simply consider the last three pages + one above 254 // marking objects, so simply consider the last three pages + one above
255 // as off-limits and adjust the reported stack size accordingly. 255 // as off-limits and adjust the reported stack size accordingly.
256 // 256 //
257 // http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-man agement.aspx 257 // http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-man agement.aspx
258 // explains the details. 258 // explains the details.
259 RELEASE_ASSERT(m_threadStackSize > 4 * 0x1000); 259 CHECK(m_threadStackSize > 4 * 0x1000);
260 m_threadStackSize -= 4 * 0x1000; 260 m_threadStackSize -= 4 * 0x1000;
261 return m_threadStackSize; 261 return m_threadStackSize;
262 } 262 }
263 #endif 263 #endif
264 264
265 void ThreadState::attachMainThread() { 265 void ThreadState::attachMainThread() {
266 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete); 266 CHECK(!ProcessHeap::s_shutdownComplete);
267 s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>(); 267 s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>();
268 new (s_mainThreadStateStorage) ThreadState(BlinkGC::MainThreadHeapMode); 268 new (s_mainThreadStateStorage) ThreadState(BlinkGC::MainThreadHeapMode);
269 } 269 }
270 270
271 void ThreadState::attachCurrentThread(BlinkGC::ThreadHeapMode threadHeapMode) { 271 void ThreadState::attachCurrentThread(BlinkGC::ThreadHeapMode threadHeapMode) {
272 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete); 272 CHECK(!ProcessHeap::s_shutdownComplete);
273 new ThreadState(threadHeapMode); 273 new ThreadState(threadHeapMode);
274 } 274 }
275 275
276 void ThreadState::cleanupPages() { 276 void ThreadState::cleanupPages() {
277 ASSERT(checkThread()); 277 DCHECK(checkThread());
278 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 278 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
279 m_arenas[i]->cleanupPages(); 279 m_arenas[i]->cleanupPages();
280 } 280 }
281 281
282 void ThreadState::runTerminationGC() { 282 void ThreadState::runTerminationGC() {
283 if (isMainThread()) { 283 if (isMainThread()) {
284 cleanupPages(); 284 cleanupPages();
285 return; 285 return;
286 } 286 }
287 ASSERT(checkThread()); 287 DCHECK(checkThread());
288 288
289 // Finish sweeping. 289 // Finish sweeping.
290 completeSweep(); 290 completeSweep();
291 291
292 releaseStaticPersistentNodes(); 292 releaseStaticPersistentNodes();
293 293
294 // From here on ignore all conservatively discovered 294 // From here on ignore all conservatively discovered
295 // pointers into the heap owned by this thread. 295 // pointers into the heap owned by this thread.
296 m_isTerminating = true; 296 m_isTerminating = true;
297 297
298 // Set the terminate flag on all heap pages of this thread. This is used to 298 // Set the terminate flag on all heap pages of this thread. This is used to
299 // ensure we don't trace pages on other threads that are not part of the 299 // ensure we don't trace pages on other threads that are not part of the
300 // thread local GC. 300 // thread local GC.
301 prepareForThreadStateTermination(); 301 prepareForThreadStateTermination();
302 302
303 ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTermination( 303 ProcessHeap::crossThreadPersistentRegion().prepareForThreadStateTermination(
304 this); 304 this);
305 305
306 // Do thread local GC's as long as the count of thread local Persistents 306 // Do thread local GC's as long as the count of thread local Persistents
307 // changes and is above zero. 307 // changes and is above zero.
308 int oldCount = -1; 308 int oldCount = -1;
309 int currentCount = getPersistentRegion()->numberOfPersistents(); 309 int currentCount = getPersistentRegion()->numberOfPersistents();
310 ASSERT(currentCount >= 0); 310 DCHECK_GE(currentCount, 0);
311 while (currentCount != oldCount) { 311 while (currentCount != oldCount) {
312 collectGarbageForTerminatingThread(); 312 collectGarbageForTerminatingThread();
313 // Release the thread-local static persistents that were 313 // Release the thread-local static persistents that were
314 // instantiated while running the termination GC. 314 // instantiated while running the termination GC.
315 releaseStaticPersistentNodes(); 315 releaseStaticPersistentNodes();
316 oldCount = currentCount; 316 oldCount = currentCount;
317 currentCount = getPersistentRegion()->numberOfPersistents(); 317 currentCount = getPersistentRegion()->numberOfPersistents();
318 } 318 }
319 // We should not have any persistents left when getting to this point, 319 // We should not have any persistents left when getting to this point,
320 // if we have it is probably a bug so adding a debug ASSERT to catch this. 320 // if we have it is probably a bug so adding a debug DCHECK to catch this.
321 ASSERT(!currentCount); 321 DCHECK(!currentCount);
322 // All of pre-finalizers should be consumed. 322 // All of pre-finalizers should be consumed.
323 ASSERT(m_orderedPreFinalizers.isEmpty()); 323 DCHECK(m_orderedPreFinalizers.isEmpty());
324 RELEASE_ASSERT(gcState() == NoGCScheduled); 324 CHECK(gcState() == NoGCScheduled);
325 325
326 // Add pages to the orphaned page pool to ensure any global GCs from this 326 // Add pages to the orphaned page pool to ensure any global GCs from this
327 // point on will not trace objects on this thread's arenas. 327 // point on will not trace objects on this thread's arenas.
328 cleanupPages(); 328 cleanupPages();
329 } 329 }
330 330
331 void ThreadState::cleanupMainThread() { 331 void ThreadState::cleanupMainThread() {
332 ASSERT(isMainThread()); 332 DCHECK(isMainThread());
333 333
334 releaseStaticPersistentNodes(); 334 releaseStaticPersistentNodes();
335 335
336 // Finish sweeping before shutting down V8. Otherwise, some destructor 336 // Finish sweeping before shutting down V8. Otherwise, some destructor
337 // may access V8 and cause crashes. 337 // may access V8 and cause crashes.
338 completeSweep(); 338 completeSweep();
339 339
340 // It is unsafe to trigger GCs after this point because some 340 // It is unsafe to trigger GCs after this point because some
341 // destructor may access already-detached V8 and cause crashes. 341 // destructor may access already-detached V8 and cause crashes.
342 // Also it is useless. So we forbid GCs. 342 // Also it is useless. So we forbid GCs.
343 enterGCForbiddenScope(); 343 enterGCForbiddenScope();
344 } 344 }
345 345
346 void ThreadState::detachMainThread() { 346 void ThreadState::detachMainThread() {
347 // Enter a safe point before trying to acquire threadAttachMutex 347 // Enter a safe point before trying to acquire threadAttachMutex
348 // to avoid dead lock if another thread is preparing for GC, has acquired 348 // to avoid dead lock if another thread is preparing for GC, has acquired
349 // threadAttachMutex and waiting for other threads to pause or reach a 349 // threadAttachMutex and waiting for other threads to pause or reach a
350 // safepoint. 350 // safepoint.
351 ThreadState* state = mainThreadState(); 351 ThreadState* state = mainThreadState();
352 ASSERT(!state->isSweepingInProgress()); 352 DCHECK(!state->isSweepingInProgress());
353 353
354 state->heap().detach(state); 354 state->heap().detach(state);
355 state->~ThreadState(); 355 state->~ThreadState();
356 } 356 }
357 357
358 void ThreadState::detachCurrentThread() { 358 void ThreadState::detachCurrentThread() {
359 ThreadState* state = current(); 359 ThreadState* state = current();
360 state->heap().detach(state); 360 state->heap().detach(state);
361 RELEASE_ASSERT(state->gcState() == ThreadState::NoGCScheduled); 361 CHECK(state->gcState() == ThreadState::NoGCScheduled);
362 delete state; 362 delete state;
363 } 363 }
364 364
365 NO_SANITIZE_ADDRESS 365 NO_SANITIZE_ADDRESS
366 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) { 366 void ThreadState::visitAsanFakeStackForPointer(Visitor* visitor, Address ptr) {
367 #if defined(ADDRESS_SANITIZER) 367 #if defined(ADDRESS_SANITIZER)
368 Address* start = reinterpret_cast<Address*>(m_startOfStack); 368 Address* start = reinterpret_cast<Address*>(m_startOfStack);
369 Address* end = reinterpret_cast<Address*>(m_endOfStack); 369 Address* end = reinterpret_cast<Address*>(m_endOfStack);
370 Address* fakeFrameStart = nullptr; 370 Address* fakeFrameStart = nullptr;
371 Address* fakeFrameEnd = nullptr; 371 Address* fakeFrameEnd = nullptr;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 liveSize(Vector<size_t>(numObjectTypes)), 449 liveSize(Vector<size_t>(numObjectTypes)),
450 deadSize(Vector<size_t>(numObjectTypes)) {} 450 deadSize(Vector<size_t>(numObjectTypes)) {}
451 451
452 void ThreadState::pushThreadLocalWeakCallback(void* object, 452 void ThreadState::pushThreadLocalWeakCallback(void* object,
453 WeakCallback callback) { 453 WeakCallback callback) {
454 CallbackStack::Item* slot = m_threadLocalWeakCallbackStack->allocateEntry(); 454 CallbackStack::Item* slot = m_threadLocalWeakCallbackStack->allocateEntry();
455 *slot = CallbackStack::Item(object, callback); 455 *slot = CallbackStack::Item(object, callback);
456 } 456 }
457 457
458 bool ThreadState::popAndInvokeThreadLocalWeakCallback(Visitor* visitor) { 458 bool ThreadState::popAndInvokeThreadLocalWeakCallback(Visitor* visitor) {
459 ASSERT(checkThread()); 459 DCHECK(checkThread());
460 // For weak processing we should never reach orphaned pages since orphaned 460 // For weak processing we should never reach orphaned pages since orphaned
461 // pages are not traced and thus objects on those pages are never be 461 // pages are not traced and thus objects on those pages are never be
462 // registered as objects on orphaned pages. We cannot assert this here since 462 // registered as objects on orphaned pages. We cannot assert this here since
463 // we might have an off-heap collection. We assert it in 463 // we might have an off-heap collection. We assert it in
464 // ThreadHeap::pushThreadLocalWeakCallback. 464 // ThreadHeap::pushThreadLocalWeakCallback.
465 if (CallbackStack::Item* item = m_threadLocalWeakCallbackStack->pop()) { 465 if (CallbackStack::Item* item = m_threadLocalWeakCallbackStack->pop()) {
466 item->call(visitor); 466 item->call(visitor);
467 return true; 467 return true;
468 } 468 }
469 return false; 469 return false;
470 } 470 }
471 471
472 void ThreadState::threadLocalWeakProcessing() { 472 void ThreadState::threadLocalWeakProcessing() {
473 ASSERT(checkThread()); 473 DCHECK(checkThread());
474 ASSERT(!sweepForbidden()); 474 DCHECK(!sweepForbidden());
475 TRACE_EVENT0("blink_gc", "ThreadState::threadLocalWeakProcessing"); 475 TRACE_EVENT0("blink_gc", "ThreadState::threadLocalWeakProcessing");
476 double startTime = WTF::currentTimeMS(); 476 double startTime = WTF::currentTimeMS();
477 477
478 SweepForbiddenScope sweepForbiddenScope(this); 478 SweepForbiddenScope sweepForbiddenScope(this);
479 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; 479 ScriptForbiddenIfMainThreadScope scriptForbiddenScope;
480 480
481 // Disallow allocation during weak processing. 481 // Disallow allocation during weak processing.
482 // It would be technically safe to allow allocations, but it is unsafe 482 // It would be technically safe to allow allocations, but it is unsafe
483 // to mutate an object graph in a way in which a dead object gets 483 // to mutate an object graph in a way in which a dead object gets
484 // resurrected or mutate a HashTable (because HashTable's weak processing 484 // resurrected or mutate a HashTable (because HashTable's weak processing
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 614
615 // If we're consuming too much memory, trigger a conservative GC 615 // If we're consuming too much memory, trigger a conservative GC
616 // aggressively. This is a safe guard to avoid OOM. 616 // aggressively. This is a safe guard to avoid OOM.
617 bool ThreadState::shouldForceMemoryPressureGC() { 617 bool ThreadState::shouldForceMemoryPressureGC() {
618 if (totalMemorySize() < 300 * 1024 * 1024) 618 if (totalMemorySize() < 300 * 1024 * 1024)
619 return false; 619 return false;
620 return judgeGCThreshold(0, 0, 1.5); 620 return judgeGCThreshold(0, 0, 1.5);
621 } 621 }
622 622
623 void ThreadState::scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType gcType) { 623 void ThreadState::scheduleV8FollowupGCIfNeeded(BlinkGC::V8GCType gcType) {
624 ASSERT(checkThread()); 624 DCHECK(checkThread());
625 ThreadHeap::reportMemoryUsageForTracing(); 625 ThreadHeap::reportMemoryUsageForTracing();
626 626
627 #if PRINT_HEAP_STATS 627 #if PRINT_HEAP_STATS
628 dataLogF("ThreadState::scheduleV8FollowupGCIfNeeded (gcType=%s)\n", 628 dataLogF("ThreadState::scheduleV8FollowupGCIfNeeded (gcType=%s)\n",
629 gcType == BlinkGC::V8MajorGC ? "MajorGC" : "MinorGC"); 629 gcType == BlinkGC::V8MajorGC ? "MajorGC" : "MinorGC");
630 #endif 630 #endif
631 631
632 if (isGCForbidden()) 632 if (isGCForbidden())
633 return; 633 return;
634 634
635 // This completeSweep() will do nothing in common cases since we've 635 // This completeSweep() will do nothing in common cases since we've
636 // called completeSweep() before V8 starts minor/major GCs. 636 // called completeSweep() before V8 starts minor/major GCs.
637 completeSweep(); 637 completeSweep();
638 ASSERT(!isSweepingInProgress()); 638 DCHECK(!isSweepingInProgress());
639 ASSERT(!sweepForbidden()); 639 DCHECK(!sweepForbidden());
640 640
641 if ((gcType == BlinkGC::V8MajorGC && shouldForceMemoryPressureGC()) || 641 if ((gcType == BlinkGC::V8MajorGC && shouldForceMemoryPressureGC()) ||
642 shouldScheduleV8FollowupGC()) { 642 shouldScheduleV8FollowupGC()) {
643 #if PRINT_HEAP_STATS 643 #if PRINT_HEAP_STATS
644 dataLogF("Scheduled PreciseGC\n"); 644 dataLogF("Scheduled PreciseGC\n");
645 #endif 645 #endif
646 schedulePreciseGC(); 646 schedulePreciseGC();
647 return; 647 return;
648 } 648 }
649 if (gcType == BlinkGC::V8MajorGC && shouldScheduleIdleGC()) { 649 if (gcType == BlinkGC::V8MajorGC && shouldScheduleIdleGC()) {
(...skipping 12 matching lines...) Expand all
662 // TODO(haraken): It's a bit too late for a major GC to schedule 662 // TODO(haraken): It's a bit too late for a major GC to schedule
663 // completeSweep() here, because gcPrologue for a major GC is called 663 // completeSweep() here, because gcPrologue for a major GC is called
664 // not at the point where the major GC started but at the point where 664 // not at the point where the major GC started but at the point where
665 // the major GC requests object grouping. 665 // the major GC requests object grouping.
666 if (gcType == BlinkGC::V8MajorGC) 666 if (gcType == BlinkGC::V8MajorGC)
667 completeSweep(); 667 completeSweep();
668 } 668 }
669 669
670 void ThreadState::schedulePageNavigationGCIfNeeded( 670 void ThreadState::schedulePageNavigationGCIfNeeded(
671 float estimatedRemovalRatio) { 671 float estimatedRemovalRatio) {
672 ASSERT(checkThread()); 672 DCHECK(checkThread());
673 ThreadHeap::reportMemoryUsageForTracing(); 673 ThreadHeap::reportMemoryUsageForTracing();
674 674
675 #if PRINT_HEAP_STATS 675 #if PRINT_HEAP_STATS
676 dataLogF( 676 dataLogF(
677 "ThreadState::schedulePageNavigationGCIfNeeded " 677 "ThreadState::schedulePageNavigationGCIfNeeded "
678 "(estimatedRemovalRatio=%.2lf)\n", 678 "(estimatedRemovalRatio=%.2lf)\n",
679 estimatedRemovalRatio); 679 estimatedRemovalRatio);
680 #endif 680 #endif
681 681
682 if (isGCForbidden()) 682 if (isGCForbidden())
683 return; 683 return;
684 684
685 // Finish on-going lazy sweeping. 685 // Finish on-going lazy sweeping.
686 // TODO(haraken): It might not make sense to force completeSweep() for all 686 // TODO(haraken): It might not make sense to force completeSweep() for all
687 // page navigations. 687 // page navigations.
688 completeSweep(); 688 completeSweep();
689 ASSERT(!isSweepingInProgress()); 689 DCHECK(!isSweepingInProgress());
690 ASSERT(!sweepForbidden()); 690 DCHECK(!sweepForbidden());
691 691
692 if (shouldForceMemoryPressureGC()) { 692 if (shouldForceMemoryPressureGC()) {
693 #if PRINT_HEAP_STATS 693 #if PRINT_HEAP_STATS
694 dataLogF("Scheduled MemoryPressureGC\n"); 694 dataLogF("Scheduled MemoryPressureGC\n");
695 #endif 695 #endif
696 collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithoutSweep, 696 collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithoutSweep,
697 BlinkGC::MemoryPressureGC); 697 BlinkGC::MemoryPressureGC);
698 return; 698 return;
699 } 699 }
700 if (shouldSchedulePageNavigationGC(estimatedRemovalRatio)) { 700 if (shouldSchedulePageNavigationGC(estimatedRemovalRatio)) {
701 #if PRINT_HEAP_STATS 701 #if PRINT_HEAP_STATS
702 dataLogF("Scheduled PageNavigationGC\n"); 702 dataLogF("Scheduled PageNavigationGC\n");
703 #endif 703 #endif
704 schedulePageNavigationGC(); 704 schedulePageNavigationGC();
705 } 705 }
706 } 706 }
707 707
708 void ThreadState::schedulePageNavigationGC() { 708 void ThreadState::schedulePageNavigationGC() {
709 ASSERT(checkThread()); 709 DCHECK(checkThread());
710 ASSERT(!isSweepingInProgress()); 710 DCHECK(!isSweepingInProgress());
711 setGCState(PageNavigationGCScheduled); 711 setGCState(PageNavigationGCScheduled);
712 } 712 }
713 713
714 void ThreadState::scheduleGCIfNeeded() { 714 void ThreadState::scheduleGCIfNeeded() {
715 ASSERT(checkThread()); 715 DCHECK(checkThread());
716 ThreadHeap::reportMemoryUsageForTracing(); 716 ThreadHeap::reportMemoryUsageForTracing();
717 717
718 #if PRINT_HEAP_STATS 718 #if PRINT_HEAP_STATS
719 dataLogF("ThreadState::scheduleGCIfNeeded\n"); 719 dataLogF("ThreadState::scheduleGCIfNeeded\n");
720 #endif 720 #endif
721 721
722 // Allocation is allowed during sweeping, but those allocations should not 722 // Allocation is allowed during sweeping, but those allocations should not
723 // trigger nested GCs. 723 // trigger nested GCs.
724 if (isGCForbidden()) 724 if (isGCForbidden())
725 return; 725 return;
726 726
727 if (isSweepingInProgress()) 727 if (isSweepingInProgress())
728 return; 728 return;
729 ASSERT(!sweepForbidden()); 729 DCHECK(!sweepForbidden());
730 730
731 reportMemoryToV8(); 731 reportMemoryToV8();
732 732
733 if (shouldForceMemoryPressureGC()) { 733 if (shouldForceMemoryPressureGC()) {
734 completeSweep(); 734 completeSweep();
735 if (shouldForceMemoryPressureGC()) { 735 if (shouldForceMemoryPressureGC()) {
736 #if PRINT_HEAP_STATS 736 #if PRINT_HEAP_STATS
737 dataLogF("Scheduled MemoryPressureGC\n"); 737 dataLogF("Scheduled MemoryPressureGC\n");
738 #endif 738 #endif
739 collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithoutSweep, 739 collectGarbage(BlinkGC::HeapPointersOnStack, BlinkGC::GCWithoutSweep,
(...skipping 16 matching lines...) Expand all
756 if (shouldScheduleIdleGC()) { 756 if (shouldScheduleIdleGC()) {
757 #if PRINT_HEAP_STATS 757 #if PRINT_HEAP_STATS
758 dataLogF("Scheduled IdleGC\n"); 758 dataLogF("Scheduled IdleGC\n");
759 #endif 759 #endif
760 scheduleIdleGC(); 760 scheduleIdleGC();
761 return; 761 return;
762 } 762 }
763 } 763 }
764 764
765 ThreadState* ThreadState::fromObject(const void* object) { 765 ThreadState* ThreadState::fromObject(const void* object) {
766 ASSERT(object); 766 DCHECK(object);
767 BasePage* page = pageFromObject(object); 767 BasePage* page = pageFromObject(object);
768 ASSERT(page); 768 DCHECK(page);
769 ASSERT(page->arena()); 769 DCHECK(page->arena());
770 return page->arena()->getThreadState(); 770 return page->arena()->getThreadState();
771 } 771 }
772 772
773 void ThreadState::performIdleGC(double deadlineSeconds) { 773 void ThreadState::performIdleGC(double deadlineSeconds) {
774 ASSERT(checkThread()); 774 DCHECK(checkThread());
775 ASSERT(isMainThread()); 775 DCHECK(isMainThread());
776 ASSERT(Platform::current()->currentThread()->scheduler()); 776 DCHECK(Platform::current()->currentThread()->scheduler());
777 777
778 if (gcState() != IdleGCScheduled) 778 if (gcState() != IdleGCScheduled)
779 return; 779 return;
780 780
781 if (isGCForbidden()) { 781 if (isGCForbidden()) {
782 // If GC is forbidden at this point, try again. 782 // If GC is forbidden at this point, try again.
783 scheduleIdleGC(); 783 scheduleIdleGC();
784 return; 784 return;
785 } 785 }
786 786
(...skipping 10 matching lines...) Expand all
797 } 797 }
798 798
799 TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds", 799 TRACE_EVENT2("blink_gc", "ThreadState::performIdleGC", "idleDeltaInSeconds",
800 idleDeltaInSeconds, "estimatedMarkingTime", 800 idleDeltaInSeconds, "estimatedMarkingTime",
801 m_heap->heapStats().estimatedMarkingTime()); 801 m_heap->heapStats().estimatedMarkingTime());
802 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep, 802 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithoutSweep,
803 BlinkGC::IdleGC); 803 BlinkGC::IdleGC);
804 } 804 }
805 805
806 void ThreadState::performIdleLazySweep(double deadlineSeconds) { 806 void ThreadState::performIdleLazySweep(double deadlineSeconds) {
807 ASSERT(checkThread()); 807 DCHECK(checkThread());
808 ASSERT(isMainThread()); 808 DCHECK(isMainThread());
809 809
810 // If we are not in a sweeping phase, there is nothing to do here. 810 // If we are not in a sweeping phase, there is nothing to do here.
811 if (!isSweepingInProgress()) 811 if (!isSweepingInProgress())
812 return; 812 return;
813 813
814 // This check is here to prevent performIdleLazySweep() from being called 814 // This check is here to prevent performIdleLazySweep() from being called
815 // recursively. I'm not sure if it can happen but it would be safer to have 815 // recursively. I'm not sure if it can happen but it would be safer to have
816 // the check just in case. 816 // the check just in case.
817 if (sweepForbidden()) 817 if (sweepForbidden())
818 return; 818 return;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 // Some threads (e.g. PPAPI thread) don't have a scheduler. 878 // Some threads (e.g. PPAPI thread) don't have a scheduler.
879 if (!Platform::current()->currentThread()->scheduler()) 879 if (!Platform::current()->currentThread()->scheduler())
880 return; 880 return;
881 881
882 Platform::current()->currentThread()->scheduler()->postIdleTask( 882 Platform::current()->currentThread()->scheduler()->postIdleTask(
883 BLINK_FROM_HERE, 883 BLINK_FROM_HERE,
884 WTF::bind(&ThreadState::performIdleLazySweep, WTF::unretained(this))); 884 WTF::bind(&ThreadState::performIdleLazySweep, WTF::unretained(this)));
885 } 885 }
886 886
887 void ThreadState::schedulePreciseGC() { 887 void ThreadState::schedulePreciseGC() {
888 ASSERT(checkThread()); 888 DCHECK(checkThread());
889 if (isSweepingInProgress()) { 889 if (isSweepingInProgress()) {
890 setGCState(SweepingAndPreciseGCScheduled); 890 setGCState(SweepingAndPreciseGCScheduled);
891 return; 891 return;
892 } 892 }
893 893
894 setGCState(PreciseGCScheduled); 894 setGCState(PreciseGCScheduled);
895 } 895 }
896 896
897 namespace { 897 namespace {
898 898
899 #define UNEXPECTED_GCSTATE(s) \ 899 #define UNEXPECTED_GCSTATE(s) \
900 case ThreadState::s: \ 900 case ThreadState::s: \
901 LOG(FATAL) << "Unexpected transition while in GCState " #s; \ 901 LOG(FATAL) << "Unexpected transition while in GCState " #s; \
902 return 902 return
903 903
904 void unexpectedGCState(ThreadState::GCState gcState) { 904 void unexpectedGCState(ThreadState::GCState gcState) {
905 switch (gcState) { 905 switch (gcState) {
906 UNEXPECTED_GCSTATE(NoGCScheduled); 906 UNEXPECTED_GCSTATE(NoGCScheduled);
907 UNEXPECTED_GCSTATE(IdleGCScheduled); 907 UNEXPECTED_GCSTATE(IdleGCScheduled);
908 UNEXPECTED_GCSTATE(PreciseGCScheduled); 908 UNEXPECTED_GCSTATE(PreciseGCScheduled);
909 UNEXPECTED_GCSTATE(FullGCScheduled); 909 UNEXPECTED_GCSTATE(FullGCScheduled);
910 UNEXPECTED_GCSTATE(GCRunning); 910 UNEXPECTED_GCSTATE(GCRunning);
911 UNEXPECTED_GCSTATE(EagerSweepScheduled); 911 UNEXPECTED_GCSTATE(EagerSweepScheduled);
912 UNEXPECTED_GCSTATE(LazySweepScheduled); 912 UNEXPECTED_GCSTATE(LazySweepScheduled);
913 UNEXPECTED_GCSTATE(Sweeping); 913 UNEXPECTED_GCSTATE(Sweeping);
914 UNEXPECTED_GCSTATE(SweepingAndIdleGCScheduled); 914 UNEXPECTED_GCSTATE(SweepingAndIdleGCScheduled);
915 UNEXPECTED_GCSTATE(SweepingAndPreciseGCScheduled); 915 UNEXPECTED_GCSTATE(SweepingAndPreciseGCScheduled);
916 default: 916 default:
917 ASSERT_NOT_REACHED(); 917 NOTREACHED();
918 return; 918 return;
919 } 919 }
920 } 920 }
921 921
922 #undef UNEXPECTED_GCSTATE 922 #undef UNEXPECTED_GCSTATE
923 923
924 } // namespace 924 } // namespace
925 925
926 #define VERIFY_STATE_TRANSITION(condition) \ 926 #define VERIFY_STATE_TRANSITION(condition) \
927 if (UNLIKELY(!(condition))) \ 927 if (UNLIKELY(!(condition))) { \
928 unexpectedGCState(m_gcState) 928 unexpectedGCState(m_gcState); \
929 }
929 930
930 void ThreadState::setGCState(GCState gcState) { 931 void ThreadState::setGCState(GCState gcState) {
931 switch (gcState) { 932 switch (gcState) {
932 case NoGCScheduled: 933 case NoGCScheduled:
933 ASSERT(checkThread()); 934 DCHECK(checkThread());
934 VERIFY_STATE_TRANSITION(m_gcState == Sweeping || 935 VERIFY_STATE_TRANSITION(m_gcState == Sweeping ||
935 m_gcState == SweepingAndIdleGCScheduled); 936 m_gcState == SweepingAndIdleGCScheduled);
936 break; 937 break;
937 case IdleGCScheduled: 938 case IdleGCScheduled:
938 case PreciseGCScheduled: 939 case PreciseGCScheduled:
939 case FullGCScheduled: 940 case FullGCScheduled:
940 case PageNavigationGCScheduled: 941 case PageNavigationGCScheduled:
941 ASSERT(checkThread()); 942 DCHECK(checkThread());
942 VERIFY_STATE_TRANSITION( 943 VERIFY_STATE_TRANSITION(
943 m_gcState == NoGCScheduled || m_gcState == IdleGCScheduled || 944 m_gcState == NoGCScheduled || m_gcState == IdleGCScheduled ||
944 m_gcState == PreciseGCScheduled || m_gcState == FullGCScheduled || 945 m_gcState == PreciseGCScheduled || m_gcState == FullGCScheduled ||
945 m_gcState == PageNavigationGCScheduled || m_gcState == Sweeping || 946 m_gcState == PageNavigationGCScheduled || m_gcState == Sweeping ||
946 m_gcState == SweepingAndIdleGCScheduled || 947 m_gcState == SweepingAndIdleGCScheduled ||
947 m_gcState == SweepingAndPreciseGCScheduled); 948 m_gcState == SweepingAndPreciseGCScheduled);
948 completeSweep(); 949 completeSweep();
949 break; 950 break;
950 case GCRunning: 951 case GCRunning:
951 ASSERT(!isInGC()); 952 DCHECK(!isInGC());
952 VERIFY_STATE_TRANSITION(m_gcState != GCRunning); 953 VERIFY_STATE_TRANSITION(m_gcState != GCRunning);
953 break; 954 break;
954 case EagerSweepScheduled: 955 case EagerSweepScheduled:
955 case LazySweepScheduled: 956 case LazySweepScheduled:
956 ASSERT(isInGC()); 957 DCHECK(isInGC());
957 VERIFY_STATE_TRANSITION(m_gcState == GCRunning); 958 VERIFY_STATE_TRANSITION(m_gcState == GCRunning);
958 break; 959 break;
959 case Sweeping: 960 case Sweeping:
960 ASSERT(checkThread()); 961 DCHECK(checkThread());
961 VERIFY_STATE_TRANSITION(m_gcState == EagerSweepScheduled || 962 VERIFY_STATE_TRANSITION(m_gcState == EagerSweepScheduled ||
962 m_gcState == LazySweepScheduled); 963 m_gcState == LazySweepScheduled);
963 break; 964 break;
964 case SweepingAndIdleGCScheduled: 965 case SweepingAndIdleGCScheduled:
965 case SweepingAndPreciseGCScheduled: 966 case SweepingAndPreciseGCScheduled:
966 ASSERT(checkThread()); 967 DCHECK(checkThread());
967 VERIFY_STATE_TRANSITION(m_gcState == Sweeping || 968 VERIFY_STATE_TRANSITION(m_gcState == Sweeping ||
968 m_gcState == SweepingAndIdleGCScheduled || 969 m_gcState == SweepingAndIdleGCScheduled ||
969 m_gcState == SweepingAndPreciseGCScheduled); 970 m_gcState == SweepingAndPreciseGCScheduled);
970 break; 971 break;
971 default: 972 default:
972 ASSERT_NOT_REACHED(); 973 NOTREACHED();
973 } 974 }
974 m_gcState = gcState; 975 m_gcState = gcState;
975 } 976 }
976 977
977 #undef VERIFY_STATE_TRANSITION 978 #undef VERIFY_STATE_TRANSITION
978 979
979 void ThreadState::runScheduledGC(BlinkGC::StackState stackState) { 980 void ThreadState::runScheduledGC(BlinkGC::StackState stackState) {
980 ASSERT(checkThread()); 981 DCHECK(checkThread());
981 if (stackState != BlinkGC::NoHeapPointersOnStack) 982 if (stackState != BlinkGC::NoHeapPointersOnStack)
982 return; 983 return;
983 984
984 // If a safe point is entered while initiating a GC, we clearly do 985 // If a safe point is entered while initiating a GC, we clearly do
985 // not want to do another as part of that -- the safe point is only 986 // not want to do another as part of that -- the safe point is only
986 // entered after checking if a scheduled GC ought to run first. 987 // entered after checking if a scheduled GC ought to run first.
987 // Prevent that from happening by marking GCs as forbidden while 988 // Prevent that from happening by marking GCs as forbidden while
988 // one is initiated and later running. 989 // one is initiated and later running.
989 if (isGCForbidden()) 990 if (isGCForbidden())
990 return; 991 return;
(...skipping 19 matching lines...) Expand all
1010 } 1011 }
1011 1012
1012 void ThreadState::flushHeapDoesNotContainCacheIfNeeded() { 1013 void ThreadState::flushHeapDoesNotContainCacheIfNeeded() {
1013 if (m_shouldFlushHeapDoesNotContainCache) { 1014 if (m_shouldFlushHeapDoesNotContainCache) {
1014 m_heap->flushHeapDoesNotContainCache(); 1015 m_heap->flushHeapDoesNotContainCache();
1015 m_shouldFlushHeapDoesNotContainCache = false; 1016 m_shouldFlushHeapDoesNotContainCache = false;
1016 } 1017 }
1017 } 1018 }
1018 1019
1019 void ThreadState::makeConsistentForGC() { 1020 void ThreadState::makeConsistentForGC() {
1020 ASSERT(isInGC()); 1021 DCHECK(isInGC());
1021 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); 1022 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC");
1022 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 1023 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
1023 m_arenas[i]->makeConsistentForGC(); 1024 m_arenas[i]->makeConsistentForGC();
1024 } 1025 }
1025 1026
1026 void ThreadState::compact() { 1027 void ThreadState::compact() {
1027 if (!heap().compaction()->isCompacting()) 1028 if (!heap().compaction()->isCompacting())
1028 return; 1029 return;
1029 1030
1030 SweepForbiddenScope scope(this); 1031 SweepForbiddenScope scope(this);
(...skipping 14 matching lines...) Expand all
1045 // TODO: implement bail out wrt any overall deadline, not compacting 1046 // TODO: implement bail out wrt any overall deadline, not compacting
1046 // the remaining arenas if the time budget has been exceeded. 1047 // the remaining arenas if the time budget has been exceeded.
1047 heap().compaction()->startThreadCompaction(); 1048 heap().compaction()->startThreadCompaction();
1048 for (int i = BlinkGC::HashTableArenaIndex; i >= BlinkGC::Vector1ArenaIndex; 1049 for (int i = BlinkGC::HashTableArenaIndex; i >= BlinkGC::Vector1ArenaIndex;
1049 --i) 1050 --i)
1050 static_cast<NormalPageArena*>(m_arenas[i])->sweepAndCompact(); 1051 static_cast<NormalPageArena*>(m_arenas[i])->sweepAndCompact();
1051 heap().compaction()->finishThreadCompaction(); 1052 heap().compaction()->finishThreadCompaction();
1052 } 1053 }
1053 1054
1054 void ThreadState::makeConsistentForMutator() { 1055 void ThreadState::makeConsistentForMutator() {
1055 ASSERT(isInGC()); 1056 DCHECK(isInGC());
1056 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 1057 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
1057 m_arenas[i]->makeConsistentForMutator(); 1058 m_arenas[i]->makeConsistentForMutator();
1058 } 1059 }
1059 1060
1060 void ThreadState::preGC() { 1061 void ThreadState::preGC() {
1061 if (RuntimeEnabledFeatures::traceWrappablesEnabled() && m_isolate && 1062 if (RuntimeEnabledFeatures::traceWrappablesEnabled() && m_isolate &&
1062 m_performCleanup) 1063 m_performCleanup)
1063 m_performCleanup(m_isolate); 1064 m_performCleanup(m_isolate);
1064 1065
1065 ASSERT(!isInGC()); 1066 DCHECK(!isInGC());
1066 setGCState(GCRunning); 1067 setGCState(GCRunning);
1067 makeConsistentForGC(); 1068 makeConsistentForGC();
1068 flushHeapDoesNotContainCacheIfNeeded(); 1069 flushHeapDoesNotContainCacheIfNeeded();
1069 clearArenaAges(); 1070 clearArenaAges();
1070 1071
1071 // It is possible, albeit rare, for a thread to be kept 1072 // It is possible, albeit rare, for a thread to be kept
1072 // at a safepoint across multiple GCs, as resuming all attached 1073 // at a safepoint across multiple GCs, as resuming all attached
1073 // threads after the "global" GC phases will contend for the shared 1074 // threads after the "global" GC phases will contend for the shared
1074 // safepoint barrier mutexes etc, which can additionally delay 1075 // safepoint barrier mutexes etc, which can additionally delay
1075 // a thread. Enough so that another thread may initiate 1076 // a thread. Enough so that another thread may initiate
1076 // a new GC before this has happened. 1077 // a new GC before this has happened.
1077 // 1078 //
1078 // In which case the parked thread's ThreadState will have unprocessed 1079 // In which case the parked thread's ThreadState will have unprocessed
1079 // entries on its local weak callback stack when that later GC goes 1080 // entries on its local weak callback stack when that later GC goes
1080 // ahead. Clear out and invalidate the stack now, as the thread 1081 // ahead. Clear out and invalidate the stack now, as the thread
1081 // should only process callbacks that's found to be reachable by 1082 // should only process callbacks that's found to be reachable by
1082 // the latest GC, when it eventually gets to next perform 1083 // the latest GC, when it eventually gets to next perform
1083 // thread-local weak processing. 1084 // thread-local weak processing.
1084 m_threadLocalWeakCallbackStack->decommit(); 1085 m_threadLocalWeakCallbackStack->decommit();
1085 m_threadLocalWeakCallbackStack->commit(); 1086 m_threadLocalWeakCallbackStack->commit();
1086 } 1087 }
1087 1088
1088 void ThreadState::postGC(BlinkGC::GCType gcType) { 1089 void ThreadState::postGC(BlinkGC::GCType gcType) {
1089 if (RuntimeEnabledFeatures::traceWrappablesEnabled() && 1090 if (RuntimeEnabledFeatures::traceWrappablesEnabled() &&
1090 m_invalidateDeadObjectsInWrappersMarkingDeque) { 1091 m_invalidateDeadObjectsInWrappersMarkingDeque) {
1091 m_invalidateDeadObjectsInWrappersMarkingDeque(m_isolate); 1092 m_invalidateDeadObjectsInWrappersMarkingDeque(m_isolate);
1092 } 1093 }
1093 1094
1094 ASSERT(isInGC()); 1095 DCHECK(isInGC());
1095 for (int i = 0; i < BlinkGC::NumberOfArenas; i++) 1096 for (int i = 0; i < BlinkGC::NumberOfArenas; i++)
1096 m_arenas[i]->prepareForSweep(); 1097 m_arenas[i]->prepareForSweep();
1097 1098
1098 if (gcType == BlinkGC::GCWithSweep) { 1099 if (gcType == BlinkGC::GCWithSweep) {
1099 setGCState(EagerSweepScheduled); 1100 setGCState(EagerSweepScheduled);
1100 } else if (gcType == BlinkGC::GCWithoutSweep) { 1101 } else if (gcType == BlinkGC::GCWithoutSweep) {
1101 setGCState(LazySweepScheduled); 1102 setGCState(LazySweepScheduled);
1102 } else { 1103 } else {
1103 takeSnapshot(SnapshotType::HeapSnapshot); 1104 takeSnapshot(SnapshotType::HeapSnapshot);
1104 1105
1105 // This unmarks all marked objects and marks all unmarked objects dead. 1106 // This unmarks all marked objects and marks all unmarked objects dead.
1106 makeConsistentForMutator(); 1107 makeConsistentForMutator();
1107 1108
1108 takeSnapshot(SnapshotType::FreelistSnapshot); 1109 takeSnapshot(SnapshotType::FreelistSnapshot);
1109 1110
1110 // Force setting NoGCScheduled to circumvent checkThread() 1111 // Force setting NoGCScheduled to circumvent checkThread()
1111 // in setGCState(). 1112 // in setGCState().
1112 m_gcState = NoGCScheduled; 1113 m_gcState = NoGCScheduled;
1113 } 1114 }
1114 } 1115 }
1115 1116
1116 void ThreadState::preSweep() { 1117 void ThreadState::preSweep() {
1117 ASSERT(checkThread()); 1118 DCHECK(checkThread());
1118 if (gcState() != EagerSweepScheduled && gcState() != LazySweepScheduled) 1119 if (gcState() != EagerSweepScheduled && gcState() != LazySweepScheduled)
1119 return; 1120 return;
1120 1121
1121 threadLocalWeakProcessing(); 1122 threadLocalWeakProcessing();
1122 1123
1123 GCState previousGCState = gcState(); 1124 GCState previousGCState = gcState();
1124 // We have to set the GCState to Sweeping before calling pre-finalizers 1125 // We have to set the GCState to Sweeping before calling pre-finalizers
1125 // to disallow a GC during the pre-finalizers. 1126 // to disallow a GC during the pre-finalizers.
1126 setGCState(Sweeping); 1127 setGCState(Sweeping);
1127 1128
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1177 // threads (e.g. in CrossThreadPersistentRegion::shouldTracePersistent) and 1178 // threads (e.g. in CrossThreadPersistentRegion::shouldTracePersistent) and
1178 // that would be fine. 1179 // that would be fine.
1179 ProcessHeap::crossThreadPersistentRegion().unpoisonCrossThreadPersistents(); 1180 ProcessHeap::crossThreadPersistentRegion().unpoisonCrossThreadPersistents();
1180 } 1181 }
1181 #endif 1182 #endif
1182 1183
1183 void ThreadState::eagerSweep() { 1184 void ThreadState::eagerSweep() {
1184 #if defined(ADDRESS_SANITIZER) 1185 #if defined(ADDRESS_SANITIZER)
1185 poisonEagerArena(); 1186 poisonEagerArena();
1186 #endif 1187 #endif
1187 ASSERT(checkThread()); 1188 DCHECK(checkThread());
1188 // Some objects need to be finalized promptly and cannot be handled 1189 // Some objects need to be finalized promptly and cannot be handled
1189 // by lazy sweeping. Keep those in a designated heap and sweep it 1190 // by lazy sweeping. Keep those in a designated heap and sweep it
1190 // eagerly. 1191 // eagerly.
1191 ASSERT(isSweepingInProgress()); 1192 DCHECK(isSweepingInProgress());
1192 1193
1193 // Mirroring the completeSweep() condition; see its comment. 1194 // Mirroring the completeSweep() condition; see its comment.
1194 if (sweepForbidden()) 1195 if (sweepForbidden())
1195 return; 1196 return;
1196 1197
1197 SweepForbiddenScope scope(this); 1198 SweepForbiddenScope scope(this);
1198 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; 1199 ScriptForbiddenIfMainThreadScope scriptForbiddenScope;
1199 1200
1200 double startTime = WTF::currentTimeMS(); 1201 double startTime = WTF::currentTimeMS();
1201 m_arenas[BlinkGC::EagerSweepArenaIndex]->completeSweep(); 1202 m_arenas[BlinkGC::EagerSweepArenaIndex]->completeSweep();
1202 accumulateSweepingTime(WTF::currentTimeMS() - startTime); 1203 accumulateSweepingTime(WTF::currentTimeMS() - startTime);
1203 } 1204 }
1204 1205
1205 void ThreadState::completeSweep() { 1206 void ThreadState::completeSweep() {
1206 ASSERT(checkThread()); 1207 DCHECK(checkThread());
1207 // If we are not in a sweeping phase, there is nothing to do here. 1208 // If we are not in a sweeping phase, there is nothing to do here.
1208 if (!isSweepingInProgress()) 1209 if (!isSweepingInProgress())
1209 return; 1210 return;
1210 1211
1211 // completeSweep() can be called recursively if finalizers can allocate 1212 // completeSweep() can be called recursively if finalizers can allocate
1212 // memory and the allocation triggers completeSweep(). This check prevents 1213 // memory and the allocation triggers completeSweep(). This check prevents
1213 // the sweeping from being executed recursively. 1214 // the sweeping from being executed recursively.
1214 if (sweepForbidden()) 1215 if (sweepForbidden())
1215 return; 1216 return;
1216 1217
(...skipping 16 matching lines...) Expand all
1233 DEFINE_STATIC_LOCAL(CustomCountHistogram, completeSweepHistogram, 1234 DEFINE_STATIC_LOCAL(CustomCountHistogram, completeSweepHistogram,
1234 ("BlinkGC.CompleteSweep", 1, 10 * 1000, 50)); 1235 ("BlinkGC.CompleteSweep", 1, 10 * 1000, 50));
1235 completeSweepHistogram.count(timeForCompleteSweep); 1236 completeSweepHistogram.count(timeForCompleteSweep);
1236 } 1237 }
1237 } 1238 }
1238 1239
1239 postSweep(); 1240 postSweep();
1240 } 1241 }
1241 1242
1242 void ThreadState::postSweep() { 1243 void ThreadState::postSweep() {
1243 ASSERT(checkThread()); 1244 DCHECK(checkThread());
1244 ThreadHeap::reportMemoryUsageForTracing(); 1245 ThreadHeap::reportMemoryUsageForTracing();
1245 1246
1246 if (isMainThread()) { 1247 if (isMainThread()) {
1247 double collectionRate = 0; 1248 double collectionRate = 0;
1248 if (m_heap->heapStats().objectSizeAtLastGC() > 0) 1249 if (m_heap->heapStats().objectSizeAtLastGC() > 0)
1249 collectionRate = 1 - 1250 collectionRate = 1 -
1250 1.0 * m_heap->heapStats().markedObjectSize() / 1251 1.0 * m_heap->heapStats().markedObjectSize() /
1251 m_heap->heapStats().objectSizeAtLastGC(); 1252 m_heap->heapStats().objectSizeAtLastGC();
1252 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), 1253 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"),
1253 "ThreadState::collectionRate", 1254 "ThreadState::collectionRate",
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 setGCState(NoGCScheduled); 1305 setGCState(NoGCScheduled);
1305 break; 1306 break;
1306 case SweepingAndPreciseGCScheduled: 1307 case SweepingAndPreciseGCScheduled:
1307 setGCState(PreciseGCScheduled); 1308 setGCState(PreciseGCScheduled);
1308 break; 1309 break;
1309 case SweepingAndIdleGCScheduled: 1310 case SweepingAndIdleGCScheduled:
1310 setGCState(NoGCScheduled); 1311 setGCState(NoGCScheduled);
1311 scheduleIdleGC(); 1312 scheduleIdleGC();
1312 break; 1313 break;
1313 default: 1314 default:
1314 ASSERT_NOT_REACHED(); 1315 NOTREACHED();
1315 } 1316 }
1316 } 1317 }
1317 1318
1318 void ThreadState::prepareForThreadStateTermination() { 1319 void ThreadState::prepareForThreadStateTermination() {
1319 ASSERT(checkThread()); 1320 DCHECK(checkThread());
1320 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 1321 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
1321 m_arenas[i]->prepareHeapForTermination(); 1322 m_arenas[i]->prepareHeapForTermination();
1322 } 1323 }
1323 1324
1324 #if ENABLE(ASSERT) 1325 #if DCHECK_IS_ON()
1325 BasePage* ThreadState::findPageFromAddress(Address address) { 1326 BasePage* ThreadState::findPageFromAddress(Address address) {
1326 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) { 1327 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) {
1327 if (BasePage* page = m_arenas[i]->findPageFromAddress(address)) 1328 if (BasePage* page = m_arenas[i]->findPageFromAddress(address))
1328 return page; 1329 return page;
1329 } 1330 }
1330 return nullptr; 1331 return nullptr;
1331 } 1332 }
1332 #endif 1333 #endif
1333 1334
1334 size_t ThreadState::objectPayloadSizeForTesting() { 1335 size_t ThreadState::objectPayloadSizeForTesting() {
1335 size_t objectPayloadSize = 0; 1336 size_t objectPayloadSize = 0;
1336 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 1337 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
1337 objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting(); 1338 objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting();
1338 return objectPayloadSize; 1339 return objectPayloadSize;
1339 } 1340 }
1340 1341
1341 void ThreadState::safePoint(BlinkGC::StackState stackState) { 1342 void ThreadState::safePoint(BlinkGC::StackState stackState) {
1342 ASSERT(checkThread()); 1343 DCHECK(checkThread());
1343 ThreadHeap::reportMemoryUsageForTracing(); 1344 ThreadHeap::reportMemoryUsageForTracing();
1344 1345
1345 runScheduledGC(stackState); 1346 runScheduledGC(stackState);
1346 ASSERT(!m_atSafePoint); 1347 DCHECK(!m_atSafePoint);
1347 m_stackState = stackState; 1348 m_stackState = stackState;
1348 m_atSafePoint = true; 1349 m_atSafePoint = true;
1349 m_heap->checkAndPark(this, nullptr); 1350 m_heap->checkAndPark(this, nullptr);
1350 m_atSafePoint = false; 1351 m_atSafePoint = false;
1351 m_stackState = BlinkGC::HeapPointersOnStack; 1352 m_stackState = BlinkGC::HeapPointersOnStack;
1352 preSweep(); 1353 preSweep();
1353 } 1354 }
1354 1355
1355 #ifdef ADDRESS_SANITIZER 1356 #ifdef ADDRESS_SANITIZER
1356 // When we are running under AddressSanitizer with 1357 // When we are running under AddressSanitizer with
1357 // detect_stack_use_after_return=1 then stack marker obtained from 1358 // detect_stack_use_after_return=1 then stack marker obtained from
1358 // SafePointScope will point into a fake stack. Detect this case by checking if 1359 // SafePointScope will point into a fake stack. Detect this case by checking if
1359 // it falls in between current stack frame and stack start and use an arbitrary 1360 // it falls in between current stack frame and stack start and use an arbitrary
1360 // high enough value for it. Don't adjust stack marker in any other case to 1361 // high enough value for it. Don't adjust stack marker in any other case to
1361 // match behavior of code running without AddressSanitizer. 1362 // match behavior of code running without AddressSanitizer.
1362 NO_SANITIZE_ADDRESS static void* adjustScopeMarkerForAdressSanitizer( 1363 NO_SANITIZE_ADDRESS static void* adjustScopeMarkerForAdressSanitizer(
1363 void* scopeMarker) { 1364 void* scopeMarker) {
1364 Address start = reinterpret_cast<Address>(StackFrameDepth::getStackStart()); 1365 Address start = reinterpret_cast<Address>(StackFrameDepth::getStackStart());
1365 Address end = reinterpret_cast<Address>(&start); 1366 Address end = reinterpret_cast<Address>(&start);
1366 RELEASE_ASSERT(end < start); 1367 CHECK(end < start);
1367 1368
1368 if (end <= scopeMarker && scopeMarker < start) 1369 if (end <= scopeMarker && scopeMarker < start)
1369 return scopeMarker; 1370 return scopeMarker;
1370 1371
1371 // 256 is as good an approximation as any else. 1372 // 256 is as good an approximation as any else.
1372 const size_t bytesToCopy = sizeof(Address) * 256; 1373 const size_t bytesToCopy = sizeof(Address) * 256;
1373 if (static_cast<size_t>(start - end) < bytesToCopy) 1374 if (static_cast<size_t>(start - end) < bytesToCopy)
1374 return start; 1375 return start;
1375 1376
1376 return end + bytesToCopy; 1377 return end + bytesToCopy;
1377 } 1378 }
1378 #endif 1379 #endif
1379 1380
1380 void ThreadState::enterSafePoint(BlinkGC::StackState stackState, 1381 void ThreadState::enterSafePoint(BlinkGC::StackState stackState,
1381 void* scopeMarker) { 1382 void* scopeMarker) {
1382 ASSERT(checkThread()); 1383 DCHECK(checkThread());
1383 #ifdef ADDRESS_SANITIZER 1384 #ifdef ADDRESS_SANITIZER
1384 if (stackState == BlinkGC::HeapPointersOnStack) 1385 if (stackState == BlinkGC::HeapPointersOnStack)
1385 scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker); 1386 scopeMarker = adjustScopeMarkerForAdressSanitizer(scopeMarker);
1386 #endif 1387 #endif
1387 ASSERT(stackState == BlinkGC::NoHeapPointersOnStack || scopeMarker); 1388 DCHECK(stackState == BlinkGC::NoHeapPointersOnStack || scopeMarker);
1388 runScheduledGC(stackState); 1389 runScheduledGC(stackState);
1389 ASSERT(!m_atSafePoint); 1390 DCHECK(!m_atSafePoint);
1390 m_atSafePoint = true; 1391 m_atSafePoint = true;
1391 m_stackState = stackState; 1392 m_stackState = stackState;
1392 m_safePointScopeMarker = scopeMarker; 1393 m_safePointScopeMarker = scopeMarker;
1393 m_heap->enterSafePoint(this); 1394 m_heap->enterSafePoint(this);
1394 } 1395 }
1395 1396
1396 void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) { 1397 void ThreadState::leaveSafePoint(SafePointAwareMutexLocker* locker) {
1397 ASSERT(checkThread()); 1398 DCHECK(checkThread());
1398 ASSERT(m_atSafePoint); 1399 DCHECK(m_atSafePoint);
1399 m_heap->leaveSafePoint(this, locker); 1400 m_heap->leaveSafePoint(this, locker);
1400 m_atSafePoint = false; 1401 m_atSafePoint = false;
1401 m_stackState = BlinkGC::HeapPointersOnStack; 1402 m_stackState = BlinkGC::HeapPointersOnStack;
1402 clearSafePointScopeMarker(); 1403 clearSafePointScopeMarker();
1403 preSweep(); 1404 preSweep();
1404 } 1405 }
1405 1406
1406 void ThreadState::reportMemoryToV8() { 1407 void ThreadState::reportMemoryToV8() {
1407 if (!m_isolate) 1408 if (!m_isolate)
1408 return; 1409 return;
(...skipping 24 matching lines...) Expand all
1433 m_markedObjectSize += delta; 1434 m_markedObjectSize += delta;
1434 m_heap->heapStats().increaseMarkedObjectSize(delta); 1435 m_heap->heapStats().increaseMarkedObjectSize(delta);
1435 } 1436 }
1436 1437
1437 void ThreadState::copyStackUntilSafePointScope() { 1438 void ThreadState::copyStackUntilSafePointScope() {
1438 if (!m_safePointScopeMarker || m_stackState == BlinkGC::NoHeapPointersOnStack) 1439 if (!m_safePointScopeMarker || m_stackState == BlinkGC::NoHeapPointersOnStack)
1439 return; 1440 return;
1440 1441
1441 Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker); 1442 Address* to = reinterpret_cast<Address*>(m_safePointScopeMarker);
1442 Address* from = reinterpret_cast<Address*>(m_endOfStack); 1443 Address* from = reinterpret_cast<Address*>(m_endOfStack);
1443 RELEASE_ASSERT(from < to); 1444 CHECK(from < to);
1444 RELEASE_ASSERT(to <= reinterpret_cast<Address*>(m_startOfStack)); 1445 CHECK(to <= reinterpret_cast<Address*>(m_startOfStack));
1445 size_t slotCount = static_cast<size_t>(to - from); 1446 size_t slotCount = static_cast<size_t>(to - from);
1446 // Catch potential performance issues. 1447 // Catch potential performance issues.
1447 #if defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) 1448 #if defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
1448 // ASan/LSan use more space on the stack and we therefore 1449 // ASan/LSan use more space on the stack and we therefore
1449 // increase the allowed stack copying for those builds. 1450 // increase the allowed stack copying for those builds.
1450 ASSERT(slotCount < 2048); 1451 DCHECK_LT(slotCount, 2048UL);
1451 #else 1452 #else
1452 ASSERT(slotCount < 1024); 1453 DCHECK_LT(slotCount, 1024UL);
1453 #endif 1454 #endif
1454 1455
1455 ASSERT(!m_safePointStackCopy.size()); 1456 DCHECK(!m_safePointStackCopy.size());
1456 m_safePointStackCopy.resize(slotCount); 1457 m_safePointStackCopy.resize(slotCount);
1457 for (size_t i = 0; i < slotCount; ++i) { 1458 for (size_t i = 0; i < slotCount; ++i) {
1458 m_safePointStackCopy[i] = from[i]; 1459 m_safePointStackCopy[i] = from[i];
1459 } 1460 }
1460 } 1461 }
1461 1462
1462 void ThreadState::addInterruptor( 1463 void ThreadState::addInterruptor(
1463 std::unique_ptr<BlinkGCInterruptor> interruptor) { 1464 std::unique_ptr<BlinkGCInterruptor> interruptor) {
1464 ASSERT(checkThread()); 1465 DCHECK(checkThread());
1465 SafePointScope scope(BlinkGC::HeapPointersOnStack); 1466 SafePointScope scope(BlinkGC::HeapPointersOnStack);
1466 { 1467 {
1467 MutexLocker locker(m_heap->threadAttachMutex()); 1468 MutexLocker locker(m_heap->threadAttachMutex());
1468 m_interruptors.append(std::move(interruptor)); 1469 m_interruptors.append(std::move(interruptor));
1469 } 1470 }
1470 } 1471 }
1471 1472
1472 void ThreadState::registerStaticPersistentNode( 1473 void ThreadState::registerStaticPersistentNode(
1473 PersistentNode* node, 1474 PersistentNode* node,
1474 PersistentClearCallback callback) { 1475 PersistentClearCallback callback) {
1475 #if defined(LEAK_SANITIZER) 1476 #if defined(LEAK_SANITIZER)
1476 if (m_disabledStaticPersistentsRegistration) 1477 if (m_disabledStaticPersistentsRegistration)
1477 return; 1478 return;
1478 #endif 1479 #endif
1479 1480
1480 ASSERT(!m_staticPersistents.contains(node)); 1481 DCHECK(!m_staticPersistents.contains(node));
1481 m_staticPersistents.add(node, callback); 1482 m_staticPersistents.add(node, callback);
1482 } 1483 }
1483 1484
1484 void ThreadState::releaseStaticPersistentNodes() { 1485 void ThreadState::releaseStaticPersistentNodes() {
1485 HashMap<PersistentNode*, ThreadState::PersistentClearCallback> 1486 HashMap<PersistentNode*, ThreadState::PersistentClearCallback>
1486 staticPersistents; 1487 staticPersistents;
1487 staticPersistents.swap(m_staticPersistents); 1488 staticPersistents.swap(m_staticPersistents);
1488 1489
1489 PersistentRegion* persistentRegion = getPersistentRegion(); 1490 PersistentRegion* persistentRegion = getPersistentRegion();
1490 for (const auto& it : staticPersistents) 1491 for (const auto& it : staticPersistents)
1491 persistentRegion->releasePersistentNode(it.key, it.value); 1492 persistentRegion->releasePersistentNode(it.key, it.value);
1492 } 1493 }
1493 1494
1494 void ThreadState::freePersistentNode(PersistentNode* persistentNode) { 1495 void ThreadState::freePersistentNode(PersistentNode* persistentNode) {
1495 PersistentRegion* persistentRegion = getPersistentRegion(); 1496 PersistentRegion* persistentRegion = getPersistentRegion();
1496 persistentRegion->freePersistentNode(persistentNode); 1497 persistentRegion->freePersistentNode(persistentNode);
1497 // Do not allow static persistents to be freed before 1498 // Do not allow static persistents to be freed before
1498 // they're all released in releaseStaticPersistentNodes(). 1499 // they're all released in releaseStaticPersistentNodes().
1499 // 1500 //
1500 // There's no fundamental reason why this couldn't be supported, 1501 // There's no fundamental reason why this couldn't be supported,
1501 // but no known use for it. 1502 // but no known use for it.
1502 ASSERT(!m_staticPersistents.contains(persistentNode)); 1503 DCHECK(!m_staticPersistents.contains(persistentNode));
1503 } 1504 }
1504 1505
1505 #if defined(LEAK_SANITIZER) 1506 #if defined(LEAK_SANITIZER)
1506 void ThreadState::enterStaticReferenceRegistrationDisabledScope() { 1507 void ThreadState::enterStaticReferenceRegistrationDisabledScope() {
1507 m_disabledStaticPersistentsRegistration++; 1508 m_disabledStaticPersistentsRegistration++;
1508 } 1509 }
1509 1510
1510 void ThreadState::leaveStaticReferenceRegistrationDisabledScope() { 1511 void ThreadState::leaveStaticReferenceRegistrationDisabledScope() {
1511 ASSERT(m_disabledStaticPersistentsRegistration); 1512 DCHECK(m_disabledStaticPersistentsRegistration);
1512 m_disabledStaticPersistentsRegistration--; 1513 m_disabledStaticPersistentsRegistration--;
1513 } 1514 }
1514 #endif 1515 #endif
1515 1516
1516 void ThreadState::lockThreadAttachMutex() { 1517 void ThreadState::lockThreadAttachMutex() {
1517 m_heap->threadAttachMutex().lock(); 1518 m_heap->threadAttachMutex().lock();
1518 } 1519 }
1519 1520
1520 void ThreadState::unlockThreadAttachMutex() { 1521 void ThreadState::unlockThreadAttachMutex() {
1521 m_heap->threadAttachMutex().unlock(); 1522 m_heap->threadAttachMutex().unlock();
1522 } 1523 }
1523 1524
1524 void ThreadState::invokePreFinalizers() { 1525 void ThreadState::invokePreFinalizers() {
1525 ASSERT(checkThread()); 1526 DCHECK(checkThread());
1526 ASSERT(!sweepForbidden()); 1527 DCHECK(!sweepForbidden());
1527 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers"); 1528 TRACE_EVENT0("blink_gc", "ThreadState::invokePreFinalizers");
1528 1529
1529 double startTime = WTF::currentTimeMS(); 1530 double startTime = WTF::currentTimeMS();
1530 if (!m_orderedPreFinalizers.isEmpty()) { 1531 if (!m_orderedPreFinalizers.isEmpty()) {
1531 SweepForbiddenScope sweepForbidden(this); 1532 SweepForbiddenScope sweepForbidden(this);
1532 ScriptForbiddenIfMainThreadScope scriptForbidden; 1533 ScriptForbiddenIfMainThreadScope scriptForbidden;
1533 1534
1534 // Call the prefinalizers in the opposite order to their registration. 1535 // Call the prefinalizers in the opposite order to their registration.
1535 // 1536 //
1536 // The prefinalizer callback wrapper returns |true| when its associated 1537 // The prefinalizer callback wrapper returns |true| when its associated
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1569 int endArenaIndex) { 1570 int endArenaIndex) {
1570 size_t minArenaAge = m_arenaAges[beginArenaIndex]; 1571 size_t minArenaAge = m_arenaAges[beginArenaIndex];
1571 int arenaIndexWithMinArenaAge = beginArenaIndex; 1572 int arenaIndexWithMinArenaAge = beginArenaIndex;
1572 for (int arenaIndex = beginArenaIndex + 1; arenaIndex <= endArenaIndex; 1573 for (int arenaIndex = beginArenaIndex + 1; arenaIndex <= endArenaIndex;
1573 arenaIndex++) { 1574 arenaIndex++) {
1574 if (m_arenaAges[arenaIndex] < minArenaAge) { 1575 if (m_arenaAges[arenaIndex] < minArenaAge) {
1575 minArenaAge = m_arenaAges[arenaIndex]; 1576 minArenaAge = m_arenaAges[arenaIndex];
1576 arenaIndexWithMinArenaAge = arenaIndex; 1577 arenaIndexWithMinArenaAge = arenaIndex;
1577 } 1578 }
1578 } 1579 }
1579 ASSERT(isVectorArenaIndex(arenaIndexWithMinArenaAge)); 1580 DCHECK(isVectorArenaIndex(arenaIndexWithMinArenaAge));
1580 return arenaIndexWithMinArenaAge; 1581 return arenaIndexWithMinArenaAge;
1581 } 1582 }
1582 1583
1583 BaseArena* ThreadState::expandedVectorBackingArena(size_t gcInfoIndex) { 1584 BaseArena* ThreadState::expandedVectorBackingArena(size_t gcInfoIndex) {
1584 ASSERT(checkThread()); 1585 DCHECK(checkThread());
1585 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; 1586 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask;
1586 --m_likelyToBePromptlyFreed[entryIndex]; 1587 --m_likelyToBePromptlyFreed[entryIndex];
1587 int arenaIndex = m_vectorBackingArenaIndex; 1588 int arenaIndex = m_vectorBackingArenaIndex;
1588 m_arenaAges[arenaIndex] = ++m_currentArenaAges; 1589 m_arenaAges[arenaIndex] = ++m_currentArenaAges;
1589 m_vectorBackingArenaIndex = arenaIndexOfVectorArenaLeastRecentlyExpanded( 1590 m_vectorBackingArenaIndex = arenaIndexOfVectorArenaLeastRecentlyExpanded(
1590 BlinkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex); 1591 BlinkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex);
1591 return m_arenas[arenaIndex]; 1592 return m_arenas[arenaIndex];
1592 } 1593 }
1593 1594
1594 void ThreadState::allocationPointAdjusted(int arenaIndex) { 1595 void ThreadState::allocationPointAdjusted(int arenaIndex) {
1595 m_arenaAges[arenaIndex] = ++m_currentArenaAges; 1596 m_arenaAges[arenaIndex] = ++m_currentArenaAges;
1596 if (m_vectorBackingArenaIndex == arenaIndex) 1597 if (m_vectorBackingArenaIndex == arenaIndex)
1597 m_vectorBackingArenaIndex = arenaIndexOfVectorArenaLeastRecentlyExpanded( 1598 m_vectorBackingArenaIndex = arenaIndexOfVectorArenaLeastRecentlyExpanded(
1598 BlinkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex); 1599 BlinkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex);
1599 } 1600 }
1600 1601
1601 void ThreadState::promptlyFreed(size_t gcInfoIndex) { 1602 void ThreadState::promptlyFreed(size_t gcInfoIndex) {
1602 ASSERT(checkThread()); 1603 DCHECK(checkThread());
1603 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; 1604 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask;
1604 // See the comment in vectorBackingArena() for why this is +3. 1605 // See the comment in vectorBackingArena() for why this is +3.
1605 m_likelyToBePromptlyFreed[entryIndex] += 3; 1606 m_likelyToBePromptlyFreed[entryIndex] += 3;
1606 } 1607 }
1607 1608
1608 void ThreadState::takeSnapshot(SnapshotType type) { 1609 void ThreadState::takeSnapshot(SnapshotType type) {
1609 ASSERT(isInGC()); 1610 DCHECK(isInGC());
1610 1611
1611 // 0 is used as index for freelist entries. Objects are indexed 1 to 1612 // 0 is used as index for freelist entries. Objects are indexed 1 to
1612 // gcInfoIndex. 1613 // gcInfoIndex.
1613 GCSnapshotInfo info(GCInfoTable::gcInfoIndex() + 1); 1614 GCSnapshotInfo info(GCInfoTable::gcInfoIndex() + 1);
1614 String threadDumpName = String::format("blink_gc/thread_%lu", 1615 String threadDumpName = String::format("blink_gc/thread_%lu",
1615 static_cast<unsigned long>(m_thread)); 1616 static_cast<unsigned long>(m_thread));
1616 const String heapsDumpName = threadDumpName + "/heaps"; 1617 const String heapsDumpName = threadDumpName + "/heaps";
1617 const String classesDumpName = threadDumpName + "/classes"; 1618 const String classesDumpName = threadDumpName + "/classes";
1618 1619
1619 int numberOfHeapsReported = 0; 1620 int numberOfHeapsReported = 0;
1620 #define SNAPSHOT_HEAP(ArenaType) \ 1621 #define SNAPSHOT_HEAP(ArenaType) \
1621 { \ 1622 { \
1622 numberOfHeapsReported++; \ 1623 numberOfHeapsReported++; \
1623 switch (type) { \ 1624 switch (type) { \
1624 case SnapshotType::HeapSnapshot: \ 1625 case SnapshotType::HeapSnapshot: \
1625 m_arenas[BlinkGC::ArenaType##ArenaIndex]->takeSnapshot( \ 1626 m_arenas[BlinkGC::ArenaType##ArenaIndex]->takeSnapshot( \
1626 heapsDumpName + "/" #ArenaType, info); \ 1627 heapsDumpName + "/" #ArenaType, info); \
1627 break; \ 1628 break; \
1628 case SnapshotType::FreelistSnapshot: \ 1629 case SnapshotType::FreelistSnapshot: \
1629 m_arenas[BlinkGC::ArenaType##ArenaIndex]->takeFreelistSnapshot( \ 1630 m_arenas[BlinkGC::ArenaType##ArenaIndex]->takeFreelistSnapshot( \
1630 heapsDumpName + "/" #ArenaType); \ 1631 heapsDumpName + "/" #ArenaType); \
1631 break; \ 1632 break; \
1632 default: \ 1633 default: \
1633 ASSERT_NOT_REACHED(); \ 1634 NOTREACHED(); \
1634 } \ 1635 } \
1635 } 1636 }
1636 1637
1637 SNAPSHOT_HEAP(NormalPage1); 1638 SNAPSHOT_HEAP(NormalPage1);
1638 SNAPSHOT_HEAP(NormalPage2); 1639 SNAPSHOT_HEAP(NormalPage2);
1639 SNAPSHOT_HEAP(NormalPage3); 1640 SNAPSHOT_HEAP(NormalPage3);
1640 SNAPSHOT_HEAP(NormalPage4); 1641 SNAPSHOT_HEAP(NormalPage4);
1641 SNAPSHOT_HEAP(EagerSweep); 1642 SNAPSHOT_HEAP(EagerSweep);
1642 SNAPSHOT_HEAP(Vector1); 1643 SNAPSHOT_HEAP(Vector1);
1643 SNAPSHOT_HEAP(Vector2); 1644 SNAPSHOT_HEAP(Vector2);
1644 SNAPSHOT_HEAP(Vector3); 1645 SNAPSHOT_HEAP(Vector3);
1645 SNAPSHOT_HEAP(Vector4); 1646 SNAPSHOT_HEAP(Vector4);
1646 SNAPSHOT_HEAP(InlineVector); 1647 SNAPSHOT_HEAP(InlineVector);
1647 SNAPSHOT_HEAP(HashTable); 1648 SNAPSHOT_HEAP(HashTable);
1648 SNAPSHOT_HEAP(LargeObject); 1649 SNAPSHOT_HEAP(LargeObject);
1649 FOR_EACH_TYPED_ARENA(SNAPSHOT_HEAP); 1650 FOR_EACH_TYPED_ARENA(SNAPSHOT_HEAP);
1650 1651
1651 ASSERT(numberOfHeapsReported == BlinkGC::NumberOfArenas); 1652 DCHECK_EQ(numberOfHeapsReported, BlinkGC::NumberOfArenas);
1652 1653
1653 #undef SNAPSHOT_HEAP 1654 #undef SNAPSHOT_HEAP
1654 1655
1655 if (type == SnapshotType::FreelistSnapshot) 1656 if (type == SnapshotType::FreelistSnapshot)
1656 return; 1657 return;
1657 1658
1658 size_t totalLiveCount = 0; 1659 size_t totalLiveCount = 0;
1659 size_t totalDeadCount = 0; 1660 size_t totalDeadCount = 0;
1660 size_t totalLiveSize = 0; 1661 size_t totalLiveSize = 0;
1661 size_t totalDeadSize = 0; 1662 size_t totalDeadSize = 0;
(...skipping 21 matching lines...) Expand all
1683 ->createMemoryAllocatorDumpForCurrentGC(classesDumpName); 1684 ->createMemoryAllocatorDumpForCurrentGC(classesDumpName);
1684 BlinkGCMemoryDumpProvider::instance() 1685 BlinkGCMemoryDumpProvider::instance()
1685 ->currentProcessMemoryDump() 1686 ->currentProcessMemoryDump()
1686 ->AddOwnershipEdge(classesDump->guid(), heapsDump->guid()); 1687 ->AddOwnershipEdge(classesDump->guid(), heapsDump->guid());
1687 } 1688 }
1688 1689
1689 void ThreadState::collectGarbage(BlinkGC::StackState stackState, 1690 void ThreadState::collectGarbage(BlinkGC::StackState stackState,
1690 BlinkGC::GCType gcType, 1691 BlinkGC::GCType gcType,
1691 BlinkGC::GCReason reason) { 1692 BlinkGC::GCReason reason) {
1692 // Nested collectGarbage() invocations aren't supported. 1693 // Nested collectGarbage() invocations aren't supported.
1693 RELEASE_ASSERT(!isGCForbidden()); 1694 CHECK(!isGCForbidden());
1694 completeSweep(); 1695 completeSweep();
1695 1696
1696 GCForbiddenScope gcForbiddenScope(this); 1697 GCForbiddenScope gcForbiddenScope(this);
1697 1698
1698 SafePointScope safePointScope(stackState, this); 1699 SafePointScope safePointScope(stackState, this);
1699 1700
1700 // Resume all parked threads upon leaving this scope. 1701 // Resume all parked threads upon leaving this scope.
1701 ParkThreadsScope parkThreadsScope(this); 1702 ParkThreadsScope parkThreadsScope(this);
1702 1703
1703 // Try to park the other threads. If we're unable to, bail out of the GC. 1704 // Try to park the other threads. If we're unable to, bail out of the GC.
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1858 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, 1859 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep,
1859 BlinkGC::ForcedGC); 1860 BlinkGC::ForcedGC);
1860 size_t liveObjects = heap().heapStats().markedObjectSize(); 1861 size_t liveObjects = heap().heapStats().markedObjectSize();
1861 if (liveObjects == previousLiveObjects) 1862 if (liveObjects == previousLiveObjects)
1862 break; 1863 break;
1863 previousLiveObjects = liveObjects; 1864 previousLiveObjects = liveObjects;
1864 } 1865 }
1865 } 1866 }
1866 1867
1867 } // namespace blink 1868 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698