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 |
472 void ThreadHeap::processMarkingStack(Visitor* visitor) | 628 void ThreadHeap::processMarkingStack(Visitor* visitor) |
473 { | 629 { |
474 // Ephemeron fixed point loop. | 630 // Ephemeron fixed point loop. |
475 do { | 631 do { |
476 { | 632 { |
477 // Iteratively mark all objects that are reachable from the objects | 633 // Iteratively mark all objects that are reachable from the objects |
478 // currently pushed onto the marking stack. | 634 // currently pushed onto the marking stack. |
479 TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThrea
ded"); | 635 TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThrea
ded"); |
480 while (popAndInvokeTraceCallback(visitor)) { } | 636 while (popAndInvokeTraceCallback(visitor)) { } |
481 } | 637 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 | 673 |
518 // It is not permitted to trace pointers of live objects in the weak | 674 // It is not permitted to trace pointers of live objects in the weak |
519 // callback phase, so the marking stack should still be empty here. | 675 // callback phase, so the marking stack should still be empty here. |
520 ASSERT(m_markingStack->isEmpty()); | 676 ASSERT(m_markingStack->isEmpty()); |
521 | 677 |
522 double timeForGlobalWeakProcessing = WTF::currentTimeMS() - startTime; | 678 double timeForGlobalWeakProcessing = WTF::currentTimeMS() - startTime; |
523 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, globalWeakTimeHistogra
m, new CustomCountHistogram("BlinkGC.TimeForGlobalWeakProcessing", 1, 10 * 1000,
50)); | 679 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, globalWeakTimeHistogra
m, new CustomCountHistogram("BlinkGC.TimeForGlobalWeakProcessing", 1, 10 * 1000,
50)); |
524 globalWeakTimeHistogram.count(timeForGlobalWeakProcessing); | 680 globalWeakTimeHistogram.count(timeForGlobalWeakProcessing); |
525 } | 681 } |
526 | 682 |
| 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 |
527 void ThreadHeap::reportMemoryUsageHistogram() | 697 void ThreadHeap::reportMemoryUsageHistogram() |
528 { | 698 { |
529 static size_t supportedMaxSizeInMB = 4 * 1024; | 699 static size_t supportedMaxSizeInMB = 4 * 1024; |
530 static size_t observedMaxSizeInMB = 0; | 700 static size_t observedMaxSizeInMB = 0; |
531 | 701 |
532 // We only report the memory in the main thread. | 702 // We only report the memory in the main thread. |
533 if (!isMainThread()) | 703 if (!isMainThread()) |
534 return; | 704 return; |
535 // +1 is for rounding up the sizeInMB. | 705 // +1 is for rounding up the sizeInMB. |
536 size_t sizeInMB = ThreadState::current()->heap().heapStats().allocatedSpace(
) / 1024 / 1024 + 1; | 706 size_t sizeInMB = ThreadState::current()->heap().heapStats().allocatedSpace(
) / 1024 / 1024 + 1; |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); | 809 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); |
640 | 810 |
641 m_stats.reset(); | 811 m_stats.reset(); |
642 for (ThreadState* state : m_threads) | 812 for (ThreadState* state : m_threads) |
643 state->resetHeapCounters(); | 813 state->resetHeapCounters(); |
644 } | 814 } |
645 | 815 |
646 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; | 816 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; |
647 | 817 |
648 } // namespace blink | 818 } // namespace blink |
OLD | NEW |