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 |