| 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 #endif | 88 #endif |
| 89 , m_startOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart(
))) | 89 , m_startOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart(
))) |
| 90 , m_endOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart())
) | 90 , m_endOfStack(reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart())
) |
| 91 , m_safePointScopeMarker(nullptr) | 91 , m_safePointScopeMarker(nullptr) |
| 92 , m_atSafePoint(false) | 92 , m_atSafePoint(false) |
| 93 , m_interruptors() | 93 , m_interruptors() |
| 94 , m_sweepForbidden(false) | 94 , m_sweepForbidden(false) |
| 95 , m_noAllocationCount(0) | 95 , m_noAllocationCount(0) |
| 96 , m_gcForbiddenCount(0) | 96 , m_gcForbiddenCount(0) |
| 97 , m_accumulatedSweepingTime(0) | 97 , m_accumulatedSweepingTime(0) |
| 98 , m_vectorBackingHeapIndex(BlinkGC::Vector1HeapIndex) | 98 , m_vectorBackingArenaIndex(BlinkGC::Vector1ArenaIndex) |
| 99 , m_currentHeapAges(0) | 99 , m_currentArenaAges(0) |
| 100 , m_isTerminating(false) | 100 , m_isTerminating(false) |
| 101 , m_gcMixinMarker(nullptr) | 101 , m_gcMixinMarker(nullptr) |
| 102 , m_shouldFlushHeapDoesNotContainCache(false) | 102 , m_shouldFlushHeapDoesNotContainCache(false) |
| 103 , m_gcState(NoGCScheduled) | 103 , m_gcState(NoGCScheduled) |
| 104 , m_isolate(nullptr) | 104 , m_isolate(nullptr) |
| 105 , m_traceDOMWrappers(nullptr) | 105 , m_traceDOMWrappers(nullptr) |
| 106 #if defined(ADDRESS_SANITIZER) | 106 #if defined(ADDRESS_SANITIZER) |
| 107 , m_asanFakeStack(__asan_get_current_fake_stack()) | 107 , m_asanFakeStack(__asan_get_current_fake_stack()) |
| 108 #endif | 108 #endif |
| 109 #if defined(LEAK_SANITIZER) | 109 #if defined(LEAK_SANITIZER) |
| 110 , m_disabledStaticPersistentsRegistration(0) | 110 , m_disabledStaticPersistentsRegistration(0) |
| 111 #endif | 111 #endif |
| 112 , m_allocatedObjectSize(0) | 112 , m_allocatedObjectSize(0) |
| 113 , m_markedObjectSize(0) | 113 , m_markedObjectSize(0) |
| 114 , m_reportedMemoryToV8(0) | 114 , m_reportedMemoryToV8(0) |
| 115 { | 115 { |
| 116 ASSERT(checkThread()); | 116 ASSERT(checkThread()); |
| 117 ASSERT(!**s_threadSpecific); | 117 ASSERT(!**s_threadSpecific); |
| 118 **s_threadSpecific = this; | 118 **s_threadSpecific = this; |
| 119 | 119 |
| 120 if (isMainThread()) { | 120 if (isMainThread()) { |
| 121 s_mainThreadStackStart = reinterpret_cast<uintptr_t>(m_startOfStack) - s
izeof(void*); | 121 s_mainThreadStackStart = reinterpret_cast<uintptr_t>(m_startOfStack) - s
izeof(void*); |
| 122 size_t underestimatedStackSize = StackFrameDepth::getUnderestimatedStack
Size(); | 122 size_t underestimatedStackSize = StackFrameDepth::getUnderestimatedStack
Size(); |
| 123 if (underestimatedStackSize > sizeof(void*)) | 123 if (underestimatedStackSize > sizeof(void*)) |
| 124 s_mainThreadUnderestimatedStackSize = underestimatedStackSize - size
of(void*); | 124 s_mainThreadUnderestimatedStackSize = underestimatedStackSize - size
of(void*); |
| 125 } | 125 } |
| 126 | 126 |
| 127 for (int heapIndex = 0; heapIndex < BlinkGC::LargeObjectHeapIndex; heapIndex
++) | 127 for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex; arenaI
ndex++) |
| 128 m_heaps[heapIndex] = new NormalPageHeap(this, heapIndex); | 128 m_arenas[arenaIndex] = new NormalPageHeap(this, arenaIndex); |
| 129 m_heaps[BlinkGC::LargeObjectHeapIndex] = new LargeObjectHeap(this, BlinkGC::
LargeObjectHeapIndex); | 129 m_arenas[BlinkGC::LargeObjectArenaIndex] = new LargeObjectHeap(this, BlinkGC
::LargeObjectArenaIndex); |
| 130 | 130 |
| 131 m_likelyToBePromptlyFreed = adoptArrayPtr(new int[likelyToBePromptlyFreedArr
aySize]); | 131 m_likelyToBePromptlyFreed = adoptArrayPtr(new int[likelyToBePromptlyFreedArr
aySize]); |
| 132 clearHeapAges(); | 132 clearArenaAges(); |
| 133 | 133 |
| 134 // There is little use of weak references and collections off the main threa
d; | 134 // There is little use of weak references and collections off the main threa
d; |
| 135 // use a much lower initial block reservation. | 135 // use a much lower initial block reservation. |
| 136 size_t initialBlockSize = isMainThread() ? CallbackStack::kDefaultBlockSize
: CallbackStack::kMinimalBlockSize; | 136 size_t initialBlockSize = isMainThread() ? CallbackStack::kDefaultBlockSize
: CallbackStack::kMinimalBlockSize; |
| 137 m_threadLocalWeakCallbackStack = new CallbackStack(initialBlockSize); | 137 m_threadLocalWeakCallbackStack = new CallbackStack(initialBlockSize); |
| 138 } | 138 } |
| 139 | 139 |
| 140 ThreadState::~ThreadState() | 140 ThreadState::~ThreadState() |
| 141 { | 141 { |
| 142 ASSERT(checkThread()); | 142 ASSERT(checkThread()); |
| 143 delete m_threadLocalWeakCallbackStack; | 143 delete m_threadLocalWeakCallbackStack; |
| 144 m_threadLocalWeakCallbackStack = nullptr; | 144 m_threadLocalWeakCallbackStack = nullptr; |
| 145 for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) | 145 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 146 delete m_heaps[i]; | 146 delete m_arenas[i]; |
| 147 | 147 |
| 148 **s_threadSpecific = nullptr; | 148 **s_threadSpecific = nullptr; |
| 149 if (isMainThread()) { | 149 if (isMainThread()) { |
| 150 s_mainThreadStackStart = 0; | 150 s_mainThreadStackStart = 0; |
| 151 s_mainThreadUnderestimatedStackSize = 0; | 151 s_mainThreadUnderestimatedStackSize = 0; |
| 152 } | 152 } |
| 153 } | 153 } |
| 154 | 154 |
| 155 void ThreadState::init() | 155 void ThreadState::init() |
| 156 { | 156 { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 { | 249 { |
| 250 RELEASE_ASSERT(!Heap::s_shutdownCalled); | 250 RELEASE_ASSERT(!Heap::s_shutdownCalled); |
| 251 MutexLocker locker(threadAttachMutex()); | 251 MutexLocker locker(threadAttachMutex()); |
| 252 ThreadState* state = new ThreadState(); | 252 ThreadState* state = new ThreadState(); |
| 253 attachedThreads().add(state); | 253 attachedThreads().add(state); |
| 254 } | 254 } |
| 255 | 255 |
| 256 void ThreadState::cleanupPages() | 256 void ThreadState::cleanupPages() |
| 257 { | 257 { |
| 258 ASSERT(checkThread()); | 258 ASSERT(checkThread()); |
| 259 for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) | 259 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 260 m_heaps[i]->cleanupPages(); | 260 m_arenas[i]->cleanupPages(); |
| 261 } | 261 } |
| 262 | 262 |
| 263 void ThreadState::cleanup() | 263 void ThreadState::cleanup() |
| 264 { | 264 { |
| 265 ASSERT(checkThread()); | 265 ASSERT(checkThread()); |
| 266 { | 266 { |
| 267 // Grab the threadAttachMutex to ensure only one thread can shutdown at | 267 // Grab the threadAttachMutex to ensure only one thread can shutdown at |
| 268 // a time and that no other thread can do a global GC. It also allows | 268 // a time and that no other thread can do a global GC. It also allows |
| 269 // safe iteration of the attachedThreads set which happens as part of | 269 // safe iteration of the attachedThreads set which happens as part of |
| 270 // thread local GC asserts. We enter a safepoint while waiting for the | 270 // thread local GC asserts. We enter a safepoint while waiting for the |
| (...skipping 26 matching lines...) Expand all Loading... |
| 297 currentCount = persistentRegion()->numberOfPersistents(); | 297 currentCount = persistentRegion()->numberOfPersistents(); |
| 298 } | 298 } |
| 299 // We should not have any persistents left when getting to this point, | 299 // We should not have any persistents left when getting to this point, |
| 300 // if we have it is probably a bug so adding a debug ASSERT to catch thi
s. | 300 // if we have it is probably a bug so adding a debug ASSERT to catch thi
s. |
| 301 ASSERT(!currentCount); | 301 ASSERT(!currentCount); |
| 302 // All of pre-finalizers should be consumed. | 302 // All of pre-finalizers should be consumed. |
| 303 ASSERT(m_orderedPreFinalizers.isEmpty()); | 303 ASSERT(m_orderedPreFinalizers.isEmpty()); |
| 304 RELEASE_ASSERT(gcState() == NoGCScheduled); | 304 RELEASE_ASSERT(gcState() == NoGCScheduled); |
| 305 | 305 |
| 306 // Add pages to the orphaned page pool to ensure any global GCs from thi
s point | 306 // Add pages to the orphaned page pool to ensure any global GCs from thi
s point |
| 307 // on will not trace objects on this thread's heaps. | 307 // on will not trace objects on this thread's arenas. |
| 308 cleanupPages(); | 308 cleanupPages(); |
| 309 | 309 |
| 310 ASSERT(attachedThreads().contains(this)); | 310 ASSERT(attachedThreads().contains(this)); |
| 311 attachedThreads().remove(this); | 311 attachedThreads().remove(this); |
| 312 } | 312 } |
| 313 } | 313 } |
| 314 | 314 |
| 315 void ThreadState::detach() | 315 void ThreadState::detach() |
| 316 { | 316 { |
| 317 ThreadState* state = current(); | 317 ThreadState* state = current(); |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 return; | 770 return; |
| 771 | 771 |
| 772 TRACE_EVENT1("blink_gc,devtools.timeline", "ThreadState::performIdleLazySwee
p", "idleDeltaInSeconds", deadlineSeconds - monotonicallyIncreasingTime()); | 772 TRACE_EVENT1("blink_gc,devtools.timeline", "ThreadState::performIdleLazySwee
p", "idleDeltaInSeconds", deadlineSeconds - monotonicallyIncreasingTime()); |
| 773 | 773 |
| 774 bool sweepCompleted = true; | 774 bool sweepCompleted = true; |
| 775 SweepForbiddenScope scope(this); | 775 SweepForbiddenScope scope(this); |
| 776 { | 776 { |
| 777 double startTime = WTF::currentTimeMS(); | 777 double startTime = WTF::currentTimeMS(); |
| 778 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; | 778 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; |
| 779 | 779 |
| 780 for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) { | 780 for (int i = 0; i < BlinkGC::NumberOfArenas; i++) { |
| 781 // lazySweepWithDeadline() won't check the deadline until it sweeps | 781 // lazySweepWithDeadline() won't check the deadline until it sweeps |
| 782 // 10 pages. So we give a small slack for safety. | 782 // 10 pages. So we give a small slack for safety. |
| 783 double slack = 0.001; | 783 double slack = 0.001; |
| 784 double remainingBudget = deadlineSeconds - slack - monotonicallyIncr
easingTime(); | 784 double remainingBudget = deadlineSeconds - slack - monotonicallyIncr
easingTime(); |
| 785 if (remainingBudget <= 0 || !m_heaps[i]->lazySweepWithDeadline(deadl
ineSeconds)) { | 785 if (remainingBudget <= 0 || !m_arenas[i]->lazySweepWithDeadline(dead
lineSeconds)) { |
| 786 // We couldn't finish the sweeping within the deadline. | 786 // We couldn't finish the sweeping within the deadline. |
| 787 // We request another idle task for the remaining sweeping. | 787 // We request another idle task for the remaining sweeping. |
| 788 scheduleIdleLazySweep(); | 788 scheduleIdleLazySweep(); |
| 789 sweepCompleted = false; | 789 sweepCompleted = false; |
| 790 break; | 790 break; |
| 791 } | 791 } |
| 792 } | 792 } |
| 793 | 793 |
| 794 accumulateSweepingTime(WTF::currentTimeMS() - startTime); | 794 accumulateSweepingTime(WTF::currentTimeMS() - startTime); |
| 795 } | 795 } |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 if (m_shouldFlushHeapDoesNotContainCache) { | 948 if (m_shouldFlushHeapDoesNotContainCache) { |
| 949 Heap::flushHeapDoesNotContainCache(); | 949 Heap::flushHeapDoesNotContainCache(); |
| 950 m_shouldFlushHeapDoesNotContainCache = false; | 950 m_shouldFlushHeapDoesNotContainCache = false; |
| 951 } | 951 } |
| 952 } | 952 } |
| 953 | 953 |
| 954 void ThreadState::makeConsistentForGC() | 954 void ThreadState::makeConsistentForGC() |
| 955 { | 955 { |
| 956 ASSERT(isInGC()); | 956 ASSERT(isInGC()); |
| 957 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); | 957 TRACE_EVENT0("blink_gc", "ThreadState::makeConsistentForGC"); |
| 958 for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) | 958 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 959 m_heaps[i]->makeConsistentForGC(); | 959 m_arenas[i]->makeConsistentForGC(); |
| 960 } | 960 } |
| 961 | 961 |
| 962 void ThreadState::makeConsistentForMutator() | 962 void ThreadState::makeConsistentForMutator() |
| 963 { | 963 { |
| 964 ASSERT(isInGC()); | 964 ASSERT(isInGC()); |
| 965 for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) | 965 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 966 m_heaps[i]->makeConsistentForMutator(); | 966 m_arenas[i]->makeConsistentForMutator(); |
| 967 } | 967 } |
| 968 | 968 |
| 969 void ThreadState::preGC() | 969 void ThreadState::preGC() |
| 970 { | 970 { |
| 971 ASSERT(!isInGC()); | 971 ASSERT(!isInGC()); |
| 972 setGCState(GCRunning); | 972 setGCState(GCRunning); |
| 973 makeConsistentForGC(); | 973 makeConsistentForGC(); |
| 974 flushHeapDoesNotContainCacheIfNeeded(); | 974 flushHeapDoesNotContainCacheIfNeeded(); |
| 975 clearHeapAges(); | 975 clearArenaAges(); |
| 976 } | 976 } |
| 977 | 977 |
| 978 void ThreadState::postGC(BlinkGC::GCType gcType) | 978 void ThreadState::postGC(BlinkGC::GCType gcType) |
| 979 { | 979 { |
| 980 ASSERT(isInGC()); | 980 ASSERT(isInGC()); |
| 981 for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) | 981 for (int i = 0; i < BlinkGC::NumberOfArenas; i++) |
| 982 m_heaps[i]->prepareForSweep(); | 982 m_arenas[i]->prepareForSweep(); |
| 983 | 983 |
| 984 if (gcType == BlinkGC::GCWithSweep) { | 984 if (gcType == BlinkGC::GCWithSweep) { |
| 985 setGCState(EagerSweepScheduled); | 985 setGCState(EagerSweepScheduled); |
| 986 } else if (gcType == BlinkGC::GCWithoutSweep) { | 986 } else if (gcType == BlinkGC::GCWithoutSweep) { |
| 987 setGCState(LazySweepScheduled); | 987 setGCState(LazySweepScheduled); |
| 988 } else { | 988 } else { |
| 989 takeSnapshot(SnapshotType::HeapSnapshot); | 989 takeSnapshot(SnapshotType::HeapSnapshot); |
| 990 | 990 |
| 991 // This unmarks all marked objects and marks all unmarked objects dead. | 991 // This unmarks all marked objects and marks all unmarked objects dead. |
| 992 makeConsistentForMutator(); | 992 makeConsistentForMutator(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1013 setGCState(Sweeping); | 1013 setGCState(Sweeping); |
| 1014 | 1014 |
| 1015 // Allocation is allowed during the pre-finalizers and destructors. | 1015 // Allocation is allowed during the pre-finalizers and destructors. |
| 1016 // However, they must not mutate an object graph in a way in which | 1016 // However, they must not mutate an object graph in a way in which |
| 1017 // a dead object gets resurrected. | 1017 // a dead object gets resurrected. |
| 1018 invokePreFinalizers(); | 1018 invokePreFinalizers(); |
| 1019 | 1019 |
| 1020 m_accumulatedSweepingTime = 0; | 1020 m_accumulatedSweepingTime = 0; |
| 1021 | 1021 |
| 1022 #if defined(ADDRESS_SANITIZER) | 1022 #if defined(ADDRESS_SANITIZER) |
| 1023 poisonEagerHeap(BlinkGC::SetPoison); | 1023 poisonEagerArena(BlinkGC::SetPoison); |
| 1024 #endif | 1024 #endif |
| 1025 eagerSweep(); | 1025 eagerSweep(); |
| 1026 #if defined(ADDRESS_SANITIZER) | 1026 #if defined(ADDRESS_SANITIZER) |
| 1027 poisonAllHeaps(); | 1027 poisonAllHeaps(); |
| 1028 #endif | 1028 #endif |
| 1029 | 1029 |
| 1030 if (previousGCState == EagerSweepScheduled) { | 1030 if (previousGCState == EagerSweepScheduled) { |
| 1031 // Eager sweeping should happen only in testing. | 1031 // Eager sweeping should happen only in testing. |
| 1032 completeSweep(); | 1032 completeSweep(); |
| 1033 } else { | 1033 } else { |
| 1034 // The default behavior is lazy sweeping. | 1034 // The default behavior is lazy sweeping. |
| 1035 scheduleIdleLazySweep(); | 1035 scheduleIdleLazySweep(); |
| 1036 } | 1036 } |
| 1037 } | 1037 } |
| 1038 | 1038 |
| 1039 #if defined(ADDRESS_SANITIZER) | 1039 #if defined(ADDRESS_SANITIZER) |
| 1040 void ThreadState::poisonAllHeaps() | 1040 void ThreadState::poisonAllHeaps() |
| 1041 { | 1041 { |
| 1042 // TODO(Oilpan): enable the poisoning always. | 1042 // TODO(Oilpan): enable the poisoning always. |
| 1043 #if ENABLE(OILPAN) | 1043 #if ENABLE(OILPAN) |
| 1044 // Unpoison the live objects remaining in the eager heaps.. | 1044 // Unpoison the live objects remaining in the eager arenas.. |
| 1045 poisonEagerHeap(BlinkGC::ClearPoison); | 1045 poisonEagerArena(BlinkGC::ClearPoison); |
| 1046 // ..along with poisoning all unmarked objects in the other heaps. | 1046 // ..along with poisoning all unmarked objects in the other arenas. |
| 1047 for (int i = 1; i < BlinkGC::NumberOfHeaps; i++) | 1047 for (int i = 1; i < BlinkGC::NumberOfArenas; i++) |
| 1048 m_heaps[i]->poisonHeap(BlinkGC::UnmarkedOnly, BlinkGC::SetPoison); | 1048 m_arenas[i]->poisonHeap(BlinkGC::UnmarkedOnly, BlinkGC::SetPoison); |
| 1049 #endif | 1049 #endif |
| 1050 } | 1050 } |
| 1051 | 1051 |
| 1052 void ThreadState::poisonEagerHeap(BlinkGC::Poisoning poisoning) | 1052 void ThreadState::poisonEagerArena(BlinkGC::Poisoning poisoning) |
| 1053 { | 1053 { |
| 1054 // TODO(Oilpan): enable the poisoning always. | 1054 // TODO(Oilpan): enable the poisoning always. |
| 1055 #if ENABLE(OILPAN) | 1055 #if ENABLE(OILPAN) |
| 1056 m_heaps[BlinkGC::EagerSweepHeapIndex]->poisonHeap(BlinkGC::MarkedAndUnmarked
, poisoning); | 1056 m_arenas[BlinkGC::EagerSweepArenaIndex]->poisonHeap(BlinkGC::MarkedAndUnmark
ed, poisoning); |
| 1057 #endif | 1057 #endif |
| 1058 } | 1058 } |
| 1059 #endif | 1059 #endif |
| 1060 | 1060 |
| 1061 void ThreadState::eagerSweep() | 1061 void ThreadState::eagerSweep() |
| 1062 { | 1062 { |
| 1063 ASSERT(checkThread()); | 1063 ASSERT(checkThread()); |
| 1064 // Some objects need to be finalized promptly and cannot be handled | 1064 // Some objects need to be finalized promptly and cannot be handled |
| 1065 // by lazy sweeping. Keep those in a designated heap and sweep it | 1065 // by lazy sweeping. Keep those in a designated heap and sweep it |
| 1066 // eagerly. | 1066 // eagerly. |
| 1067 ASSERT(isSweepingInProgress()); | 1067 ASSERT(isSweepingInProgress()); |
| 1068 | 1068 |
| 1069 // Mirroring the completeSweep() condition; see its comment. | 1069 // Mirroring the completeSweep() condition; see its comment. |
| 1070 if (sweepForbidden()) | 1070 if (sweepForbidden()) |
| 1071 return; | 1071 return; |
| 1072 | 1072 |
| 1073 SweepForbiddenScope scope(this); | 1073 SweepForbiddenScope scope(this); |
| 1074 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; | 1074 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; |
| 1075 | 1075 |
| 1076 double startTime = WTF::currentTimeMS(); | 1076 double startTime = WTF::currentTimeMS(); |
| 1077 m_heaps[BlinkGC::EagerSweepHeapIndex]->completeSweep(); | 1077 m_arenas[BlinkGC::EagerSweepArenaIndex]->completeSweep(); |
| 1078 accumulateSweepingTime(WTF::currentTimeMS() - startTime); | 1078 accumulateSweepingTime(WTF::currentTimeMS() - startTime); |
| 1079 } | 1079 } |
| 1080 | 1080 |
| 1081 void ThreadState::completeSweep() | 1081 void ThreadState::completeSweep() |
| 1082 { | 1082 { |
| 1083 ASSERT(checkThread()); | 1083 ASSERT(checkThread()); |
| 1084 // If we are not in a sweeping phase, there is nothing to do here. | 1084 // If we are not in a sweeping phase, there is nothing to do here. |
| 1085 if (!isSweepingInProgress()) | 1085 if (!isSweepingInProgress()) |
| 1086 return; | 1086 return; |
| 1087 | 1087 |
| 1088 // completeSweep() can be called recursively if finalizers can allocate | 1088 // completeSweep() can be called recursively if finalizers can allocate |
| 1089 // memory and the allocation triggers completeSweep(). This check prevents | 1089 // memory and the allocation triggers completeSweep(). This check prevents |
| 1090 // the sweeping from being executed recursively. | 1090 // the sweeping from being executed recursively. |
| 1091 if (sweepForbidden()) | 1091 if (sweepForbidden()) |
| 1092 return; | 1092 return; |
| 1093 | 1093 |
| 1094 SweepForbiddenScope scope(this); | 1094 SweepForbiddenScope scope(this); |
| 1095 { | 1095 { |
| 1096 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; | 1096 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; |
| 1097 | 1097 |
| 1098 TRACE_EVENT0("blink_gc,devtools.timeline", "ThreadState::completeSweep")
; | 1098 TRACE_EVENT0("blink_gc,devtools.timeline", "ThreadState::completeSweep")
; |
| 1099 double startTime = WTF::currentTimeMS(); | 1099 double startTime = WTF::currentTimeMS(); |
| 1100 | 1100 |
| 1101 static_assert(BlinkGC::EagerSweepHeapIndex == 0, "Eagerly swept heaps mu
st be processed first."); | 1101 static_assert(BlinkGC::EagerSweepArenaIndex == 0, "Eagerly swept arenas
must be processed first."); |
| 1102 for (int i = 0; i < BlinkGC::NumberOfHeaps; i++) | 1102 for (int i = 0; i < BlinkGC::NumberOfArenas; i++) |
| 1103 m_heaps[i]->completeSweep(); | 1103 m_arenas[i]->completeSweep(); |
| 1104 | 1104 |
| 1105 double timeForCompleteSweep = WTF::currentTimeMS() - startTime; | 1105 double timeForCompleteSweep = WTF::currentTimeMS() - startTime; |
| 1106 accumulateSweepingTime(timeForCompleteSweep); | 1106 accumulateSweepingTime(timeForCompleteSweep); |
| 1107 | 1107 |
| 1108 if (isMainThread()) { | 1108 if (isMainThread()) { |
| 1109 DEFINE_STATIC_LOCAL(CustomCountHistogram, completeSweepHistogram, ("
BlinkGC.CompleteSweep", 1, 10 * 1000, 50)); | 1109 DEFINE_STATIC_LOCAL(CustomCountHistogram, completeSweepHistogram, ("
BlinkGC.CompleteSweep", 1, 10 * 1000, 50)); |
| 1110 completeSweepHistogram.count(timeForCompleteSweep); | 1110 completeSweepHistogram.count(timeForCompleteSweep); |
| 1111 } | 1111 } |
| 1112 } | 1112 } |
| 1113 | 1113 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 scheduleIdleGC(); | 1155 scheduleIdleGC(); |
| 1156 break; | 1156 break; |
| 1157 default: | 1157 default: |
| 1158 ASSERT_NOT_REACHED(); | 1158 ASSERT_NOT_REACHED(); |
| 1159 } | 1159 } |
| 1160 } | 1160 } |
| 1161 | 1161 |
| 1162 void ThreadState::prepareForThreadStateTermination() | 1162 void ThreadState::prepareForThreadStateTermination() |
| 1163 { | 1163 { |
| 1164 ASSERT(checkThread()); | 1164 ASSERT(checkThread()); |
| 1165 for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) | 1165 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 1166 m_heaps[i]->prepareHeapForTermination(); | 1166 m_arenas[i]->prepareHeapForTermination(); |
| 1167 } | 1167 } |
| 1168 | 1168 |
| 1169 #if ENABLE(ASSERT) | 1169 #if ENABLE(ASSERT) |
| 1170 BasePage* ThreadState::findPageFromAddress(Address address) | 1170 BasePage* ThreadState::findPageFromAddress(Address address) |
| 1171 { | 1171 { |
| 1172 for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) { | 1172 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) { |
| 1173 if (BasePage* page = m_heaps[i]->findPageFromAddress(address)) | 1173 if (BasePage* page = m_arenas[i]->findPageFromAddress(address)) |
| 1174 return page; | 1174 return page; |
| 1175 } | 1175 } |
| 1176 return nullptr; | 1176 return nullptr; |
| 1177 } | 1177 } |
| 1178 #endif | 1178 #endif |
| 1179 | 1179 |
| 1180 size_t ThreadState::objectPayloadSizeForTesting() | 1180 size_t ThreadState::objectPayloadSizeForTesting() |
| 1181 { | 1181 { |
| 1182 size_t objectPayloadSize = 0; | 1182 size_t objectPayloadSize = 0; |
| 1183 for (int i = 0; i < BlinkGC::NumberOfHeaps; ++i) | 1183 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
| 1184 objectPayloadSize += m_heaps[i]->objectPayloadSizeForTesting(); | 1184 objectPayloadSize += m_arenas[i]->objectPayloadSizeForTesting(); |
| 1185 return objectPayloadSize; | 1185 return objectPayloadSize; |
| 1186 } | 1186 } |
| 1187 | 1187 |
| 1188 bool ThreadState::stopThreads() | 1188 bool ThreadState::stopThreads() |
| 1189 { | 1189 { |
| 1190 return s_safePointBarrier->parkOthers(); | 1190 return s_safePointBarrier->parkOthers(); |
| 1191 } | 1191 } |
| 1192 | 1192 |
| 1193 void ThreadState::resumeThreads() | 1193 void ThreadState::resumeThreads() |
| 1194 { | 1194 { |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1419 m_orderedPreFinalizers.remove(entry); | 1419 m_orderedPreFinalizers.remove(entry); |
| 1420 } while (!done); | 1420 } while (!done); |
| 1421 } | 1421 } |
| 1422 if (isMainThread()) { | 1422 if (isMainThread()) { |
| 1423 double timeForInvokingPreFinalizers = WTF::currentTimeMS() - startTime; | 1423 double timeForInvokingPreFinalizers = WTF::currentTimeMS() - startTime; |
| 1424 DEFINE_STATIC_LOCAL(CustomCountHistogram, preFinalizersHistogram, ("Blin
kGC.TimeForInvokingPreFinalizers", 1, 10 * 1000, 50)); | 1424 DEFINE_STATIC_LOCAL(CustomCountHistogram, preFinalizersHistogram, ("Blin
kGC.TimeForInvokingPreFinalizers", 1, 10 * 1000, 50)); |
| 1425 preFinalizersHistogram.count(timeForInvokingPreFinalizers); | 1425 preFinalizersHistogram.count(timeForInvokingPreFinalizers); |
| 1426 } | 1426 } |
| 1427 } | 1427 } |
| 1428 | 1428 |
| 1429 void ThreadState::clearHeapAges() | 1429 void ThreadState::clearArenaAges() |
| 1430 { | 1430 { |
| 1431 memset(m_heapAges, 0, sizeof(size_t) * BlinkGC::NumberOfHeaps); | 1431 memset(m_arenaAges, 0, sizeof(size_t) * BlinkGC::NumberOfArenas); |
| 1432 memset(m_likelyToBePromptlyFreed.get(), 0, sizeof(int) * likelyToBePromptlyF
reedArraySize); | 1432 memset(m_likelyToBePromptlyFreed.get(), 0, sizeof(int) * likelyToBePromptlyF
reedArraySize); |
| 1433 m_currentHeapAges = 0; | 1433 m_currentArenaAges = 0; |
| 1434 } | 1434 } |
| 1435 | 1435 |
| 1436 int ThreadState::heapIndexOfVectorHeapLeastRecentlyExpanded(int beginHeapIndex,
int endHeapIndex) | 1436 int ThreadState::arenaIndexOfVectorArenaLeastRecentlyExpanded(int beginArenaInde
x, int endArenaIndex) |
| 1437 { | 1437 { |
| 1438 size_t minHeapAge = m_heapAges[beginHeapIndex]; | 1438 size_t minArenaAge = m_arenaAges[beginArenaIndex]; |
| 1439 int heapIndexWithMinHeapAge = beginHeapIndex; | 1439 int arenaIndexWithMinArenaAge = beginArenaIndex; |
| 1440 for (int heapIndex = beginHeapIndex + 1; heapIndex <= endHeapIndex; heapInde
x++) { | 1440 for (int arenaIndex = beginArenaIndex + 1; arenaIndex <= endArenaIndex; aren
aIndex++) { |
| 1441 if (m_heapAges[heapIndex] < minHeapAge) { | 1441 if (m_arenaAges[arenaIndex] < minArenaAge) { |
| 1442 minHeapAge = m_heapAges[heapIndex]; | 1442 minArenaAge = m_arenaAges[arenaIndex]; |
| 1443 heapIndexWithMinHeapAge = heapIndex; | 1443 arenaIndexWithMinArenaAge = arenaIndex; |
| 1444 } | 1444 } |
| 1445 } | 1445 } |
| 1446 ASSERT(isVectorHeapIndex(heapIndexWithMinHeapAge)); | 1446 ASSERT(isVectorArenaIndex(arenaIndexWithMinArenaAge)); |
| 1447 return heapIndexWithMinHeapAge; | 1447 return arenaIndexWithMinArenaAge; |
| 1448 } | 1448 } |
| 1449 | 1449 |
| 1450 BaseHeap* ThreadState::expandedVectorBackingHeap(size_t gcInfoIndex) | 1450 BaseArena* ThreadState::expandedVectorBackingHeap(size_t gcInfoIndex) |
| 1451 { | 1451 { |
| 1452 ASSERT(checkThread()); | 1452 ASSERT(checkThread()); |
| 1453 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; | 1453 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; |
| 1454 --m_likelyToBePromptlyFreed[entryIndex]; | 1454 --m_likelyToBePromptlyFreed[entryIndex]; |
| 1455 int heapIndex = m_vectorBackingHeapIndex; | 1455 int arenaIndex = m_vectorBackingArenaIndex; |
| 1456 m_heapAges[heapIndex] = ++m_currentHeapAges; | 1456 m_arenaAges[arenaIndex] = ++m_currentArenaAges; |
| 1457 m_vectorBackingHeapIndex = heapIndexOfVectorHeapLeastRecentlyExpanded(BlinkG
C::Vector1HeapIndex, BlinkGC::Vector4HeapIndex); | 1457 m_vectorBackingArenaIndex = arenaIndexOfVectorArenaLeastRecentlyExpanded(Bli
nkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex); |
| 1458 return m_heaps[heapIndex]; | 1458 return m_arenas[arenaIndex]; |
| 1459 } | 1459 } |
| 1460 | 1460 |
| 1461 void ThreadState::allocationPointAdjusted(int heapIndex) | 1461 void ThreadState::allocationPointAdjusted(int arenaIndex) |
| 1462 { | 1462 { |
| 1463 m_heapAges[heapIndex] = ++m_currentHeapAges; | 1463 m_arenaAges[arenaIndex] = ++m_currentArenaAges; |
| 1464 if (m_vectorBackingHeapIndex == heapIndex) | 1464 if (m_vectorBackingArenaIndex == arenaIndex) |
| 1465 m_vectorBackingHeapIndex = heapIndexOfVectorHeapLeastRecentlyExpanded(Bl
inkGC::Vector1HeapIndex, BlinkGC::Vector4HeapIndex); | 1465 m_vectorBackingArenaIndex = arenaIndexOfVectorArenaLeastRecentlyExpanded
(BlinkGC::Vector1ArenaIndex, BlinkGC::Vector4ArenaIndex); |
| 1466 } | 1466 } |
| 1467 | 1467 |
| 1468 void ThreadState::promptlyFreed(size_t gcInfoIndex) | 1468 void ThreadState::promptlyFreed(size_t gcInfoIndex) |
| 1469 { | 1469 { |
| 1470 ASSERT(checkThread()); | 1470 ASSERT(checkThread()); |
| 1471 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; | 1471 size_t entryIndex = gcInfoIndex & likelyToBePromptlyFreedArrayMask; |
| 1472 // See the comment in vectorBackingHeap() for why this is +3. | 1472 // See the comment in vectorBackingArena() for why this is +3. |
| 1473 m_likelyToBePromptlyFreed[entryIndex] += 3; | 1473 m_likelyToBePromptlyFreed[entryIndex] += 3; |
| 1474 } | 1474 } |
| 1475 | 1475 |
| 1476 void ThreadState::takeSnapshot(SnapshotType type) | 1476 void ThreadState::takeSnapshot(SnapshotType type) |
| 1477 { | 1477 { |
| 1478 ASSERT(isInGC()); | 1478 ASSERT(isInGC()); |
| 1479 | 1479 |
| 1480 // 0 is used as index for freelist entries. Objects are indexed 1 to | 1480 // 0 is used as index for freelist entries. Objects are indexed 1 to |
| 1481 // gcInfoIndex. | 1481 // gcInfoIndex. |
| 1482 GCSnapshotInfo info(GCInfoTable::gcInfoIndex() + 1); | 1482 GCSnapshotInfo info(GCInfoTable::gcInfoIndex() + 1); |
| 1483 String threadDumpName = String::format("blink_gc/thread_%lu", static_cast<un
signed long>(m_thread)); | 1483 String threadDumpName = String::format("blink_gc/thread_%lu", static_cast<un
signed long>(m_thread)); |
| 1484 const String heapsDumpName = threadDumpName + "/heaps"; | 1484 const String heapsDumpName = threadDumpName + "/heaps"; |
| 1485 const String classesDumpName = threadDumpName + "/classes"; | 1485 const String classesDumpName = threadDumpName + "/classes"; |
| 1486 | 1486 |
| 1487 int numberOfHeapsReported = 0; | 1487 int numberOfHeapsReported = 0; |
| 1488 #define SNAPSHOT_HEAP(HeapType)
\ | 1488 #define SNAPSHOT_HEAP(ArenaType)
\ |
| 1489 {
\ | 1489 {
\ |
| 1490 numberOfHeapsReported++;
\ | 1490 numberOfHeapsReported++;
\ |
| 1491 switch (type) {
\ | 1491 switch (type) {
\ |
| 1492 case SnapshotType::HeapSnapshot:
\ | 1492 case SnapshotType::HeapSnapshot:
\ |
| 1493 m_heaps[BlinkGC::HeapType##HeapIndex]->takeSnapshot(heapsDumpName +
"/" #HeapType, info); \ | 1493 m_arenas[BlinkGC::ArenaType##ArenaIndex]->takeSnapshot(heapsDumpName
+ "/" #ArenaType, info); \ |
| 1494 break;
\ | 1494 break;
\ |
| 1495 case SnapshotType::FreelistSnapshot:
\ | 1495 case SnapshotType::FreelistSnapshot:
\ |
| 1496 m_heaps[BlinkGC::HeapType##HeapIndex]->takeFreelistSnapshot(heapsDum
pName + "/" #HeapType); \ | 1496 m_arenas[BlinkGC::ArenaType##ArenaIndex]->takeFreelistSnapshot(heaps
DumpName + "/" #ArenaType); \ |
| 1497 break;
\ | 1497 break;
\ |
| 1498 default:
\ | 1498 default:
\ |
| 1499 ASSERT_NOT_REACHED();
\ | 1499 ASSERT_NOT_REACHED();
\ |
| 1500 }
\ | 1500 }
\ |
| 1501 } | 1501 } |
| 1502 | 1502 |
| 1503 SNAPSHOT_HEAP(NormalPage1); | 1503 SNAPSHOT_HEAP(NormalPage1); |
| 1504 SNAPSHOT_HEAP(NormalPage2); | 1504 SNAPSHOT_HEAP(NormalPage2); |
| 1505 SNAPSHOT_HEAP(NormalPage3); | 1505 SNAPSHOT_HEAP(NormalPage3); |
| 1506 SNAPSHOT_HEAP(NormalPage4); | 1506 SNAPSHOT_HEAP(NormalPage4); |
| 1507 SNAPSHOT_HEAP(EagerSweep); | 1507 SNAPSHOT_HEAP(EagerSweep); |
| 1508 SNAPSHOT_HEAP(Vector1); | 1508 SNAPSHOT_HEAP(Vector1); |
| 1509 SNAPSHOT_HEAP(Vector2); | 1509 SNAPSHOT_HEAP(Vector2); |
| 1510 SNAPSHOT_HEAP(Vector3); | 1510 SNAPSHOT_HEAP(Vector3); |
| 1511 SNAPSHOT_HEAP(Vector4); | 1511 SNAPSHOT_HEAP(Vector4); |
| 1512 SNAPSHOT_HEAP(InlineVector); | 1512 SNAPSHOT_HEAP(InlineVector); |
| 1513 SNAPSHOT_HEAP(HashTable); | 1513 SNAPSHOT_HEAP(HashTable); |
| 1514 SNAPSHOT_HEAP(LargeObject); | 1514 SNAPSHOT_HEAP(LargeObject); |
| 1515 FOR_EACH_TYPED_HEAP(SNAPSHOT_HEAP); | 1515 FOR_EACH_TYPED_ARENA(SNAPSHOT_HEAP); |
| 1516 | 1516 |
| 1517 ASSERT(numberOfHeapsReported == BlinkGC::NumberOfHeaps); | 1517 ASSERT(numberOfHeapsReported == BlinkGC::NumberOfArenas); |
| 1518 | 1518 |
| 1519 #undef SNAPSHOT_HEAP | 1519 #undef SNAPSHOT_HEAP |
| 1520 | 1520 |
| 1521 if (type == SnapshotType::FreelistSnapshot) | 1521 if (type == SnapshotType::FreelistSnapshot) |
| 1522 return; | 1522 return; |
| 1523 | 1523 |
| 1524 size_t totalLiveCount = 0; | 1524 size_t totalLiveCount = 0; |
| 1525 size_t totalDeadCount = 0; | 1525 size_t totalDeadCount = 0; |
| 1526 size_t totalLiveSize = 0; | 1526 size_t totalLiveSize = 0; |
| 1527 size_t totalDeadSize = 0; | 1527 size_t totalDeadSize = 0; |
| 1528 for (size_t gcInfoIndex = 1; gcInfoIndex <= GCInfoTable::gcInfoIndex(); ++gc
InfoIndex) { | 1528 for (size_t gcInfoIndex = 1; gcInfoIndex <= GCInfoTable::gcInfoIndex(); ++gc
InfoIndex) { |
| 1529 totalLiveCount += info.liveCount[gcInfoIndex]; | 1529 totalLiveCount += info.liveCount[gcInfoIndex]; |
| 1530 totalDeadCount += info.deadCount[gcInfoIndex]; | 1530 totalDeadCount += info.deadCount[gcInfoIndex]; |
| 1531 totalLiveSize += info.liveSize[gcInfoIndex]; | 1531 totalLiveSize += info.liveSize[gcInfoIndex]; |
| 1532 totalDeadSize += info.deadSize[gcInfoIndex]; | 1532 totalDeadSize += info.deadSize[gcInfoIndex]; |
| 1533 } | 1533 } |
| 1534 | 1534 |
| 1535 WebMemoryAllocatorDump* threadDump = BlinkGCMemoryDumpProvider::instance()->
createMemoryAllocatorDumpForCurrentGC(threadDumpName); | 1535 WebMemoryAllocatorDump* threadDump = BlinkGCMemoryDumpProvider::instance()->
createMemoryAllocatorDumpForCurrentGC(threadDumpName); |
| 1536 threadDump->addScalar("live_count", "objects", totalLiveCount); | 1536 threadDump->addScalar("live_count", "objects", totalLiveCount); |
| 1537 threadDump->addScalar("dead_count", "objects", totalDeadCount); | 1537 threadDump->addScalar("dead_count", "objects", totalDeadCount); |
| 1538 threadDump->addScalar("live_size", "bytes", totalLiveSize); | 1538 threadDump->addScalar("live_size", "bytes", totalLiveSize); |
| 1539 threadDump->addScalar("dead_size", "bytes", totalDeadSize); | 1539 threadDump->addScalar("dead_size", "bytes", totalDeadSize); |
| 1540 | 1540 |
| 1541 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c
reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); | 1541 WebMemoryAllocatorDump* heapsDump = BlinkGCMemoryDumpProvider::instance()->c
reateMemoryAllocatorDumpForCurrentGC(heapsDumpName); |
| 1542 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()-
>createMemoryAllocatorDumpForCurrentGC(classesDumpName); | 1542 WebMemoryAllocatorDump* classesDump = BlinkGCMemoryDumpProvider::instance()-
>createMemoryAllocatorDumpForCurrentGC(classesDumpName); |
| 1543 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners
hipEdge(classesDump->guid(), heapsDump->guid()); | 1543 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOwners
hipEdge(classesDump->guid(), heapsDump->guid()); |
| 1544 } | 1544 } |
| 1545 | 1545 |
| 1546 } // namespace blink | 1546 } // namespace blink |
| OLD | NEW |