Index: Source/platform/heap/ThreadState.h |
diff --git a/Source/platform/heap/ThreadState.h b/Source/platform/heap/ThreadState.h |
index 2513756aae2b550b1871a7f1c07efebffb3c35b5..e7da7687359dbd4f9e8f113bf621fc55e09cd0ee 100644 |
--- a/Source/platform/heap/ThreadState.h |
+++ b/Source/platform/heap/ThreadState.h |
@@ -34,6 +34,7 @@ |
#include "platform/PlatformExport.h" |
#include "platform/heap/AddressSanitizer.h" |
#include "public/platform/WebThread.h" |
+#include "wtf/HashMap.h" |
#include "wtf/HashSet.h" |
#include "wtf/OwnPtr.h" |
#include "wtf/PassOwnPtr.h" |
@@ -42,10 +43,6 @@ |
#include "wtf/ThreadingPrimitives.h" |
#include "wtf/Vector.h" |
-#if ENABLE(GC_PROFILE_HEAP) |
-#include "wtf/HashMap.h" |
-#endif |
- |
namespace blink { |
class BaseHeap; |
@@ -131,6 +128,51 @@ struct ThreadingTrait { |
template<typename U> class ThreadingTrait<const U> : public ThreadingTrait<U> { }; |
+// Declare that a class has a pre-finalizer function. The function is called in |
+// the object's owner thread, and can access Member<>s to other |
+// garbarge-collected objects allocated in the thread. However we must not |
+// allocate new garbage-collected objects, nor must update Member<> and |
+// Persistent<> pointers. |
haraken
2014/10/06 05:26:42
nor must update => nor update
(I'm not familiar w
|
+// |
+// This feature is similar to the HeapHashMap<WeakMember<Foo>, OwnPtr<Disposer>> |
+// idiom. The difference between this and the idiom is that pre-finalizer |
+// function is called whenever an object is destructed with this feature. With |
+// the HeapHashMap<WeakMember...> idiom, a Disposer object is not destructed |
+// before the corresponding ~Foo if the Foo object and the onwer of the |
+// HeapHashMap are collected at same time. |
haraken
2014/10/06 05:26:42
I'm a bit confused with this description.
class B
tkent
2014/10/06 06:02:24
It's not correct. ~Disposer is called when a back
haraken
2014/10/06 06:28:09
Thanks, understood.
Then is the only difference w
tkent
2014/10/06 07:00:52
Right. Both of them have O(n) cost, and the pre-f
haraken
2014/10/06 07:04:09
Sounds great. Then let's replace this comment with
tkent
2014/10/06 07:17:59
Done. Added a FIXME.
|
+// |
+// See ThreadState::registerPreFinalizer. |
+// |
+// Usage: |
+// |
+// class Foo : GarbageCollected<Foo> { |
+// USING_PRE_FINALIZER(Foo, dispose); |
+// public: |
+// Foo() |
+// { |
+// registerPreFinalizer(); |
haraken
2014/10/06 05:26:42
registerPreFinalizer(*this);
|
+// } |
+// private: |
+// void dispose(); |
+// Member<Bar> m_bar; |
+// }; |
+// |
+// void Foo::dispose() |
+// { |
+// m_bar->... |
+// } |
+#define USING_PRE_FINALIZER(Class, method) \ |
+ public: \ |
+ static bool invokePreFinalizer(void* object, Visitor& visitor) \ |
+ { \ |
+ Class* self = reinterpret_cast<Class*>(object); \ |
+ if (visitor.isAlive(self)) \ |
+ return false; \ |
+ self->method(); \ |
+ return true; \ |
+ } \ |
+ typedef char UsingPreFinazlizerMacroNeedsTrailingSemiColon |
+ |
// List of typed heaps. The list is used to generate the implementation |
// of typed heap related methods. |
// |
@@ -629,6 +671,29 @@ public: |
void registerSweepingTask(); |
void unregisterSweepingTask(); |
+ // Request to call a pref-finalizer of the target object before the object |
+ // is destructed. The class T must have USING_PRE_FINALIZER(). The |
+ // argument should be |*this|. Registering a lot of objects affects GC |
+ // performance. We should register an object only if the object really |
+ // requires pre-finalizer, and we should unregister the object if |
+ // pre-finalizer is unnecessary. |
+ template<typename T> |
+ void registerPreFinalizer(T& target) |
+ { |
+ ASSERT(!m_preFinalizers.contains(&target)); |
+ ASSERT(!isSweepInProgress()); |
+ m_preFinalizers.add(&target, &T::invokePreFinalizer); |
+ } |
+ |
+ // Cancel above requests. The argument should be |*this|. This function is |
+ // ignored if it is called in pre-finalizer functions. |
+ template<typename T> |
+ void unregisterPreFinalizer(T& target) |
+ { |
+ ASSERT(&T::invokePreFinalizer); |
+ unregisterPreFinalizerInternal(&target); |
+ } |
+ |
Mutex& sweepMutex() { return m_sweepMutex; } |
private: |
@@ -667,6 +732,8 @@ private: |
void setLowCollectionRate(bool value) { m_lowCollectionRate = value; } |
void waitUntilSweepersDone(); |
+ void unregisterPreFinalizerInternal(void*); |
+ void invokePreFinalizers(Visitor&); |
static WTF::ThreadSpecific<ThreadState*>* s_threadSpecific; |
static SafePointBarrier* s_safePointBarrier; |
@@ -718,6 +785,7 @@ private: |
ThreadCondition m_sweepThreadCondition; |
CallbackStack* m_weakCallbackStack; |
+ HashMap<void*, bool (*)(void*, Visitor&)> m_preFinalizers; |
#if defined(ADDRESS_SANITIZER) |
void* m_asanFakeStack; |