<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[208306] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/208306">208306</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-11-02 15:01:04 -0700 (Wed, 02 Nov 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>The GC should be in a thread
https://bugs.webkit.org/show_bug.cgi?id=163562

Reviewed by Geoffrey Garen and Andreas Kling.
Source/JavaScriptCore:

        
In a concurrent GC, the work of collecting happens on a separate thread. This patch
implements this, and schedules the thread the way that a concurrent GC thread would be
scheduled. But, the GC isn't actually concurrent yet because it calls stopTheWorld() before
doing anything and calls resumeTheWorld() after it's done with everything. The next step will
be to make it really concurrent by basically calling stopTheWorld()/resumeTheWorld() around
bounded snippets of work while making most of the work happen with the world running. Our GC
will probably always have stop-the-world phases because the semantics of JSC weak references
call for it.
        
This implements concurrent GC scheduling. This means that there is no longer a
Heap::collect() API. Instead, you can call collectAsync() which makes sure that a GC is
scheduled (it will do nothing if one is scheduled or ongoing) or you can call collectSync()
to schedule a GC and wait for it to happen. I made our debugging stuff call collectSync().
It should be a goal to never call collectSync() except for debugging or benchmark harness
hacks.
        
The collector thread is an AutomaticThread, so it won't linger when not in use. It works on
a ticket-based system, like you would see at the DMV. A ticket is a 64-bit integer. There are
two ticket counters: last granted and last served. When you request a collection, last
granted is incremented and its new value given to you. When a collection completes, last
served is incremented. collectSync() waits until last served catches up to what last granted
had been at the time you requested a GC. This means that if you request a sync GC in the
middle of an async GC, you will wait for that async GC to finish and then you will request
and wait for your sync GC.
        
The synchronization between the collector thread and the main threads is complex. The
collector thread needs to be able to ask the main thread to stop. It needs to be able to do
some post-GC clean-up, like the synchronous CodeBlock and LargeAllocation sweeps, on the main
thread. The collector needs to be able to ask the main thread to execute a cross-modifying
code fence before running any JIT code, since the GC might aid the JIT worklist and run JIT
finalization. It's possible for the GC to want the main thread to run something at the same
time that the main thread wants to wait for the GC. The main thread needs to be able to run
non-JSC stuff without causing the GC to completely stall. The main thread needs to be able
to query its own state (is there a request to stop?) and change it (running JSC versus not)
quickly, since this may happen on hot paths. This kind of intertwined system of requests,
notifications, and state changes requires a combination of lock-free algorithms and waiting.
So, this is all implemented using a Atomic&lt;unsigned&gt; Heap::m_worldState, which has bits to
represent things being requested by the collector and the heap access state of the mutator. I
am borrowing a lot of terms that I've seen in other VMs that I've worked on. Here's what they
mean:
        
- Stop the world: make sure that either the mutator is not running, or that it's not running
  code that could mess with the heap.
        
- Heap access: the mutator is said to have heap access if it could mess with the heap.
        
If you stop the world and the mutator doesn't have heap access, all you're doing is making
sure that it will block when it tries to acquire heap access. This means that our GC is
already fully concurrent in cases where the GC is requested while the mutator has no heap
access. This probably won't happen, but if it did then it should just work. Usually, stopping
the world means that we state our shouldStop request with m_worldState, and a future call
to Heap::stopIfNecessary() will go to slow path and stop. The act of stopping or waiting to
acquire heap access is managed by using ParkingLot API directly on m_worldState. This works
out great because it would be very awkward to get the same functionality using locks and
condition variables, since we want stopIfNecessary/acquireAccess/requestAccess fast paths
that are single atomic instructions (load/CAS/CAS, respectively). The mutator will call these
things frequently. Currently we have Heap::stopIfNecessary() polling on every allocator slow
path, but we may want to make it even more frequent than that.
        
Currently only JSC API clients benefit from the heap access optimization. The DOM forces us
to assume that heap access is permanently on, since DOM manipulation doesn't always hold the
JSLock. We could still allow the GC to proceed when the runloop is idle by having the GC put
a task on the runloop that just calls stopIfNecessary().
        
This is perf neutral. The only behavior change that clients ought to observe is that marking
and the weak fixpoint happen on a separate thread. Marking was already parallel so it already
handled multiple threads, but now it _never_ runs on the main thread. The weak fixpoint
needed some help to be able to run on another thread - mostly because there was some code in
IndexedDB that was using thread specifics in the weak fixpoint.

* API/JSBase.cpp:
(JSSynchronousEdenCollectForDebugging):
* API/JSManagedValue.mm:
(-[JSManagedValue initWithValue:]):
* heap/EdenGCActivityCallback.cpp:
(JSC::EdenGCActivityCallback::doCollection):
* heap/FullGCActivityCallback.cpp:
(JSC::FullGCActivityCallback::doCollection):
* heap/Heap.cpp:
(JSC::Heap::Thread::Thread):
(JSC::Heap::Heap):
(JSC::Heap::lastChanceToFinalize):
(JSC::Heap::markRoots):
(JSC::Heap::gatherStackRoots):
(JSC::Heap::deleteUnmarkedCompiledCode):
(JSC::Heap::collectAllGarbage):
(JSC::Heap::collectAsync):
(JSC::Heap::collectSync):
(JSC::Heap::shouldCollectInThread):
(JSC::Heap::collectInThread):
(JSC::Heap::stopTheWorld):
(JSC::Heap::resumeTheWorld):
(JSC::Heap::stopIfNecessarySlow):
(JSC::Heap::acquireAccessSlow):
(JSC::Heap::releaseAccessSlow):
(JSC::Heap::handleDidJIT):
(JSC::Heap::handleNeedFinalize):
(JSC::Heap::setDidJIT):
(JSC::Heap::setNeedFinalize):
(JSC::Heap::waitWhileNeedFinalize):
(JSC::Heap::finalize):
(JSC::Heap::requestCollection):
(JSC::Heap::waitForCollection):
(JSC::Heap::didFinishCollection):
(JSC::Heap::canCollect):
(JSC::Heap::shouldCollectHeuristic):
(JSC::Heap::shouldCollect):
(JSC::Heap::collectIfNecessaryOrDefer):
(JSC::Heap::collectAccordingToDeferGCProbability):
(JSC::Heap::collect): Deleted.
(JSC::Heap::collectWithoutAnySweep): Deleted.
(JSC::Heap::collectImpl): Deleted.
* heap/Heap.h:
(JSC::Heap::ReleaseAccessScope::ReleaseAccessScope):
(JSC::Heap::ReleaseAccessScope::~ReleaseAccessScope):
* heap/HeapInlines.h:
(JSC::Heap::acquireAccess):
(JSC::Heap::releaseAccess):
(JSC::Heap::stopIfNecessary):
* heap/MachineStackMarker.cpp:
(JSC::MachineThreads::gatherConservativeRoots):
(JSC::MachineThreads::gatherFromCurrentThread): Deleted.
* heap/MachineStackMarker.h:
* jit/JITWorklist.cpp:
(JSC::JITWorklist::completeAllForVM):
* jit/JITWorklist.h:
* jsc.cpp:
(functionFullGC):
(functionEdenGC):
* runtime/InitializeThreading.cpp:
(JSC::initializeThreading):
* runtime/JSLock.cpp:
(JSC::JSLock::didAcquireLock):
(JSC::JSLock::unlock):
(JSC::JSLock::willReleaseLock):
* tools/JSDollarVMPrototype.cpp:
(JSC::JSDollarVMPrototype::edenGC):

Source/WebCore:


No new tests because existing tests cover this.
        
We now need to be more careful about using JSLock. This fixes some places that were not
holding it. New assertions in the GC are more likely to catch this than before.

* bindings/js/WorkerScriptController.cpp:
(WebCore::WorkerScriptController::WorkerScriptController):

Source/WTF:

        
This fixes some bugs and adds a few features.

