| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 class ThreadState; | 64 class ThreadState; |
| 65 class Visitor; | 65 class Visitor; |
| 66 | 66 |
| 67 using Address = uint8_t*; | 67 using Address = uint8_t*; |
| 68 | 68 |
| 69 using FinalizationCallback = void (*)(void*); | 69 using FinalizationCallback = void (*)(void*); |
| 70 using VisitorCallback = void (*)(Visitor*, void* self); | 70 using VisitorCallback = void (*)(Visitor*, void* self); |
| 71 using TraceCallback = VisitorCallback; | 71 using TraceCallback = VisitorCallback; |
| 72 using WeakCallback = VisitorCallback; | 72 using WeakCallback = VisitorCallback; |
| 73 using EphemeronCallback = VisitorCallback; | 73 using EphemeronCallback = VisitorCallback; |
| 74 using PreFinalizerCallback = bool(*)(void*); |
| 74 | 75 |
| 75 // Declare that a class has a pre-finalizer function. The function is called in | 76 // Declare that a class has a pre-finalizer. The pre-finalizer is called |
| 76 // the object's owner thread. The pre-finalizer is called before any object gets | 77 // before any object gets swept, so it is safe to touch on-heap objects |
| 77 // swept, so it is allowed to touch on-heap objects that may be collected in the | 78 // that may be collected in the same GC cycle. If you cannot avoid touching |
| 78 // GC cycle. If you cannot avoid touching on-heap objects in a destructor (which | 79 // on-heap objects in a destructor (which is not allowed), you can consider |
| 79 // is not allowed), you can consider using the pre-finalizer or | 80 // using the pre-finalizer. The only restriction is that the pre-finalizer |
| 80 // EARGERY_FINALIZED. The only restriction is that the pre-finalizer must not | 81 // must not resurrect dead objects (e.g., store unmarked objects into |
| 81 // resurrect dead objects (e.g., store unmarked objects into Members etc). | 82 // Members etc). The pre-finalizer is called on the thread that registered |
| 83 // the pre-finalizer. |
| 82 // | 84 // |
| 83 // This feature is similar to the HeapHashMap<WeakMember<Foo>, OwnPtr<Disposer>> | 85 // Since a pre-finalizer adds pressure on GC performance, you should use it |
| 86 // only if necessary. |
| 87 // |
| 88 // A pre-finalizer is similar to the HeapHashMap<WeakMember<Foo>, OwnPtr<Dispose
r>> |
| 84 // idiom. The difference between this and the idiom is that pre-finalizer | 89 // idiom. The difference between this and the idiom is that pre-finalizer |
| 85 // function is called whenever an object is destructed with this feature. The | 90 // function is called whenever an object is destructed with this feature. The |
| 86 // HeapHashMap<WeakMember<Foo>, OwnPtr<Disposer>> idiom requires an assumption | 91 // HeapHashMap<WeakMember<Foo>, OwnPtr<Disposer>> idiom requires an assumption |
| 87 // that the HeapHashMap outlives objects pointed by WeakMembers. | 92 // that the HeapHashMap outlives objects pointed by WeakMembers. |
| 88 // FIXME: Replace all of the HeapHashMap<WeakMember<Foo>, OwnPtr<Disposer>> | 93 // FIXME: Replace all of the HeapHashMap<WeakMember<Foo>, OwnPtr<Disposer>> |
| 89 // idiom usages with the pre-finalizer if the replacement won't cause | 94 // idiom usages with the pre-finalizer if the replacement won't cause |
| 90 // performance regressions. | 95 // performance regressions. |
| 91 // | 96 // |
| 92 // See ThreadState::registerPreFinalizer. | |
| 93 // | |
| 94 // Usage: | 97 // Usage: |
| 95 // | 98 // |
| 96 // class Foo : GarbageCollected<Foo> { | 99 // class Foo : GarbageCollected<Foo> { |
| 97 // USING_PRE_FINALIZER(Foo, dispose); | 100 // USING_PRE_FINALIZER(Foo, dispose); |
| 98 // public: | 101 // public: |
| 99 // Foo() | 102 // Foo() |
| 100 // { | 103 // { |
| 101 // ThreadState::current()->registerPreFinalizer(*this); | 104 // ThreadState::current()->registerPreFinalizer(this, dispose); |
| 102 // } | 105 // } |
| 103 // private: | 106 // private: |
| 104 // void dispose(); | 107 // void dispose() |
| 108 // { |
| 109 // m_bar->...; // It is safe to touch other on-heap objects. |
| 110 // } |
| 105 // Member<Bar> m_bar; | 111 // Member<Bar> m_bar; |
| 106 // }; | 112 // }; |
| 107 // | 113 #define USING_PRE_FINALIZER(Class, preFinalizer) \ |
| 108 // void Foo::dispose() | 114 public: \ |
| 109 // { | 115 static bool invokePreFinalizer(void* object) \ |
| 110 // m_bar->... | 116 { \ |
| 111 // } | 117 Class* self = reinterpret_cast<Class*>(object); \ |
| 112 #define USING_PRE_FINALIZER(Class, method) \ | 118 if (Heap::isHeapObjectAlive(self)) \ |
| 113 public: \ | 119 return false; \ |
| 114 static bool invokePreFinalizer(void* object) \ | 120 self->Class::preFinalizer(); \ |
| 115 { \ | 121 return true; \ |
| 116 Class* self = reinterpret_cast<Class*>(object); \ | 122 } \ |
| 117 if (Heap::isHeapObjectAlive(self)) \ | 123 using UsingPreFinazlizerMacroNeedsTrailingSemiColon = char |
| 118 return false; \ | |
| 119 self->method(); \ | |
| 120 return true; \ | |
| 121 } \ | |
| 122 using UsingPreFinazlizerMacroNeedsTrailingSemiColon = char | |
| 123 | 124 |
| 124 #if ENABLE(OILPAN) | 125 #if ENABLE(OILPAN) |
| 125 #define WILL_BE_USING_PRE_FINALIZER(Class, method) USING_PRE_FINALIZER(Class, me
thod) | 126 #define WILL_BE_USING_PRE_FINALIZER(Class, method) USING_PRE_FINALIZER(Class, me
thod) |
| 126 #else | 127 #else |
| 127 #define WILL_BE_USING_PRE_FINALIZER(Class, method) | 128 #define WILL_BE_USING_PRE_FINALIZER(Class, method) |
| 128 #endif | 129 #endif |
| 129 | 130 |
| 130 // List of typed heaps. The list is used to generate the implementation | 131 // List of typed heaps. The list is used to generate the implementation |
| 131 // of typed heap related methods. | 132 // of typed heap related methods. |
| 132 // | 133 // |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 void reportMarkSweepStats(const char* statsName, const ClassAgeCountsMap&) c
onst; | 530 void reportMarkSweepStats(const char* statsName, const ClassAgeCountsMap&) c
onst; |
| 530 #endif | 531 #endif |
| 531 | 532 |
| 532 void pushThreadLocalWeakCallback(void*, WeakCallback); | 533 void pushThreadLocalWeakCallback(void*, WeakCallback); |
| 533 bool popAndInvokeThreadLocalWeakCallback(Visitor*); | 534 bool popAndInvokeThreadLocalWeakCallback(Visitor*); |
| 534 void threadLocalWeakProcessing(); | 535 void threadLocalWeakProcessing(); |
| 535 | 536 |
| 536 size_t objectPayloadSizeForTesting(); | 537 size_t objectPayloadSizeForTesting(); |
| 537 void prepareHeapForTermination(); | 538 void prepareHeapForTermination(); |
| 538 | 539 |
| 539 // Request to call a pref-finalizer of the target object before the object | 540 // Register the pre-finalizer for the |self| object. This method is normally |
| 540 // is destructed. The class T must have USING_PRE_FINALIZER(). The | 541 // called in the constructor of the |self| object. The class T must have |
| 541 // argument should be |*this|. Registering a lot of objects affects GC | 542 // USING_PRE_FINALIZER(). |
| 542 // performance. We should register an object only if the object really | |
| 543 // requires pre-finalizer, and we should unregister the object if | |
| 544 // pre-finalizer is unnecessary. | |
| 545 template<typename T> | 543 template<typename T> |
| 546 void registerPreFinalizer(T& target) | 544 void registerPreFinalizer(T* self) |
| 547 { | 545 { |
| 546 static_assert(sizeof(&T::invokePreFinalizer) > 0, "USING_PRE_FINALIZER(T
) must be defined."); |
| 548 checkThread(); | 547 checkThread(); |
| 549 ASSERT(!m_preFinalizers.contains(&target)); | |
| 550 ASSERT(!sweepForbidden()); | 548 ASSERT(!sweepForbidden()); |
| 551 m_preFinalizers.add(&target, &T::invokePreFinalizer); | 549 auto it = m_preFinalizers.find(self); |
| 550 Vector<PreFinalizerCallback>* callbackVector; |
| 551 if (it == m_preFinalizers.end()) { |
| 552 callbackVector = m_preFinalizers.add(self, adoptPtr(new Vector<PreFi
nalizerCallback>)).storedValue->value.get(); |
| 553 } else { |
| 554 callbackVector = it->value.get(); |
| 555 } |
| 556 ASSERT(!callbackVector->contains(&T::invokePreFinalizer)); |
| 557 callbackVector->append(&T::invokePreFinalizer); |
| 552 } | 558 } |
| 553 | 559 |
| 554 // Cancel above requests. The argument should be |*this|. This function is | 560 // Unregister the pre-finalizer for the |self| object. |
| 555 // ignored if it is called in pre-finalizer functions. | |
| 556 template<typename T> | 561 template<typename T> |
| 557 void unregisterPreFinalizer(T& target) | 562 void unregisterPreFinalizer(T* self) |
| 558 { | 563 { |
| 559 static_assert(sizeof(&T::invokePreFinalizer) > 0, "Declaration of USING_
PRE_FINALIZER()'s prefinalizer trampoline not in scope."); | 564 static_assert(sizeof(&T::invokePreFinalizer) > 0, "USING_PRE_FINALIZER(T
) must be defined."); |
| 560 checkThread(); | 565 checkThread(); |
| 561 unregisterPreFinalizerInternal(&target); | 566 // Ignore pre-finalizers called during pre-finalizers or destructors. |
| 567 if (sweepForbidden()) |
| 568 return; |
| 569 auto it = m_preFinalizers.find(self); |
| 570 ASSERT(it != m_preFinalizers.end()); |
| 571 Vector<PreFinalizerCallback>* callbackVector = it->value.get(); |
| 572 ASSERT(it->value->contains(&T::invokePreFinalizer)); |
| 573 callbackVector->remove(callbackVector->find(&T::invokePreFinalizer)); |
| 574 if (callbackVector->isEmpty()) |
| 575 m_preFinalizers.remove(it); |
| 562 } | 576 } |
| 563 | 577 |
| 564 Vector<PageMemoryRegion*>& allocatedRegionsSinceLastGC() { return m_allocate
dRegionsSinceLastGC; } | 578 Vector<PageMemoryRegion*>& allocatedRegionsSinceLastGC() { return m_allocate
dRegionsSinceLastGC; } |
| 565 | 579 |
| 566 void shouldFlushHeapDoesNotContainCache() { m_shouldFlushHeapDoesNotContainC
ache = true; } | 580 void shouldFlushHeapDoesNotContainCache() { m_shouldFlushHeapDoesNotContainC
ache = true; } |
| 567 | 581 |
| 568 void registerTraceDOMWrappers(v8::Isolate* isolate, void (*traceDOMWrappers)
(v8::Isolate*, Visitor*)) | 582 void registerTraceDOMWrappers(v8::Isolate* isolate, void (*traceDOMWrappers)
(v8::Isolate*, Visitor*)) |
| 569 { | 583 { |
| 570 m_isolate = isolate; | 584 m_isolate = isolate; |
| 571 m_traceDOMWrappers = traceDOMWrappers; | 585 m_traceDOMWrappers = traceDOMWrappers; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 // When ThreadState is detaching from non-main thread its | 698 // When ThreadState is detaching from non-main thread its |
| 685 // heap is expected to be empty (because it is going away). | 699 // heap is expected to be empty (because it is going away). |
| 686 // Perform registered cleanup tasks and garbage collection | 700 // Perform registered cleanup tasks and garbage collection |
| 687 // to sweep away any objects that are left on this heap. | 701 // to sweep away any objects that are left on this heap. |
| 688 // We assert that nothing must remain after this cleanup. | 702 // We assert that nothing must remain after this cleanup. |
| 689 // If assertion does not hold we crash as we are potentially | 703 // If assertion does not hold we crash as we are potentially |
| 690 // in the dangling pointer situation. | 704 // in the dangling pointer situation. |
| 691 void cleanup(); | 705 void cleanup(); |
| 692 void cleanupPages(); | 706 void cleanupPages(); |
| 693 | 707 |
| 694 void unregisterPreFinalizerInternal(void*); | |
| 695 void invokePreFinalizers(); | 708 void invokePreFinalizers(); |
| 696 | 709 |
| 697 void takeSnapshot(SnapshotType); | 710 void takeSnapshot(SnapshotType); |
| 698 #if ENABLE(GC_PROFILING) | 711 #if ENABLE(GC_PROFILING) |
| 699 void snapshotFreeList(); | 712 void snapshotFreeList(); |
| 700 #endif | 713 #endif |
| 701 void clearHeapAges(); | 714 void clearHeapAges(); |
| 702 int heapIndexOfVectorHeapLeastRecentlyExpanded(int beginHeapIndex, int endHe
apIndex); | 715 int heapIndexOfVectorHeapLeastRecentlyExpanded(int beginHeapIndex, int endHe
apIndex); |
| 703 | 716 |
| 704 friend class SafePointAwareMutexLocker; | 717 friend class SafePointAwareMutexLocker; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 size_t m_heapAges[NumberOfHeaps]; | 750 size_t m_heapAges[NumberOfHeaps]; |
| 738 size_t m_currentHeapAges; | 751 size_t m_currentHeapAges; |
| 739 | 752 |
| 740 bool m_isTerminating; | 753 bool m_isTerminating; |
| 741 GarbageCollectedMixinConstructorMarker* m_gcMixinMarker; | 754 GarbageCollectedMixinConstructorMarker* m_gcMixinMarker; |
| 742 | 755 |
| 743 bool m_shouldFlushHeapDoesNotContainCache; | 756 bool m_shouldFlushHeapDoesNotContainCache; |
| 744 GCState m_gcState; | 757 GCState m_gcState; |
| 745 | 758 |
| 746 CallbackStack* m_threadLocalWeakCallbackStack; | 759 CallbackStack* m_threadLocalWeakCallbackStack; |
| 747 HashMap<void*, bool (*)(void*)> m_preFinalizers; | 760 HashMap<void*, OwnPtr<Vector<PreFinalizerCallback>>> m_preFinalizers; |
| 748 | 761 |
| 749 v8::Isolate* m_isolate; | 762 v8::Isolate* m_isolate; |
| 750 void (*m_traceDOMWrappers)(v8::Isolate*, Visitor*); | 763 void (*m_traceDOMWrappers)(v8::Isolate*, Visitor*); |
| 751 | 764 |
| 752 #if defined(ADDRESS_SANITIZER) | 765 #if defined(ADDRESS_SANITIZER) |
| 753 void* m_asanFakeStack; | 766 void* m_asanFakeStack; |
| 754 #endif | 767 #endif |
| 755 | 768 |
| 756 Vector<PageMemoryRegion*> m_allocatedRegionsSinceLastGC; | 769 Vector<PageMemoryRegion*> m_allocatedRegionsSinceLastGC; |
| 757 | 770 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 780 }; | 793 }; |
| 781 | 794 |
| 782 template<> class ThreadStateFor<AnyThread> { | 795 template<> class ThreadStateFor<AnyThread> { |
| 783 public: | 796 public: |
| 784 static ThreadState* state() { return ThreadState::current(); } | 797 static ThreadState* state() { return ThreadState::current(); } |
| 785 }; | 798 }; |
| 786 | 799 |
| 787 } // namespace blink | 800 } // namespace blink |
| 788 | 801 |
| 789 #endif // ThreadState_h | 802 #endif // ThreadState_h |
| OLD | NEW |