Index: Source/platform/heap/ThreadState.cpp |
diff --git a/Source/platform/heap/ThreadState.cpp b/Source/platform/heap/ThreadState.cpp |
index b7756d3418cab62cb43047a1743b329f49086dc6..78bb414ad1345c5730bf4c97b0b79f7e319d1fa1 100644 |
--- a/Source/platform/heap/ThreadState.cpp |
+++ b/Source/platform/heap/ThreadState.cpp |
@@ -76,6 +76,9 @@ uintptr_t ThreadState::s_mainThreadStackStart = 0; |
uintptr_t ThreadState::s_mainThreadUnderestimatedStackSize = 0; |
uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; |
SafePointBarrier* ThreadState::s_safePointBarrier = nullptr; |
+#if ENABLE(ASSERT) |
+int ThreadState::s_selfKeepAliveAllocationsOnMainThread = 0; |
+#endif |
RecursiveMutex& ThreadState::threadAttachMutex() |
{ |
@@ -166,6 +169,9 @@ void ThreadState::attachMainThread() |
MutexLocker locker(threadAttachMutex()); |
ThreadState* state = new(s_mainThreadStateStorage) ThreadState(); |
attachedThreads().add(state); |
+#if ENABLE(ASSERT) |
+ s_selfKeepAliveAllocationsOnMainThread = 0; |
+#endif |
} |
void ThreadState::detachMainThread() |
@@ -189,6 +195,8 @@ void ThreadState::detachMainThread() |
attachedThreads().remove(state); |
state->~ThreadState(); |
} |
+ // Catch out any self-referential leaks created by the main thread. |
+ ASSERT(s_selfKeepAliveAllocationsOnMainThread == 0); |
shutdownHeapIfNecessary(); |
} |
@@ -257,7 +265,10 @@ void ThreadState::cleanup() |
} |
// We should not have any persistents left when getting to this point, |
// if we have it is probably a bug so adding a debug ASSERT to catch this. |
- ASSERT(!currentCount); |
+ // (debug tip: use persistentRegion()->dumpLivePersistents() to get a list of |
+ // the remaining live Persistent<>s. In gdb, performing "info symbol" on the |
+ // trace callback addresses printed should tell you what Persistent<T>s are leaking.) |
+ ASSERT(!currentCount && "Persistent<>s leak on thread heap shutdown"); |
// All of pre-finalizers should be consumed. |
ASSERT(m_orderedPreFinalizers.isEmpty()); |
RELEASE_ASSERT(gcState() == NoGCScheduled); |
@@ -1542,4 +1553,23 @@ void ThreadState::reportMarkSweepStats(const char* statsName, const ClassAgeCoun |
} |
#endif |
+#if ENABLE(ASSERT) |
+void ThreadState::incrementSelfKeepAliveAllocations() |
+{ |
+ if (!ThreadState::current()->isMainThread()) |
+ return; |
+ |
+ s_selfKeepAliveAllocationsOnMainThread++; |
+} |
+ |
+void ThreadState::decrementSelfKeepAliveAllocations() |
+{ |
+ if (!ThreadState::current()->isMainThread()) |
+ return; |
+ |
+ ASSERT(s_selfKeepAliveAllocationsOnMainThread > 0); |
+ s_selfKeepAliveAllocationsOnMainThread--; |
+} |
+#endif |
+ |
} // namespace blink |