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 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 state->preGC(); | 462 state->preGC(); |
463 } | 463 } |
464 | 464 |
465 void ThreadHeap::postGC(BlinkGC::GCType gcType) | 465 void ThreadHeap::postGC(BlinkGC::GCType gcType) |
466 { | 466 { |
467 ASSERT(ThreadState::current()->isInGC()); | 467 ASSERT(ThreadState::current()->isInGC()); |
468 for (ThreadState* state : m_threads) | 468 for (ThreadState* state : m_threads) |
469 state->postGC(gcType); | 469 state->postGC(gcType); |
470 } | 470 } |
471 | 471 |
472 const char* ThreadHeap::gcReasonString(BlinkGC::GCReason reason) | |
473 { | |
474 switch (reason) { | |
475 case BlinkGC::IdleGC: | |
476 return "IdleGC"; | |
477 case BlinkGC::PreciseGC: | |
478 return "PreciseGC"; | |
479 case BlinkGC::ConservativeGC: | |
480 return "ConservativeGC"; | |
481 case BlinkGC::ForcedGC: | |
482 return "ForcedGC"; | |
483 case BlinkGC::MemoryPressureGC: | |
484 return "MemoryPressureGC"; | |
485 case BlinkGC::PageNavigationGC: | |
486 return "PageNavigationGC"; | |
487 default: | |
488 ASSERT_NOT_REACHED(); | |
489 } | |
490 return "<Unknown>"; | |
491 } | |
492 | |
493 void ThreadHeap::collectGarbage(BlinkGC::StackState stackState, BlinkGC::GCType
gcType, BlinkGC::GCReason reason) | |
494 { | |
495 ASSERT(gcType != BlinkGC::ThreadTerminationGC); | |
496 | |
497 ThreadState* state = ThreadState::current(); | |
498 // Nested collectGarbage() invocations aren't supported. | |
499 RELEASE_ASSERT(!state->isGCForbidden()); | |
500 state->completeSweep(); | |
501 | |
502 std::unique_ptr<Visitor> visitor = Visitor::create(state, gcType); | |
503 | |
504 SafePointScope safePointScope(stackState, state); | |
505 | |
506 // Resume all parked threads upon leaving this scope. | |
507 ParkThreadsScope parkThreadsScope(state); | |
508 | |
509 // Try to park the other threads. If we're unable to, bail out of the GC. | |
510 if (!parkThreadsScope.parkThreads()) | |
511 return; | |
512 | |
513 ScriptForbiddenIfMainThreadScope scriptForbidden; | |
514 | |
515 TRACE_EVENT2("blink_gc,devtools.timeline", "BlinkGCMarking", | |
516 "lazySweeping", gcType == BlinkGC::GCWithoutSweep, | |
517 "gcReason", gcReasonString(reason)); | |
518 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); | |
519 double startTime = WTF::currentTimeMS(); | |
520 | |
521 if (gcType == BlinkGC::TakeSnapshot) | |
522 BlinkGCMemoryDumpProvider::instance()->clearProcessDumpForCurrentGC(); | |
523 | |
524 // Disallow allocation during garbage collection (but not during the | |
525 // finalization that happens when the visitorScope is torn down). | |
526 ThreadState::NoAllocationScope noAllocationScope(state); | |
527 | |
528 state->heap().commitCallbackStacks(); | |
529 state->heap().preGC(); | |
530 | |
531 StackFrameDepthScope stackDepthScope(&state->heap().stackFrameDepth()); | |
532 | |
533 size_t totalObjectSize = state->heap().heapStats().allocatedObjectSize() + s
tate->heap().heapStats().markedObjectSize(); | |
534 if (gcType != BlinkGC::TakeSnapshot) | |
535 state->heap().resetHeapCounters(); | |
536 | |
537 { | |
538 // Access to the CrossThreadPersistentRegion has to be prevented while | |
539 // marking and global weak processing is in progress. If not, threads | |
540 // not attached to Oilpan and participating in this GC are able | |
541 // to allocate & free PersistentNodes, something the marking phase isn't | |
542 // capable of handling. | |
543 CrossThreadPersistentRegion::LockScope persistentLock(ProcessHeap::cross
ThreadPersistentRegion()); | |
544 | |
545 // 1. Trace persistent roots. | |
546 state->heap().visitPersistentRoots(visitor.get()); | |
547 | |
548 // 2. Trace objects reachable from the stack. We do this independent of
the | |
549 // given stackState since other threads might have a different stack sta
te. | |
550 state->heap().visitStackRoots(visitor.get()); | |
551 | |
552 // 3. Transitive closure to trace objects including ephemerons. | |
553 state->heap().processMarkingStack(visitor.get()); | |
554 | |
555 state->heap().postMarkingProcessing(visitor.get()); | |
556 state->heap().globalWeakProcessing(visitor.get()); | |
557 } | |
558 | |
559 // Now we can delete all orphaned pages because there are no dangling | |
560 // pointers to the orphaned pages. (If we have such dangling pointers, | |
561 // we should have crashed during marking before getting here.) | |
562 state->heap().getOrphanedPagePool()->decommitOrphanedPages(); | |
563 | |
564 double markingTimeInMilliseconds = WTF::currentTimeMS() - startTime; | |
565 state->heap().heapStats().setEstimatedMarkingTimePerByte(totalObjectSize ? (
markingTimeInMilliseconds / 1000 / totalObjectSize) : 0); | |
566 | |
567 #if PRINT_HEAP_STATS | |
568 dataLogF("ThreadHeap::collectGarbage (gcReason=%s, lazySweeping=%d, time=%.1
lfms)\n", gcReasonString(reason), gcType == BlinkGC::GCWithoutSweep, markingTime
InMilliseconds); | |
569 #endif | |
570 | |
571 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, markingTimeHistogram,
new CustomCountHistogram("BlinkGC.CollectGarbage", 0, 10 * 1000, 50)); | |
572 markingTimeHistogram.count(markingTimeInMilliseconds); | |
573 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, totalObjectSpaceHistog
ram, new CustomCountHistogram("BlinkGC.TotalObjectSpace", 0, 4 * 1024 * 1024, 50
)); | |
574 totalObjectSpaceHistogram.count(ProcessHeap::totalAllocatedObjectSize() / 10
24); | |
575 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, totalAllocatedSpaceHis
togram, new CustomCountHistogram("BlinkGC.TotalAllocatedSpace", 0, 4 * 1024 * 10
24, 50)); | |
576 totalAllocatedSpaceHistogram.count(ProcessHeap::totalAllocatedSpace() / 1024
); | |
577 DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, gcReasonHistogram, new
EnumerationHistogram("BlinkGC.GCReason", BlinkGC::NumberOfGCReason)); | |
578 gcReasonHistogram.count(reason); | |
579 | |
580 state->heap().m_lastGCReason = reason; | |
581 | |
582 ThreadHeap::reportMemoryUsageHistogram(); | |
583 WTF::Partitions::reportMemoryUsageHistogram(); | |
584 | |
585 state->heap().postGC(gcType); | |
586 state->heap().decommitCallbackStacks(); | |
587 } | |
588 | |
589 void ThreadHeap::collectGarbageForTerminatingThread(ThreadState* state) | |
590 { | |
591 { | |
592 // A thread-specific termination GC must not allow other global GCs to g
o | |
593 // ahead while it is running, hence the termination GC does not enter a | |
594 // safepoint. VisitorScope will not enter also a safepoint scope for | |
595 // ThreadTerminationGC. | |
596 std::unique_ptr<Visitor> visitor = Visitor::create(state, BlinkGC::Threa
dTerminationGC); | |
597 | |
598 ThreadState::NoAllocationScope noAllocationScope(state); | |
599 | |
600 state->heap().commitCallbackStacks(); | |
601 state->preGC(); | |
602 | |
603 // 1. Trace the thread local persistent roots. For thread local GCs we | |
604 // don't trace the stack (ie. no conservative scanning) since this is | |
605 // only called during thread shutdown where there should be no objects | |
606 // on the stack. | |
607 // We also assume that orphaned pages have no objects reachable from | |
608 // persistent handles on other threads or CrossThreadPersistents. The | |
609 // only cases where this could happen is if a subsequent conservative | |
610 // global GC finds a "pointer" on the stack or due to a programming | |
611 // error where an object has a dangling cross-thread pointer to an | |
612 // object on this heap. | |
613 state->visitPersistents(visitor.get()); | |
614 | |
615 // 2. Trace objects reachable from the thread's persistent roots | |
616 // including ephemerons. | |
617 state->heap().processMarkingStack(visitor.get()); | |
618 | |
619 state->heap().postMarkingProcessing(visitor.get()); | |
620 state->heap().globalWeakProcessing(visitor.get()); | |
621 | |
622 state->postGC(BlinkGC::GCWithSweep); | |
623 state->heap().decommitCallbackStacks(); | |
624 } | |
625 state->preSweep(); | |
626 } | |
627 | |
628 void ThreadHeap::processMarkingStack(Visitor* visitor) | 472 void ThreadHeap::processMarkingStack(Visitor* visitor) |
629 { | 473 { |
630 // Ephemeron fixed point loop. | 474 // Ephemeron fixed point loop. |
631 do { | 475 do { |
632 { | 476 { |
633 // Iteratively mark all objects that are reachable from the objects | 477 // Iteratively mark all objects that are reachable from the objects |
634 // currently pushed onto the marking stack. | 478 // currently pushed onto the marking stack. |
635 TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThrea
ded"); | 479 TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThrea
ded"); |
636 while (popAndInvokeTraceCallback(visitor)) { } | 480 while (popAndInvokeTraceCallback(visitor)) { } |
637 } | 481 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 | 517 |
674 // It is not permitted to trace pointers of live objects in the weak | 518 // It is not permitted to trace pointers of live objects in the weak |
675 // callback phase, so the marking stack should still be empty here. | 519 // callback phase, so the marking stack should still be empty here. |
676 ASSERT(m_markingStack->isEmpty()); | 520 ASSERT(m_markingStack->isEmpty()); |
677 | 521 |
678 double timeForGlobalWeakProcessing = WTF::currentTimeMS() - startTime; | 522 double timeForGlobalWeakProcessing = WTF::currentTimeMS() - startTime; |
679 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, globalWeakTimeHistogra
m, new CustomCountHistogram("BlinkGC.TimeForGlobalWeakProcessing", 1, 10 * 1000,
50)); | 523 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, globalWeakTimeHistogra
m, new CustomCountHistogram("BlinkGC.TimeForGlobalWeakProcessing", 1, 10 * 1000,
50)); |
680 globalWeakTimeHistogram.count(timeForGlobalWeakProcessing); | 524 globalWeakTimeHistogram.count(timeForGlobalWeakProcessing); |
681 } | 525 } |
682 | 526 |
683 void ThreadHeap::collectAllGarbage() | |
684 { | |
685 // We need to run multiple GCs to collect a chain of persistent handles. | |
686 size_t previousLiveObjects = 0; | |
687 ThreadState* state = ThreadState::current(); | |
688 for (int i = 0; i < 5; ++i) { | |
689 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, Bli
nkGC::ForcedGC); | |
690 size_t liveObjects = state->heap().heapStats().markedObjectSize(); | |
691 if (liveObjects == previousLiveObjects) | |
692 break; | |
693 previousLiveObjects = liveObjects; | |
694 } | |
695 } | |
696 | |
697 void ThreadHeap::reportMemoryUsageHistogram() | 527 void ThreadHeap::reportMemoryUsageHistogram() |
698 { | 528 { |
699 static size_t supportedMaxSizeInMB = 4 * 1024; | 529 static size_t supportedMaxSizeInMB = 4 * 1024; |
700 static size_t observedMaxSizeInMB = 0; | 530 static size_t observedMaxSizeInMB = 0; |
701 | 531 |
702 // We only report the memory in the main thread. | 532 // We only report the memory in the main thread. |
703 if (!isMainThread()) | 533 if (!isMainThread()) |
704 return; | 534 return; |
705 // +1 is for rounding up the sizeInMB. | 535 // +1 is for rounding up the sizeInMB. |
706 size_t sizeInMB = ThreadState::current()->heap().heapStats().allocatedSpace(
) / 1024 / 1024 + 1; | 536 size_t sizeInMB = ThreadState::current()->heap().heapStats().allocatedSpace(
) / 1024 / 1024 + 1; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); | 639 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); |
810 | 640 |
811 m_stats.reset(); | 641 m_stats.reset(); |
812 for (ThreadState* state : m_threads) | 642 for (ThreadState* state : m_threads) |
813 state->resetHeapCounters(); | 643 state->resetHeapCounters(); |
814 } | 644 } |
815 | 645 |
816 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; | 646 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; |
817 | 647 |
818 } // namespace blink | 648 } // namespace blink |
OLD | NEW |