| 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 | 
|  |