Index: Source/platform/heap/PersistentNode.cpp |
diff --git a/Source/platform/heap/PersistentNode.cpp b/Source/platform/heap/PersistentNode.cpp |
index d8e22fc6cff30e688c7ac5ba96c984c4e041e02c..aed8a39bcae70c543f5b9b58f96e615780779fd9 100644 |
--- a/Source/platform/heap/PersistentNode.cpp |
+++ b/Source/platform/heap/PersistentNode.cpp |
@@ -5,6 +5,8 @@ |
#include "config.h" |
#include "platform/heap/PersistentNode.h" |
+#include "platform/heap/Handle.h" |
+ |
namespace blink { |
PersistentRegion::~PersistentRegion() |
@@ -90,4 +92,38 @@ void PersistentRegion::tracePersistentNodes(Visitor* visitor) |
ASSERT(persistentCount == m_persistentCount); |
} |
+void CrossThreadPersistentRegion::prepareForThreadStateTermination(ThreadState* threadState) |
+{ |
+ // For heaps belonging to a thread that's detaching, any cross-thread persistents |
+ // pointing into them needs to be disabled. Do that by clearing out the underlying |
+ // heap reference. |
+ MutexLocker lock(m_mutex); |
+ |
+ class Object; |
+ using GCObject = GarbageCollected<Object>; |
+ |
+ // TODO(sof): consider ways of reducing overhead. (e.g., tracking number of active |
+ // CrossThreadPersistent<>s pointing into the heaps of each ThreadState and use that |
+ // count to bail out early.) |
+ PersistentNodeSlots* slots = m_persistentRegion->m_slots; |
+ while (slots) { |
+ for (int i = 0; i < PersistentNodeSlots::slotCount; ++i) { |
+ if (slots->m_slot[i].isUnused()) |
+ continue; |
+ |
+ // 'self' is in use, containing the cross-thread persistent wrapper object. |
+ CrossThreadPersistent<GCObject>* persistent = reinterpret_cast<CrossThreadPersistent<GCObject>*>(slots->m_slot[i].self()); |
+ ASSERT(persistent); |
+ void* rawObject = persistent->get(); |
+ if (!rawObject) |
+ continue; |
+ BasePage* page = pageFromObject(rawObject); |
+ ASSERT(page); |
+ if (page->heap()->threadState() == threadState) |
+ persistent->clear(); |
+ } |
+ slots = slots->m_next; |
+ } |
+} |
+ |
} // namespace blink |