| 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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 m_sweepForbidden(false), | 110 m_sweepForbidden(false), |
| 111 m_noAllocationCount(0), | 111 m_noAllocationCount(0), |
| 112 m_gcForbiddenCount(0), | 112 m_gcForbiddenCount(0), |
| 113 m_mixinsBeingConstructedCount(0), | 113 m_mixinsBeingConstructedCount(0), |
| 114 m_accumulatedSweepingTime(0), | 114 m_accumulatedSweepingTime(0), |
| 115 m_vectorBackingArenaIndex(BlinkGC::Vector1ArenaIndex), | 115 m_vectorBackingArenaIndex(BlinkGC::Vector1ArenaIndex), |
| 116 m_currentArenaAges(0), | 116 m_currentArenaAges(0), |
| 117 m_gcMixinMarker(nullptr), | 117 m_gcMixinMarker(nullptr), |
| 118 m_shouldFlushHeapDoesNotContainCache(false), | 118 m_shouldFlushHeapDoesNotContainCache(false), |
| 119 m_gcState(NoGCScheduled), | 119 m_gcState(NoGCScheduled), |
| 120 m_threadLocalWeakCallbackStack(CallbackStack::create()), | |
| 121 m_isolate(nullptr), | 120 m_isolate(nullptr), |
| 122 m_traceDOMWrappers(nullptr), | 121 m_traceDOMWrappers(nullptr), |
| 123 m_invalidateDeadObjectsInWrappersMarkingDeque(nullptr), | 122 m_invalidateDeadObjectsInWrappersMarkingDeque(nullptr), |
| 124 #if defined(ADDRESS_SANITIZER) | 123 #if defined(ADDRESS_SANITIZER) |
| 125 m_asanFakeStack(__asan_get_current_fake_stack()), | 124 m_asanFakeStack(__asan_get_current_fake_stack()), |
| 126 #endif | 125 #endif |
| 127 #if defined(LEAK_SANITIZER) | 126 #if defined(LEAK_SANITIZER) |
| 128 m_disabledStaticPersistentsRegistration(0), | 127 m_disabledStaticPersistentsRegistration(0), |
| 129 #endif | 128 #endif |
| 130 m_allocatedObjectSize(0), | 129 m_allocatedObjectSize(0), |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 m_traceDOMWrappers(m_isolate, visitor); | 297 m_traceDOMWrappers(m_isolate, visitor); |
| 299 } | 298 } |
| 300 } | 299 } |
| 301 | 300 |
| 302 ThreadState::GCSnapshotInfo::GCSnapshotInfo(size_t numObjectTypes) | 301 ThreadState::GCSnapshotInfo::GCSnapshotInfo(size_t numObjectTypes) |
| 303 : liveCount(Vector<int>(numObjectTypes)), | 302 : liveCount(Vector<int>(numObjectTypes)), |
| 304 deadCount(Vector<int>(numObjectTypes)), | 303 deadCount(Vector<int>(numObjectTypes)), |
| 305 liveSize(Vector<size_t>(numObjectTypes)), | 304 liveSize(Vector<size_t>(numObjectTypes)), |
| 306 deadSize(Vector<size_t>(numObjectTypes)) {} | 305 deadSize(Vector<size_t>(numObjectTypes)) {} |
| 307 | 306 |
| 308 void ThreadState::pushThreadLocalWeakCallback(void* object, | |
| 309 WeakCallback callback) { | |
| 310 CallbackStack::Item* slot = m_threadLocalWeakCallbackStack->allocateEntry(); | |
| 311 *slot = CallbackStack::Item(object, callback); | |
| 312 } | |
| 313 | |
| 314 bool ThreadState::popAndInvokeThreadLocalWeakCallback(Visitor* visitor) { | |
| 315 ASSERT(checkThread()); | |
| 316 if (CallbackStack::Item* item = m_threadLocalWeakCallbackStack->pop()) { | |
| 317 item->call(visitor); | |
| 318 return true; | |
| 319 } | |
| 320 return false; | |
| 321 } | |
| 322 | |
| 323 void ThreadState::threadLocalWeakProcessing() { | |
| 324 ASSERT(checkThread()); | |
| 325 ASSERT(!sweepForbidden()); | |
| 326 TRACE_EVENT0("blink_gc", "ThreadState::threadLocalWeakProcessing"); | |
| 327 double startTime = WTF::currentTimeMS(); | |
| 328 | |
| 329 SweepForbiddenScope sweepForbiddenScope(this); | |
| 330 ScriptForbiddenIfMainThreadScope scriptForbiddenScope; | |
| 331 | |
| 332 // Disallow allocation during weak processing. | |
| 333 // It would be technically safe to allow allocations, but it is unsafe | |
| 334 // to mutate an object graph in a way in which a dead object gets | |
| 335 // resurrected or mutate a HashTable (because HashTable's weak processing | |
| 336 // assumes that the HashTable hasn't been mutated since the latest marking). | |
| 337 // Due to the complexity, we just forbid allocations. | |
| 338 NoAllocationScope noAllocationScope(this); | |
| 339 | |
| 340 GCForbiddenScope gcForbiddenScope(this); | |
| 341 std::unique_ptr<Visitor> visitor = | |
| 342 Visitor::create(this, Visitor::WeakProcessing); | |
| 343 | |
| 344 // Perform thread-specific weak processing. | |
| 345 while (popAndInvokeThreadLocalWeakCallback(visitor.get())) { | |
| 346 } | |
| 347 | |
| 348 m_threadLocalWeakCallbackStack->decommit(); | |
| 349 | |
| 350 if (isMainThread()) { | |
| 351 double timeForThreadLocalWeakProcessing = WTF::currentTimeMS() - startTime; | |
| 352 DEFINE_STATIC_LOCAL( | |
| 353 CustomCountHistogram, timeForWeakHistogram, | |
| 354 ("BlinkGC.TimeForThreadLocalWeakProcessing", 1, 10 * 1000, 50)); | |
| 355 timeForWeakHistogram.count(timeForThreadLocalWeakProcessing); | |
| 356 } | |
| 357 } | |
| 358 | |
| 359 size_t ThreadState::totalMemorySize() { | 307 size_t ThreadState::totalMemorySize() { |
| 360 return m_heap->heapStats().allocatedObjectSize() + | 308 return m_heap->heapStats().allocatedObjectSize() + |
| 361 m_heap->heapStats().markedObjectSize() + | 309 m_heap->heapStats().markedObjectSize() + |
| 362 WTF::Partitions::totalSizeOfCommittedPages(); | 310 WTF::Partitions::totalSizeOfCommittedPages(); |
| 363 } | 311 } |
| 364 | 312 |
| 365 size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, | 313 size_t ThreadState::estimatedLiveSize(size_t estimationBaseSize, |
| 366 size_t sizeAtLastGC) { | 314 size_t sizeAtLastGC) { |
| 367 if (m_heap->heapStats().wrapperCountAtLastGC() == 0) { | 315 if (m_heap->heapStats().wrapperCountAtLastGC() == 0) { |
| 368 // We'll reach here only before hitting the first GC. | 316 // We'll reach here only before hitting the first GC. |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 | 851 |
| 904 void ThreadState::preGC() { | 852 void ThreadState::preGC() { |
| 905 if (m_isolate && m_performCleanup) | 853 if (m_isolate && m_performCleanup) |
| 906 m_performCleanup(m_isolate); | 854 m_performCleanup(m_isolate); |
| 907 | 855 |
| 908 ASSERT(!isInGC()); | 856 ASSERT(!isInGC()); |
| 909 setGCState(GCRunning); | 857 setGCState(GCRunning); |
| 910 makeConsistentForGC(); | 858 makeConsistentForGC(); |
| 911 flushHeapDoesNotContainCacheIfNeeded(); | 859 flushHeapDoesNotContainCacheIfNeeded(); |
| 912 clearArenaAges(); | 860 clearArenaAges(); |
| 913 | |
| 914 // It is possible, albeit rare, for a thread to be kept | |
| 915 // at a safepoint across multiple GCs, as resuming all attached | |
| 916 // threads after the "global" GC phases will contend for the shared | |
| 917 // safepoint barrier mutexes etc, which can additionally delay | |
| 918 // a thread. Enough so that another thread may initiate | |
| 919 // a new GC before this has happened. | |
| 920 // | |
| 921 // In which case the parked thread's ThreadState will have unprocessed | |
| 922 // entries on its local weak callback stack when that later GC goes | |
| 923 // ahead. Clear out and invalidate the stack now, as the thread | |
| 924 // should only process callbacks that's found to be reachable by | |
| 925 // the latest GC, when it eventually gets to next perform | |
| 926 // thread-local weak processing. | |
| 927 m_threadLocalWeakCallbackStack->decommit(); | |
| 928 m_threadLocalWeakCallbackStack->commit(); | |
| 929 } | 861 } |
| 930 | 862 |
| 931 void ThreadState::postGC(BlinkGC::GCType gcType) { | 863 void ThreadState::postGC(BlinkGC::GCType gcType) { |
| 932 if (m_invalidateDeadObjectsInWrappersMarkingDeque) | 864 if (m_invalidateDeadObjectsInWrappersMarkingDeque) |
| 933 m_invalidateDeadObjectsInWrappersMarkingDeque(m_isolate); | 865 m_invalidateDeadObjectsInWrappersMarkingDeque(m_isolate); |
| 934 | 866 |
| 935 ASSERT(isInGC()); | 867 DCHECK(isInGC()); |
| 868 DCHECK(checkThread()); |
| 936 for (int i = 0; i < BlinkGC::NumberOfArenas; i++) | 869 for (int i = 0; i < BlinkGC::NumberOfArenas; i++) |
| 937 m_arenas[i]->prepareForSweep(); | 870 m_arenas[i]->prepareForSweep(); |
| 938 | 871 |
| 939 if (gcType == BlinkGC::TakeSnapshot) { | 872 if (gcType == BlinkGC::TakeSnapshot) { |
| 940 takeSnapshot(SnapshotType::HeapSnapshot); | 873 takeSnapshot(SnapshotType::HeapSnapshot); |
| 941 | 874 |
| 942 // This unmarks all marked objects and marks all unmarked objects dead. | 875 // This unmarks all marked objects and marks all unmarked objects dead. |
| 943 makeConsistentForMutator(); | 876 makeConsistentForMutator(); |
| 944 | 877 |
| 945 takeSnapshot(SnapshotType::FreelistSnapshot); | 878 takeSnapshot(SnapshotType::FreelistSnapshot); |
| 946 | 879 |
| 947 // Force setting NoGCScheduled to circumvent checkThread() | 880 // Force setting NoGCScheduled to circumvent checkThread() |
| 948 // in setGCState(). | 881 // in setGCState(). |
| 949 m_gcState = NoGCScheduled; | 882 m_gcState = NoGCScheduled; |
| 950 return; | 883 return; |
| 951 } | 884 } |
| 952 | |
| 953 ASSERT(checkThread()); | |
| 954 | |
| 955 threadLocalWeakProcessing(); | |
| 956 } | 885 } |
| 957 | 886 |
| 958 void ThreadState::preSweep(BlinkGC::GCType gcType) { | 887 void ThreadState::preSweep(BlinkGC::GCType gcType) { |
| 959 if (gcState() == NoGCScheduled) | 888 if (gcState() == NoGCScheduled) |
| 960 return; | 889 return; |
| 961 // We have to set the GCState to Sweeping before calling pre-finalizers | 890 // We have to set the GCState to Sweeping before calling pre-finalizers |
| 962 // to disallow a GC during the pre-finalizers. | 891 // to disallow a GC during the pre-finalizers. |
| 963 setGCState(Sweeping); | 892 setGCState(Sweeping); |
| 964 | 893 |
| 965 // Allocation is allowed during the pre-finalizers and destructors. | 894 // Allocation is allowed during the pre-finalizers and destructors. |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1639 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, | 1568 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, |
| 1640 BlinkGC::ForcedGC); | 1569 BlinkGC::ForcedGC); |
| 1641 size_t liveObjects = heap().heapStats().markedObjectSize(); | 1570 size_t liveObjects = heap().heapStats().markedObjectSize(); |
| 1642 if (liveObjects == previousLiveObjects) | 1571 if (liveObjects == previousLiveObjects) |
| 1643 break; | 1572 break; |
| 1644 previousLiveObjects = liveObjects; | 1573 previousLiveObjects = liveObjects; |
| 1645 } | 1574 } |
| 1646 } | 1575 } |
| 1647 | 1576 |
| 1648 } // namespace blink | 1577 } // namespace blink |
| OLD | NEW |