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

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

Issue 2531973002: Simple BlinkGC heap compaction. (Closed)
Patch Set: Clear unused pages before decommitting Created 4 years 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 20 matching lines...) Expand all
31 #include "platform/heap/ThreadState.h" 31 #include "platform/heap/ThreadState.h"
32 32
33 #include "base/trace_event/process_memory_dump.h" 33 #include "base/trace_event/process_memory_dump.h"
34 #include "platform/Histogram.h" 34 #include "platform/Histogram.h"
35 #include "platform/RuntimeEnabledFeatures.h" 35 #include "platform/RuntimeEnabledFeatures.h"
36 #include "platform/ScriptForbiddenScope.h" 36 #include "platform/ScriptForbiddenScope.h"
37 #include "platform/heap/BlinkGCMemoryDumpProvider.h" 37 #include "platform/heap/BlinkGCMemoryDumpProvider.h"
38 #include "platform/heap/CallbackStack.h" 38 #include "platform/heap/CallbackStack.h"
39 #include "platform/heap/Handle.h" 39 #include "platform/heap/Handle.h"
40 #include "platform/heap/Heap.h" 40 #include "platform/heap/Heap.h"
41 #include "platform/heap/HeapCompact.h"
41 #include "platform/heap/PagePool.h" 42 #include "platform/heap/PagePool.h"
42 #include "platform/heap/SafePoint.h" 43 #include "platform/heap/SafePoint.h"
43 #include "platform/heap/Visitor.h" 44 #include "platform/heap/Visitor.h"
44 #include "platform/tracing/TraceEvent.h" 45 #include "platform/tracing/TraceEvent.h"
45 #include "platform/tracing/web_memory_allocator_dump.h" 46 #include "platform/tracing/web_memory_allocator_dump.h"
46 #include "platform/tracing/web_process_memory_dump.h" 47 #include "platform/tracing/web_process_memory_dump.h"
47 #include "public/platform/Platform.h" 48 #include "public/platform/Platform.h"
48 #include "public/platform/WebScheduler.h" 49 #include "public/platform/WebScheduler.h"
49 #include "public/platform/WebThread.h" 50 #include "public/platform/WebThread.h"
50 #include "public/platform/WebTraceLocation.h" 51 #include "public/platform/WebTraceLocation.h"
(...skipping 21 matching lines...) Expand all
72 73
73 namespace blink { 74 namespace blink {
74 75
75 WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = nullptr; 76 WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = nullptr;
76 uintptr_t ThreadState::s_mainThreadStackStart = 0; 77 uintptr_t ThreadState::s_mainThreadStackStart = 0;
77 uintptr_t ThreadState::s_mainThreadUnderestimatedStackSize = 0; 78 uintptr_t ThreadState::s_mainThreadUnderestimatedStackSize = 0;
78 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; 79 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)];
79 80
80 const size_t defaultAllocatedObjectSizeThreshold = 100 * 1024; 81 const size_t defaultAllocatedObjectSizeThreshold = 100 * 1024;
81 82
82 const char* gcReasonString(BlinkGC::GCReason reason) { 83 const char* ThreadState::gcReasonString(BlinkGC::GCReason reason) {
83 switch (reason) { 84 switch (reason) {
84 case BlinkGC::IdleGC: 85 case BlinkGC::IdleGC:
85 return "IdleGC"; 86 return "IdleGC";
86 case BlinkGC::PreciseGC: 87 case BlinkGC::PreciseGC:
87 return "PreciseGC"; 88 return "PreciseGC";
88 case BlinkGC::ConservativeGC: 89 case BlinkGC::ConservativeGC:
89 return "ConservativeGC"; 90 return "ConservativeGC";
90 case BlinkGC::ForcedGC: 91 case BlinkGC::ForcedGC:
91 return "ForcedGC"; 92 return "ForcedGC";
92 case BlinkGC::MemoryPressureGC: 93 case BlinkGC::MemoryPressureGC:
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; 498 ScriptForbiddenIfMainThreadScope scriptForbiddenScope;
498 499
499 // Disallow allocation during weak processing. 500 // Disallow allocation during weak processing.
500 // It would be technically safe to allow allocations, but it is unsafe 501 // It would be technically safe to allow allocations, but it is unsafe
501 // to mutate an object graph in a way in which a dead object gets 502 // to mutate an object graph in a way in which a dead object gets
502 // resurrected or mutate a HashTable (because HashTable's weak processing 503 // resurrected or mutate a HashTable (because HashTable's weak processing
503 // assumes that the HashTable hasn't been mutated since the latest marking). 504 // assumes that the HashTable hasn't been mutated since the latest marking).
504 // Due to the complexity, we just forbid allocations. 505 // Due to the complexity, we just forbid allocations.
505 NoAllocationScope noAllocationScope(this); 506 NoAllocationScope noAllocationScope(this);
506 507
508 GCForbiddenScope gcForbiddenScope(this);
507 std::unique_ptr<Visitor> visitor = 509 std::unique_ptr<Visitor> visitor =
508 Visitor::create(this, BlinkGC::ThreadLocalWeakProcessing); 510 Visitor::create(this, BlinkGC::ThreadLocalWeakProcessing);
509 511
510 // Perform thread-specific weak processing. 512 // Perform thread-specific weak processing.
511 while (popAndInvokeThreadLocalWeakCallback(visitor.get())) { 513 while (popAndInvokeThreadLocalWeakCallback(visitor.get())) {
512 } 514 }
513 515
514 m_threadLocalWeakCallbackStack->decommit(); 516 m_threadLocalWeakCallbackStack->decommit();
515 517
516 if (isMainThread()) { 518 if (isMainThread()) {
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 } 994 }
993 995
994 #undef VERIFY_STATE_TRANSITION 996 #undef VERIFY_STATE_TRANSITION
995 997
996 void ThreadState::runScheduledGC(BlinkGC::StackState stackState) { 998 void ThreadState::runScheduledGC(BlinkGC::StackState stackState) {
997 ASSERT(checkThread()); 999 ASSERT(checkThread());
998 if (stackState != BlinkGC::NoHeapPointersOnStack) 1000 if (stackState != BlinkGC::NoHeapPointersOnStack)
999 return; 1001 return;
1000 1002
1001 // If a safe point is entered while initiating a GC, we clearly do 1003 // If a safe point is entered while initiating a GC, we clearly do
1002 // not want to do another as part that -- the safe point is only 1004 // not want to do another as part of that -- the safe point is only
1003 // entered after checking if a scheduled GC ought to run first. 1005 // entered after checking if a scheduled GC ought to run first.
1004 // Prevent that from happening by marking GCs as forbidden while 1006 // Prevent that from happening by marking GCs as forbidden while
1005 // one is initiated and later running. 1007 // one is initiated and later running.
1006 if (isGCForbidden()) 1008 if (isGCForbidden())
1007 return; 1009 return;
1008 1010
1009 switch (gcState()) { 1011 switch (gcState()) {
1010 case FullGCScheduled: 1012 case FullGCScheduled:
1011 collectAllGarbage(); 1013 collectAllGarbage();
1012 break; 1014 break;
(...skipping 20 matching lines...) Expand all
1033 } 1035 }
1034 } 1036 }
1035 1037
1036 void ThreadState::makeConsistentForGC() { 1038 void ThreadState::makeConsistentForGC() {
1037 ASSERT(isInGC()); 1039 ASSERT(isInGC());
1038 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); 1040 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC");
1039 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 1041 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
1040 m_arenas[i]->makeConsistentForGC(); 1042 m_arenas[i]->makeConsistentForGC();
1041 } 1043 }
1042 1044
1045 void ThreadState::compact() {
1046 if (!heap().compaction()->isCompacting())
1047 return;
1048
1049 SweepForbiddenScope scope(this);
1050 ScriptForbiddenIfMainThreadScope scriptForbiddenScope;
1051 NoAllocationScope noAllocationScope(this);
1052
1053 // Compaction is done eagerly and before the mutator threads get
1054 // to run again. Doing it lazily is problematic, as the mutator's
1055 // references to live objects could suddenly be invalidated by
1056 // compaction of a page/heap. We do know all the references to
1057 // the relocating objects just after marking, but won't later.
1058 // (e.g., stack references could have been created, new objects
1059 // created which refer to old collection objects, and so on.)
1060
1061 // Compact the hash table backing store arena first, it usually has
1062 // higher fragmentation and is larger.
1063 //
1064 // TODO: implement bail out wrt any overall deadline, not compacting
1065 // the remaining arenas if the time budget has been exceeded.
1066 heap().compaction()->startThreadCompaction();
1067 for (int i = BlinkGC::HashTableArenaIndex; i >= BlinkGC::Vector1ArenaIndex;
1068 --i)
1069 static_cast<NormalPageArena*>(m_arenas[i])->sweepAndCompact();
1070 heap().compaction()->finishThreadCompaction();
1071 }
1072
1043 void ThreadState::makeConsistentForMutator() { 1073 void ThreadState::makeConsistentForMutator() {
1044 ASSERT(isInGC()); 1074 ASSERT(isInGC());
1045 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) 1075 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i)
1046 m_arenas[i]->makeConsistentForMutator(); 1076 m_arenas[i]->makeConsistentForMutator();
1047 } 1077 }
1048 1078
1049 void ThreadState::preGC() { 1079 void ThreadState::preGC() {
1050 if (RuntimeEnabledFeatures::traceWrappablesEnabled() && m_isolate && 1080 if (RuntimeEnabledFeatures::traceWrappablesEnabled() && m_isolate &&
1051 m_performCleanup) 1081 m_performCleanup)
1052 m_performCleanup(m_isolate); 1082 m_performCleanup(m_isolate);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 1146
1117 // Allocation is allowed during the pre-finalizers and destructors. 1147 // Allocation is allowed during the pre-finalizers and destructors.
1118 // However, they must not mutate an object graph in a way in which 1148 // However, they must not mutate an object graph in a way in which
1119 // a dead object gets resurrected. 1149 // a dead object gets resurrected.
1120 invokePreFinalizers(); 1150 invokePreFinalizers();
1121 1151
1122 m_accumulatedSweepingTime = 0; 1152 m_accumulatedSweepingTime = 0;
1123 1153
1124 eagerSweep(); 1154 eagerSweep();
1125 1155
1156 // Any sweep compaction must happen after pre-finalizers and eager
1157 // sweeping, as it will finalize dead objects in compactable arenas
1158 // (e.g., backing stores for container objects.)
1159 //
1160 // As per-contract for prefinalizers, those finalizable objects must
1161 // still be accessible when the prefinalizer runs, hence we cannot
1162 // schedule compaction until those have run. Similarly for eager sweeping.
1163 compact();
1164
1126 #if defined(ADDRESS_SANITIZER) 1165 #if defined(ADDRESS_SANITIZER)
1127 poisonAllHeaps(); 1166 poisonAllHeaps();
1128 #endif 1167 #endif
1168
1129 if (previousGCState == EagerSweepScheduled) { 1169 if (previousGCState == EagerSweepScheduled) {
1130 // Eager sweeping should happen only in testing. 1170 // Eager sweeping should happen only in testing.
1131 completeSweep(); 1171 completeSweep();
1132 } else { 1172 } else {
1133 // The default behavior is lazy sweeping. 1173 // The default behavior is lazy sweeping.
1134 scheduleIdleLazySweep(); 1174 scheduleIdleLazySweep();
1135 } 1175 }
1136 } 1176 }
1137 1177
1138 #if defined(ADDRESS_SANITIZER) 1178 #if defined(ADDRESS_SANITIZER)
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 1707
1668 void ThreadState::collectGarbage(BlinkGC::StackState stackState, 1708 void ThreadState::collectGarbage(BlinkGC::StackState stackState,
1669 BlinkGC::GCType gcType, 1709 BlinkGC::GCType gcType,
1670 BlinkGC::GCReason reason) { 1710 BlinkGC::GCReason reason) {
1671 DCHECK_NE(gcType, BlinkGC::ThreadTerminationGC); 1711 DCHECK_NE(gcType, BlinkGC::ThreadTerminationGC);
1672 1712
1673 // Nested collectGarbage() invocations aren't supported. 1713 // Nested collectGarbage() invocations aren't supported.
1674 RELEASE_ASSERT(!isGCForbidden()); 1714 RELEASE_ASSERT(!isGCForbidden());
1675 completeSweep(); 1715 completeSweep();
1676 1716
1677 std::unique_ptr<Visitor> visitor = Visitor::create(this, gcType); 1717 GCForbiddenScope gcForbiddenScope(this);
1678 1718
1679 SafePointScope safePointScope(stackState, this); 1719 SafePointScope safePointScope(stackState, this);
1680 1720
1681 // Resume all parked threads upon leaving this scope. 1721 // Resume all parked threads upon leaving this scope.
1682 ParkThreadsScope parkThreadsScope(this); 1722 ParkThreadsScope parkThreadsScope(this);
1683 1723
1684 // Try to park the other threads. If we're unable to, bail out of the GC. 1724 // Try to park the other threads. If we're unable to, bail out of the GC.
1685 if (!parkThreadsScope.parkThreads()) 1725 if (!parkThreadsScope.parkThreads())
1686 return; 1726 return;
1687 1727
1728 BlinkGC::GCType visitorType = gcType;
1729 if (heap().compaction()->shouldCompact(this, gcType, reason))
1730 visitorType = heap().compaction()->initialize(this);
1731
1732 std::unique_ptr<Visitor> visitor = Visitor::create(this, visitorType);
1733
1688 ScriptForbiddenIfMainThreadScope scriptForbidden; 1734 ScriptForbiddenIfMainThreadScope scriptForbidden;
1689 1735
1690 TRACE_EVENT2("blink_gc,devtools.timeline", "BlinkGCMarking", "lazySweeping", 1736 TRACE_EVENT2("blink_gc,devtools.timeline", "BlinkGCMarking", "lazySweeping",
1691 gcType == BlinkGC::GCWithoutSweep, "gcReason", 1737 gcType == BlinkGC::GCWithoutSweep, "gcReason",
1692 gcReasonString(reason)); 1738 gcReasonString(reason));
1693 double startTime = WTF::currentTimeMS(); 1739 double startTime = WTF::currentTimeMS();
1694 1740
1695 if (gcType == BlinkGC::TakeSnapshot) 1741 if (gcType == BlinkGC::TakeSnapshot)
1696 BlinkGCMemoryDumpProvider::instance()->clearProcessDumpForCurrentGC(); 1742 BlinkGCMemoryDumpProvider::instance()->clearProcessDumpForCurrentGC();
1697 1743
1698 // Disallow allocation during garbage collection (but not during the 1744 // Disallow allocation during garbage collection (but not during the
1699 // finalization that happens when the visitorScope is torn down). 1745 // finalization that happens when the visitorScope is torn down).
1700 ThreadState::NoAllocationScope noAllocationScope(this); 1746 NoAllocationScope noAllocationScope(this);
1701 1747
1702 heap().commitCallbackStacks(); 1748 heap().commitCallbackStacks();
1703 heap().preGC(); 1749 heap().preGC();
1704 1750
1705 StackFrameDepthScope stackDepthScope(&heap().stackFrameDepth()); 1751 StackFrameDepthScope stackDepthScope(&heap().stackFrameDepth());
1706 1752
1707 size_t totalObjectSize = heap().heapStats().allocatedObjectSize() + 1753 size_t totalObjectSize = heap().heapStats().allocatedObjectSize() +
1708 heap().heapStats().markedObjectSize(); 1754 heap().heapStats().markedObjectSize();
1709 if (gcType != BlinkGC::TakeSnapshot) 1755 if (gcType != BlinkGC::TakeSnapshot)
1710 heap().resetHeapCounters(); 1756 heap().resetHeapCounters();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1778 heap().postGC(gcType); 1824 heap().postGC(gcType);
1779 heap().decommitCallbackStacks(); 1825 heap().decommitCallbackStacks();
1780 } 1826 }
1781 1827
1782 void ThreadState::collectGarbageForTerminatingThread() { 1828 void ThreadState::collectGarbageForTerminatingThread() {
1783 { 1829 {
1784 // A thread-specific termination GC must not allow other global GCs to go 1830 // A thread-specific termination GC must not allow other global GCs to go
1785 // ahead while it is running, hence the termination GC does not enter a 1831 // ahead while it is running, hence the termination GC does not enter a
1786 // safepoint. VisitorScope will not enter also a safepoint scope for 1832 // safepoint. VisitorScope will not enter also a safepoint scope for
1787 // ThreadTerminationGC. 1833 // ThreadTerminationGC.
1834 GCForbiddenScope gcForbiddenScope(this);
1788 std::unique_ptr<Visitor> visitor = 1835 std::unique_ptr<Visitor> visitor =
1789 Visitor::create(this, BlinkGC::ThreadTerminationGC); 1836 Visitor::create(this, BlinkGC::ThreadTerminationGC);
1790 1837
1791 ThreadState::NoAllocationScope noAllocationScope(this); 1838 NoAllocationScope noAllocationScope(this);
1792 1839
1793 heap().commitCallbackStacks(); 1840 heap().commitCallbackStacks();
1794 preGC(); 1841 preGC();
1795 1842
1796 // 1. Trace the thread local persistent roots. For thread local GCs we 1843 // 1. Trace the thread local persistent roots. For thread local GCs we
1797 // don't trace the stack (ie. no conservative scanning) since this is 1844 // don't trace the stack (ie. no conservative scanning) since this is
1798 // only called during thread shutdown where there should be no objects 1845 // only called during thread shutdown where there should be no objects
1799 // on the stack. 1846 // on the stack.
1800 // We also assume that orphaned pages have no objects reachable from 1847 // We also assume that orphaned pages have no objects reachable from
1801 // persistent handles on other threads or CrossThreadPersistents. The 1848 // persistent handles on other threads or CrossThreadPersistents. The
(...skipping 23 matching lines...) Expand all
1825 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, 1872 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep,
1826 BlinkGC::ForcedGC); 1873 BlinkGC::ForcedGC);
1827 size_t liveObjects = heap().heapStats().markedObjectSize(); 1874 size_t liveObjects = heap().heapStats().markedObjectSize();
1828 if (liveObjects == previousLiveObjects) 1875 if (liveObjects == previousLiveObjects)
1829 break; 1876 break;
1830 previousLiveObjects = liveObjects; 1877 previousLiveObjects = liveObjects;
1831 } 1878 }
1832 } 1879 }
1833 1880
1834 } // namespace blink 1881 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698