* wtf/Atomics.h: The GC may do work on behalf of the JIT. If it does, the main thread needs to execute a cross-modifying code fence. This is cpuid on x86 and I believe it's isb on ARM. It would have been an isync on PPC and I think that isb is the ARM equivalent.
(WTF::arm_isb):
(WTF::crossModifyingCodeFence):
(WTF::x86_ortop):
(WTF::x86_cpuid):
* wtf/AutomaticThread.cpp: I accidentally had AutomaticThreadCondition inherit from ThreadSafeRefCounted&lt;AutomaticThread&gt; [sic]. This never crashed before because all of our prior AutomaticThreadConditions were immortal.
(WTF::AutomaticThread::AutomaticThread):
(WTF::AutomaticThread::~AutomaticThread):
(WTF::AutomaticThread::start):
* wtf/AutomaticThread.h:
* wtf/MainThread.cpp: Need to allow initializeGCThreads() to be called separately because it's now more than just a debugging thing.
(WTF::initializeGCThreads):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreAPIJSBasecpp">trunk/Source/JavaScriptCore/API/JSBase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreAPIJSManagedValuemm">trunk/Source/JavaScriptCore/API/JSManagedValue.mm</a></li>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDrivercpp">trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGWorklistcpp">trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGWorklisth">trunk/Source/JavaScriptCore/dfg/DFGWorklist.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompilecpp">trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapEdenGCActivityCallbackcpp">trunk/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapFullGCActivityCallbackcpp">trunk/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapGCActivityCallbackh">trunk/Source/JavaScriptCore/heap/GCActivityCallback.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapInlinesh">trunk/Source/JavaScriptCore/heap/HeapInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapTimercpp">trunk/Source/JavaScriptCore/heap/HeapTimer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapTimerh">trunk/Source/JavaScriptCore/heap/HeapTimer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapIncrementalSweepercpp">trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapIncrementalSweeperh">trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMachineStackMarkercpp">trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMachineStackMarkerh">trunk/Source/JavaScriptCore/heap/MachineStackMarker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgentcpp">trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITWorklistcpp">trunk/Source/JavaScriptCore/jit/JITWorklist.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITWorklisth">trunk/Source/JavaScriptCore/jit/JITWorklist.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeAtomicsObjectcpp">trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeInitializeThreadingcpp">trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSLockcpp">trunk/Source/JavaScriptCore/runtime/JSLock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSLockh">trunk/Source/JavaScriptCore/runtime/JSLock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoretoolsJSDollarVMPrototypecpp">trunk/Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfAtomicsh">trunk/Source/WTF/wtf/Atomics.h</a></li>
<li><a href="#trunkSourceWTFwtfAutomaticThreadcpp">trunk/Source/WTF/wtf/AutomaticThread.cpp</a></li>
<li><a href="#trunkSourceWTFwtfAutomaticThreadh">trunk/Source/WTF/wtf/AutomaticThread.h</a></li>
<li><a href="#trunkSourceWTFwtfCompilationThreadcpp">trunk/Source/WTF/wtf/CompilationThread.cpp</a></li>
<li><a href="#trunkSourceWTFwtfMainThreadcpp">trunk/Source/WTF/wtf/MainThread.cpp</a></li>
<li><a href="#trunkSourceWTFwtfMainThreadh">trunk/Source/WTF/wtf/MainThread.h</a></li>
<li><a href="#trunkSourceWTFwtfOptionalh">trunk/Source/WTF/wtf/Optional.h</a></li>
<li><a href="#trunkSourceWTFwtfParkingLotcpp">trunk/Source/WTF/wtf/ParkingLot.cpp</a></li>
<li><a href="#trunkSourceWTFwtfThreadSpecifich">trunk/Source/WTF/wtf/ThreadSpecific.h</a></li>
<li><a href="#trunkSourceWTFwtfWordLockcpp">trunk/Source/WTF/wtf/WordLock.cpp</a></li>
<li><a href="#trunkSourceWTFwtftextAtomicStringImplcpp">trunk/Source/WTF/wtf/text/AtomicStringImpl.cpp</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBDatabasecpp">trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBDatabaseh">trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.h</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBRequestcpp">trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp</a></li>
<li><a href="#trunkSourceWebCoreModulesindexeddbIDBTransactioncpp">trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMWindowBasecpp">trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsWorkerScriptControllercpp">trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsWorkerScriptControllerh">trunk/Source/WebCore/bindings/js/WorkerScriptController.h</a></li>
<li><a href="#trunkSourceWebCoredomEventTargetcpp">trunk/Source/WebCore/dom/EventTarget.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalscpp">trunk/Source/WebCore/testing/Internals.cpp</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsh">trunk/Source/WebCore/testing/Internals.h</a></li>
<li><a href="#trunkSourceWebCoretestingInternalsidl">trunk/Source/WebCore/testing/Internals.idl</a></li>
<li><a href="#trunkSourceWebCoreworkersWorkerRunLoopcpp">trunk/Source/WebCore/workers/WorkerRunLoop.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreheapReleaseHeapAccessScopeh">trunk/Source/JavaScriptCore/heap/ReleaseHeapAccessScope.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapStopIfNecessaryTimercpp">trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapStopIfNecessaryTimerh">trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformiosWebSafeGCActivityCallbackIOSh">trunk/Source/WebCore/platform/ios/WebSafeGCActivityCallbackIOS.h</a></li>
<li><a href="#trunkSourceWebCoreplatformiosWebSafeIncrementalSweeperIOSh">trunk/Source/WebCore/platform/ios/WebSafeIncrementalSweeperIOS.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreAPIJSBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/JSBase.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/JSBase.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/API/JSBase.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -165,7 +165,7 @@
</span><span class="cx"> 
</span><span class="cx">     ExecState* exec = toJS(ctx);
</span><span class="cx">     JSLockHolder locker(exec);
</span><del>-    exec-&gt;vm().heap.collect(CollectionScope::Eden);
</del><ins>+    exec-&gt;vm().heap.collectSync(CollectionScope::Eden);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JSDisableGCTimer(void)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreAPIJSManagedValuemm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/API/JSManagedValue.mm (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/API/JSManagedValue.mm        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/API/JSManagedValue.mm        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -486,6 +486,7 @@
</span><span class="cx">     heap/MarkedSpace.cpp
</span><span class="cx">     heap/MutatorState.cpp
</span><span class="cx">     heap/SlotVisitor.cpp
</span><ins>+    heap/StopIfNecessaryTimer.cpp
</ins><span class="cx">     heap/Weak.cpp
</span><span class="cx">     heap/WeakBlock.cpp
</span><span class="cx">     heap/WeakHandleOwner.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,3 +1,148 @@
</span><ins>+2016-11-02  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        The GC should be in a thread
+        https://bugs.webkit.org/show_bug.cgi?id=163562
+
+        Reviewed by Geoffrey Garen and Andreas Kling.
+        
+        In a concurrent GC, the work of collecting happens on a separate thread. This patch
+        implements this, and schedules the thread the way that a concurrent GC thread would be
+        scheduled. But, the GC isn't actually concurrent yet because it calls stopTheWorld() before
+        doing anything and calls resumeTheWorld() after it's done with everything. The next step will
+        be to make it really concurrent by basically calling stopTheWorld()/resumeTheWorld() around
+        bounded snippets of work while making most of the work happen with the world running. Our GC
+        will probably always have stop-the-world phases because the semantics of JSC weak references
+        call for it.
+        
+        This implements concurrent GC scheduling. This means that there is no longer a
+        Heap::collect() API. Instead, you can call collectAsync() which makes sure that a GC is
+        scheduled (it will do nothing if one is scheduled or ongoing) or you can call collectSync()
+        to schedule a GC and wait for it to happen. I made our debugging stuff call collectSync().
+        It should be a goal to never call collectSync() except for debugging or benchmark harness
+        hacks.
+        
+        The collector thread is an AutomaticThread, so it won't linger when not in use. It works on
+        a ticket-based system, like you would see at the DMV. A ticket is a 64-bit integer. There are
+        two ticket counters: last granted and last served. When you request a collection, last
+        granted is incremented and its new value given to you. When a collection completes, last
+        served is incremented. collectSync() waits until last served catches up to what last granted
+        had been at the time you requested a GC. This means that if you request a sync GC in the
+        middle of an async GC, you will wait for that async GC to finish and then you will request
+        and wait for your sync GC.
+        
+        The synchronization between the collector thread and the main threads is complex. The
+        collector thread needs to be able to ask the main thread to stop. It needs to be able to do
+        some post-GC clean-up, like the synchronous CodeBlock and LargeAllocation sweeps, on the main
+        thread. The collector needs to be able to ask the main thread to execute a cross-modifying
+        code fence before running any JIT code, since the GC might aid the JIT worklist and run JIT
+        finalization. It's possible for the GC to want the main thread to run something at the same
+        time that the main thread wants to wait for the GC. The main thread needs to be able to run
+        non-JSC stuff without causing the GC to completely stall. The main thread needs to be able
+        to query its own state (is there a request to stop?) and change it (running JSC versus not)
+        quickly, since this may happen on hot paths. This kind of intertwined system of requests,
+        notifications, and state changes requires a combination of lock-free algorithms and waiting.
+        So, this is all implemented using a Atomic&lt;unsigned&gt; Heap::m_worldState, which has bits to
+        represent things being requested by the collector and the heap access state of the mutator. I
+        am borrowing a lot of terms that I've seen in other VMs that I've worked on. Here's what they
+        mean:
+        
+        - Stop the world: make sure that either the mutator is not running, or that it's not running
+          code that could mess with the heap.
+        
+        - Heap access: the mutator is said to have heap access if it could mess with the heap.
+        
+        If you stop the world and the mutator doesn't have heap access, all you're doing is making
+        sure that it will block when it tries to acquire heap access. This means that our GC is
+        already fully concurrent in cases where the GC is requested while the mutator has no heap
+        access. This probably won't happen, but if it did then it should just work. Usually, stopping
+        the world means that we state our shouldStop request with m_worldState, and a future call
+        to Heap::stopIfNecessary() will go to slow path and stop. The act of stopping or waiting to
+        acquire heap access is managed by using ParkingLot API directly on m_worldState. This works
+        out great because it would be very awkward to get the same functionality using locks and
+        condition variables, since we want stopIfNecessary/acquireAccess/requestAccess fast paths
+        that are single atomic instructions (load/CAS/CAS, respectively). The mutator will call these
+        things frequently. Currently we have Heap::stopIfNecessary() polling on every allocator slow
+        path, but we may want to make it even more frequent than that.
+        
+        Currently only JSC API clients benefit from the heap access optimization. The DOM forces us
+        to assume that heap access is permanently on, since DOM manipulation doesn't always hold the
+        JSLock. We could still allow the GC to proceed when the runloop is idle by having the GC put
+        a task on the runloop that just calls stopIfNecessary().
+        
+        This is perf neutral. The only behavior change that clients ought to observe is that marking
+        and the weak fixpoint happen on a separate thread. Marking was already parallel so it already
+        handled multiple threads, but now it _never_ runs on the main thread. The weak fixpoint
+        needed some help to be able to run on another thread - mostly because there was some code in
+        IndexedDB that was using thread specifics in the weak fixpoint.
+
+        * API/JSBase.cpp:
+        (JSSynchronousEdenCollectForDebugging):
+        * API/JSManagedValue.mm:
+        (-[JSManagedValue initWithValue:]):
+        * heap/EdenGCActivityCallback.cpp:
+        (JSC::EdenGCActivityCallback::doCollection):
+        * heap/FullGCActivityCallback.cpp:
+        (JSC::FullGCActivityCallback::doCollection):
+        * heap/Heap.cpp:
+        (JSC::Heap::Thread::Thread):
+        (JSC::Heap::Heap):
+        (JSC::Heap::lastChanceToFinalize):
+        (JSC::Heap::markRoots):
+        (JSC::Heap::gatherStackRoots):
+        (JSC::Heap::deleteUnmarkedCompiledCode):
+        (JSC::Heap::collectAllGarbage):
+        (JSC::Heap::collectAsync):
+        (JSC::Heap::collectSync):
+        (JSC::Heap::shouldCollectInThread):
+        (JSC::Heap::collectInThread):
+        (JSC::Heap::stopTheWorld):
+        (JSC::Heap::resumeTheWorld):
+        (JSC::Heap::stopIfNecessarySlow):
+        (JSC::Heap::acquireAccessSlow):
+        (JSC::Heap::releaseAccessSlow):
+        (JSC::Heap::handleDidJIT):
+        (JSC::Heap::handleNeedFinalize):
+        (JSC::Heap::setDidJIT):
+        (JSC::Heap::setNeedFinalize):
+        (JSC::Heap::waitWhileNeedFinalize):
+        (JSC::Heap::finalize):
+        (JSC::Heap::requestCollection):
+        (JSC::Heap::waitForCollection):
+        (JSC::Heap::didFinishCollection):
+        (JSC::Heap::canCollect):
+        (JSC::Heap::shouldCollectHeuristic):
+        (JSC::Heap::shouldCollect):
+        (JSC::Heap::collectIfNecessaryOrDefer):
+        (JSC::Heap::collectAccordingToDeferGCProbability):
+        (JSC::Heap::collect): Deleted.
+        (JSC::Heap::collectWithoutAnySweep): Deleted.
+        (JSC::Heap::collectImpl): Deleted.
+        * heap/Heap.h:
+        (JSC::Heap::ReleaseAccessScope::ReleaseAccessScope):
+        (JSC::Heap::ReleaseAccessScope::~ReleaseAccessScope):
+        * heap/HeapInlines.h:
+        (JSC::Heap::acquireAccess):
+        (JSC::Heap::releaseAccess):
+        (JSC::Heap::stopIfNecessary):
+        * heap/MachineStackMarker.cpp:
+        (JSC::MachineThreads::gatherConservativeRoots):
+        (JSC::MachineThreads::gatherFromCurrentThread): Deleted.
+        * heap/MachineStackMarker.h:
+        * jit/JITWorklist.cpp:
+        (JSC::JITWorklist::completeAllForVM):
+        * jit/JITWorklist.h:
+        * jsc.cpp:
+        (functionFullGC):
+        (functionEdenGC):
+        * runtime/InitializeThreading.cpp:
+        (JSC::initializeThreading):
+        * runtime/JSLock.cpp:
+        (JSC::JSLock::didAcquireLock):
+        (JSC::JSLock::unlock):
+        (JSC::JSLock::willReleaseLock):
+        * tools/JSDollarVMPrototype.cpp:
+        (JSC::JSDollarVMPrototype::edenGC):
+
</ins><span class="cx"> 2016-11-02  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Crash beneath SlotVisitor::drain @ cooksillustrated.com
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -505,6 +505,9 @@
</span><span class="cx">                 0F7C39FF1C90C55B00480151 /* DFGOpInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */; };
</span><span class="cx">                 0F7C5FB81D888A0C0044F5E2 /* MarkedBlockInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C5FB71D888A010044F5E2 /* MarkedBlockInlines.h */; };
</span><span class="cx">                 0F7C5FBA1D8895070044F5E2 /* MarkedSpaceInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7C5FB91D8895050044F5E2 /* MarkedSpaceInlines.h */; };
</span><ins>+                0F7CF94F1DBEEE880098CC12 /* ReleaseHeapAccessScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7CF94E1DBEEE860098CC12 /* ReleaseHeapAccessScope.h */; };
+                0F7CF9521DC027D90098CC12 /* StopIfNecessaryTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7CF9511DC027D70098CC12 /* StopIfNecessaryTimer.h */; };
+                0F7CF9531DC027DB0098CC12 /* StopIfNecessaryTimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7CF9501DC027D70098CC12 /* StopIfNecessaryTimer.cpp */; };
</ins><span class="cx">                 0F7CF9561DC1258D0098CC12 /* AtomicsObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7CF9541DC1258B0098CC12 /* AtomicsObject.cpp */; };
</span><span class="cx">                 0F7CF9571DC125900098CC12 /* AtomicsObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7CF9551DC1258B0098CC12 /* AtomicsObject.h */; };
</span><span class="cx">                 0F7F988B1D9596C500F4F12E /* DFGStoreBarrierClusteringPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7F98891D9596C300F4F12E /* DFGStoreBarrierClusteringPhase.cpp */; };
</span><span class="lines">@@ -2864,6 +2867,9 @@
</span><span class="cx">                 0F7C39FE1C90C55B00480151 /* DFGOpInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOpInfo.h; path = dfg/DFGOpInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7C5FB71D888A010044F5E2 /* MarkedBlockInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedBlockInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7C5FB91D8895050044F5E2 /* MarkedSpaceInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedSpaceInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F7CF94E1DBEEE860098CC12 /* ReleaseHeapAccessScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReleaseHeapAccessScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7CF9501DC027D70098CC12 /* StopIfNecessaryTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StopIfNecessaryTimer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F7CF9511DC027D70098CC12 /* StopIfNecessaryTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StopIfNecessaryTimer.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F7CF9541DC1258B0098CC12 /* AtomicsObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AtomicsObject.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7CF9551DC1258B0098CC12 /* AtomicsObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtomicsObject.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F7F98891D9596C300F4F12E /* DFGStoreBarrierClusteringPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierClusteringPhase.cpp; path = dfg/DFGStoreBarrierClusteringPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5619,9 +5625,12 @@
</span><span class="cx">                                 0FA762021DB9242300B7A2FD /* MutatorState.cpp */,
</span><span class="cx">                                 0FA762031DB9242300B7A2FD /* MutatorState.h */,
</span><span class="cx">                                 ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */,
</span><ins>+                                0F7CF94E1DBEEE860098CC12 /* ReleaseHeapAccessScope.h */,
</ins><span class="cx">                                 C225494215F7DBAA0065E898 /* SlotVisitor.cpp */,
</span><span class="cx">                                 14BA78F013AAB88F005B7C2C /* SlotVisitor.h */,
</span><span class="cx">                                 0FCB408515C0A3C30048932B /* SlotVisitorInlines.h */,
</span><ins>+                                0F7CF9501DC027D70098CC12 /* StopIfNecessaryTimer.cpp */,
+                                0F7CF9511DC027D70098CC12 /* StopIfNecessaryTimer.h */,
</ins><span class="cx">                                 142E3132134FF0A600AFADB5 /* Strong.h */,
</span><span class="cx">                                 145722851437E140005FDE26 /* StrongInlines.h */,
</span><span class="cx">                                 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */,
</span><span class="lines">@@ -7832,6 +7841,7 @@
</span><span class="cx">                                 0F3B3A281544C997003ED0FF /* DFGCFGSimplificationPhase.h in Headers */,
</span><span class="cx">                                 E3FFC8531DAD7D1500DEA53E /* DOMJITValue.h in Headers */,
</span><span class="cx">                                 0F9D36951AE9CC33000D4DFB /* DFGCleanUpPhase.h in Headers */,
</span><ins>+                                0F7CF94F1DBEEE880098CC12 /* ReleaseHeapAccessScope.h in Headers */,
</ins><span class="cx">                                 A77A424017A0BBFD00A8DB81 /* DFGClobberize.h in Headers */,
</span><span class="cx">                                 0F37308D1C0BD29100052BFA /* B3PhiChildren.h in Headers */,
</span><span class="cx">                                 A77A424217A0BBFD00A8DB81 /* DFGClobberSet.h in Headers */,
</span><span class="lines">@@ -8671,6 +8681,7 @@
</span><span class="cx">                                 933040040E6A749400786E6A /* SmallStrings.h in Headers */,
</span><span class="cx">                                 BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */,
</span><span class="cx">                                 0F7C39FD1C8F659500480151 /* RegExpObjectInlines.h in Headers */,
</span><ins>+                                0F7CF9521DC027D90098CC12 /* StopIfNecessaryTimer.h in Headers */,
</ins><span class="cx">                                 BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */,
</span><span class="cx">                                 E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */,
</span><span class="cx">                                 E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */,
</span><span class="lines">@@ -9906,6 +9917,7 @@
</span><span class="cx">                                 7C184E1A17BEDBD3007CB63A /* JSPromise.cpp in Sources */,
</span><span class="cx">                                 7C184E2217BEE240007CB63A /* JSPromiseConstructor.cpp in Sources */,
</span><span class="cx">                                 7C008CDA187124BB00955C24 /* JSPromiseDeferred.cpp in Sources */,
</span><ins>+                                0F7CF9531DC027DB0098CC12 /* StopIfNecessaryTimer.cpp in Sources */,
</ins><span class="cx">                                 7C184E1E17BEE22E007CB63A /* JSPromisePrototype.cpp in Sources */,
</span><span class="cx">                                 2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */,
</span><span class="cx">                                 E3EF88741B66DF23003F26CB /* JSPropertyNameIterator.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -2607,8 +2607,11 @@
</span><span class="cx"> 
</span><span class="cx">     if (m_jitCode)
</span><span class="cx">         visitor.reportExtraMemoryVisited(m_jitCode-&gt;size());
</span><del>-    if (m_instructions.size())
-        visitor.reportExtraMemoryVisited(m_instructions.size() * sizeof(Instruction) / m_instructions.refCount());
</del><ins>+    if (m_instructions.size()) {
+        unsigned refCount = m_instructions.refCount();
+        RELEASE_ASSERT(refCount);
+        visitor.reportExtraMemoryVisited(m_instructions.size() * sizeof(Instruction) / refCount);
+    }
</ins><span class="cx"> 
</span><span class="cx">     stronglyVisitStrongReferences(visitor);
</span><span class="cx">     stronglyVisitWeakReferences(visitor);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDrivercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -101,10 +101,10 @@
</span><span class="cx">     
</span><span class="cx">     plan-&gt;callback = callback;
</span><span class="cx">     if (Options::useConcurrentJIT()) {
</span><del>-        Worklist* worklist = ensureGlobalWorklistFor(mode);
</del><ins>+        Worklist&amp; worklist = ensureGlobalWorklistFor(mode);
</ins><span class="cx">         if (logCompilationChanges(mode))
</span><del>-            dataLog(&quot;Deferring DFG compilation of &quot;, *codeBlock, &quot; with queue length &quot;, worklist-&gt;queueLength(), &quot;.\n&quot;);
-        worklist-&gt;enqueue(plan);
</del><ins>+            dataLog(&quot;Deferring DFG compilation of &quot;, *codeBlock, &quot; with queue length &quot;, worklist.queueLength(), &quot;.\n&quot;);
+        worklist.enqueue(plan);
</ins><span class="cx">         return CompilationDeferred;
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGWorklistcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;DFGSafepoint.h&quot;
</span><span class="cx"> #include &quot;DeferGC.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;ReleaseHeapAccessScope.h&quot;
</ins><span class="cx"> #include &lt;mutex&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="lines">@@ -104,9 +105,17 @@
</span><span class="cx">             dataLog(m_worklist, &quot;: Compiling &quot;, m_plan-&gt;key(), &quot; asynchronously\n&quot;);
</span><span class="cx">         
</span><span class="cx">         // There's no way for the GC to be safepointing since we own rightToRun.
</span><del>-        RELEASE_ASSERT(m_plan-&gt;vm-&gt;heap.mutatorState() != MutatorState::HelpingGC);
</del><ins>+        if (m_plan-&gt;vm-&gt;heap.collectorBelievesThatTheWorldIsStopped()) {
+            dataLog(&quot;Heap is stoped but here we are! (1)\n&quot;);
+            RELEASE_ASSERT_NOT_REACHED();
+        }
</ins><span class="cx">         m_plan-&gt;compileInThread(*m_longLivedState, &amp;m_data);
</span><del>-        RELEASE_ASSERT(m_plan-&gt;stage == Plan::Cancelled || m_plan-&gt;vm-&gt;heap.mutatorState() != MutatorState::HelpingGC);
</del><ins>+        if (m_plan-&gt;stage != Plan::Cancelled) {
+            if (m_plan-&gt;vm-&gt;heap.collectorBelievesThatTheWorldIsStopped()) {
+                dataLog(&quot;Heap is stopped but here we are! (2)\n&quot;);
+                RELEASE_ASSERT_NOT_REACHED();
+            }
+        }
</ins><span class="cx">         
</span><span class="cx">         {
</span><span class="cx">             LockHolder locker(*m_worklist.m_lock);
</span><span class="lines">@@ -124,7 +133,7 @@
</span><span class="cx">             
</span><span class="cx">             m_worklist.m_planCompiled.notifyAll();
</span><span class="cx">         }
</span><del>-        RELEASE_ASSERT(m_plan-&gt;vm-&gt;heap.mutatorState() != MutatorState::HelpingGC);
</del><ins>+        RELEASE_ASSERT(!m_plan-&gt;vm-&gt;heap.collectorBelievesThatTheWorldIsStopped());
</ins><span class="cx">         
</span><span class="cx">         return WorkResult::Continue;
</span><span class="cx">     }
</span><span class="lines">@@ -238,6 +247,13 @@
</span><span class="cx"> void Worklist::waitUntilAllPlansForVMAreReady(VM&amp; vm)
</span><span class="cx"> {
</span><span class="cx">     DeferGC deferGC(vm.heap);
</span><ins>+    
+    // While we are waiting for the compiler to finish, the collector might have already suspended
+    // the compiler and then it will be waiting for us to stop. That's a deadlock. We avoid that
+    // deadlock by relinquishing our heap access, so that the collector pretends that we are stopped
+    // even if we aren't.
+    ReleaseHeapAccessScope releaseHeapAccessScope(vm.heap);
+    
</ins><span class="cx">     // Wait for all of the plans for the given VM to complete. The idea here
</span><span class="cx">     // is that we want all of the caller VM's plans to be done. We don't care
</span><span class="cx">     // about any other VM's plans, and we won't attempt to wait on those.
</span><span class="lines">@@ -483,13 +499,13 @@
</span><span class="cx"> 
</span><span class="cx"> static Worklist* theGlobalDFGWorklist;
</span><span class="cx"> 
</span><del>-Worklist* ensureGlobalDFGWorklist()
</del><ins>+Worklist&amp; ensureGlobalDFGWorklist()
</ins><span class="cx"> {
</span><span class="cx">     static std::once_flag initializeGlobalWorklistOnceFlag;
</span><span class="cx">     std::call_once(initializeGlobalWorklistOnceFlag, [] {
</span><span class="cx">         theGlobalDFGWorklist = &amp;Worklist::create(&quot;DFG Worklist&quot;, Options::numberOfDFGCompilerThreads(), Options::priorityDeltaOfDFGCompilerThreads()).leakRef();
</span><span class="cx">     });
</span><del>-    return theGlobalDFGWorklist;
</del><ins>+    return *theGlobalDFGWorklist;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Worklist* existingGlobalDFGWorklistOrNull()
</span><span class="lines">@@ -499,13 +515,13 @@
</span><span class="cx"> 
</span><span class="cx"> static Worklist* theGlobalFTLWorklist;
</span><span class="cx"> 
</span><del>-Worklist* ensureGlobalFTLWorklist()
</del><ins>+Worklist&amp; ensureGlobalFTLWorklist()
</ins><span class="cx"> {
</span><span class="cx">     static std::once_flag initializeGlobalWorklistOnceFlag;
</span><span class="cx">     std::call_once(initializeGlobalWorklistOnceFlag, [] {
</span><span class="cx">         theGlobalFTLWorklist = &amp;Worklist::create(&quot;FTL Worklist&quot;, Options::numberOfFTLCompilerThreads(), Options::priorityDeltaOfFTLCompilerThreads()).leakRef();
</span><span class="cx">     });
</span><del>-    return theGlobalFTLWorklist;
</del><ins>+    return *theGlobalFTLWorklist;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Worklist* existingGlobalFTLWorklistOrNull()
</span><span class="lines">@@ -513,12 +529,12 @@
</span><span class="cx">     return theGlobalFTLWorklist;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Worklist* ensureGlobalWorklistFor(CompilationMode mode)
</del><ins>+Worklist&amp; ensureGlobalWorklistFor(CompilationMode mode)
</ins><span class="cx"> {
</span><span class="cx">     switch (mode) {
</span><span class="cx">     case InvalidCompilationMode:
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><del>-        return 0;
</del><ins>+        return ensureGlobalDFGWorklist();
</ins><span class="cx">     case DFGMode:
</span><span class="cx">         return ensureGlobalDFGWorklist();
</span><span class="cx">     case FTLMode:
</span><span class="lines">@@ -526,13 +542,13 @@
</span><span class="cx">         return ensureGlobalFTLWorklist();
</span><span class="cx">     }
</span><span class="cx">     RELEASE_ASSERT_NOT_REACHED();
</span><del>-    return 0;
</del><ins>+    return ensureGlobalDFGWorklist();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void completeAllPlansForVM(VM&amp; vm)
</span><span class="cx"> {
</span><span class="cx">     for (unsigned i = DFG::numberOfWorklists(); i--;) {
</span><del>-        if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
</del><ins>+        if (DFG::Worklist* worklist = DFG::existingWorklistForIndexOrNull(i))
</ins><span class="cx">             worklist-&gt;completeAllPlansForVM(vm);
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -540,7 +556,7 @@
</span><span class="cx"> void rememberCodeBlocks(VM&amp; vm)
</span><span class="cx"> {
</span><span class="cx">     for (unsigned i = DFG::numberOfWorklists(); i--;) {
</span><del>-        if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
</del><ins>+        if (DFG::Worklist* worklist = DFG::existingWorklistForIndexOrNull(i))
</ins><span class="cx">             worklist-&gt;rememberCodeBlocks(vm);
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGWorklisth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGWorklist.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGWorklist.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/dfg/DFGWorklist.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -121,21 +121,33 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> // For DFGMode compilations.
</span><del>-Worklist* ensureGlobalDFGWorklist();
</del><ins>+Worklist&amp; ensureGlobalDFGWorklist();
</ins><span class="cx"> Worklist* existingGlobalDFGWorklistOrNull();
</span><span class="cx"> 
</span><span class="cx"> // For FTLMode and FTLForOSREntryMode compilations.
</span><del>-Worklist* ensureGlobalFTLWorklist();
</del><ins>+Worklist&amp; ensureGlobalFTLWorklist();
</ins><span class="cx"> Worklist* existingGlobalFTLWorklistOrNull();
</span><span class="cx"> 
</span><del>-Worklist* ensureGlobalWorklistFor(CompilationMode);
</del><ins>+Worklist&amp; ensureGlobalWorklistFor(CompilationMode);
</ins><span class="cx"> 
</span><span class="cx"> // Simplify doing things for all worklists.
</span><span class="cx"> inline unsigned numberOfWorklists() { return 2; }
</span><del>-inline Worklist* worklistForIndexOrNull(unsigned index)
</del><ins>+inline Worklist&amp; ensureWorklistForIndex(unsigned index)
</ins><span class="cx"> {
</span><span class="cx">     switch (index) {
</span><span class="cx">     case 0:
</span><ins>+        return ensureGlobalDFGWorklist();
+    case 1:
+        return ensureGlobalFTLWorklist();
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        return ensureGlobalDFGWorklist();
+    }
+}
+inline Worklist* existingWorklistForIndexOrNull(unsigned index)
+{
+    switch (index) {
+    case 0:
</ins><span class="cx">         return existingGlobalDFGWorklistOrNull();
</span><span class="cx">     case 1:
</span><span class="cx">         return existingGlobalFTLWorklistOrNull();
</span><span class="lines">@@ -144,6 +156,12 @@
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><span class="cx"> }
</span><ins>+inline Worklist&amp; existingWorklistForIndex(unsigned index)
+{
+    Worklist* result = existingWorklistForIndexOrNull(index);
+    RELEASE_ASSERT(result);
+    return *result;
+}
</ins><span class="cx"> 
</span><span class="cx"> void completeAllPlansForVM(VM&amp;);
</span><span class="cx"> void rememberCodeBlocks(VM&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (safepointResult.didGetCancelled())
</span><span class="cx">         return;
</span><del>-    RELEASE_ASSERT(state.graph.m_vm.heap.mutatorState() != MutatorState::HelpingGC);
</del><ins>+    RELEASE_ASSERT(!state.graph.m_vm.heap.collectorBelievesThatTheWorldIsStopped());
</ins><span class="cx">     
</span><span class="cx">     if (state.allocationFailed)
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapEdenGCActivityCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/EdenGCActivityCallback.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> 
</span><span class="cx"> void EdenGCActivityCallback::doCollection()
</span><span class="cx"> {
</span><del>-    m_vm-&gt;heap.collect(CollectionScope::Eden);
</del><ins>+    m_vm-&gt;heap.collectAsync(CollectionScope::Eden);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> double EdenGCActivityCallback::lastGCLength()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapFullGCActivityCallbackcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/FullGCActivityCallback.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -55,7 +55,7 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    heap.collect(CollectionScope::Full);
</del><ins>+    heap.collectAsync(CollectionScope::Full);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> double FullGCActivityCallback::lastGCLength()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapGCActivityCallbackh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/GCActivityCallback.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/GCActivityCallback.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/GCActivityCallback.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2010 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2010, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -40,8 +40,7 @@
</span><span class="cx"> class FullGCActivityCallback;
</span><span class="cx"> class Heap;
</span><span class="cx"> 
</span><del>-class JS_EXPORT_PRIVATE GCActivityCallback : public HeapTimer, public ThreadSafeRefCounted&lt;GCActivityCallback&gt; {
-    WTF_MAKE_FAST_ALLOCATED;
</del><ins>+class JS_EXPORT_PRIVATE GCActivityCallback : public HeapTimer {
</ins><span class="cx"> public:
</span><span class="cx">     static RefPtr&lt;FullGCActivityCallback&gt; createFullTimer(Heap*);
</span><span class="cx">     static RefPtr&lt;GCActivityCallback&gt; createEdenTimer(Heap*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx"> #include &quot;SamplingProfiler.h&quot;
</span><span class="cx"> #include &quot;ShadowChicken.h&quot;
</span><span class="cx"> #include &quot;SuperSampler.h&quot;
</span><ins>+#include &quot;StopIfNecessaryTimer.h&quot;
</ins><span class="cx"> #include &quot;TypeProfilerLog.h&quot;
</span><span class="cx"> #include &quot;UnlinkedCodeBlock.h&quot;
</span><span class="cx"> #include &quot;VM.h&quot;
</span><span class="lines">@@ -189,6 +190,41 @@
</span><span class="cx"> 
</span><span class="cx"> } // anonymous namespace
</span><span class="cx"> 
</span><ins>+class Heap::Thread : public AutomaticThread {
+public:
+    Thread(const LockHolder&amp; locker, Heap&amp; heap)
+        : AutomaticThread(locker, heap.m_threadLock, heap.m_threadCondition)
+        , m_heap(heap)
+    {
+    }
+    
+protected:
+    PollResult poll(const LockHolder&amp; locker) override
+    {
+        if (m_heap.m_threadShouldStop) {
+            m_heap.notifyThreadStopping(locker);
+            return PollResult::Stop;
+        }
+        if (m_heap.shouldCollectInThread(locker))
+            return PollResult::Work;
+        return PollResult::Wait;
+    }
+    
+    WorkResult work() override
+    {
+        m_heap.collectInThread();
+        return WorkResult::Continue;
+    }
+    
+    void threadDidStart() override
+    {
+        WTF::registerGCThread(GCThreadType::Main);
+    }
+
+private:
+    Heap&amp; m_heap;
+};
+
</ins><span class="cx"> Heap::Heap(VM* vm, HeapType heapType)
</span><span class="cx">     : m_heapType(heapType)
</span><span class="cx">     , m_ramSize(Options::forceRAMSize() ? Options::forceRAMSize() : ramSize())
</span><span class="lines">@@ -224,15 +260,23 @@
</span><span class="cx"> #endif // USE(CF)
</span><span class="cx">     , m_fullActivityCallback(GCActivityCallback::createFullTimer(this))
</span><span class="cx">     , m_edenActivityCallback(GCActivityCallback::createEdenTimer(this))
</span><del>-    , m_sweeper(std::make_unique&lt;IncrementalSweeper&gt;(this))
</del><ins>+    , m_sweeper(adoptRef(new IncrementalSweeper(this)))
+    , m_stopIfNecessaryTimer(adoptRef(new StopIfNecessaryTimer(vm)))
</ins><span class="cx">     , m_deferralDepth(0)
</span><span class="cx"> #if USE(FOUNDATION)
</span><span class="cx">     , m_delayedReleaseRecursionCount(0)
</span><span class="cx"> #endif
</span><span class="cx">     , m_helperClient(&amp;heapHelperPool())
</span><ins>+    , m_threadLock(Box&lt;Lock&gt;::create())
+    , m_threadCondition(AutomaticThreadCondition::create())
</ins><span class="cx"> {
</span><ins>+    m_worldState.store(0);
+    
</ins><span class="cx">     if (Options::verifyHeap())
</span><span class="cx">         m_verifier = std::make_unique&lt;HeapVerifier&gt;(this, Options::numberOfGCCyclesToRecordForVerification());
</span><ins>+    
+    LockHolder locker(*m_threadLock);
+    m_thread = adoptRef(new Thread(locker, *this));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> Heap::~Heap()
</span><span class="lines">@@ -251,9 +295,28 @@
</span><span class="cx"> void Heap::lastChanceToFinalize()
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!m_vm-&gt;entryScope);
</span><del>-    RELEASE_ASSERT(!m_collectionScope);
</del><span class="cx">     RELEASE_ASSERT(m_mutatorState == MutatorState::Running);
</span><del>-
</del><ins>+    
+    // Carefully bring the thread down. We need to use waitForCollector() until we know that there
+    // won't be any other collections.
+    bool stopped = false;
+    {
+        LockHolder locker(*m_threadLock);
+        stopped = m_thread-&gt;tryStop(locker);
+        if (!stopped) {
+            m_threadShouldStop = true;
+            m_threadCondition-&gt;notifyOne(locker);
+        }
+    }
+    if (!stopped) {
+        waitForCollector(
+            [&amp;] (const LockHolder&amp;) -&gt; bool {
+                return m_threadIsStopping;
+            });
+        // It's now safe to join the thread, since we know that there will not be any more collections.
+        m_thread-&gt;join();
+    }
+    
</ins><span class="cx">     m_arrayBuffers.lastChanceToFinalize();
</span><span class="cx">     m_codeBlocks-&gt;lastChanceToFinalize();
</span><span class="cx">     m_objectSpace.lastChanceToFinalize();
</span><span class="lines">@@ -381,12 +444,10 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::markRoots(double gcStartTime, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&amp; calleeSavedRegisters)
</del><ins>+void Heap::markRoots(double gcStartTime)
</ins><span class="cx"> {
</span><span class="cx">     TimingScope markRootsTimingScope(*this, &quot;Heap::markRoots&quot;);
</span><span class="cx">     
</span><del>-    ASSERT(isValidThreadState(m_vm));
-
</del><span class="cx">     HeapRootVisitor heapRootVisitor(m_slotVisitor);
</span><span class="cx">     
</span><span class="cx">     {
</span><span class="lines">@@ -459,7 +520,7 @@
</span><span class="cx">             TimingScope preConvergenceTimingScope(*this, &quot;Heap::markRoots conservative scan&quot;);
</span><span class="cx">             ConservativeRoots conservativeRoots(*this);
</span><span class="cx">             SuperSamplerScope superSamplerScope(false);
</span><del>-            gatherStackRoots(conservativeRoots, stackOrigin, stackTop, calleeSavedRegisters);
</del><ins>+            gatherStackRoots(conservativeRoots);
</ins><span class="cx">             gatherJSStackRoots(conservativeRoots);
</span><span class="cx">             gatherScratchBufferRoots(conservativeRoots);
</span><span class="cx">             visitConservativeRoots(conservativeRoots);
</span><span class="lines">@@ -499,10 +560,10 @@
</span><span class="cx">     endMarking();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::gatherStackRoots(ConservativeRoots&amp; roots, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&amp; calleeSavedRegisters)
</del><ins>+void Heap::gatherStackRoots(ConservativeRoots&amp; roots)
</ins><span class="cx"> {
</span><span class="cx">     m_jitStubRoutines-&gt;clearMarks();
</span><del>-    m_machineThreads.gatherConservativeRoots(roots, *m_jitStubRoutines, *m_codeBlocks, stackOrigin, stackTop, calleeSavedRegisters);
</del><ins>+    m_machineThreads.gatherConservativeRoots(roots, *m_jitStubRoutines, *m_codeBlocks);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::gatherJSStackRoots(ConservativeRoots&amp; roots)
</span><span class="lines">@@ -566,8 +627,8 @@
</span><span class="cx"> void Heap::visitCompilerWorklistWeakReferences()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-    for (auto worklist : m_suspendedCompilerWorklists)
-        worklist-&gt;visitWeakReferences(m_slotVisitor);
</del><ins>+    for (unsigned i = DFG::numberOfWorklists(); i--;)
+        DFG::existingWorklistForIndex(i).visitWeakReferences(m_slotVisitor);
</ins><span class="cx"> 
</span><span class="cx">     if (Options::logGC() == GCLogging::Verbose)
</span><span class="cx">         dataLog(&quot;DFG Worklists:\n&quot;, m_slotVisitor);
</span><span class="lines">@@ -577,8 +638,8 @@
</span><span class="cx"> void Heap::removeDeadCompilerWorklistEntries()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-    for (auto worklist : m_suspendedCompilerWorklists)
-        worklist-&gt;removeDeadPlans(*m_vm);
</del><ins>+    for (unsigned i = DFG::numberOfWorklists(); i--;)
+        DFG::existingWorklistForIndex(i).removeDeadPlans(*m_vm);
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -908,7 +969,7 @@
</span><span class="cx"> void Heap::deleteUnmarkedCompiledCode()
</span><span class="cx"> {
</span><span class="cx">     clearUnmarkedExecutables();
</span><del>-    m_codeBlocks-&gt;deleteUnmarkedAndUnreferenced(*m_collectionScope);
</del><ins>+    m_codeBlocks-&gt;deleteUnmarkedAndUnreferenced(*m_lastCollectionScope);
</ins><span class="cx">     m_jitStubRoutines-&gt;deleteUnmarkedJettisonedStubRoutines();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -928,12 +989,11 @@
</span><span class="cx"> 
</span><span class="cx"> void Heap::collectAllGarbage()
</span><span class="cx"> {
</span><del>-    SuperSamplerScope superSamplerScope(false);
</del><span class="cx">     if (!m_isSafeToCollect)
</span><span class="cx">         return;
</span><ins>+    
+    collectSync(CollectionScope::Full);
</ins><span class="cx"> 
</span><del>-    collectWithoutAnySweep(CollectionScope::Full);
-
</del><span class="cx">     DeferGCForAWhile deferGC(*this);
</span><span class="cx">     if (UNLIKELY(Options::useImmortalObjects()))
</span><span class="cx">         sweeper()-&gt;willFinishSweeping();
</span><span class="lines">@@ -955,34 +1015,74 @@
</span><span class="cx">     sweepAllLogicallyEmptyWeakBlocks();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::collect(Optional&lt;CollectionScope&gt; scope)
</del><ins>+void Heap::collectAsync(Optional&lt;CollectionScope&gt; scope)
</ins><span class="cx"> {
</span><del>-    SuperSamplerScope superSamplerScope(false);
</del><span class="cx">     if (!m_isSafeToCollect)
</span><span class="cx">         return;
</span><ins>+
+    bool alreadyRequested = false;
+    {
+        LockHolder locker(*m_threadLock);
+        for (Optional&lt;CollectionScope&gt; request : m_requests) {
+            if (scope) {
+                if (scope == CollectionScope::Eden) {
+                    alreadyRequested = true;
+                    break;
+                } else {
+                    RELEASE_ASSERT(scope == CollectionScope::Full);
+                    if (request == CollectionScope::Full) {
+                        alreadyRequested = true;
+                        break;
+                    }
+                }
+            } else {
+                if (!request || request == CollectionScope::Full) {
+                    alreadyRequested = true;
+                    break;
+                }
+            }
+        }
+    }
+    if (alreadyRequested)
+        return;
+
+    requestCollection(scope);
+}
+
+void Heap::collectSync(Optional&lt;CollectionScope&gt; scope)
+{
+    if (!m_isSafeToCollect)
+        return;
</ins><span class="cx">     
</span><del>-    collectWithoutAnySweep(scope);
</del><ins>+    waitForCollection(requestCollection(scope));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-NEVER_INLINE void Heap::collectWithoutAnySweep(Optional&lt;CollectionScope&gt; scope)
</del><ins>+bool Heap::shouldCollectInThread(const LockHolder&amp;)
</ins><span class="cx"> {
</span><del>-    void* stackTop;
-    ALLOCATE_AND_GET_REGISTER_STATE(registers);
-
-    collectImpl(scope, wtfThreadData().stack().origin(), &amp;stackTop, registers);
-
-    sanitizeStackForVM(m_vm);
</del><ins>+    RELEASE_ASSERT(m_requests.isEmpty() == (m_lastServedTicket == m_lastGrantedTicket));
+    RELEASE_ASSERT(m_lastServedTicket &lt;= m_lastGrantedTicket);
+    
+    return !m_requests.isEmpty();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-NEVER_INLINE void Heap::collectImpl(Optional&lt;CollectionScope&gt; scope, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&amp; calleeSavedRegisters)
</del><ins>+void Heap::collectInThread()
</ins><span class="cx"> {
</span><ins>+    Optional&lt;CollectionScope&gt; scope;
+    {
+        LockHolder locker(*m_threadLock);
+        RELEASE_ASSERT(!m_requests.isEmpty());
+        scope = m_requests.first();
+    }
+    
</ins><span class="cx">     SuperSamplerScope superSamplerScope(false);
</span><del>-    TimingScope collectImplTimingScope(scope, &quot;Heap::collectImpl&quot;);
</del><ins>+    TimingScope collectImplTimingScope(scope, &quot;Heap::collectInThread&quot;);
</ins><span class="cx">     
</span><span class="cx"> #if ENABLE(ALLOCATION_LOGGING)
</span><span class="cx">     dataLogF(&quot;JSC GC starting collection.\n&quot;);
</span><span class="cx"> #endif
</span><span class="cx">     
</span><ins>+    stopTheWorld();
+
</ins><span class="cx">     double before = 0;
</span><span class="cx">     if (Options::logGC()) {
</span><span class="cx">         dataLog(&quot;[GC: &quot;, capacity() / 1024, &quot; kb &quot;);
</span><span class="lines">@@ -999,72 +1099,65 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx">     {
</span><span class="cx">         DeferGCForAWhile awhile(*this);
</span><del>-        JITWorklist::instance()-&gt;completeAllForVM(*m_vm);
</del><ins>+        if (JITWorklist::instance()-&gt;completeAllForVM(*m_vm))
+            setGCDidJIT();
</ins><span class="cx">     }
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx">     
</span><span class="cx">     vm()-&gt;shadowChicken().update(*vm(), vm()-&gt;topCallFrame);
</span><span class="cx">     
</span><del>-    RELEASE_ASSERT(!m_deferralDepth);
-    ASSERT(vm()-&gt;currentThreadIsHoldingAPILock());
-    RELEASE_ASSERT(vm()-&gt;atomicStringTable() == wtfThreadData().atomicStringTable());
</del><span class="cx">     ASSERT(m_isSafeToCollect);
</span><del>-    RELEASE_ASSERT(!m_collectionScope);
</del><ins>+    if (m_collectionScope) {
+        dataLog(&quot;Collection scope already set during GC: &quot;, m_collectionScope, &quot;\n&quot;);
+        RELEASE_ASSERT_NOT_REACHED();
+    }
</ins><span class="cx">     
</span><del>-    suspendCompilerThreads();
</del><span class="cx">     willStartCollection(scope);
</span><del>-    {
-        HelpingGCScope helpingHeapScope(*this);
</del><ins>+    collectImplTimingScope.setScope(*this);
</ins><span class="cx">         
</span><del>-        collectImplTimingScope.setScope(*this);
-        
-        gcStartTime = WTF::monotonicallyIncreasingTime();
-        if (m_verifier) {
-            // Verify that live objects from the last GC cycle haven't been corrupted by
-            // mutators before we begin this new GC cycle.
-            m_verifier-&gt;verify(HeapVerifier::Phase::BeforeGC);
</del><ins>+    gcStartTime = WTF::monotonicallyIncreasingTime();
+    if (m_verifier) {
+        // Verify that live objects from the last GC cycle haven't been corrupted by
+        // mutators before we begin this new GC cycle.
+        m_verifier-&gt;verify(HeapVerifier::Phase::BeforeGC);
</ins><span class="cx">             
</span><del>-            m_verifier-&gt;initializeGCCycle();
-            m_verifier-&gt;gatherLiveObjects(HeapVerifier::Phase::BeforeMarking);
-        }
</del><ins>+        m_verifier-&gt;initializeGCCycle();
+        m_verifier-&gt;gatherLiveObjects(HeapVerifier::Phase::BeforeMarking);
+    }
</ins><span class="cx">         
</span><del>-        flushOldStructureIDTables();
-        stopAllocation();
-        prepareForMarking();
-        flushWriteBarrierBuffer();
</del><ins>+    flushOldStructureIDTables();
+    stopAllocation();
+    prepareForMarking();
+    flushWriteBarrierBuffer();
</ins><span class="cx">         
</span><del>-        if (HasOwnPropertyCache* cache = vm()-&gt;hasOwnPropertyCache())
-            cache-&gt;clear();
</del><ins>+    if (HasOwnPropertyCache* cache = vm()-&gt;hasOwnPropertyCache())
+        cache-&gt;clear();
</ins><span class="cx">         
</span><del>-        markRoots(gcStartTime, stackOrigin, stackTop, calleeSavedRegisters);
</del><ins>+    markRoots(gcStartTime);
</ins><span class="cx">         
</span><del>-        if (m_verifier) {
-            m_verifier-&gt;gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
-            m_verifier-&gt;verify(HeapVerifier::Phase::AfterMarking);
-        }
</del><ins>+    if (m_verifier) {
+        m_verifier-&gt;gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
+        m_verifier-&gt;verify(HeapVerifier::Phase::AfterMarking);
+    }
</ins><span class="cx">         
</span><del>-        if (vm()-&gt;typeProfiler())
-            vm()-&gt;typeProfiler()-&gt;invalidateTypeSetCache();
</del><ins>+    if (vm()-&gt;typeProfiler())
+        vm()-&gt;typeProfiler()-&gt;invalidateTypeSetCache();
</ins><span class="cx">         
</span><del>-        reapWeakHandles();
-        pruneStaleEntriesFromWeakGCMaps();
-        sweepArrayBuffers();
-        snapshotUnswept();
-        finalizeUnconditionalFinalizers();
-        removeDeadCompilerWorklistEntries();
-        deleteUnmarkedCompiledCode();
-        deleteSourceProviderCaches();
</del><ins>+    reapWeakHandles();
+    pruneStaleEntriesFromWeakGCMaps();
+    sweepArrayBuffers();
+    snapshotUnswept();
+    finalizeUnconditionalFinalizers();
+    removeDeadCompilerWorklistEntries();
+    notifyIncrementalSweeper();
</ins><span class="cx">         
</span><del>-        notifyIncrementalSweeper();
-        m_codeBlocks-&gt;writeBarrierCurrentlyExecuting(this);
-        m_codeBlocks-&gt;clearCurrentlyExecuting();
</del><ins>+    m_codeBlocks-&gt;writeBarrierCurrentlyExecuting(this);
+    m_codeBlocks-&gt;clearCurrentlyExecuting();
</ins><span class="cx">         
</span><del>-        prepareForAllocation();
-        updateAllocationLimits();
-    }
</del><ins>+    prepareForAllocation();
+    updateAllocationLimits();
+
</ins><span class="cx">     didFinishCollection(gcStartTime);
</span><del>-    resumeCompilerThreads();
-    sweepLargeAllocations();
</del><span class="cx">     
</span><span class="cx">     if (m_verifier) {
</span><span class="cx">         m_verifier-&gt;trimDeadObjects();
</span><span class="lines">@@ -1071,17 +1164,338 @@
</span><span class="cx">         m_verifier-&gt;verify(HeapVerifier::Phase::AfterGC);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (false) {
+        dataLog(&quot;Heap state after GC:\n&quot;);
+        m_objectSpace.dumpBits();
+    }
+    
</ins><span class="cx">     if (Options::logGC()) {
</span><span class="cx">         double after = currentTimeMS();
</span><span class="cx">         dataLog(after - before, &quot; ms]\n&quot;);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (false) {
-        dataLog(&quot;Heap state after GC:\n&quot;);
-        m_objectSpace.dumpBits();
</del><ins>+    {
+        LockHolder locker(*m_threadLock);
+        m_requests.removeFirst();
+        m_lastServedTicket++;
+        clearMutatorWaiting();
</ins><span class="cx">     }
</span><ins>+    ParkingLot::unparkAll(&amp;m_worldState);
+
+    setNeedFinalize();
+    resumeTheWorld();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Heap::stopTheWorld()
+{
+    RELEASE_ASSERT(!m_collectorBelievesThatTheWorldIsStopped);
+    waitWhileNeedFinalize();
+    stopTheMutator();
+    suspendCompilerThreads();
+    m_collectorBelievesThatTheWorldIsStopped = true;
+}
+
+void Heap::resumeTheWorld()
+{
+    RELEASE_ASSERT(m_collectorBelievesThatTheWorldIsStopped);
+    m_collectorBelievesThatTheWorldIsStopped = false;
+    resumeCompilerThreads();
+    resumeTheMutator();
+}
+
+void Heap::stopTheMutator()
+{
+    for (;;) {
+        unsigned oldState = m_worldState.load();
+        if ((oldState &amp; stoppedBit)
+            &amp;&amp; (oldState &amp; shouldStopBit))
+            return;
+        
+        // Note: We could just have the mutator stop in-place like we do when !hasAccessBit. We could
+        // switch to that if it turned out to be less confusing, but then it would not give the
+        // mutator the opportunity to react to the world being stopped.
+        if (oldState &amp; mutatorWaitingBit) {
+            if (m_worldState.compareExchangeWeak(oldState, oldState &amp; ~mutatorWaitingBit))
+                ParkingLot::unparkAll(&amp;m_worldState);
+            continue;
+        }
+        
+        if (!(oldState &amp; hasAccessBit)
+            || (oldState &amp; stoppedBit)) {
+            // We can stop the world instantly.
+            if (m_worldState.compareExchangeWeak(oldState, oldState | stoppedBit | shouldStopBit))
+                return;
+            continue;
+        }
+        
+        RELEASE_ASSERT(oldState &amp; hasAccessBit);
+        RELEASE_ASSERT(!(oldState &amp; stoppedBit));
+        m_worldState.compareExchangeStrong(oldState, oldState | shouldStopBit);
+        m_stopIfNecessaryTimer-&gt;scheduleSoon();
+        ParkingLot::compareAndPark(&amp;m_worldState, oldState | shouldStopBit);
+    }
+}
+
+void Heap::resumeTheMutator()
+{
+    for (;;) {
+        unsigned oldState = m_worldState.load();
+        RELEASE_ASSERT(oldState &amp; shouldStopBit);
+        
+        if (!(oldState &amp; hasAccessBit)) {
+            // We can resume the world instantly.
+            if (m_worldState.compareExchangeWeak(oldState, oldState &amp; ~(stoppedBit | shouldStopBit))) {
+                ParkingLot::unparkAll(&amp;m_worldState);
+                return;
+            }
+            continue;
+        }
+        
+        // We can tell the world to resume.
+        if (m_worldState.compareExchangeWeak(oldState, oldState &amp; ~shouldStopBit)) {
+            ParkingLot::unparkAll(&amp;m_worldState);
+            return;
+        }
+    }
+}
+
+void Heap::stopIfNecessarySlow()
+{
+    while (stopIfNecessarySlow(m_worldState.load())) { }
+    handleGCDidJIT();
+}
+
+bool Heap::stopIfNecessarySlow(unsigned oldState)
+{
+    RELEASE_ASSERT(oldState &amp; hasAccessBit);
+    
+    if (handleNeedFinalize(oldState))
+        return true;
+    
+    if (!(oldState &amp; shouldStopBit)) {
+        if (!(oldState &amp; stoppedBit))
+            return false;
+        m_worldState.compareExchangeStrong(oldState, oldState &amp; ~stoppedBit);
+        return true;
+    }
+    
+    m_worldState.compareExchangeStrong(oldState, oldState | stoppedBit);
+    ParkingLot::unparkAll(&amp;m_worldState);
+    ParkingLot::compareAndPark(&amp;m_worldState, oldState | stoppedBit);
+    return true;
+}
+
+template&lt;typename Func&gt;
+void Heap::waitForCollector(const Func&amp; func)
+{
+    for (;;) {
+        bool done;
+        {
+            LockHolder locker(*m_threadLock);
+            done = func(locker);
+            if (!done) {
+                setMutatorWaiting();
+                // At this point, the collector knows that we intend to wait, and he will clear the
+                // waiting bit and then unparkAll when the GC cycle finishes. Clearing the bit
+                // prevents us from parking except if there is also stop-the-world. Unparking after
+                // clearing means that if the clearing happens after we park, then we will unpark.
+            }
+        }
+
+        // If we're in a stop-the-world scenario, we need to wait for that even if done is true.
+        unsigned oldState = m_worldState.load();
+        if (stopIfNecessarySlow(oldState))
+            continue;
+        
+        if (done) {
+            clearMutatorWaiting(); // Clean up just in case.
+            return;
+        }
+        
+        // If mutatorWaitingBit is still set then we want to wait.
+        ParkingLot::compareAndPark(&amp;m_worldState, oldState | mutatorWaitingBit);
+    }
+}
+
+void Heap::acquireAccessSlow()
+{
+    for (;;) {
+        unsigned oldState = m_worldState.load();
+        RELEASE_ASSERT(!(oldState &amp; hasAccessBit));
+        
+        if (oldState &amp; shouldStopBit) {
+            RELEASE_ASSERT(oldState &amp; stoppedBit);
+            // Wait until we're not stopped anymore.
+            ParkingLot::compareAndPark(&amp;m_worldState, oldState);
+            continue;
+        }
+        
+        RELEASE_ASSERT(!(oldState &amp; stoppedBit));
+        unsigned newState = oldState | hasAccessBit;
+        if (m_worldState.compareExchangeWeak(oldState, newState)) {
+            handleGCDidJIT();
+            handleNeedFinalize();
+            return;
+        }
+    }
+}
+
+void Heap::releaseAccessSlow()
+{
+    for (;;) {
+        unsigned oldState = m_worldState.load();
+        RELEASE_ASSERT(oldState &amp; hasAccessBit);
+        RELEASE_ASSERT(!(oldState &amp; stoppedBit));
+        
+        if (handleNeedFinalize(oldState))
+            continue;
+        
+        if (oldState &amp; shouldStopBit) {
+            unsigned newState = (oldState &amp; ~hasAccessBit) | stoppedBit;
+            if (m_worldState.compareExchangeWeak(oldState, newState)) {
+                ParkingLot::unparkAll(&amp;m_worldState);
+                return;
+            }
+            continue;
+        }
+        
+        RELEASE_ASSERT(!(oldState &amp; shouldStopBit));
+        
+        if (m_worldState.compareExchangeWeak(oldState, oldState &amp; ~hasAccessBit))
+            return;
+    }
+}
+
+bool Heap::handleGCDidJIT(unsigned oldState)
+{
+    RELEASE_ASSERT(oldState &amp; hasAccessBit);
+    if (!(oldState &amp; gcDidJITBit))
+        return false;
+    if (m_worldState.compareExchangeWeak(oldState, oldState &amp; ~gcDidJITBit)) {
+        WTF::crossModifyingCodeFence();
+        return true;
+    }
+    return true;
+}
+
+bool Heap::handleNeedFinalize(unsigned oldState)
+{
+    RELEASE_ASSERT(oldState &amp; hasAccessBit);
+    if (!(oldState &amp; needFinalizeBit))
+        return false;
+    if (m_worldState.compareExchangeWeak(oldState, oldState &amp; ~needFinalizeBit)) {
+        finalize();
+        // Wake up anyone waiting for us to finalize. Note that they may have woken up already, in
+        // which case they would be waiting for us to release heap access.
+        ParkingLot::unparkAll(&amp;m_worldState);
+        return true;
+    }
+    return true;
+}
+
+void Heap::handleGCDidJIT()
+{
+    while (handleGCDidJIT(m_worldState.load())) { }
+}
+
+void Heap::handleNeedFinalize()
+{
+    while (handleNeedFinalize(m_worldState.load())) { }
+}
+
+void Heap::setGCDidJIT()
+{
+    for (;;) {
+        unsigned oldState = m_worldState.load();
+        RELEASE_ASSERT(oldState &amp; stoppedBit);
+        if (m_worldState.compareExchangeWeak(oldState, oldState | gcDidJITBit))
+            return;
+    }
+}
+
+void Heap::setNeedFinalize()
+{
+    for (;;) {
+        unsigned oldState = m_worldState.load();
+        if (m_worldState.compareExchangeWeak(oldState, oldState | needFinalizeBit)) {
+            m_stopIfNecessaryTimer-&gt;scheduleSoon();
+            return;
+        }
+    }
+}
+
+void Heap::waitWhileNeedFinalize()
+{
+    for (;;) {
+        unsigned oldState = m_worldState.load();
+        if (!(oldState &amp; needFinalizeBit)) {
+            // This means that either there was no finalize request or the main thread will finalize
+            // with heap access, so a subsequent call to stopTheWorld() will return only when
+            // finalize finishes.
+            return;
+        }
+        ParkingLot::compareAndPark(&amp;m_worldState, oldState);
+    }
+}
+
+unsigned Heap::setMutatorWaiting()
+{
+    for (;;) {
+        unsigned oldState = m_worldState.load();
+        unsigned newState = oldState | mutatorWaitingBit;
+        if (m_worldState.compareExchangeWeak(oldState, newState))
+            return newState;
+    }
+}
+
+void Heap::clearMutatorWaiting()
+{
+    for (;;) {
+        unsigned oldState = m_worldState.load();
+        if (m_worldState.compareExchangeWeak(oldState, oldState &amp; ~mutatorWaitingBit))
+            return;
+    }
+}
+
+void Heap::notifyThreadStopping(const LockHolder&amp;)
+{
+    m_threadIsStopping = true;
+    clearMutatorWaiting();
+    ParkingLot::unparkAll(&amp;m_worldState);
+}
+
+void Heap::finalize()
+{
+    HelpingGCScope helpingGCScope(*this);
+    deleteUnmarkedCompiledCode();
+    deleteSourceProviderCaches();
+    sweepLargeAllocations();
+}
+
+Heap::Ticket Heap::requestCollection(Optional&lt;CollectionScope&gt; scope)
+{
+    stopIfNecessary();
+    
+    ASSERT(vm()-&gt;currentThreadIsHoldingAPILock());
+    RELEASE_ASSERT(vm()-&gt;atomicStringTable() == wtfThreadData().atomicStringTable());
+    
+    sanitizeStackForVM(m_vm);
+
+    LockHolder locker(*m_threadLock);
+    m_requests.append(scope);
+    m_lastGrantedTicket++;
+    m_threadCondition-&gt;notifyOne(locker);
+    return m_lastGrantedTicket;
+}
+
+void Heap::waitForCollection(Ticket ticket)
+{
+    waitForCollector(
+        [&amp;] (const LockHolder&amp;) -&gt; bool {
+            return m_lastServedTicket &gt;= ticket;
+        });
+}
+
</ins><span class="cx"> void Heap::sweepLargeAllocations()
</span><span class="cx"> {
</span><span class="cx">     m_objectSpace.sweepLargeAllocations();
</span><span class="lines">@@ -1090,13 +1504,11 @@
</span><span class="cx"> void Heap::suspendCompilerThreads()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-    ASSERT(m_suspendedCompilerWorklists.isEmpty());
-    for (unsigned i = DFG::numberOfWorklists(); i--;) {
-        if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i)) {
-            m_suspendedCompilerWorklists.append(worklist);
-            worklist-&gt;suspendAllThreads();
-        }
-    }
</del><ins>+    // We ensure the worklists so that it's not possible for the mutator to start a new worklist
+    // after we have suspended the ones that he had started before. That's not very expensive since
+    // the worklists use AutomaticThreads anyway.
+    for (unsigned i = DFG::numberOfWorklists(); i--;)
+        DFG::ensureWorklistForIndex(i).suspendAllThreads();
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1320,6 +1732,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RELEASE_ASSERT(m_collectionScope);
</span><ins>+    m_lastCollectionScope = m_collectionScope;
</ins><span class="cx">     m_collectionScope = Nullopt;
</span><span class="cx"> 
</span><span class="cx">     for (auto* observer : m_observers)
</span><span class="lines">@@ -1329,22 +1742,11 @@
</span><span class="cx"> void Heap::resumeCompilerThreads()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>-    for (auto worklist : m_suspendedCompilerWorklists)
-        worklist-&gt;resumeAllThreads();
-    m_suspendedCompilerWorklists.clear();
</del><ins>+    for (unsigned i = DFG::numberOfWorklists(); i--;)
+        DFG::existingWorklistForIndex(i).resumeAllThreads();
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::setFullActivityCallback(PassRefPtr&lt;FullGCActivityCallback&gt; activityCallback)
-{
-    m_fullActivityCallback = activityCallback;
-}
-
-void Heap::setEdenActivityCallback(PassRefPtr&lt;EdenGCActivityCallback&gt; activityCallback)
-{
-    m_edenActivityCallback = activityCallback;
-}
-
</del><span class="cx"> GCActivityCallback* Heap::fullActivityCallback()
</span><span class="cx"> {
</span><span class="cx">     return m_fullActivityCallback.get();
</span><span class="lines">@@ -1355,11 +1757,6 @@
</span><span class="cx">     return m_edenActivityCallback.get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::setIncrementalSweeper(std::unique_ptr&lt;IncrementalSweeper&gt; sweeper)
-{
-    m_sweeper = WTFMove(sweeper);
-}
-
</del><span class="cx"> IncrementalSweeper* Heap::sweeper()
</span><span class="cx"> {
</span><span class="cx">     return m_sweeper.get();
</span><span class="lines">@@ -1546,7 +1943,7 @@
</span><span class="cx">     addToRememberedSet(from);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Heap::shouldCollect()
</del><ins>+bool Heap::canCollect()
</ins><span class="cx"> {
</span><span class="cx">     if (isDeferred())
</span><span class="cx">         return false;
</span><span class="lines">@@ -1554,11 +1951,21 @@
</span><span class="cx">         return false;
</span><span class="cx">     if (collectionScope() || mutatorState() == MutatorState::HelpingGC)
</span><span class="cx">         return false;
</span><ins>+    return true;
+}
+
+bool Heap::shouldCollectHeuristic()
+{
</ins><span class="cx">     if (Options::gcMaxHeapSize())
</span><span class="cx">         return m_bytesAllocatedThisCycle &gt; Options::gcMaxHeapSize();
</span><span class="cx">     return m_bytesAllocatedThisCycle &gt; m_maxEdenSize;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool Heap::shouldCollect()
+{
+    return canCollect() &amp;&amp; shouldCollectHeuristic();
+}
+
</ins><span class="cx"> bool Heap::isCurrentThreadBusy()
</span><span class="cx"> {
</span><span class="cx">     return mayBeGCThread() || mutatorState() != MutatorState::Running;
</span><span class="lines">@@ -1598,13 +2005,22 @@
</span><span class="cx"> 
</span><span class="cx"> bool Heap::collectIfNecessaryOrDefer(GCDeferralContext* deferralContext)
</span><span class="cx"> {
</span><del>-    if (!shouldCollect())
</del><ins>+    if (!canCollect())
</ins><span class="cx">         return false;
</span><ins>+    
+    if (deferralContext) {
+        deferralContext-&gt;m_shouldGC |=
+            !!(m_worldState.load() &amp; (shouldStopBit | needFinalizeBit | gcDidJITBit));
+    } else
+        stopIfNecessary();
+    
+    if (!shouldCollectHeuristic())
+        return false;
</ins><span class="cx"> 
</span><span class="cx">     if (deferralContext)
</span><span class="cx">         deferralContext-&gt;m_shouldGC = true;
</span><span class="cx">     else
</span><del>-        collect();
</del><ins>+        collectAsync();
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1614,7 +2030,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     if (randomNumber() &lt; Options::deferGCProbability()) {
</span><del>-        collect();
</del><ins>+        collectAsync();
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1660,4 +2076,14 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if USE(CF)
+void Heap::setRunLoop(CFRunLoopRef runLoop)
+{
+    m_runLoop = runLoop;
+    m_fullActivityCallback-&gt;setRunLoop(runLoop);
+    m_edenActivityCallback-&gt;setRunLoop(runLoop);
+    m_sweeper-&gt;setRunLoop(runLoop);
+}
+#endif // USE(CF)
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -43,6 +43,8 @@
</span><span class="cx"> #include &quot;WeakReferenceHarvester.h&quot;
</span><span class="cx"> #include &quot;WriteBarrierBuffer.h&quot;
</span><span class="cx"> #include &quot;WriteBarrierSupport.h&quot;
</span><ins>+#include &lt;wtf/AutomaticThread.h&gt;
+#include &lt;wtf/Deque.h&gt;
</ins><span class="cx"> #include &lt;wtf/HashCountedSet.h&gt;
</span><span class="cx"> #include &lt;wtf/HashSet.h&gt;
</span><span class="cx"> #include &lt;wtf/ParallelHelperPool.h&gt;
</span><span class="lines">@@ -69,6 +71,7 @@
</span><span class="cx"> class JSValue;
</span><span class="cx"> class LLIntOffsetsExtractor;
</span><span class="cx"> class MarkedArgumentBuffer;
</span><ins>+class StopIfNecessaryTimer;
</ins><span class="cx"> class VM;
</span><span class="cx"> 
</span><span class="cx"> namespace DFG {
</span><span class="lines">@@ -130,12 +133,9 @@
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE GCActivityCallback* fullActivityCallback();
</span><span class="cx">     JS_EXPORT_PRIVATE GCActivityCallback* edenActivityCallback();
</span><del>-    JS_EXPORT_PRIVATE void setFullActivityCallback(PassRefPtr&lt;FullGCActivityCallback&gt;);
-    JS_EXPORT_PRIVATE void setEdenActivityCallback(PassRefPtr&lt;EdenGCActivityCallback&gt;);
</del><span class="cx">     JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool);
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
</span><del>-    JS_EXPORT_PRIVATE void setIncrementalSweeper(std::unique_ptr&lt;IncrementalSweeper&gt;);
</del><span class="cx"> 
</span><span class="cx">     void addObserver(HeapObserver* observer) { m_observers.append(observer); }
</span><span class="cx">     void removeObserver(HeapObserver* observer) { m_observers.removeFirst(observer); }
</span><span class="lines">@@ -142,6 +142,9 @@
</span><span class="cx"> 
</span><span class="cx">     MutatorState mutatorState() const { return m_mutatorState; }
</span><span class="cx">     Optional&lt;CollectionScope&gt; collectionScope() const { return m_collectionScope; }
</span><ins>+    bool hasHeapAccess() const;
+    bool mutatorIsStopped() const;
+    bool collectorBelievesThatTheWorldIsStopped() const;
</ins><span class="cx"> 
</span><span class="cx">     // We're always busy on the collection threads. On the main thread, this returns true if we're
</span><span class="cx">     // helping heap.
</span><span class="lines">@@ -173,8 +176,24 @@
</span><span class="cx">     JS_EXPORT_PRIVATE void collectAllGarbageIfNotDoneRecently();
</span><span class="cx">     JS_EXPORT_PRIVATE void collectAllGarbage();
</span><span class="cx"> 
</span><ins>+    bool canCollect();
+    bool shouldCollectHeuristic();
</ins><span class="cx">     bool shouldCollect();
</span><del>-    JS_EXPORT_PRIVATE void collect(Optional&lt;CollectionScope&gt; = Nullopt);
</del><ins>+    
+    // Queue up a collection. Returns immediately. This will not queue a collection if a collection
+    // of equal or greater strength exists. Full collections are stronger than Nullopt collections
+    // and Nullopt collections are stronger than Eden collections. Nullopt means that the GC can
+    // choose Eden or Full. This implies that if you request a GC while that GC is ongoing, nothing
+    // will happen.
+    JS_EXPORT_PRIVATE void collectAsync(Optional&lt;CollectionScope&gt; = Nullopt);
+    
+    // Queue up a collection and wait for it to complete. This won't return until you get your own
+    // complete collection. For example, if there was an ongoing asynchronous collection at the time
+    // you called this, then this would wait for that one to complete and then trigger your
+    // collection and then return. In weird cases, there could be multiple GC requests in the backlog
+    // and this will wait for that backlog before running its GC and returning.
+    JS_EXPORT_PRIVATE void collectSync(Optional&lt;CollectionScope&gt; = Nullopt);
+    
</ins><span class="cx">     bool collectIfNecessaryOrDefer(GCDeferralContext* = nullptr); // Returns true if it did collect.
</span><span class="cx">     void collectAccordingToDeferGCProbability();
</span><span class="cx"> 
</span><span class="lines">@@ -270,8 +289,52 @@
</span><span class="cx">     unsigned barrierThreshold() const { return m_barrierThreshold; }
</span><span class="cx">     const unsigned* addressOfBarrierThreshold() const { return &amp;m_barrierThreshold; }
</span><span class="cx"> 
</span><ins>+    // If true, the GC believes that the mutator is currently messing with the heap. We call this
+    // &quot;having heap access&quot;. The GC may block if the mutator is in this state. If false, the GC may
+    // currently be doing things to the heap that make the heap unsafe to access for the mutator.
+    bool hasAccess() const;
+    
+    // If the mutator does not currently have heap access, this function will acquire it. If the GC
+    // is currently using the lack of heap access to do dangerous things to the heap then this
+    // function will block, waiting for the GC to finish. It's not valid to call this if the mutator
+    // already has heap access. The mutator is required to precisely track whether or not it has
+    // heap access.
+    //
+    // It's totally fine to acquireAccess() upon VM instantiation and keep it that way. This is how
+    // WebCore uses us. For most other clients, JSLock does acquireAccess()/releaseAccess() for you.
+    void acquireAccess();
+    
+    // Releases heap access. If the GC is blocking waiting to do bad things to the heap, it will be
+    // allowed to run now.
+    //
+    // Ordinarily, you should use the ReleaseHeapAccessScope to release and then reacquire heap
+    // access. You should do this anytime you're about do perform a blocking operation, like waiting
+    // on the ParkingLot.
+    void releaseAccess();
+    
+    // This is like a super optimized way of saying:
+    //
+    //     releaseAccess()
+    //     acquireAccess()
+    //
+    // The fast path is an inlined relaxed load and branch. The slow path will block the mutator if
+    // the GC wants to do bad things to the heap.
+    //
+    // All allocations logically call this. As an optimization to improve GC progress, you can call
+    // this anywhere that you can afford a load-branch and where an object allocation would have been
+    // safe.
+    //
+    // The GC will also push a stopIfNecessary() event onto the runloop of the thread that
+    // instantiated the VM whenever it wants the mutator to stop. This means that if you never block
+    // but instead use the runloop to wait for events, then you could safely run in a mode where the
+    // mutator has permanent heap access (like the DOM does). If you have good event handling
+    // discipline (i.e. you don't block the runloop) then you can be sure that stopIfNecessary() will
+    // already be called for you at the right times.
+    void stopIfNecessary();
+    
</ins><span class="cx"> #if USE(CF)
</span><span class="cx">     CFRunLoopRef runLoop() const { return m_runLoop.get(); }
</span><ins>+    JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef);
</ins><span class="cx"> #endif // USE(CF)
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="lines">@@ -296,13 +359,15 @@
</span><span class="cx">     friend class HeapStatistics;
</span><span class="cx">     friend class VM;
</span><span class="cx">     friend class WeakSet;
</span><ins>+
+    class Thread;
+    friend class Thread;
+
</ins><span class="cx">     template&lt;typename T&gt; friend void* allocateCell(Heap&amp;);
</span><span class="cx">     template&lt;typename T&gt; friend void* allocateCell(Heap&amp;, size_t);
</span><span class="cx">     template&lt;typename T&gt; friend void* allocateCell(Heap&amp;, GCDeferralContext*);
</span><span class="cx">     template&lt;typename T&gt; friend void* allocateCell(Heap&amp;, GCDeferralContext*, size_t);
</span><span class="cx"> 
</span><del>-    void collectWithoutAnySweep(Optional&lt;CollectionScope&gt; = Nullopt);
-
</del><span class="cx">     void* allocateWithDestructor(size_t); // For use with objects with destructors.
</span><span class="cx">     void* allocateWithoutDestructor(size_t); // For use with objects without destructors.
</span><span class="cx">     void* allocateWithDestructor(GCDeferralContext*, size_t);
</span><span class="lines">@@ -319,9 +384,42 @@
</span><span class="cx">     JS_EXPORT_PRIVATE bool isValidAllocation(size_t);
</span><span class="cx">     JS_EXPORT_PRIVATE void reportExtraMemoryAllocatedSlowCase(size_t);
</span><span class="cx">     JS_EXPORT_PRIVATE void deprecatedReportExtraMemorySlowCase(size_t);
</span><del>-
-    void collectImpl(Optional&lt;CollectionScope&gt;, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&amp;);
-
</del><ins>+    
+    bool shouldCollectInThread(const LockHolder&amp;);
+    void collectInThread();
+    
+    void stopTheWorld();
+    void resumeTheWorld();
+    
+    void stopTheMutator();
+    void resumeTheMutator();
+    
+    void stopIfNecessarySlow();
+    bool stopIfNecessarySlow(unsigned extraStateBits);
+    
+    template&lt;typename Func&gt;
+    void waitForCollector(const Func&amp;);
+    
+    JS_EXPORT_PRIVATE void acquireAccessSlow();
+    JS_EXPORT_PRIVATE void releaseAccessSlow();
+    
+    bool handleGCDidJIT(unsigned);
+    bool handleNeedFinalize(unsigned);
+    void handleGCDidJIT();
+    void handleNeedFinalize();
+    
+    void setGCDidJIT();
+    void setNeedFinalize();
+    void waitWhileNeedFinalize();
+    
+    unsigned setMutatorWaiting();
+    void clearMutatorWaiting();
+    void notifyThreadStopping(const LockHolder&amp;);
+    
+    typedef uint64_t Ticket;
+    Ticket requestCollection(Optional&lt;CollectionScope&gt;);
+    void waitForCollection(Ticket);
+    
</ins><span class="cx">     void suspendCompilerThreads();
</span><span class="cx">     void willStartCollection(Optional&lt;CollectionScope&gt;);
</span><span class="cx">     void flushOldStructureIDTables();
</span><span class="lines">@@ -329,8 +427,8 @@
</span><span class="cx">     void stopAllocation();
</span><span class="cx">     void prepareForMarking();
</span><span class="cx">     
</span><del>-    void markRoots(double gcStartTime, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&amp;);
-    void gatherStackRoots(ConservativeRoots&amp;, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&amp;);
</del><ins>+    void markRoots(double gcStartTime);
+    void gatherStackRoots(ConservativeRoots&amp;);
</ins><span class="cx">     void gatherJSStackRoots(ConservativeRoots&amp;);
</span><span class="cx">     void gatherScratchBufferRoots(ConservativeRoots&amp;);
</span><span class="cx">     void beginMarking();
</span><span class="lines">@@ -369,6 +467,7 @@
</span><span class="cx">     void zombifyDeadObjects();
</span><span class="cx">     void gatherExtraHeapSnapshotData(HeapProfiler&amp;);
</span><span class="cx">     void removeDeadHeapSnapshotNodes(HeapProfiler&amp;);
</span><ins>+    void finalize();
</ins><span class="cx">     void sweepLargeAllocations();
</span><span class="cx">     
</span><span class="cx">     void sweepAllLogicallyEmptyWeakBlocks();
</span><span class="lines">@@ -403,6 +502,7 @@
</span><span class="cx">     size_t m_totalBytesVisitedThisCycle;
</span><span class="cx">     
</span><span class="cx">     Optional&lt;CollectionScope&gt; m_collectionScope;
</span><ins>+    Optional&lt;CollectionScope&gt; m_lastCollectionScope;
</ins><span class="cx">     MutatorState m_mutatorState { MutatorState::Running };
</span><span class="cx">     StructureIDTable m_structureIDTable;
</span><span class="cx">     MarkedSpace m_objectSpace;
</span><span class="lines">@@ -453,12 +553,12 @@
</span><span class="cx"> #endif // USE(CF)
</span><span class="cx">     RefPtr&lt;FullGCActivityCallback&gt; m_fullActivityCallback;
</span><span class="cx">     RefPtr&lt;GCActivityCallback&gt; m_edenActivityCallback;
</span><del>-    std::unique_ptr&lt;IncrementalSweeper&gt; m_sweeper;
</del><ins>+    RefPtr&lt;IncrementalSweeper&gt; m_sweeper;
+    RefPtr&lt;StopIfNecessaryTimer&gt; m_stopIfNecessaryTimer;
</ins><span class="cx"> 
</span><span class="cx">     Vector&lt;HeapObserver*&gt; m_observers;
</span><span class="cx"> 
</span><span class="cx">     unsigned m_deferralDepth;
</span><del>-    Vector&lt;DFG::Worklist*&gt; m_suspendedCompilerWorklists;
</del><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;HeapVerifier&gt; m_verifier;
</span><span class="cx"> 
</span><span class="lines">@@ -490,6 +590,24 @@
</span><span class="cx">     size_t m_blockBytesAllocated { 0 };
</span><span class="cx">     size_t m_externalMemorySize { 0 };
</span><span class="cx"> #endif
</span><ins>+    
+    static const unsigned shouldStopBit = 1u &lt;&lt; 0u;
+    static const unsigned stoppedBit = 1u &lt;&lt; 1u;
+    static const unsigned hasAccessBit = 1u &lt;&lt; 2u;
+    static const unsigned gcDidJITBit = 1u &lt;&lt; 3u; // Set when the GC did some JITing, so on resume we need to cpuid.
+    static const unsigned needFinalizeBit = 1u &lt;&lt; 4u;
+    static const unsigned mutatorWaitingBit = 1u &lt;&lt; 5u; // Allows the mutator to use this as a condition variable.
+    Atomic&lt;unsigned&gt; m_worldState;
+    bool m_collectorBelievesThatTheWorldIsStopped { false };
+    
+    Deque&lt;Optional&lt;CollectionScope&gt;&gt; m_requests;
+    Ticket m_lastServedTicket { 0 };
+    Ticket m_lastGrantedTicket { 0 };
+    bool m_threadShouldStop { false };
+    bool m_threadIsStopping { false };
+    Box&lt;Lock&gt; m_threadLock;
+    RefPtr&lt;AutomaticThreadCondition&gt; m_threadCondition; // The mutator must not wait on this. It would cause a deadlock.
+    RefPtr&lt;AutomaticThread&gt; m_thread;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapInlines.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapInlines.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/HeapInlines.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -51,6 +51,34 @@
</span><span class="cx">     return heap(v.asCell());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool Heap::hasHeapAccess() const
+{
+    return m_worldState.load() &amp; hasAccessBit;
+}
+
+inline bool Heap::mutatorIsStopped() const
+{
+    unsigned state = m_worldState.load();
+    bool shouldStop = state &amp; shouldStopBit;
+    bool stopped = state &amp; stoppedBit;
+    // I only got it right when I considered all four configurations of shouldStop/stopped:
+    // !shouldStop, !stopped: The GC has not requested that we stop and we aren't stopped, so we
+    //     should return false.
+    // !shouldStop, stopped: The mutator is still stopped but the GC is done and the GC has requested
+    //     that we resume, so we should return false.
+    // shouldStop, !stopped: The GC called stopTheWorld() but the mutator hasn't hit a safepoint yet.
+    //     The mutator should be able to do whatever it wants in this state, as if we were not
+    //     stopped. So return false.
+    // shouldStop, stopped: The GC requested stop the world and the mutator obliged. The world is
+    //     stopped, so return true.
+    return shouldStop &amp; stopped;
+}
+
+inline bool Heap::collectorBelievesThatTheWorldIsStopped() const
+{
+    return m_collectorBelievesThatTheWorldIsStopped;
+}
+
</ins><span class="cx"> ALWAYS_INLINE bool Heap::isMarked(const void* rawCell)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(mayBeGCThread() != GCThreadType::Helper);
</span><span class="lines">@@ -310,4 +338,30 @@
</span><span class="cx">         deprecatedReportExtraMemorySlowCase(size);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void Heap::acquireAccess()
+{
+    if (m_worldState.compareExchangeWeak(0, hasAccessBit))
+        return;
+    acquireAccessSlow();
+}
+
+inline bool Heap::hasAccess() const
+{
+    return m_worldState.loadRelaxed() &amp; hasAccessBit;
+}
+
+inline void Heap::releaseAccess()
+{
+    if (m_worldState.compareExchangeWeak(hasAccessBit, 0))
+        return;
+    releaseAccessSlow();
+}
+
+inline void Heap::stopIfNecessary()
+{
+    if (m_worldState.loadRelaxed() == hasAccessBit)
+        return;
+    stopIfNecessarySlow();
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapTimercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapTimer.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapTimer.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/HeapTimer.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -99,11 +99,13 @@
</span><span class="cx"> void HeapTimer::scheduleTimer(double intervalInSeconds)
</span><span class="cx"> {
</span><span class="cx">     CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + intervalInSeconds);
</span><ins>+    m_isScheduled = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HeapTimer::cancelTimer()
</span><span class="cx"> {
</span><span class="cx">     CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() + s_decade);
</span><ins>+    m_isScheduled = false;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #elif PLATFORM(EFL)
</span><span class="lines">@@ -152,11 +154,13 @@
</span><span class="cx"> 
</span><span class="cx">     double targetTime = currentTime() + intervalInSeconds;
</span><span class="cx">     ecore_timer_interval_set(m_timer, targetTime);
</span><ins>+    m_isScheduled = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HeapTimer::cancelTimer()
</span><span class="cx"> {
</span><span class="cx">     ecore_timer_freeze(m_timer);
</span><ins>+    m_isScheduled = false;
</ins><span class="cx"> }
</span><span class="cx"> #elif USE(GLIB)
</span><span class="cx"> 
</span><span class="lines">@@ -219,11 +223,13 @@
</span><span class="cx">     gint64 targetTime = currentTime + std::min&lt;gint64&gt;(G_MAXINT64 - currentTime, delayDuration.count());
</span><span class="cx">     ASSERT(targetTime &gt;= currentTime);
</span><span class="cx">     g_source_set_ready_time(m_timer.get(), targetTime);
</span><ins>+    m_isScheduled = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void HeapTimer::cancelTimer()
</span><span class="cx"> {
</span><span class="cx">     g_source_set_ready_time(m_timer.get(), -1);
</span><ins>+    m_isScheduled = false;
</ins><span class="cx"> }
</span><span class="cx"> #else
</span><span class="cx"> HeapTimer::HeapTimer(VM* vm)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapTimerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapTimer.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapTimer.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/HeapTimer.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx"> class JSLock;
</span><span class="cx"> class VM;
</span><span class="cx"> 
</span><del>-class HeapTimer {
</del><ins>+class HeapTimer : public ThreadSafeRefCounted&lt;HeapTimer&gt; {
</ins><span class="cx"> public:
</span><span class="cx">     HeapTimer(VM*);
</span><span class="cx"> #if USE(CF)
</span><span class="lines">@@ -56,6 +56,7 @@
</span><span class="cx"> 
</span><span class="cx">     void scheduleTimer(double intervalInSeconds);
</span><span class="cx">     void cancelTimer();
</span><ins>+    bool isScheduled() const { return m_isScheduled; }
</ins><span class="cx"> 
</span><span class="cx"> #if USE(CF)
</span><span class="cx">     JS_EXPORT_PRIVATE void setRunLoop(CFRunLoopRef);
</span><span class="lines">@@ -65,6 +66,7 @@
</span><span class="cx">     VM* m_vm;
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;JSLock&gt; m_apiLock;
</span><ins>+    bool m_isScheduled { false };
</ins><span class="cx"> #if USE(CF)
</span><span class="cx">     static const CFTimeInterval s_decade;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapIncrementalSweepercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -71,6 +71,8 @@
</span><span class="cx"> 
</span><span class="cx"> bool IncrementalSweeper::sweepNextBlock()
</span><span class="cx"> {
</span><ins>+    m_vm-&gt;heap.stopIfNecessary();
+
</ins><span class="cx">     MarkedBlock::Handle* block = nullptr;
</span><span class="cx">     
</span><span class="cx">     for (; m_currentAllocator; m_currentAllocator = m_currentAllocator-&gt;nextAllocator()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapIncrementalSweeperh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -34,7 +34,6 @@
</span><span class="cx"> class MarkedAllocator;
</span><span class="cx"> 
</span><span class="cx"> class IncrementalSweeper : public HeapTimer {
</span><del>-    WTF_MAKE_FAST_ALLOCATED;
</del><span class="cx"> public:
</span><span class="cx">     JS_EXPORT_PRIVATE explicit IncrementalSweeper(Heap*);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMachineStackMarkercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- *  Copyright (C) 2003-2009, 2015 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2009, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *  Copyright (C) 2007 Eric Seidel &lt;eric@webkit.org&gt;
</span><span class="cx">  *  Copyright (C) 2009 Acision BV. All rights reserved.
</span><span class="cx">  *
</span><span class="lines">@@ -301,16 +301,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-SUPPRESS_ASAN
-void MachineThreads::gatherFromCurrentThread(ConservativeRoots&amp; conservativeRoots, JITStubRoutineSet&amp; jitStubRoutines, CodeBlockSet&amp; codeBlocks, void* stackOrigin, void* stackTop, RegisterState&amp; calleeSavedRegisters)
-{
-    void* registersBegin = &amp;calleeSavedRegisters;
-    void* registersEnd = reinterpret_cast&lt;void*&gt;(roundUpToMultipleOf&lt;sizeof(void*)&gt;(reinterpret_cast&lt;uintptr_t&gt;(&amp;calleeSavedRegisters + 1)));
-    conservativeRoots.add(registersBegin, registersEnd, jitStubRoutines, codeBlocks);
-
-    conservativeRoots.add(stackTop, stackOrigin, jitStubRoutines, codeBlocks);
-}
-
</del><span class="cx"> MachineThreads::Thread::Thread(const PlatformThread&amp; platThread, void* base, void* end)
</span><span class="cx">     : platformThread(platThread)
</span><span class="cx">     , stackBase(base)
</span><span class="lines">@@ -1018,10 +1008,8 @@
</span><span class="cx">     *buffer = fastMalloc(*capacity);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MachineThreads::gatherConservativeRoots(ConservativeRoots&amp; conservativeRoots, JITStubRoutineSet&amp; jitStubRoutines, CodeBlockSet&amp; codeBlocks, void* stackOrigin, void* stackTop, RegisterState&amp; calleeSavedRegisters)
</del><ins>+void MachineThreads::gatherConservativeRoots(ConservativeRoots&amp; conservativeRoots, JITStubRoutineSet&amp; jitStubRoutines, CodeBlockSet&amp; codeBlocks)
</ins><span class="cx"> {
</span><del>-    gatherFromCurrentThread(conservativeRoots, jitStubRoutines, codeBlocks, stackOrigin, stackTop, calleeSavedRegisters);
-
</del><span class="cx">     size_t size;
</span><span class="cx">     size_t capacity = 0;
</span><span class="cx">     void* buffer = nullptr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMachineStackMarkerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MachineStackMarker.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MachineStackMarker.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/heap/MachineStackMarker.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
</span><del>- *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2015 Apple Inc. All rights reserved.
</del><ins>+ *  Copyright (C) 2003-2009, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  *  This library is free software; you can redistribute it and/or
</span><span class="cx">  *  modify it under the terms of the GNU Lesser General Public
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx">     MachineThreads(Heap*);
</span><span class="cx">     ~MachineThreads();
</span><span class="cx"> 
</span><del>-    void gatherConservativeRoots(ConservativeRoots&amp;, JITStubRoutineSet&amp;, CodeBlockSet&amp;, void* stackOrigin, void* stackTop, RegisterState&amp; calleeSavedRegisters);
</del><ins>+    void gatherConservativeRoots(ConservativeRoots&amp;, JITStubRoutineSet&amp;, CodeBlockSet&amp;);
</ins><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
</span><span class="cx"> 
</span><span class="lines">@@ -145,8 +145,6 @@
</span><span class="cx">     Thread* machineThreadForCurrentThread();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    void gatherFromCurrentThread(ConservativeRoots&amp;, JITStubRoutineSet&amp;, CodeBlockSet&amp;, void* stackOrigin, void* stackTop, RegisterState&amp; calleeSavedRegisters);
-
</del><span class="cx">     void tryCopyOtherThreadStack(Thread*, void*, size_t capacity, size_t*);
</span><span class="cx">     bool tryCopyOtherThreadStacks(LockHolder&amp;, void*, size_t capacity, size_t*);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapReleaseHeapAccessScopeh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/ReleaseHeapAccessScope.h (0 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/ReleaseHeapAccessScope.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/ReleaseHeapAccessScope.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include &quot;Heap.h&quot;
+
+namespace JSC {
+
+// Almost all of the VM's code runs with &quot;heap access&quot;. This means that the GC thread believes that
+// the VM is messing with the heap in a way that would be unsafe for certain phases of the collector,
+// like the weak reference fixpoint, stack scanning, and changing barrier modes. However, many long
+// running operations inside the VM don't require heap access. For example, memcpying a typed array
+// if a reference to it is on the stack is totally fine without heap access. Blocking on a futex is
+// also fine without heap access. Releasing heap access for long-running code (in the case of futex
+// wait, possibly infinitely long-running) ensures that the GC can finish a collection cycle while
+// you are waiting.
+class ReleaseHeapAccessScope {
+public:
+    ReleaseHeapAccessScope(Heap&amp; heap)
+        : m_heap(heap)
+    {
+        m_heap.releaseAccess();
+    }
+    
+    ~ReleaseHeapAccessScope()
+    {
+        m_heap.acquireAccess();
+    }
+
+private:
+    Heap&amp; m_heap;
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapStopIfNecessaryTimercpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp (0 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -0,0 +1,55 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;StopIfNecessaryTimer.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+StopIfNecessaryTimer::StopIfNecessaryTimer(VM* vm)
+    : HeapTimer(vm)
+{
+}
+
+void StopIfNecessaryTimer::doWork()
+{
+    cancelTimer();
+    WTF::storeStoreFence();
+    m_vm-&gt;heap.stopIfNecessary();
+}
+
+void StopIfNecessaryTimer::scheduleSoon()
+{
+    if (isScheduled()) {
+        WTF::loadLoadFence();
+        return;
+    }
+    scheduleTimer(0);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapStopIfNecessaryTimerh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h (0 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/heap/StopIfNecessaryTimer.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -0,0 +1,44 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#pragma once
+
+#include &quot;HeapTimer.h&quot;
+
+namespace JSC {
+
+class Heap;
+
+class StopIfNecessaryTimer : public HeapTimer {
+public:
+    explicit StopIfNecessaryTimer(VM*);
+    
+    void doWork() override;
+    
+    void scheduleSoon();
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectoragentsInspectorDebuggerAgentcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -455,6 +455,7 @@
</span><span class="cx"> 
</span><span class="cx"> void InspectorDebuggerAgent::setBreakpoint(JSC::Breakpoint&amp; breakpoint, bool&amp; existing)
</span><span class="cx"> {
</span><ins>+    JSC::JSLockHolder locker(m_scriptDebugServer.vm());
</ins><span class="cx">     m_scriptDebugServer.setBreakpoint(breakpoint, existing);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -469,6 +470,7 @@
</span><span class="cx">         for (auto&amp; action : breakpointActions)
</span><span class="cx">             m_injectedScriptManager.releaseObjectGroup(objectGroupForBreakpointAction(action));
</span><span class="cx"> 
</span><ins>+        JSC::JSLockHolder locker(m_scriptDebugServer.vm());
</ins><span class="cx">         m_scriptDebugServer.removeBreakpointActions(breakpointID);
</span><span class="cx">         m_scriptDebugServer.removeBreakpoint(breakpointID);
</span><span class="cx">     }
</span><span class="lines">@@ -560,6 +562,7 @@
</span><span class="cx"> 
</span><span class="cx">     m_breakReason = breakReason;
</span><span class="cx">     m_breakAuxData = WTFMove(data);
</span><ins>+    JSC::JSLockHolder locker(m_scriptDebugServer.vm());
</ins><span class="cx">     m_scriptDebugServer.setPauseOnNextStatement(true);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -881,9 +884,12 @@
</span><span class="cx"> 
</span><span class="cx"> void InspectorDebuggerAgent::clearDebuggerBreakpointState()
</span><span class="cx"> {
</span><del>-    m_scriptDebugServer.clearBreakpointActions();
-    m_scriptDebugServer.clearBreakpoints();
-    m_scriptDebugServer.clearBlacklist();
</del><ins>+    {
+        JSC::JSLockHolder holder(m_scriptDebugServer.vm());
+        m_scriptDebugServer.clearBreakpointActions();
+        m_scriptDebugServer.clearBreakpoints();
+        m_scriptDebugServer.clearBlacklist();
+    }
</ins><span class="cx"> 
</span><span class="cx">     m_pausedScriptState = nullptr;
</span><span class="cx">     m_currentCallStack = { };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITWorklistcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITWorklist.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITWorklist.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/jit/JITWorklist.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -158,8 +158,9 @@
</span><span class="cx">     UNREACHABLE_FOR_PLATFORM();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JITWorklist::completeAllForVM(VM&amp; vm)
</del><ins>+bool JITWorklist::completeAllForVM(VM&amp; vm)
</ins><span class="cx"> {
</span><ins>+    bool result = false;
</ins><span class="cx">     DeferGC deferGC(vm.heap);
</span><span class="cx">     for (;;) {
</span><span class="cx">         Vector&lt;RefPtr&lt;Plan&gt;, 32&gt; myPlans;
</span><span class="lines">@@ -186,12 +187,14 @@
</span><span class="cx">                 // If we don't find plans, then we're either done or we need to wait, depending on
</span><span class="cx">                 // whether we found some unfinished plans.
</span><span class="cx">                 if (!didFindUnfinishedPlan)
</span><del>-                    return;
</del><ins>+                    return result;
</ins><span class="cx">                 
</span><span class="cx">                 m_condition-&gt;wait(*m_lock);
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        RELEASE_ASSERT(!myPlans.isEmpty());
+        result = true;
</ins><span class="cx">         finalizePlans(myPlans);
</span><span class="cx">     }
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITWorklisth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITWorklist.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITWorklist.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/jit/JITWorklist.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx"> public:
</span><span class="cx">     ~JITWorklist();
</span><span class="cx">     
</span><del>-    void completeAllForVM(VM&amp;);
</del><ins>+    bool completeAllForVM(VM&amp;); // Return true if any JIT work happened.
</ins><span class="cx">     void poll(VM&amp;);
</span><span class="cx">     
</span><span class="cx">     void compileLater(CodeBlock*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1677,7 +1677,7 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL functionFullGC(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     JSLockHolder lock(exec);
</span><del>-    exec-&gt;heap()-&gt;collect(CollectionScope::Full);
</del><ins>+    exec-&gt;heap()-&gt;collectSync(CollectionScope::Full);
</ins><span class="cx">     return JSValue::encode(jsNumber(exec-&gt;heap()-&gt;sizeAfterLastFullCollection()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1684,7 +1684,7 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     JSLockHolder lock(exec);
</span><del>-    exec-&gt;heap()-&gt;collect(CollectionScope::Eden);
</del><ins>+    exec-&gt;heap()-&gt;collectSync(CollectionScope::Eden);
</ins><span class="cx">     return JSValue::encode(jsNumber(exec-&gt;heap()-&gt;sizeAfterLastEdenCollection()));
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeAtomicsObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/runtime/AtomicsObject.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSTypedArrays.h&quot;
</span><span class="cx"> #include &quot;ObjectPrototype.h&quot;
</span><ins>+#include &quot;ReleaseHeapAccessScope.h&quot;
</ins><span class="cx"> #include &quot;TypedArrayController.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -340,14 +341,18 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     bool didPassValidation = false;
</span><del>-    ParkingLot::ParkResult result = ParkingLot::parkConditionally(
-        ptr,
-        [&amp;] () -&gt; bool {
-            didPassValidation = WTF::atomicLoad(ptr) == expectedValue;
-            return didPassValidation;
-        },
-        [] () { },
-        timeout);
</del><ins>+    ParkingLot::ParkResult result;
+    {
+        ReleaseHeapAccessScope releaseHeapAccessScope(vm.heap);
+        result = ParkingLot::parkConditionally(
+            ptr,
+            [&amp;] () -&gt; bool {
+                didPassValidation = WTF::atomicLoad(ptr) == expectedValue;
+                return didPassValidation;
+            },
+            [] () { },
+            timeout);
+    }
</ins><span class="cx">     const char* resultString;
</span><span class="cx">     if (!didPassValidation)
</span><span class="cx">         resultString = &quot;not-equal&quot;;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeInitializeThreadingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2015-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -42,8 +42,9 @@
</span><span class="cx"> #include &quot;SuperSampler.h&quot;
</span><span class="cx"> #include &quot;WriteBarrier.h&quot;
</span><span class="cx"> #include &lt;mutex&gt;
</span><ins>+#include &lt;wtf/MainThread.h&gt;
+#include &lt;wtf/Threading.h&gt;
</ins><span class="cx"> #include &lt;wtf/dtoa.h&gt;
</span><del>-#include &lt;wtf/Threading.h&gt;
</del><span class="cx"> #include &lt;wtf/dtoa/cached-powers.h&gt;
</span><span class="cx"> 
</span><span class="cx"> using namespace WTF;
</span><span class="lines">@@ -57,6 +58,7 @@
</span><span class="cx">     std::call_once(initializeThreadingOnceFlag, []{
</span><span class="cx">         WTF::double_conversion::initialize();
</span><span class="cx">         WTF::initializeThreading();
</span><ins>+        WTF::initializeGCThreads();
</ins><span class="cx">         Options::initialize();
</span><span class="cx">         if (Options::recordGCPauseTimes())
</span><span class="cx">             HeapStatistics::initialize();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSLockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSLock.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSLock.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/runtime/JSLock.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2005, 2008, 2012, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2005, 2008, 2012, 2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * This library is free software; you can redistribute it and/or
</span><span class="cx">  * modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -128,18 +128,25 @@
</span><span class="cx">     // FIXME: What should happen to the per-thread identifier table if we don't have a VM?
</span><span class="cx">     if (!m_vm)
</span><span class="cx">         return;
</span><ins>+    
+    WTFThreadData&amp; threadData = wtfThreadData();
+    ASSERT(!m_entryAtomicStringTable);
+    m_entryAtomicStringTable = threadData.setCurrentAtomicStringTable(m_vm-&gt;atomicStringTable());
+    ASSERT(m_entryAtomicStringTable);
</ins><span class="cx"> 
</span><ins>+    if (m_vm-&gt;heap.hasAccess())
+        m_shouldReleaseHeapAccess = false;
+    else {
+        m_vm-&gt;heap.acquireAccess();
+        m_shouldReleaseHeapAccess = true;
+    }
+
</ins><span class="cx">     RELEASE_ASSERT(!m_vm-&gt;stackPointerAtVMEntry());
</span><span class="cx">     void* p = &amp;p; // A proxy for the current stack pointer.
</span><span class="cx">     m_vm-&gt;setStackPointerAtVMEntry(p);
</span><span class="cx"> 
</span><del>-    WTFThreadData&amp; threadData = wtfThreadData();
</del><span class="cx">     m_vm-&gt;setLastStackTop(threadData.savedLastStackTop());
</span><span class="cx"> 
</span><del>-    ASSERT(!m_entryAtomicStringTable);
-    m_entryAtomicStringTable = threadData.setCurrentAtomicStringTable(m_vm-&gt;atomicStringTable());
-    ASSERT(m_entryAtomicStringTable);
-
</del><span class="cx">     m_vm-&gt;heap.machineThreads().addCurrentThread();
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(SAMPLING_PROFILER)
</span><span class="lines">@@ -167,7 +174,7 @@
</span><span class="cx">     m_lockCount -= unlockCount;
</span><span class="cx"> 
</span><span class="cx">     if (!m_lockCount) {
</span><del>-
</del><ins>+        
</ins><span class="cx">         if (!m_hasExclusiveThread) {
</span><span class="cx">             m_ownerThreadID = std::thread::id();
</span><span class="cx">             m_lock.unlock();
</span><span class="lines">@@ -183,6 +190,9 @@
</span><span class="cx"> 
</span><span class="cx">         vm-&gt;heap.releaseDelayedReleasedObjects();
</span><span class="cx">         vm-&gt;setStackPointerAtVMEntry(nullptr);
</span><ins>+        
+        if (m_shouldReleaseHeapAccess)
+            vm-&gt;heap.releaseAccess();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (m_entryAtomicStringTable) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSLockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSLock.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSLock.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/runtime/JSLock.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2005, 2008, 2009, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2005, 2008, 2009, 2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * This library is free software; you can redistribute it and/or
</span><span class="cx">  * modify it under the terms of the GNU Library General Public
</span><span class="lines">@@ -136,6 +136,7 @@
</span><span class="cx">     intptr_t m_lockCount;
</span><span class="cx">     unsigned m_lockDropDepth;
</span><span class="cx">     bool m_hasExclusiveThread;
</span><ins>+    bool m_shouldReleaseHeapAccess;
</ins><span class="cx">     VM* m_vm;
</span><span class="cx">     AtomicStringTable* m_entryAtomicStringTable; 
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -354,7 +354,7 @@
</span><span class="cx">     // Make sure concurrent compilations are done, but don't install them, since there is
</span><span class="cx">     // no point to doing so.
</span><span class="cx">     for (unsigned i = DFG::numberOfWorklists(); i--;) {
</span><del>-        if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i)) {
</del><ins>+        if (DFG::Worklist* worklist = DFG::existingWorklistForIndexOrNull(i)) {
</ins><span class="cx">             worklist-&gt;removeNonCompilingPlansForVM(*this);
</span><span class="cx">             worklist-&gt;waitUntilAllPlansForVMAreReady(*this);
</span><span class="cx">             worklist-&gt;removeAllReadyPlansForVM(*this);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretoolsJSDollarVMPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/JavaScriptCore/tools/JSDollarVMPrototype.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -130,7 +130,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (!ensureCurrentThreadOwnsJSLock(exec))
</span><span class="cx">         return;
</span><del>-    exec-&gt;heap()-&gt;collect(CollectionScope::Eden);
</del><ins>+    exec-&gt;heap()-&gt;collectSync(CollectionScope::Eden);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL functionEdenGC(ExecState* exec)
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/ChangeLog        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,3 +1,25 @@
</span><ins>+2016-11-02  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        The GC should be in a thread
+        https://bugs.webkit.org/show_bug.cgi?id=163562
+
+        Reviewed by Geoffrey Garen and Andreas Kling.
+        
+        This fixes some bugs and adds a few features.
+
+        * wtf/Atomics.h: The GC may do work on behalf of the JIT. If it does, the main thread needs to execute a cross-modifying code fence. This is cpuid on x86 and I believe it's isb on ARM. It would have been an isync on PPC and I think that isb is the ARM equivalent.
+        (WTF::arm_isb):
+        (WTF::crossModifyingCodeFence):
+        (WTF::x86_ortop):
+        (WTF::x86_cpuid):
+        * wtf/AutomaticThread.cpp: I accidentally had AutomaticThreadCondition inherit from ThreadSafeRefCounted&lt;AutomaticThread&gt; [sic]. This never crashed before because all of our prior AutomaticThreadConditions were immortal.
+        (WTF::AutomaticThread::AutomaticThread):
+        (WTF::AutomaticThread::~AutomaticThread):
+        (WTF::AutomaticThread::start):
+        * wtf/AutomaticThread.h:
+        * wtf/MainThread.cpp: Need to allow initializeGCThreads() to be called separately because it's now more than just a debugging thing.
+        (WTF::initializeGCThreads):
+
</ins><span class="cx"> 2016-11-02  Carlos Alberto Lopez Perez  &lt;clopez@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Clean wrong comment about compositing on the UI process.
</span></span></pre></div>
<a id="trunkSourceWTFwtfAtomicsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Atomics.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Atomics.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/Atomics.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -35,6 +35,7 @@
</span><span class="cx"> #pragma intrinsic(_ReadWriteBarrier)
</span><span class="cx"> #endif
</span><span class="cx"> #include &lt;windows.h&gt;
</span><ins>+#include &lt;intrin.h&gt;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="lines">@@ -53,6 +54,8 @@
</span><span class="cx">     // is usually not high enough to justify the risk.
</span><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE T load(std::memory_order order = std::memory_order_seq_cst) const { return value.load(order); }
</span><ins>+    
+    ALWAYS_INLINE T loadRelaxed() const { return load(std::memory_order_relaxed); }
</ins><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE void store(T desired, std::memory_order order = std::memory_order_seq_cst) { value.store(desired, order); }
</span><span class="cx"> 
</span><span class="lines">@@ -200,6 +203,11 @@
</span><span class="cx">     asm volatile(&quot;dmb ishst&quot; ::: &quot;memory&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void arm_isb()
+{
+    asm volatile(&quot;isb&quot; ::: &quot;memory&quot;);
+}
+
</ins><span class="cx"> inline void loadLoadFence() { arm_dmb(); }
</span><span class="cx"> inline void loadStoreFence() { arm_dmb(); }
</span><span class="cx"> inline void storeLoadFence() { arm_dmb(); }
</span><span class="lines">@@ -206,6 +214,7 @@
</span><span class="cx"> inline void storeStoreFence() { arm_dmb_st(); }
</span><span class="cx"> inline void memoryBarrierAfterLock() { arm_dmb(); }
</span><span class="cx"> inline void memoryBarrierBeforeUnlock() { arm_dmb(); }
</span><ins>+inline void crossModifyingCodeFence() { arm_isb(); }
</ins><span class="cx"> 
</span><span class="cx"> #elif CPU(X86) || CPU(X86_64)
</span><span class="cx"> 
</span><span class="lines">@@ -212,10 +221,6 @@
</span><span class="cx"> inline void x86_ortop()
</span><span class="cx"> {
</span><span class="cx"> #if OS(WINDOWS)
</span><del>-    // I think that this does the equivalent of a dummy interlocked instruction,
-    // instead of using the 'mfence' instruction, at least according to MSDN. I
-    // know that it is equivalent for our purposes, but it would be good to
-    // investigate if that is actually better.
</del><span class="cx">     MemoryBarrier();
</span><span class="cx"> #elif CPU(X86_64)
</span><span class="cx">     // This has acqrel semantics and is much cheaper than mfence. For exampe, in the JSC GC, using
</span><span class="lines">@@ -226,6 +231,21 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline void x86_cpuid()
+{
+#if OS(WINDOWS)
+    int info[4];
+    __cpuid(info, 0);
+#else
+    intptr_t a = 0, b, c, d;
+    asm volatile(
+        &quot;cpuid&quot;
+        : &quot;+a&quot;(a), &quot;=b&quot;(b), &quot;=c&quot;(c), &quot;=d&quot;(d)
+        :
+        : &quot;memory&quot;);
+#endif
+}
+
</ins><span class="cx"> inline void loadLoadFence() { compilerFence(); }
</span><span class="cx"> inline void loadStoreFence() { compilerFence(); }
</span><span class="cx"> inline void storeLoadFence() { x86_ortop(); }
</span><span class="lines">@@ -232,6 +252,7 @@
</span><span class="cx"> inline void storeStoreFence() { compilerFence(); }
</span><span class="cx"> inline void memoryBarrierAfterLock() { compilerFence(); }
</span><span class="cx"> inline void memoryBarrierBeforeUnlock() { compilerFence(); }
</span><ins>+inline void crossModifyingCodeFence() { x86_cpuid(); }
</ins><span class="cx"> 
</span><span class="cx"> #else
</span><span class="cx"> 
</span><span class="lines">@@ -241,6 +262,7 @@
</span><span class="cx"> inline void storeStoreFence() { std::atomic_thread_fence(std::memory_order_seq_cst); }
</span><span class="cx"> inline void memoryBarrierAfterLock() { std::atomic_thread_fence(std::memory_order_seq_cst); }
</span><span class="cx"> inline void memoryBarrierBeforeUnlock() { std::atomic_thread_fence(std::memory_order_seq_cst); }
</span><ins>+inline void crossModifyingCodeFence() { std::atomic_thread_fence(std::memory_order_seq_cst); } // Probably not strong enough.
</ins><span class="cx"> 
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFwtfAutomaticThreadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/AutomaticThread.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/AutomaticThread.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/AutomaticThread.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -78,7 +78,6 @@
</span><span class="cx"> 
</span><span class="cx"> void AutomaticThreadCondition::remove(const LockHolder&amp;, AutomaticThread* thread)
</span><span class="cx"> {
</span><del>-    ASSERT(m_threads.contains(thread));
</del><span class="cx">     m_threads.removeFirst(thread);
</span><span class="cx">     ASSERT(!m_threads.contains(thread));
</span><span class="cx"> }
</span><span class="lines">@@ -92,11 +91,15 @@
</span><span class="cx">     : m_lock(lock)
</span><span class="cx">     , m_condition(condition)
</span><span class="cx"> {
</span><ins>+    if (verbose)
+        dataLog(RawPointer(this), &quot;: Allocated AutomaticThread.\n&quot;);
</ins><span class="cx">     m_condition-&gt;add(locker, this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> AutomaticThread::~AutomaticThread()
</span><span class="cx"> {
</span><ins>+    if (verbose)
+        dataLog(RawPointer(this), &quot;: Deleting AutomaticThread.\n&quot;);
</ins><span class="cx">     LockHolder locker(*m_lock);
</span><span class="cx">     
</span><span class="cx">     // It's possible that we're in a waiting state with the thread shut down. This is a goofy way to
</span><span class="lines">@@ -104,6 +107,16 @@
</span><span class="cx">     m_condition-&gt;remove(locker, this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool AutomaticThread::tryStop(const LockHolder&amp;)
+{
+    if (!m_isRunning)
+        return true;
+    if (m_hasUnderlyingThread)
+        return false;
+    m_isRunning = false;
+    return true;
+}
+
</ins><span class="cx"> void AutomaticThread::join()
</span><span class="cx"> {
</span><span class="cx">     LockHolder locker(*m_lock);
</span><span class="lines">@@ -113,39 +126,44 @@
</span><span class="cx"> 
</span><span class="cx"> class AutomaticThread::ThreadScope {
</span><span class="cx"> public:
</span><del>-    ThreadScope(AutomaticThread&amp; thread)
</del><ins>+    ThreadScope(RefPtr&lt;AutomaticThread&gt; thread)
</ins><span class="cx">         : m_thread(thread)
</span><span class="cx">     {
</span><del>-        m_thread.threadDidStart();
</del><ins>+        m_thread-&gt;threadDidStart();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     ~ThreadScope()
</span><span class="cx">     {
</span><del>-        m_thread.threadWillStop();
</del><ins>+        m_thread-&gt;threadWillStop();
+        
+        LockHolder locker(*m_thread-&gt;m_lock);
+        m_thread-&gt;m_hasUnderlyingThread = false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> private:
</span><del>-    AutomaticThread&amp; m_thread;
</del><ins>+    RefPtr&lt;AutomaticThread&gt; m_thread;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> void AutomaticThread::start(const LockHolder&amp;)
</span><span class="cx"> {
</span><ins>+    RELEASE_ASSERT(m_isRunning);
+    
</ins><span class="cx">     RefPtr&lt;AutomaticThread&gt; preserveThisForThread = this;
</span><span class="cx">     
</span><ins>+    m_hasUnderlyingThread = true;
+    
</ins><span class="cx">     ThreadIdentifier thread = createThread(
</span><span class="cx">         &quot;WTF::AutomaticThread&quot;,
</span><span class="cx">         [=] () {
</span><span class="cx">             if (verbose)
</span><del>-                dataLog(&quot;Running automatic thread!\n&quot;);
-            RefPtr&lt;AutomaticThread&gt; preserveThisInThread = preserveThisForThread;
</del><ins>+                dataLog(RawPointer(this), &quot;: Running automatic thread!\n&quot;);
+            ThreadScope threadScope(preserveThisForThread);
</ins><span class="cx">             
</span><del>-            {
</del><ins>+            if (!ASSERT_DISABLED) {
</ins><span class="cx">                 LockHolder locker(*m_lock);
</span><span class="cx">                 ASSERT(!m_condition-&gt;contains(locker, this));
</span><span class="cx">             }
</span><span class="cx">             
</span><del>-            ThreadScope threadScope(*this);
-            
</del><span class="cx">             auto stop = [&amp;] (const LockHolder&amp;) {
</span><span class="cx">                 m_isRunning = false;
</span><span class="cx">                 m_isRunningCondition.notifyAll();
</span><span class="lines">@@ -167,7 +185,7 @@
</span><span class="cx">                             m_condition-&gt;m_condition.waitUntilMonotonicClockSeconds(*m_lock, timeout);
</span><span class="cx">                         if (!awokenByNotify) {
</span><span class="cx">                             if (verbose)
</span><del>-                                dataLog(&quot;Going to sleep!\n&quot;);
</del><ins>+                                dataLog(RawPointer(this), &quot;: Going to sleep!\n&quot;);
</ins><span class="cx">                             m_condition-&gt;add(locker, this);
</span><span class="cx">                             return;
</span><span class="cx">                         }
</span></span></pre></div>
<a id="trunkSourceWTFwtfAutomaticThreadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/AutomaticThread.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/AutomaticThread.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/AutomaticThread.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx"> 
</span><span class="cx"> class AutomaticThread;
</span><span class="cx"> 
</span><del>-class AutomaticThreadCondition : public ThreadSafeRefCounted&lt;AutomaticThread&gt; {
</del><ins>+class AutomaticThreadCondition : public ThreadSafeRefCounted&lt;AutomaticThreadCondition&gt; {
</ins><span class="cx"> public:
</span><span class="cx">     static WTF_EXPORT_PRIVATE RefPtr&lt;AutomaticThreadCondition&gt; create();
</span><span class="cx">     
</span><span class="lines">@@ -112,6 +112,15 @@
</span><span class="cx">     // AutomaticThread).
</span><span class="cx">     virtual ~AutomaticThread();
</span><span class="cx">     
</span><ins>+    // Sometimes it's possible to optimize for the case that there is no underlying thread.
+    bool hasUnderlyingThread(const LockHolder&amp;) const { return m_hasUnderlyingThread; }
+    
+    // This attempts to quickly stop the thread. This will succeed if the thread happens to not be
+    // running. Returns true if the thread has been stopped. A good idiom for stopping your automatic
+    // thread is to first try this, and if that doesn't work, to tell the thread using your own
+    // mechanism (set some flag and then notify the condition).
+    bool tryStop(const LockHolder&amp;);
+    
</ins><span class="cx">     void join();
</span><span class="cx">     
</span><span class="cx"> protected:
</span><span class="lines">@@ -151,9 +160,6 @@
</span><span class="cx">     enum class WorkResult { Continue, Stop };
</span><span class="cx">     virtual WorkResult work() = 0;
</span><span class="cx">     
</span><del>-    class ThreadScope;
-    friend class ThreadScope;
-    
</del><span class="cx">     // It's sometimes useful to allocate resources while the thread is running, and to destroy them
</span><span class="cx">     // when the thread dies. These methods let you do this. You can override these methods, and you
</span><span class="cx">     // can be sure that the default ones don't do anything (so you don't need a super call).
</span><span class="lines">@@ -163,11 +169,15 @@
</span><span class="cx"> private:
</span><span class="cx">     friend class AutomaticThreadCondition;
</span><span class="cx">     
</span><ins>+    class ThreadScope;
+    friend class ThreadScope;
+    
</ins><span class="cx">     void start(const LockHolder&amp;);
</span><span class="cx">     
</span><span class="cx">     Box&lt;Lock&gt; m_lock;
</span><span class="cx">     RefPtr&lt;AutomaticThreadCondition&gt; m_condition;
</span><span class="cx">     bool m_isRunning { true };
</span><ins>+    bool m_hasUnderlyingThread { false };
</ins><span class="cx">     Condition m_isRunningCondition;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFwtfCompilationThreadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/CompilationThread.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/CompilationThread.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/CompilationThread.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -33,13 +33,13 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="cx"> 
</span><del>-static ThreadSpecific&lt;bool&gt;* s_isCompilationThread;
</del><ins>+static ThreadSpecific&lt;bool, CanBeGCThread::True&gt;* s_isCompilationThread;
</ins><span class="cx"> 
</span><span class="cx"> static void initializeCompilationThreads()
</span><span class="cx"> {
</span><span class="cx">     static std::once_flag initializeCompilationThreadsOnceFlag;
</span><span class="cx">     std::call_once(initializeCompilationThreadsOnceFlag, []{
</span><del>-        s_isCompilationThread = new ThreadSpecific&lt;bool&gt;();
</del><ins>+        s_isCompilationThread = new ThreadSpecific&lt;bool, CanBeGCThread::True&gt;();
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWTFwtfMainThreadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MainThread.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MainThread.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/MainThread.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -190,11 +190,16 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-static ThreadSpecific&lt;Optional&lt;GCThreadType&gt;&gt;* isGCThread;
</del><ins>+static ThreadSpecific&lt;Optional&lt;GCThreadType&gt;, CanBeGCThread::True&gt;* isGCThread;
</ins><span class="cx"> 
</span><span class="cx"> void initializeGCThreads()
</span><span class="cx"> {
</span><del>-    isGCThread = new ThreadSpecific&lt;Optional&lt;GCThreadType&gt;&gt;();
</del><ins>+    static std::once_flag flag;
+    std::call_once(
+        flag,
+        [] {
+            isGCThread = new ThreadSpecific&lt;Optional&lt;GCThreadType&gt;, CanBeGCThread::True&gt;();
+        });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void registerGCThread(GCThreadType type)
</span></span></pre></div>
<a id="trunkSourceWTFwtfMainThreadh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/MainThread.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/MainThread.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/MainThread.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx"> inline bool isUIThread() { return isMainThread(); }
</span><span class="cx"> #endif // USE(WEB_THREAD)
</span><span class="cx"> 
</span><del>-void initializeGCThreads();
</del><ins>+WTF_EXPORT_PRIVATE void initializeGCThreads();
</ins><span class="cx"> 
</span><span class="cx"> enum class GCThreadType {
</span><span class="cx">     Main,
</span></span></pre></div>
<a id="trunkSourceWTFwtfOptionalh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/Optional.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/Optional.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/Optional.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;type_traits&gt;
</span><span class="cx"> #include &lt;wtf/Assertions.h&gt;
</span><ins>+#include &lt;wtf/PrintStream.h&gt;
</ins><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> 
</span><span class="cx"> // WTF::Optional is a class based on std::optional, described here:
</span><span class="lines">@@ -263,6 +264,15 @@
</span><span class="cx">     return Optional&lt;typename std::decay&lt;T&gt;::type&gt;(std::forward&lt;T&gt;(value));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T&gt;
+void printInternal(PrintStream&amp; out, const Optional&lt;T&gt;&amp; optional)
+{
+    if (optional)
+        out.print(*optional);
+    else
+        out.print(&quot;Nullopt&quot;);
+}
+
</ins><span class="cx"> } // namespace WTF
</span><span class="cx"> 
</span><span class="cx"> using WTF::InPlace;
</span></span></pre></div>
<a id="trunkSourceWTFwtfParkingLotcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/ParkingLot.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/ParkingLot.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/ParkingLot.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -447,12 +447,12 @@
</span><span class="cx"> 
</span><span class="cx"> ThreadData* myThreadData()
</span><span class="cx"> {
</span><del>-    static ThreadSpecific&lt;RefPtr&lt;ThreadData&gt;&gt;* threadData;
</del><ins>+    static ThreadSpecific&lt;RefPtr&lt;ThreadData&gt;, CanBeGCThread::True&gt;* threadData;
</ins><span class="cx">     static std::once_flag initializeOnce;
</span><span class="cx">     std::call_once(
</span><span class="cx">         initializeOnce,
</span><span class="cx">         [] {
</span><del>-            threadData = new ThreadSpecific&lt;RefPtr&lt;ThreadData&gt;&gt;();
</del><ins>+            threadData = new ThreadSpecific&lt;RefPtr&lt;ThreadData&gt;, CanBeGCThread::True&gt;();
</ins><span class="cx">         });
</span><span class="cx">     
</span><span class="cx">     RefPtr&lt;ThreadData&gt;&amp; result = **threadData;
</span></span></pre></div>
<a id="trunkSourceWTFwtfThreadSpecifich"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/ThreadSpecific.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/ThreadSpecific.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/ThreadSpecific.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2009 Jian Li &lt;jianli@chromium.org&gt;
</span><span class="cx">  * Copyright (C) 2012 Patrick Gansterer &lt;paroga@paroga.com&gt;
</span><span class="cx">  *
</span><span class="lines">@@ -42,6 +42,7 @@
</span><span class="cx"> #ifndef WTF_ThreadSpecific_h
</span><span class="cx"> #define WTF_ThreadSpecific_h
</span><span class="cx"> 
</span><ins>+#include &lt;wtf/MainThread.h&gt;
</ins><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -59,7 +60,12 @@
</span><span class="cx"> #define THREAD_SPECIFIC_CALL
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt; class ThreadSpecific {
</del><ins>+enum class CanBeGCThread {
+    False,
+    True
+};
+
+template&lt;typename T, CanBeGCThread canBeGCThread = CanBeGCThread::False&gt; class ThreadSpecific {
</ins><span class="cx">     WTF_MAKE_NONCOPYABLE(ThreadSpecific);
</span><span class="cx"> public:
</span><span class="cx">     ThreadSpecific();
</span><span class="lines">@@ -86,10 +92,10 @@
</span><span class="cx">     struct Data {
</span><span class="cx">         WTF_MAKE_NONCOPYABLE(Data);
</span><span class="cx">     public:
</span><del>-        Data(T* value, ThreadSpecific&lt;T&gt;* owner) : value(value), owner(owner) {}
</del><ins>+        Data(T* value, ThreadSpecific&lt;T, canBeGCThread&gt;* owner) : value(value), owner(owner) {}
</ins><span class="cx"> 
</span><span class="cx">         T* value;
</span><del>-        ThreadSpecific&lt;T&gt;* owner;
</del><ins>+        ThreadSpecific&lt;T, canBeGCThread&gt;* owner;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx"> #if USE(PTHREADS)
</span><span class="lines">@@ -127,8 +133,8 @@
</span><span class="cx">     return pthread_getspecific(key);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline ThreadSpecific&lt;T&gt;::ThreadSpecific()
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline ThreadSpecific&lt;T, canBeGCThread&gt;::ThreadSpecific()
</ins><span class="cx"> {
</span><span class="cx">     int error = pthread_key_create(&amp;m_key, destroy);
</span><span class="cx">     if (error)
</span><span class="lines">@@ -135,16 +141,20 @@
</span><span class="cx">         CRASH();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline T* ThreadSpecific&lt;T&gt;::get()
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline T* ThreadSpecific&lt;T, canBeGCThread&gt;::get()
</ins><span class="cx"> {
</span><span class="cx">     Data* data = static_cast&lt;Data*&gt;(pthread_getspecific(m_key));
</span><del>-    return data ? data-&gt;value : 0;
</del><ins>+    if (data)
+        return data-&gt;value;
+    RELEASE_ASSERT(canBeGCThread == CanBeGCThread::True || !mayBeGCThread());
+    return nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline void ThreadSpecific&lt;T&gt;::set(T* ptr)
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline void ThreadSpecific&lt;T, canBeGCThread&gt;::set(T* ptr)
</ins><span class="cx"> {
</span><ins>+    RELEASE_ASSERT(canBeGCThread == CanBeGCThread::True || !mayBeGCThread());
</ins><span class="cx">     ASSERT(!get());
</span><span class="cx">     pthread_setspecific(m_key, new Data(ptr, this));
</span><span class="cx"> }
</span><span class="lines">@@ -185,8 +195,8 @@
</span><span class="cx">     return FlsGetValue(key);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline ThreadSpecific&lt;T&gt;::ThreadSpecific()
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline ThreadSpecific&lt;T, canBeGCThread&gt;::ThreadSpecific()
</ins><span class="cx">     : m_index(-1)
</span><span class="cx"> {
</span><span class="cx">     DWORD flsKey = FlsAlloc(destroy);
</span><span class="lines">@@ -199,22 +209,26 @@
</span><span class="cx">     flsKeys()[m_index] = flsKey;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline ThreadSpecific&lt;T&gt;::~ThreadSpecific()
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline ThreadSpecific&lt;T, canBeGCThread&gt;::~ThreadSpecific()
</ins><span class="cx"> {
</span><span class="cx">     FlsFree(flsKeys()[m_index]);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline T* ThreadSpecific&lt;T&gt;::get()
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline T* ThreadSpecific&lt;T, canBeGCThread&gt;::get()
</ins><span class="cx"> {
</span><span class="cx">     Data* data = static_cast&lt;Data*&gt;(FlsGetValue(flsKeys()[m_index]));
</span><del>-    return data ? data-&gt;value : 0;
</del><ins>+    if (data)
+        return data-&gt;value;
+    RELEASE_ASSERT(canBeGCThread == CanBeGCThread::True || !mayBeGCThread());
+    return nullptr;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline void ThreadSpecific&lt;T&gt;::set(T* ptr)
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline void ThreadSpecific&lt;T, canBeGCThread&gt;::set(T* ptr)
</ins><span class="cx"> {
</span><ins>+    RELEASE_ASSERT(canBeGCThread == CanBeGCThread::True || !mayBeGCThread());
</ins><span class="cx">     ASSERT(!get());
</span><span class="cx">     Data* data = new Data(ptr, this);
</span><span class="cx">     FlsSetValue(flsKeys()[m_index], data);
</span><span class="lines">@@ -224,8 +238,8 @@
</span><span class="cx"> #error ThreadSpecific is not implemented for this platform.
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline void THREAD_SPECIFIC_CALL ThreadSpecific&lt;T&gt;::destroy(void* ptr)
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline void THREAD_SPECIFIC_CALL ThreadSpecific&lt;T, canBeGCThread&gt;::destroy(void* ptr)
</ins><span class="cx"> {
</span><span class="cx">     Data* data = static_cast&lt;Data*&gt;(ptr);
</span><span class="cx"> 
</span><span class="lines">@@ -249,14 +263,14 @@
</span><span class="cx">     delete data;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline bool ThreadSpecific&lt;T&gt;::isSet()
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline bool ThreadSpecific&lt;T, canBeGCThread&gt;::isSet()
</ins><span class="cx"> {
</span><span class="cx">     return !!get();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline ThreadSpecific&lt;T&gt;::operator T*()
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline ThreadSpecific&lt;T, canBeGCThread&gt;::operator T*()
</ins><span class="cx"> {
</span><span class="cx">     T* ptr = static_cast&lt;T*&gt;(get());
</span><span class="cx">     if (!ptr) {
</span><span class="lines">@@ -269,21 +283,21 @@
</span><span class="cx">     return ptr;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline T* ThreadSpecific&lt;T&gt;::operator-&gt;()
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline T* ThreadSpecific&lt;T, canBeGCThread&gt;::operator-&gt;()
</ins><span class="cx"> {
</span><span class="cx">     return operator T*();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename T&gt;
-inline T&amp; ThreadSpecific&lt;T&gt;::operator*()
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline T&amp; ThreadSpecific&lt;T, canBeGCThread&gt;::operator*()
</ins><span class="cx"> {
</span><span class="cx">     return *operator T*();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #if USE(WEB_THREAD)
</span><del>-template&lt;typename T&gt;
-inline void ThreadSpecific&lt;T&gt;::replace(T* newPtr)
</del><ins>+template&lt;typename T, CanBeGCThread canBeGCThread&gt;
+inline void ThreadSpecific&lt;T, canBeGCThread&gt;::replace(T* newPtr)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(newPtr);
</span><span class="cx">     Data* data = static_cast&lt;Data*&gt;(pthread_getspecific(m_key));
</span></span></pre></div>
<a id="trunkSourceWTFwtfWordLockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/WordLock.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/WordLock.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/WordLock.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx">     ThreadData* queueTail { nullptr };
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-ThreadSpecific&lt;ThreadData&gt;* threadData;
</del><ins>+ThreadSpecific&lt;ThreadData, CanBeGCThread::True&gt;* threadData;
</ins><span class="cx"> 
</span><span class="cx"> ThreadData* myThreadData()
</span><span class="cx"> {
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">     std::call_once(
</span><span class="cx">         initializeOnce,
</span><span class="cx">         [] {
</span><del>-            threadData = new ThreadSpecific&lt;ThreadData&gt;();
</del><ins>+            threadData = new ThreadSpecific&lt;ThreadData, CanBeGCThread::True&gt;();
</ins><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">     return *threadData;
</span></span></pre></div>
<a id="trunkSourceWTFwtftextAtomicStringImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/AtomicStringImpl.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/AtomicStringImpl.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WTF/wtf/text/AtomicStringImpl.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -25,9 +25,12 @@
</span><span class="cx"> #include &quot;AtomicStringImpl.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AtomicStringTable.h&quot;
</span><ins>+#include &quot;CommaPrinter.h&quot;
+#include &quot;DataLog.h&quot;
</ins><span class="cx"> #include &quot;HashSet.h&quot;
</span><span class="cx"> #include &quot;IntegerToStringConversion.h&quot;
</span><span class="cx"> #include &quot;StringHash.h&quot;
</span><ins>+#include &quot;StringPrintStream.h&quot;
</ins><span class="cx"> #include &quot;Threading.h&quot;
</span><span class="cx"> #include &quot;WTFThreadData.h&quot;
</span><span class="cx"> #include &lt;wtf/unicode/UTF8.h&gt;
</span><span class="lines">@@ -75,7 +78,8 @@
</span><span class="cx"> {
</span><span class="cx">     AtomicStringTableLocker locker;
</span><span class="cx"> 
</span><del>-    HashSet&lt;StringImpl*&gt;::AddResult addResult = stringTable().add&lt;HashTranslator&gt;(value);
</del><ins>+    HashSet&lt;StringImpl*&gt;&amp; atomicStringTable = stringTable();
+    HashSet&lt;StringImpl*&gt;::AddResult addResult = atomicStringTable.add&lt;HashTranslator&gt;(value);
</ins><span class="cx"> 
</span><span class="cx">     // If the string is newly-translated, then we need to adopt it.
</span><span class="cx">     // The boolean in the pair tells us if that is so.
</span><span class="lines">@@ -451,6 +455,7 @@
</span><span class="cx">     HashSet&lt;StringImpl*&gt;&amp; atomicStringTable = stringTable();
</span><span class="cx">     HashSet&lt;StringImpl*&gt;::iterator iterator = atomicStringTable.find(string);
</span><span class="cx">     ASSERT_WITH_MESSAGE(iterator != atomicStringTable.end(), &quot;The string being removed is atomic in the string table of an other thread!&quot;);
</span><ins>+    ASSERT(string == *iterator);
</ins><span class="cx">     atomicStringTable.remove(iterator);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/ChangeLog        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2016-11-02  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        The GC should be in a thread
+        https://bugs.webkit.org/show_bug.cgi?id=163562
+
+        Reviewed by Geoffrey Garen and Andreas Kling.
+
+        No new tests because existing tests cover this.
+        
+        We now need to be more careful about using JSLock. This fixes some places that were not
+        holding it. New assertions in the GC are more likely to catch this than before.
+
+        * bindings/js/WorkerScriptController.cpp:
+        (WebCore::WorkerScriptController::WorkerScriptController):
+
</ins><span class="cx"> 2016-11-02  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: Include DebuggerAgent in Workers - see, pause, and step through scripts
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBDatabasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -55,6 +55,7 @@
</span><span class="cx">     , m_connectionProxy(connectionProxy)
</span><span class="cx">     , m_info(resultData.databaseInfo())
</span><span class="cx">     , m_databaseConnectionIdentifier(resultData.databaseConnectionIdentifier())
</span><ins>+    , m_eventNames(eventNames())
</ins><span class="cx"> {
</span><span class="cx">     LOG(IndexedDB, &quot;IDBDatabase::IDBDatabase - Creating database %s with version %&quot; PRIu64 &quot; connection %&quot; PRIu64 &quot; (%p)&quot;, m_info.name().utf8().data(), m_info.version(), m_databaseConnectionIdentifier, this);
</span><span class="cx">     suspendIfNeeded();
</span><span class="lines">@@ -73,7 +74,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool IDBDatabase::hasPendingActivity() const
</span><span class="cx"> {
</span><del>-    ASSERT(currentThread() == originThreadID());
</del><ins>+    ASSERT(currentThread() == originThreadID() || mayBeGCThread());
</ins><span class="cx"> 
</span><span class="cx">     if (m_closedInServer)
</span><span class="cx">         return false;
</span><span class="lines">@@ -81,7 +82,7 @@
</span><span class="cx">     if (!m_activeTransactions.isEmpty() || !m_committingTransactions.isEmpty() || !m_abortingTransactions.isEmpty())
</span><span class="cx">         return true;
</span><span class="cx"> 
</span><del>-    return hasEventListeners(eventNames().abortEvent) || hasEventListeners(eventNames().errorEvent) || hasEventListeners(eventNames().versionchangeEvent);
</del><ins>+    return hasEventListeners(m_eventNames.abortEvent) || hasEventListeners(m_eventNames.errorEvent) || hasEventListeners(m_eventNames.versionchangeEvent);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> const String IDBDatabase::name() const
</span><span class="lines">@@ -252,7 +253,7 @@
</span><span class="cx">     for (auto&amp; transaction : m_activeTransactions.values())
</span><span class="cx">         transaction-&gt;connectionClosedFromServer(error);
</span><span class="cx"> 
</span><del>-    Ref&lt;Event&gt; event = Event::create(eventNames().errorEvent, true, false);
</del><ins>+    Ref&lt;Event&gt; event = Event::create(m_eventNames.errorEvent, true, false);
</ins><span class="cx">     event-&gt;setTarget(this);
</span><span class="cx"> 
</span><span class="cx">     if (auto* context = scriptExecutionContext())
</span><span class="lines">@@ -446,8 +447,8 @@
</span><span class="cx">         connectionProxy().didFireVersionChangeEvent(m_databaseConnectionIdentifier, requestIdentifier);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-
-    Ref&lt;Event&gt; event = IDBVersionChangeEvent::create(requestIdentifier, currentVersion, requestedVersion, eventNames().versionchangeEvent);
</del><ins>+    
+    Ref&lt;Event&gt; event = IDBVersionChangeEvent::create(requestIdentifier, currentVersion, requestedVersion, m_eventNames.versionchangeEvent);
</ins><span class="cx">     event-&gt;setTarget(this);
</span><span class="cx">     scriptExecutionContext()-&gt;eventQueue().enqueueEvent(WTFMove(event));
</span><span class="cx"> }
</span><span class="lines">@@ -459,7 +460,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool result = EventTargetWithInlineData::dispatchEvent(event);
</span><span class="cx"> 
</span><del>-    if (event.isVersionChangeEvent() &amp;&amp; event.type() == eventNames().versionchangeEvent)
</del><ins>+    if (event.isVersionChangeEvent() &amp;&amp; event.type() == m_eventNames.versionchangeEvent)
</ins><span class="cx">         connectionProxy().didFireVersionChangeEvent(m_databaseConnectionIdentifier, downcast&lt;IDBVersionChangeEvent&gt;(event).requestIdentifier());
</span><span class="cx"> 
</span><span class="cx">     return result;
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBDatabaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx"> class IDBResultData;
</span><span class="cx"> class IDBTransaction;
</span><span class="cx"> class IDBTransactionInfo;
</span><ins>+struct EventNames;
</ins><span class="cx"> 
</span><span class="cx"> class IDBDatabase : public ThreadSafeRefCounted&lt;IDBDatabase&gt;, public EventTargetWithInlineData, public IDBActiveDOMObject {
</span><span class="cx"> public:
</span><span class="lines">@@ -129,6 +130,8 @@
</span><span class="cx">     HashMap&lt;IDBResourceIdentifier, RefPtr&lt;IDBTransaction&gt;&gt; m_activeTransactions;
</span><span class="cx">     HashMap&lt;IDBResourceIdentifier, RefPtr&lt;IDBTransaction&gt;&gt; m_committingTransactions;
</span><span class="cx">     HashMap&lt;IDBResourceIdentifier, RefPtr&lt;IDBTransaction&gt;&gt; m_abortingTransactions;
</span><ins>+    
+    const EventNames&amp; m_eventNames; // Need to cache this so we can use it from GC threads.
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBRequestcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -228,7 +228,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool IDBRequest::hasPendingActivity() const
</span><span class="cx"> {
</span><del>-    ASSERT(currentThread() == originThreadID());
</del><ins>+    ASSERT(currentThread() == originThreadID() || mayBeGCThread());
</ins><span class="cx">     return m_hasPendingActivity;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreModulesindexeddbIDBTransactioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -264,7 +264,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool IDBTransaction::hasPendingActivity() const
</span><span class="cx"> {
</span><del>-    ASSERT(currentThread() == m_database-&gt;originThreadID());
</del><ins>+    ASSERT(currentThread() == m_database-&gt;originThreadID() || mayBeGCThread());
</ins><span class="cx">     return !m_contextStopped &amp;&amp; m_state != IndexedDB::TransactionState::Finished;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -3884,7 +3884,6 @@
</span><span class="cx">                 A456FA2611AD4A830020B420 /* LabelsNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A456FA2411AD4A830020B420 /* LabelsNodeList.cpp */; };
</span><span class="cx">                 A456FA2711AD4A830020B420 /* LabelsNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = A456FA2511AD4A830020B420 /* LabelsNodeList.h */; };
</span><span class="cx">                 A501920E132EBF2E008BFE55 /* Autocapitalize.h in Headers */ = {isa = PBXBuildFile; fileRef = A501920C132EBF2E008BFE55 /* Autocapitalize.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                A502C5DF13049B3500FC7D53 /* WebSafeGCActivityCallbackIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = A502C5DD13049B3500FC7D53 /* WebSafeGCActivityCallbackIOS.h */; };
</del><span class="cx">                 A5071E801C506B66009951BE /* InspectorMemoryAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5071E7E1C5067A0009951BE /* InspectorMemoryAgent.cpp */; };
</span><span class="cx">                 A5071E811C506B69009951BE /* InspectorMemoryAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A5071E7F1C5067A0009951BE /* InspectorMemoryAgent.h */; };
</span><span class="cx">                 A5071E851C56D0DC009951BE /* ResourceUsageData.h in Headers */ = {isa = PBXBuildFile; fileRef = A5071E821C56D079009951BE /* ResourceUsageData.h */; };
</span><span class="lines">@@ -5901,7 +5900,6 @@
</span><span class="cx">                 CE7B2DB51586ABAD0098B3FA /* TextAlternativeWithRange.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7B2DB11586ABAD0098B3FA /* TextAlternativeWithRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 CE7B2DB61586ABAD0098B3FA /* TextAlternativeWithRange.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE7B2DB21586ABAD0098B3FA /* TextAlternativeWithRange.mm */; };
</span><span class="cx">                 CE7E17831C83A49100AD06AF /* ContentSecurityPolicyHash.h in Headers */ = {isa = PBXBuildFile; fileRef = CE7E17821C83A49100AD06AF /* ContentSecurityPolicyHash.h */; };
</span><del>-                CE95208A1811B475007A5392 /* WebSafeIncrementalSweeperIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C4CB1D161A131200D214DA /* WebSafeIncrementalSweeperIOS.h */; };
</del><span class="cx">                 CEC337AD1A46071F009B8523 /* ServersSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CEC337AC1A46071F009B8523 /* ServersSPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 CEC337AF1A46086D009B8523 /* GraphicsServicesSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = CEC337AE1A46086D009B8523 /* GraphicsServicesSPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 CECADFC6153778FF00E37068 /* DictationAlternative.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CECADFC2153778FF00E37068 /* DictationAlternative.cpp */; };
</span><span class="lines">@@ -11408,7 +11406,6 @@
</span><span class="cx">                 A456FA2411AD4A830020B420 /* LabelsNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LabelsNodeList.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 A456FA2511AD4A830020B420 /* LabelsNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelsNodeList.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 A501920C132EBF2E008BFE55 /* Autocapitalize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Autocapitalize.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                A502C5DD13049B3500FC7D53 /* WebSafeGCActivityCallbackIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSafeGCActivityCallbackIOS.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 A5071E7E1C5067A0009951BE /* InspectorMemoryAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorMemoryAgent.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 A5071E7F1C5067A0009951BE /* InspectorMemoryAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorMemoryAgent.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 A5071E821C56D079009951BE /* ResourceUsageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceUsageData.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -13351,7 +13348,6 @@
</span><span class="cx">                 C280833D1C6DC22C001451B6 /* JSFontFace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFontFace.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C280833E1C6DC22C001451B6 /* JSFontFace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSFontFace.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C28083411C6DC96A001451B6 /* JSFontFaceCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSFontFaceCustom.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                C2C4CB1D161A131200D214DA /* WebSafeIncrementalSweeperIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSafeIncrementalSweeperIOS.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 C330A22113EC196B0000B45B /* ColorChooser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorChooser.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C33EE5C214FB49610002095A /* BaseClickableWithKeyInputType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BaseClickableWithKeyInputType.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 C33EE5C314FB49610002095A /* BaseClickableWithKeyInputType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseClickableWithKeyInputType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -19349,8 +19345,6 @@
</span><span class="cx">                                 FE0D84EA1048436E001A179E /* WebEvent.mm */,
</span><span class="cx">                                 CDA29A2E1CBF73FC00901CCF /* WebPlaybackSessionInterfaceAVKit.h */,
</span><span class="cx">                                 CDA29A2F1CBF73FC00901CCF /* WebPlaybackSessionInterfaceAVKit.mm */,
</span><del>-                                A502C5DD13049B3500FC7D53 /* WebSafeGCActivityCallbackIOS.h */,
-                                C2C4CB1D161A131200D214DA /* WebSafeIncrementalSweeperIOS.h */,
</del><span class="cx">                                 3F42B31B1881191B00278AAC /* WebVideoFullscreenControllerAVKit.h */,
</span><span class="cx">                                 3F42B31C1881191B00278AAC /* WebVideoFullscreenControllerAVKit.mm */,
</span><span class="cx">                                 3FBC4AF2189881560046EE38 /* WebVideoFullscreenInterfaceAVKit.h */,
</span><span class="lines">@@ -27865,8 +27859,6 @@
</span><span class="cx">                                 CDA29A0B1CBD9A7400901CCF /* WebPlaybackSessionModel.h in Headers */,
</span><span class="cx">                                 CDA29A0F1CBD9CFE00901CCF /* WebPlaybackSessionModelMediaElement.h in Headers */,
</span><span class="cx">                                 99CC0B6B18BEA1FF006CEBCC /* WebReplayInputs.h in Headers */,
</span><del>-                                A502C5DF13049B3500FC7D53 /* WebSafeGCActivityCallbackIOS.h in Headers */,
-                                CE95208A1811B475007A5392 /* WebSafeIncrementalSweeperIOS.h in Headers */,
</del><span class="cx">                                 1CAF34810A6C405200ABE06E /* WebScriptObject.h in Headers */,
</span><span class="cx">                                 1CAF34830A6C405200ABE06E /* WebScriptObjectPrivate.h in Headers */,
</span><span class="cx">                                 1A569D1B0D7E2B82007C3983 /* WebScriptObjectProtocol.h in Headers */,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMWindowBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  *  Copyright (C) 2000 Harri Porten (porten@kde.org)
</span><span class="cx">  *  Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
</span><del>- *  Copyright (C) 2003-2009, 2014 Apple Inc. All rights reseved.
</del><ins>+ *  Copyright (C) 2003-2009, 2014, 2016 Apple Inc. All rights reseved.
</ins><span class="cx">  *  Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
</span><span class="cx">  *  Copyright (c) 2015 Canon Inc. All rights reserved.
</span><span class="cx">  *
</span><span class="lines">@@ -49,8 +49,6 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> #include &quot;ChromeClient.h&quot;
</span><del>-#include &quot;WebSafeGCActivityCallbackIOS.h&quot;
-#include &quot;WebSafeIncrementalSweeperIOS.h&quot;
</del><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> using namespace JSC;
</span><span class="lines">@@ -244,13 +242,11 @@
</span><span class="cx">     if (!vm) {
</span><span class="cx">         ScriptController::initializeThreading();
</span><span class="cx">         vm = &amp;VM::createLeaked(LargeHeap).leakRef();
</span><ins>+        vm-&gt;heap.acquireAccess(); // At any time, we may do things that affect the GC.
</ins><span class="cx"> #if !PLATFORM(IOS)
</span><span class="cx">         vm-&gt;setExclusiveThread(std::this_thread::get_id());
</span><span class="cx"> #else
</span><del>-        vm-&gt;heap.setFullActivityCallback(WebSafeFullGCActivityCallback::create(&amp;vm-&gt;heap));
-        vm-&gt;heap.setEdenActivityCallback(WebSafeEdenGCActivityCallback::create(&amp;vm-&gt;heap));
-
-        vm-&gt;heap.setIncrementalSweeper(std::make_unique&lt;WebSafeIncrementalSweeper&gt;(&amp;vm-&gt;heap));
</del><ins>+        vm-&gt;heap.setRunLoop(WebThreadRunLoop());
</ins><span class="cx">         vm-&gt;heap.machineThreads().addCurrentThread();
</span><span class="cx"> #endif
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsWorkerScriptControllercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/bindings/js/WorkerScriptController.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx">     , m_workerGlobalScope(workerGlobalScope)
</span><span class="cx">     , m_workerGlobalScopeWrapper(*m_vm)
</span><span class="cx"> {
</span><ins>+    m_vm-&gt;heap.acquireAccess(); // It's not clear that we have good discipline for heap access, so turn it on permanently.
</ins><span class="cx">     m_vm-&gt;ensureWatchdog();
</span><span class="cx">     initNormalWorldClientData(m_vm.get());
</span><span class="cx"> }
</span><span class="lines">@@ -188,6 +189,16 @@
</span><span class="cx">     m_workerGlobalScopeWrapper-&gt;setEvalEnabled(false, errorMessage);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WorkerScriptController::releaseHeapAccess()
+{
+    m_vm-&gt;heap.releaseAccess();
+}
+
+void WorkerScriptController::acquireHeapAccess()
+{
+    m_vm-&gt;heap.acquireAccess();
+}
+
</ins><span class="cx"> void WorkerScriptController::attachDebugger(JSC::Debugger* debugger)
</span><span class="cx"> {
</span><span class="cx">     initScriptIfNeeded();
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsWorkerScriptControllerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/WorkerScriptController.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/WorkerScriptController.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/bindings/js/WorkerScriptController.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2015 Apple Inc. All Rights Reserved.
</del><ins>+ * Copyright (C) 2008, 2015, 2016 Apple Inc. All Rights Reserved.
</ins><span class="cx">  * Copyright (C) 2012 Google Inc. All Rights Reserved.
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -76,6 +76,9 @@
</span><span class="cx">         void disableEval(const String&amp; errorMessage);
</span><span class="cx"> 
</span><span class="cx">         JSC::VM&amp; vm() { return *m_vm; }
</span><ins>+        
+        void releaseHeapAccess();
+        void acquireHeapAccess();
</ins><span class="cx"> 
</span><span class="cx">         void attachDebugger(JSC::Debugger*);
</span><span class="cx">         void detachDebugger(JSC::Debugger*);
</span></span></pre></div>
<a id="trunkSourceWebCoredomEventTargetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/EventTarget.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/EventTarget.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/dom/EventTarget.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -131,7 +131,8 @@
</span><span class="cx">         eventTargetData()-&gt;eventListenerMap.replace(eventType, *existingListener, listener.releaseNonNull(), { });
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><del>-    return addEventListener(eventType, listener.releaseNonNull());}
</del><ins>+    return addEventListener(eventType, listener.releaseNonNull());
+}
</ins><span class="cx"> 
</span><span class="cx"> EventListener* EventTarget::getAttributeEventListener(const AtomicString&amp; eventType)
</span><span class="cx"> {
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformiosWebSafeGCActivityCallbackIOSh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/platform/ios/WebSafeGCActivityCallbackIOS.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/WebSafeGCActivityCallbackIOS.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/platform/ios/WebSafeGCActivityCallbackIOS.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,70 +0,0 @@
</span><del>-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef WebSafeGCActivityCallbackIOS_h
-#define WebSafeGCActivityCallbackIOS_h
-
-#include &quot;WebCoreThread.h&quot;
-#include &lt;JavaScriptCore/EdenGCActivityCallback.h&gt;
-#include &lt;JavaScriptCore/FullGCActivityCallback.h&gt;
-
-namespace WebCore {
-
-class WebSafeFullGCActivityCallback final : public JSC::FullGCActivityCallback {
-public:
-    static PassRefPtr&lt;WebSafeFullGCActivityCallback&gt; create(JSC::Heap* heap)
-    {
-        return adoptRef(new WebSafeFullGCActivityCallback(heap));
-    }
-
-    ~WebSafeFullGCActivityCallback() override { }
-
-private:
-    WebSafeFullGCActivityCallback(JSC::Heap* heap)
-        : JSC::FullGCActivityCallback(heap)
-    {
-        setRunLoop(WebThreadRunLoop());
-    }
-};
-
-class WebSafeEdenGCActivityCallback final : public JSC::EdenGCActivityCallback {
-public:
-    static PassRefPtr&lt;WebSafeEdenGCActivityCallback&gt; create(JSC::Heap* heap)
-    {
-        return adoptRef(new WebSafeEdenGCActivityCallback(heap));
-    }
-
-    ~WebSafeEdenGCActivityCallback() override { }
-
-private:
-    WebSafeEdenGCActivityCallback(JSC::Heap* heap)
-        : JSC::EdenGCActivityCallback(heap)
-    {
-        setRunLoop(WebThreadRunLoop());
-    }
-};
-} // namespace WebCore
-
-#endif // WebSafeGCActivityCallbackIOS_h
</del></span></pre></div>
<a id="trunkSourceWebCoreplatformiosWebSafeIncrementalSweeperIOSh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/WebCore/platform/ios/WebSafeIncrementalSweeperIOS.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/ios/WebSafeIncrementalSweeperIOS.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/platform/ios/WebSafeIncrementalSweeperIOS.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,48 +0,0 @@
</span><del>-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef WebSafeIncrementalSweeperIOS_h
-#define WebSafeIncrementalSweeperIOS_h
-
-#include &quot;WebCoreThread.h&quot;
-#include &lt;JavaScriptCore/IncrementalSweeper.h&gt;
-
-namespace WebCore {
-
-class WebSafeIncrementalSweeper final : public JSC::IncrementalSweeper {
-public:
-    explicit WebSafeIncrementalSweeper(JSC::Heap* heap)
-        : JSC::IncrementalSweeper(heap)
-    {
-        setRunLoop(WebThreadRunLoop());
-    }
-
-    ~WebSafeIncrementalSweeper() override { }
-
-};
-
-} // namespace WebCore
-
-#endif // WebSafeIncrementalSweeperIOS_h
</del></span></pre></div>
<a id="trunkSourceWebCoretestingInternalscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/testing/Internals.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2012 Google Inc. All rights reserved.
</span><del>- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -3293,4 +3293,9 @@
</span><span class="cx"> 
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+void Internals::reportBacktrace()
+{
+    WTFReportBacktrace();
+}
+
</ins><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.h (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.h        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/testing/Internals.h        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -496,6 +496,8 @@
</span><span class="cx">     void setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection);
</span><span class="cx"> 
</span><span class="cx">     bool userPrefersReducedMotion() const;
</span><ins>+    
+    void reportBacktrace();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     explicit Internals(Document&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoretestingInternalsidl"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/testing/Internals.idl (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/testing/Internals.idl        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/testing/Internals.idl        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2012 Google Inc. All rights reserved.
</span><del>- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -468,4 +468,6 @@
</span><span class="cx">     void setUserInterfaceLayoutDirection(UserInterfaceLayoutDirection userInterfaceLayoutDirection);
</span><span class="cx"> 
</span><span class="cx">     boolean userPrefersReducedMotion();
</span><ins>+    
+    void reportBacktrace();
</ins><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebCoreworkersWorkerRunLoopcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/workers/WorkerRunLoop.cpp (208305 => 208306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/workers/WorkerRunLoop.cpp        2016-11-02 21:57:51 UTC (rev 208305)
+++ trunk/Source/WebCore/workers/WorkerRunLoop.cpp        2016-11-02 22:01:04 UTC (rev 208306)
</span><span class="lines">@@ -173,7 +173,11 @@
</span><span class="cx">             absoluteTime = deadline;
</span><span class="cx">     }
</span><span class="cx">     MessageQueueWaitResult result;
</span><ins>+    if (WorkerScriptController* script = context-&gt;script())
+        script-&gt;releaseHeapAccess();
</ins><span class="cx">     auto task = m_messageQueue.waitForMessageFilteredWithTimeout(result, predicate, absoluteTime);
</span><ins>+    if (WorkerScriptController* script = context-&gt;script())
+        script-&gt;acquireHeapAccess();
</ins><span class="cx"> 
</span><span class="cx">     // If the context is closing, don't execute any further JavaScript tasks (per section 4.1.1 of the Web Workers spec).  However, there may be implementation cleanup tasks in the queue, so keep running through it.
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>