| 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 1228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) | 1239 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) |
| 1240 page->getStats(scannedStats); | 1240 page->getStats(scannedStats); |
| 1241 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur
rent = current->next()) | 1241 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current; cur
rent = current->next()) |
| 1242 current->getStats(scannedStats); | 1242 current->getStats(scannedStats); |
| 1243 } | 1243 } |
| 1244 #endif | 1244 #endif |
| 1245 | 1245 |
| 1246 template<typename Header> | 1246 template<typename Header> |
| 1247 void ThreadHeap<Header>::sweepNormalPages(HeapStats* stats) | 1247 void ThreadHeap<Header>::sweepNormalPages(HeapStats* stats) |
| 1248 { | 1248 { |
| 1249 TRACE_EVENT0("blink_gc", "ThreadHeap::sweepNormalPages"); |
| 1249 HeapPage<Header>* page = m_firstPage; | 1250 HeapPage<Header>* page = m_firstPage; |
| 1250 HeapPage<Header>** previousNext = &m_firstPage; | 1251 HeapPage<Header>** previousNext = &m_firstPage; |
| 1251 HeapPage<Header>* previous = 0; | 1252 HeapPage<Header>* previous = 0; |
| 1252 while (page) { | 1253 while (page) { |
| 1253 page->resetPromptlyFreedSize(); | 1254 page->resetPromptlyFreedSize(); |
| 1254 if (page->isEmpty()) { | 1255 if (page->isEmpty()) { |
| 1255 HeapPage<Header>* unused = page; | 1256 HeapPage<Header>* unused = page; |
| 1256 if (unused == m_mergePoint) | 1257 if (unused == m_mergePoint) |
| 1257 m_mergePoint = previous; | 1258 m_mergePoint = previous; |
| 1258 page = page->next(); | 1259 page = page->next(); |
| 1259 HeapPage<Header>::unlink(this, unused, previousNext); | 1260 HeapPage<Header>::unlink(this, unused, previousNext); |
| 1260 --m_numberOfNormalPages; | 1261 --m_numberOfNormalPages; |
| 1261 } else { | 1262 } else { |
| 1262 page->sweep(stats, this); | 1263 page->sweep(stats, this); |
| 1263 previousNext = &page->m_next; | 1264 previousNext = &page->m_next; |
| 1264 previous = page; | 1265 previous = page; |
| 1265 page = page->next(); | 1266 page = page->next(); |
| 1266 } | 1267 } |
| 1267 } | 1268 } |
| 1268 } | 1269 } |
| 1269 | 1270 |
| 1270 template<typename Header> | 1271 template<typename Header> |
| 1271 void ThreadHeap<Header>::sweepLargePages(HeapStats* stats) | 1272 void ThreadHeap<Header>::sweepLargePages(HeapStats* stats) |
| 1272 { | 1273 { |
| 1274 TRACE_EVENT0("blink_gc", "ThreadHeap::sweepLargePages"); |
| 1273 LargeHeapObject<Header>** previousNext = &m_firstLargeHeapObject; | 1275 LargeHeapObject<Header>** previousNext = &m_firstLargeHeapObject; |
| 1274 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current;) { | 1276 for (LargeHeapObject<Header>* current = m_firstLargeHeapObject; current;) { |
| 1275 if (current->isMarked()) { | 1277 if (current->isMarked()) { |
| 1276 stats->increaseAllocatedSpace(current->size()); | 1278 stats->increaseAllocatedSpace(current->size()); |
| 1277 stats->increaseObjectSpace(current->payloadSize()); | 1279 stats->increaseObjectSpace(current->payloadSize()); |
| 1278 current->unmark(); | 1280 current->unmark(); |
| 1279 previousNext = ¤t->m_next; | 1281 previousNext = ¤t->m_next; |
| 1280 current = current->next(); | 1282 current = current->next(); |
| 1281 } else { | 1283 } else { |
| 1282 LargeHeapObject<Header>* next = current->next(); | 1284 LargeHeapObject<Header>* next = current->next(); |
| (...skipping 1171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2454 #endif | 2456 #endif |
| 2455 | 2457 |
| 2456 void Heap::prepareForGC() | 2458 void Heap::prepareForGC() |
| 2457 { | 2459 { |
| 2458 ASSERT(ThreadState::isAnyThreadInGC()); | 2460 ASSERT(ThreadState::isAnyThreadInGC()); |
| 2459 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); | 2461 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); |
| 2460 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) | 2462 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) |
| 2461 (*it)->prepareForGC(); | 2463 (*it)->prepareForGC(); |
| 2462 } | 2464 } |
| 2463 | 2465 |
| 2464 void Heap::collectGarbage(ThreadState::StackState stackState) | 2466 void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::Cause
OfGC cause) |
| 2465 { | 2467 { |
| 2466 ThreadState* state = ThreadState::current(); | 2468 ThreadState* state = ThreadState::current(); |
| 2467 state->clearGCRequested(); | 2469 state->clearGCRequested(); |
| 2468 | 2470 |
| 2469 GCScope gcScope(stackState); | 2471 GCScope gcScope(stackState); |
| 2470 // Check if we successfully parked the other threads. If not we bail out of
the GC. | 2472 // Check if we successfully parked the other threads. If not we bail out of
the GC. |
| 2471 if (!gcScope.allThreadsParked()) { | 2473 if (!gcScope.allThreadsParked()) { |
| 2472 ThreadState::current()->setGCRequested(); | 2474 ThreadState::current()->setGCRequested(); |
| 2473 return; | 2475 return; |
| 2474 } | 2476 } |
| 2475 | 2477 |
| 2476 if (state->isMainThread()) | 2478 if (state->isMainThread()) |
| 2477 ScriptForbiddenScope::enter(); | 2479 ScriptForbiddenScope::enter(); |
| 2478 | 2480 |
| 2479 s_lastGCWasConservative = false; | 2481 s_lastGCWasConservative = false; |
| 2480 | 2482 |
| 2481 TRACE_EVENT0("blink_gc", "Heap::collectGarbage"); | 2483 TRACE_EVENT2("blink_gc", "Heap::collectGarbage", |
| 2484 "precise", stackState == ThreadState::NoHeapPointersOnStack, |
| 2485 "forced", cause == ThreadState::ForcedGC); |
| 2482 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); | 2486 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); |
| 2483 double timeStamp = WTF::currentTimeMS(); | 2487 double timeStamp = WTF::currentTimeMS(); |
| 2484 #if ENABLE(GC_PROFILE_MARKING) | 2488 #if ENABLE(GC_PROFILE_MARKING) |
| 2485 static_cast<MarkingVisitor*>(s_markingVisitor)->objectGraph().clear(); | 2489 static_cast<MarkingVisitor*>(s_markingVisitor)->objectGraph().clear(); |
| 2486 #endif | 2490 #endif |
| 2487 | 2491 |
| 2488 // Disallow allocation during garbage collection (but not | 2492 // Disallow allocation during garbage collection (but not |
| 2489 // during the finalization that happens when the gcScope is | 2493 // during the finalization that happens when the gcScope is |
| 2490 // torn down). | 2494 // torn down). |
| 2491 NoAllocationScope<AnyThread> noAllocationScope; | 2495 NoAllocationScope<AnyThread> noAllocationScope; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2568 postMarkingProcessing(); | 2572 postMarkingProcessing(); |
| 2569 globalWeakProcessing(); | 2573 globalWeakProcessing(); |
| 2570 | 2574 |
| 2571 state->leaveGC(); | 2575 state->leaveGC(); |
| 2572 } | 2576 } |
| 2573 state->performPendingSweep(); | 2577 state->performPendingSweep(); |
| 2574 } | 2578 } |
| 2575 | 2579 |
| 2576 void Heap::processMarkingStackEntries(int* runningMarkingThreads) | 2580 void Heap::processMarkingStackEntries(int* runningMarkingThreads) |
| 2577 { | 2581 { |
| 2582 TRACE_EVENT0("blink_gc", "Heap::processMarkingStackEntries"); |
| 2578 CallbackStack* stack = 0; | 2583 CallbackStack* stack = 0; |
| 2579 MarkingVisitor visitor(&stack); | 2584 MarkingVisitor visitor(&stack); |
| 2580 { | 2585 { |
| 2581 MutexLocker locker(markingMutex()); | 2586 MutexLocker locker(markingMutex()); |
| 2582 stack = s_markingStack->takeCallbacks(&s_markingStack); | 2587 stack = s_markingStack->takeCallbacks(&s_markingStack); |
| 2583 } | 2588 } |
| 2584 while (stack) { | 2589 while (stack) { |
| 2585 while (stack->popAndInvokeCallback<GlobalMarking>(&stack, &visitor)) { } | 2590 while (stack->popAndInvokeCallback<GlobalMarking>(&stack, &visitor)) { } |
| 2586 delete stack; | 2591 delete stack; |
| 2587 { | 2592 { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2615 { | 2620 { |
| 2616 static const int numberOfBlocksForParallelMarking = 2; | 2621 static const int numberOfBlocksForParallelMarking = 2; |
| 2617 // Ephemeron fixed point loop run on the garbage collecting thread. | 2622 // Ephemeron fixed point loop run on the garbage collecting thread. |
| 2618 do { | 2623 do { |
| 2619 // Iteratively mark all objects that are reachable from the objects | 2624 // Iteratively mark all objects that are reachable from the objects |
| 2620 // currently pushed onto the marking stack. Do so in parallel if there | 2625 // currently pushed onto the marking stack. Do so in parallel if there |
| 2621 // are multiple blocks on the global marking stack. | 2626 // are multiple blocks on the global marking stack. |
| 2622 if (s_markingStack->numberOfBlocksExceeds(numberOfBlocksForParallelMarki
ng)) { | 2627 if (s_markingStack->numberOfBlocksExceeds(numberOfBlocksForParallelMarki
ng)) { |
| 2623 processMarkingStackOnMultipleThreads(); | 2628 processMarkingStackOnMultipleThreads(); |
| 2624 } else { | 2629 } else { |
| 2630 TRACE_EVENT0("blink_gc", "Heap::processMarkingStackSingleThreaded"); |
| 2625 while (popAndInvokeTraceCallback<GlobalMarking>(s_markingVisitor)) {
} | 2631 while (popAndInvokeTraceCallback<GlobalMarking>(s_markingVisitor)) {
} |
| 2626 } | 2632 } |
| 2627 | 2633 |
| 2628 // Mark any strong pointers that have now become reachable in ephemeron | 2634 // Mark any strong pointers that have now become reachable in ephemeron |
| 2629 // maps. | 2635 // maps. |
| 2636 TRACE_EVENT0("blink_gc", "Heap::processEphemeronStack"); |
| 2630 CallbackStack::invokeCallbacks(&s_ephemeronStack, s_markingVisitor); | 2637 CallbackStack::invokeCallbacks(&s_ephemeronStack, s_markingVisitor); |
| 2631 | 2638 |
| 2632 // Rerun loop if ephemeron processing queued more objects for tracing. | 2639 // Rerun loop if ephemeron processing queued more objects for tracing. |
| 2633 } while (!s_markingStack->isEmpty()); | 2640 } while (!s_markingStack->isEmpty()); |
| 2634 } | 2641 } |
| 2635 | 2642 |
| 2636 template<CallbackInvocationMode Mode> | 2643 template<CallbackInvocationMode Mode> |
| 2637 void Heap::processMarkingStack() | 2644 void Heap::processMarkingStack() |
| 2638 { | 2645 { |
| 2639 // Ephemeron fixed point loop. | 2646 // Ephemeron fixed point loop. |
| 2640 do { | 2647 do { |
| 2641 // Iteratively mark all objects that are reachable from the objects | 2648 // Iteratively mark all objects that are reachable from the objects |
| 2642 // currently pushed onto the marking stack. If Mode is ThreadLocalMarkin
g | 2649 // currently pushed onto the marking stack. If Mode is ThreadLocalMarkin
g |
| 2643 // don't continue tracing if the trace hits an object on another thread'
s | 2650 // don't continue tracing if the trace hits an object on another thread'
s |
| 2644 // heap. | 2651 // heap. |
| 2652 TRACE_EVENT0("blink_gc", "Heap::processMarkingStackSingleThreaded"); |
| 2645 while (popAndInvokeTraceCallback<Mode>(s_markingVisitor)) { } | 2653 while (popAndInvokeTraceCallback<Mode>(s_markingVisitor)) { } |
| 2646 | 2654 |
| 2647 // Mark any strong pointers that have now become reachable in ephemeron | 2655 // Mark any strong pointers that have now become reachable in ephemeron |
| 2648 // maps. | 2656 // maps. |
| 2657 TRACE_EVENT0("blink_gc", "Heap::processEphemeronStack"); |
| 2649 CallbackStack::invokeCallbacks(&s_ephemeronStack, s_markingVisitor); | 2658 CallbackStack::invokeCallbacks(&s_ephemeronStack, s_markingVisitor); |
| 2650 | 2659 |
| 2651 // Rerun loop if ephemeron processing queued more objects for tracing. | 2660 // Rerun loop if ephemeron processing queued more objects for tracing. |
| 2652 } while (!s_markingStack->isEmpty()); | 2661 } while (!s_markingStack->isEmpty()); |
| 2653 } | 2662 } |
| 2654 | 2663 |
| 2655 void Heap::postMarkingProcessing() | 2664 void Heap::postMarkingProcessing() |
| 2656 { | 2665 { |
| 2666 TRACE_EVENT0("blink_gc", "Heap::postMarkingProcessing"); |
| 2657 // Call post-marking callbacks including: | 2667 // Call post-marking callbacks including: |
| 2658 // 1. the ephemeronIterationDone callbacks on weak tables to do cleanup | 2668 // 1. the ephemeronIterationDone callbacks on weak tables to do cleanup |
| 2659 // (specifically to clear the queued bits for weak hash tables), and | 2669 // (specifically to clear the queued bits for weak hash tables), and |
| 2660 // 2. the markNoTracing callbacks on collection backings to mark them | 2670 // 2. the markNoTracing callbacks on collection backings to mark them |
| 2661 // if they are only reachable from their front objects. | 2671 // if they are only reachable from their front objects. |
| 2662 while (popAndInvokePostMarkingCallback(s_markingVisitor)) { } | 2672 while (popAndInvokePostMarkingCallback(s_markingVisitor)) { } |
| 2663 | 2673 |
| 2664 CallbackStack::clear(&s_ephemeronStack); | 2674 CallbackStack::clear(&s_ephemeronStack); |
| 2665 | 2675 |
| 2666 // Post-marking callbacks should not trace any objects and | 2676 // Post-marking callbacks should not trace any objects and |
| 2667 // therefore the marking stack should be empty after the | 2677 // therefore the marking stack should be empty after the |
| 2668 // post-marking callbacks. | 2678 // post-marking callbacks. |
| 2669 ASSERT(s_markingStack->isEmpty()); | 2679 ASSERT(s_markingStack->isEmpty()); |
| 2670 } | 2680 } |
| 2671 | 2681 |
| 2672 void Heap::globalWeakProcessing() | 2682 void Heap::globalWeakProcessing() |
| 2673 { | 2683 { |
| 2684 TRACE_EVENT0("blink_gc", "Heap::globalWeakProcessing"); |
| 2674 // Call weak callbacks on objects that may now be pointing to dead | 2685 // Call weak callbacks on objects that may now be pointing to dead |
| 2675 // objects. | 2686 // objects. |
| 2676 while (popAndInvokeWeakPointerCallback(s_markingVisitor)) { } | 2687 while (popAndInvokeWeakPointerCallback(s_markingVisitor)) { } |
| 2677 | 2688 |
| 2678 // It is not permitted to trace pointers of live objects in the weak | 2689 // It is not permitted to trace pointers of live objects in the weak |
| 2679 // callback phase, so the marking stack should still be empty here. | 2690 // callback phase, so the marking stack should still be empty here. |
| 2680 ASSERT(s_markingStack->isEmpty()); | 2691 ASSERT(s_markingStack->isEmpty()); |
| 2681 } | 2692 } |
| 2682 | 2693 |
| 2683 void Heap::collectAllGarbage() | 2694 void Heap::collectAllGarbage() |
| 2684 { | 2695 { |
| 2685 // FIXME: oilpan: we should perform a single GC and everything | 2696 // FIXME: oilpan: we should perform a single GC and everything |
| 2686 // should die. Unfortunately it is not the case for all objects | 2697 // should die. Unfortunately it is not the case for all objects |
| 2687 // because the hierarchy was not completely moved to the heap and | 2698 // because the hierarchy was not completely moved to the heap and |
| 2688 // some heap allocated objects own objects that contain persistents | 2699 // some heap allocated objects own objects that contain persistents |
| 2689 // pointing to other heap allocated objects. | 2700 // pointing to other heap allocated objects. |
| 2690 for (int i = 0; i < 5; i++) | 2701 for (int i = 0; i < 5; i++) |
| 2691 collectGarbage(ThreadState::NoHeapPointersOnStack); | 2702 collectGarbage(ThreadState::NoHeapPointersOnStack, ThreadState::ForcedGC
); |
| 2692 } | 2703 } |
| 2693 | 2704 |
| 2694 void Heap::setForcePreciseGCForTesting() | 2705 void Heap::setForcePreciseGCForTesting() |
| 2695 { | 2706 { |
| 2696 ThreadState::current()->setForcePreciseGCForTesting(true); | 2707 ThreadState::current()->setForcePreciseGCForTesting(true); |
| 2697 } | 2708 } |
| 2698 | 2709 |
| 2699 template<typename Header> | 2710 template<typename Header> |
| 2700 void ThreadHeap<Header>::prepareHeapForTermination() | 2711 void ThreadHeap<Header>::prepareHeapForTermination() |
| 2701 { | 2712 { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2845 CallbackStack* Heap::s_markingStack; | 2856 CallbackStack* Heap::s_markingStack; |
| 2846 CallbackStack* Heap::s_postMarkingCallbackStack; | 2857 CallbackStack* Heap::s_postMarkingCallbackStack; |
| 2847 CallbackStack* Heap::s_weakCallbackStack; | 2858 CallbackStack* Heap::s_weakCallbackStack; |
| 2848 CallbackStack* Heap::s_ephemeronStack; | 2859 CallbackStack* Heap::s_ephemeronStack; |
| 2849 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; | 2860 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; |
| 2850 bool Heap::s_shutdownCalled = false; | 2861 bool Heap::s_shutdownCalled = false; |
| 2851 bool Heap::s_lastGCWasConservative = false; | 2862 bool Heap::s_lastGCWasConservative = false; |
| 2852 FreePagePool* Heap::s_freePagePool; | 2863 FreePagePool* Heap::s_freePagePool; |
| 2853 OrphanedPagePool* Heap::s_orphanedPagePool; | 2864 OrphanedPagePool* Heap::s_orphanedPagePool; |
| 2854 } | 2865 } |
| OLD | NEW |