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 20 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 |
| 1052 // Compaction is done eagerly and before the mutator threads get |
| 1053 // to run again. Doing it lazily is problematic, as the mutator's |
| 1054 // references to live objects could suddenly be invalidated by |
| 1055 // compaction of a page/heap. We do know all the references to |
| 1056 // the relocating objects just after marking, but won't later. |
| 1057 // (e.g., stack references could have been created, new objects |
| 1058 // created which refer to old collection objects, and so on.) |
| 1059 |
| 1060 // Compact the hash table backing store arena first, it usually has |
| 1061 // higher fragmentation and is larger. |
| 1062 // |
| 1063 // TODO: implement bail out wrt any overall deadline, not compacting |
| 1064 // the remaining arenas if the time budget has been exceeded. |
| 1065 heap().compaction()->startThreadCompaction(this); |
| 1066 for (int i = BlinkGC::HashTableArenaIndex; i >= BlinkGC::Vector1ArenaIndex; |
| 1067 --i) |
| 1068 static_cast<NormalPageArena*>(m_arenas[i])->sweepAndCompact(); |
| 1069 heap().compaction()->finishedThreadCompaction(this); |
| 1070 } |
| 1071 |
1043 void ThreadState::makeConsistentForMutator() { | 1072 void ThreadState::makeConsistentForMutator() { |
1044 ASSERT(isInGC()); | 1073 ASSERT(isInGC()); |
1045 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) | 1074 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
1046 m_arenas[i]->makeConsistentForMutator(); | 1075 m_arenas[i]->makeConsistentForMutator(); |
1047 } | 1076 } |
1048 | 1077 |
1049 void ThreadState::preGC() { | 1078 void ThreadState::preGC() { |
1050 if (RuntimeEnabledFeatures::traceWrappablesEnabled() && m_isolate && | 1079 if (RuntimeEnabledFeatures::traceWrappablesEnabled() && m_isolate && |
1051 m_performCleanup) | 1080 m_performCleanup) |
1052 m_performCleanup(m_isolate); | 1081 m_performCleanup(m_isolate); |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1116 | 1145 |
1117 // Allocation is allowed during the pre-finalizers and destructors. | 1146 // Allocation is allowed during the pre-finalizers and destructors. |
1118 // However, they must not mutate an object graph in a way in which | 1147 // However, they must not mutate an object graph in a way in which |
1119 // a dead object gets resurrected. | 1148 // a dead object gets resurrected. |
1120 invokePreFinalizers(); | 1149 invokePreFinalizers(); |
1121 | 1150 |
1122 m_accumulatedSweepingTime = 0; | 1151 m_accumulatedSweepingTime = 0; |
1123 | 1152 |
1124 eagerSweep(); | 1153 eagerSweep(); |
1125 | 1154 |
| 1155 compact(); |
| 1156 |
1126 #if defined(ADDRESS_SANITIZER) | 1157 #if defined(ADDRESS_SANITIZER) |
1127 poisonAllHeaps(); | 1158 poisonAllHeaps(); |
1128 #endif | 1159 #endif |
| 1160 |
1129 if (previousGCState == EagerSweepScheduled) { | 1161 if (previousGCState == EagerSweepScheduled) { |
1130 // Eager sweeping should happen only in testing. | 1162 // Eager sweeping should happen only in testing. |
1131 completeSweep(); | 1163 completeSweep(); |
1132 } else { | 1164 } else { |
1133 // The default behavior is lazy sweeping. | 1165 // The default behavior is lazy sweeping. |
1134 scheduleIdleLazySweep(); | 1166 scheduleIdleLazySweep(); |
1135 } | 1167 } |
1136 } | 1168 } |
1137 | 1169 |
1138 #if defined(ADDRESS_SANITIZER) | 1170 #if defined(ADDRESS_SANITIZER) |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 | 1699 |
1668 void ThreadState::collectGarbage(BlinkGC::StackState stackState, | 1700 void ThreadState::collectGarbage(BlinkGC::StackState stackState, |
1669 BlinkGC::GCType gcType, | 1701 BlinkGC::GCType gcType, |
1670 BlinkGC::GCReason reason) { | 1702 BlinkGC::GCReason reason) { |
1671 DCHECK_NE(gcType, BlinkGC::ThreadTerminationGC); | 1703 DCHECK_NE(gcType, BlinkGC::ThreadTerminationGC); |
1672 | 1704 |
1673 // Nested collectGarbage() invocations aren't supported. | 1705 // Nested collectGarbage() invocations aren't supported. |
1674 RELEASE_ASSERT(!isGCForbidden()); | 1706 RELEASE_ASSERT(!isGCForbidden()); |
1675 completeSweep(); | 1707 completeSweep(); |
1676 | 1708 |
1677 std::unique_ptr<Visitor> visitor = Visitor::create(this, gcType); | 1709 GCForbiddenScope gcForbiddenScope(this); |
1678 | 1710 |
1679 SafePointScope safePointScope(stackState, this); | 1711 SafePointScope safePointScope(stackState, this); |
1680 | 1712 |
1681 // Resume all parked threads upon leaving this scope. | 1713 // Resume all parked threads upon leaving this scope. |
1682 ParkThreadsScope parkThreadsScope(this); | 1714 ParkThreadsScope parkThreadsScope(this); |
1683 | 1715 |
1684 // Try to park the other threads. If we're unable to, bail out of the GC. | 1716 // Try to park the other threads. If we're unable to, bail out of the GC. |
1685 if (!parkThreadsScope.parkThreads()) | 1717 if (!parkThreadsScope.parkThreads()) |
1686 return; | 1718 return; |
1687 | 1719 |
| 1720 BlinkGC::GCType visitorType = gcType; |
| 1721 if (heap().compaction()->shouldCompact(this, gcType, reason)) |
| 1722 visitorType = heap().compaction()->initialize(this); |
| 1723 |
| 1724 std::unique_ptr<Visitor> visitor = Visitor::create(this, visitorType); |
| 1725 |
1688 ScriptForbiddenIfMainThreadScope scriptForbidden; | 1726 ScriptForbiddenIfMainThreadScope scriptForbidden; |
1689 | 1727 |
1690 TRACE_EVENT2("blink_gc,devtools.timeline", "BlinkGCMarking", "lazySweeping", | 1728 TRACE_EVENT2("blink_gc,devtools.timeline", "BlinkGCMarking", "lazySweeping", |
1691 gcType == BlinkGC::GCWithoutSweep, "gcReason", | 1729 gcType == BlinkGC::GCWithoutSweep, "gcReason", |
1692 gcReasonString(reason)); | 1730 gcReasonString(reason)); |
1693 double startTime = WTF::currentTimeMS(); | 1731 double startTime = WTF::currentTimeMS(); |
1694 | 1732 |
1695 if (gcType == BlinkGC::TakeSnapshot) | 1733 if (gcType == BlinkGC::TakeSnapshot) |
1696 BlinkGCMemoryDumpProvider::instance()->clearProcessDumpForCurrentGC(); | 1734 BlinkGCMemoryDumpProvider::instance()->clearProcessDumpForCurrentGC(); |
1697 | 1735 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 heap().postGC(gcType); | 1816 heap().postGC(gcType); |
1779 heap().decommitCallbackStacks(); | 1817 heap().decommitCallbackStacks(); |
1780 } | 1818 } |
1781 | 1819 |
1782 void ThreadState::collectGarbageForTerminatingThread() { | 1820 void ThreadState::collectGarbageForTerminatingThread() { |
1783 { | 1821 { |
1784 // A thread-specific termination GC must not allow other global GCs to go | 1822 // 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 | 1823 // ahead while it is running, hence the termination GC does not enter a |
1786 // safepoint. VisitorScope will not enter also a safepoint scope for | 1824 // safepoint. VisitorScope will not enter also a safepoint scope for |
1787 // ThreadTerminationGC. | 1825 // ThreadTerminationGC. |
| 1826 GCForbiddenScope gcForbiddenScope(this); |
1788 std::unique_ptr<Visitor> visitor = | 1827 std::unique_ptr<Visitor> visitor = |
1789 Visitor::create(this, BlinkGC::ThreadTerminationGC); | 1828 Visitor::create(this, BlinkGC::ThreadTerminationGC); |
1790 | 1829 |
1791 ThreadState::NoAllocationScope noAllocationScope(this); | 1830 ThreadState::NoAllocationScope noAllocationScope(this); |
1792 | 1831 |
1793 heap().commitCallbackStacks(); | 1832 heap().commitCallbackStacks(); |
1794 preGC(); | 1833 preGC(); |
1795 | 1834 |
1796 // 1. Trace the thread local persistent roots. For thread local GCs we | 1835 // 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 | 1836 // don't trace the stack (ie. no conservative scanning) since this is |
(...skipping 27 matching lines...) Expand all Loading... |
1825 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, | 1864 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, |
1826 BlinkGC::ForcedGC); | 1865 BlinkGC::ForcedGC); |
1827 size_t liveObjects = heap().heapStats().markedObjectSize(); | 1866 size_t liveObjects = heap().heapStats().markedObjectSize(); |
1828 if (liveObjects == previousLiveObjects) | 1867 if (liveObjects == previousLiveObjects) |
1829 break; | 1868 break; |
1830 previousLiveObjects = liveObjects; | 1869 previousLiveObjects = liveObjects; |
1831 } | 1870 } |
1832 } | 1871 } |
1833 | 1872 |
1834 } // namespace blink | 1873 } // namespace blink |
OLD | NEW |