<!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>[210653] branches/safari-603-branch/Source/JavaScriptCore</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/210653">210653</a></dd>
<dt>Author</dt> <dd>matthew_hanson@apple.com</dd>
<dt>Date</dt> <dd>2017-01-12 08:45:48 -0800 (Thu, 12 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/210521">r210521</a>. rdar://problem/29909896</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari603branchSourceJavaScriptCoreCMakeListstxt">branches/safari-603-branch/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreChangeLog">branches/safari-603-branch/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">branches/safari-603-branch/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGPlancpp">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGPlanh">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlan.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGWorklistcpp">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklist.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGWorklisth">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklist.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapCodeBlockSetcpp">branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSet.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapCodeBlockSeth">branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSet.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapCodeBlockSetInlinesh">branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSetInlines.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapHeapcpp">branches/safari-603-branch/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapHeaph">branches/safari-603-branch/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapOpaqueRootSeth">branches/safari-603-branch/Source/JavaScriptCore/heap/OpaqueRootSet.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapSlotVisitorcpp">branches/safari-603-branch/Source/JavaScriptCore/heap/SlotVisitor.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapSlotVisitorh">branches/safari-603-branch/Source/JavaScriptCore/heap/SlotVisitor.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreruntimeOptionsh">branches/safari-603-branch/Source/JavaScriptCore/runtime/Options.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGPlanInlinesh">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlanInlines.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoredfgDFGWorklistInlinesh">branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklistInlines.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapMarkingConstraintcpp">branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraint.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapMarkingConstrainth">branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraint.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapMarkingConstraintSetcpp">branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraintSet.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapMarkingConstraintSeth">branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraintSet.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapMutatorSchedulercpp">branches/safari-603-branch/Source/JavaScriptCore/heap/MutatorScheduler.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapMutatorSchedulerh">branches/safari-603-branch/Source/JavaScriptCore/heap/MutatorScheduler.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapSpaceTimeMutatorSchedulercpp">branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeMutatorScheduler.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapSpaceTimeMutatorSchedulerh">branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeMutatorScheduler.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapSynchronousStopTheWorldMutatorSchedulercpp">branches/safari-603-branch/Source/JavaScriptCore/heap/SynchronousStopTheWorldMutatorScheduler.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapSynchronousStopTheWorldMutatorSchedulerh">branches/safari-603-branch/Source/JavaScriptCore/heap/SynchronousStopTheWorldMutatorScheduler.h</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapVisitingTimeouth">branches/safari-603-branch/Source/JavaScriptCore/heap/VisitingTimeout.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapSpaceTimeSchedulercpp">branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.cpp</a></li>
<li><a href="#branchessafari603branchSourceJavaScriptCoreheapSpaceTimeSchedulerh">branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari603branchSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/CMakeLists.txt (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/CMakeLists.txt        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/CMakeLists.txt        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -497,10 +497,14 @@
</span><span class="cx">     heap/MarkedAllocator.cpp
</span><span class="cx">     heap/MarkedBlock.cpp
</span><span class="cx">     heap/MarkedSpace.cpp
</span><ins>+    heap/MarkingConstraint.cpp
+    heap/MarkingConstraintSet.cpp
+    heap/MutatorScheduler.cpp
</ins><span class="cx">     heap/MutatorState.cpp
</span><span class="cx">     heap/SlotVisitor.cpp
</span><del>-    heap/SpaceTimeScheduler.cpp
</del><ins>+    heap/SpaceTimeMutatorScheduler.cpp
</ins><span class="cx">     heap/StopIfNecessaryTimer.cpp
</span><ins>+    heap/SynchronousStopTheWorldMutatorScheduler.cpp
</ins><span class="cx">     heap/VisitRaceKey.cpp
</span><span class="cx">     heap/Weak.cpp
</span><span class="cx">     heap/WeakBlock.cpp
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/ChangeLog (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/ChangeLog        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/ChangeLog        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,5 +1,255 @@
</span><span class="cx"> 2017-01-12  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r210521. rdar://problem/29909896
+
+    2017-01-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+            Make the collector's fixpoint smart about scheduling work
+            https://bugs.webkit.org/show_bug.cgi?id=165910
+
+            Reviewed by Keith Miller.
+
+            Prior to this change, every time the GC would run any constraints in markToFixpoint, it
+            would run all of the constraints. It would always run them in the same order. That means
+            that so long as any one constraint was generating new work, we'd pay the price of all
+            constraints. This is usually OK because most constraints are cheap but it artificially
+            inflates the cost of slow constraints - especially ones that are expensive but usually
+            generate no new work.
+
+            This patch redoes how the GC runs constraints by applying ideas from data flow analysis.
+            The GC now builds a MarkingConstraintSet when it boots up, and this contains all of the
+            constraints as well as some meta-data about them. Now, markToFixpoint just calls into
+            MarkingConstraintSet to execute constraints. Because constraint execution and scheduling
+            need to be aware of each other, I rewrote markToFixpoint in such a way that it's more
+            obvious how the GC goes between constraint solving, marking with stopped mutator, and
+            marking with resumed mutator. This also changes the scheduler API in such a way that a
+            synchronous stop-the-world collection no longer needs to do fake stop/resume - instead we
+            just swap the space-time scheduler for the stop-the-world scheduler.
+
+            This is a big streamlining of the GC. This is a speed-up in GC-heavy tests because we
+            now execute most constraints exactly twice regardless of how many total fixpoint
+            iterations we do. Now, when we run out of marking work, the constraint solver will just
+            run the constraint that is most likely to generate new visiting work, and if it does
+            generate work, then the GC now goes back to marking. Before, it would run *all*
+            constraints and then go back to marking. The constraint solver is armed with three
+            information signals that it uses to sort the constraints in order of descending likelihood
+            to generate new marking work. Then it runs them in that order until it there is new
+            marking work. The signals are:
+
+            1) Whether the constraint is greyed by marking or execution. We call this the volatility
+               of the constraint. For example, weak reference constraints have GreyedByMarking as
+               their volatility because they are most likely to have something to say after we've done
+               some marking. On the other hand, conservative roots have GreyedByExecution as their
+               volatility because they will give new information anytime we let the mutator run. The
+               constraint solver will only run GreyedByExecution constraints as roots and after the
+               GreyedByMarking constraints go silent. This ensures that we don't try to scan
+               conservative roots every time we need to re-run weak references and vice-versa.
+
+               Another way to look at it is that the constraint solver tries to predict if the
+               wavefront is advancing or retreating. The wavefront is almost certainly advancing so
+               long as the mark stacks are non-empty or so long as at least one of the GreyedByMarking
+               constraints is still producing work. Otherwise the wavefront is almost certainly
+               retreating. It's most profitable to run GreyedByMarking constraints when the wavefront
+               is advancing, and most profitable to run GreyedByExecution constraints when the
+               wavefront is retreating.
+
+               We use the predicted wavefront direction and the volatility of constraints as a
+               first-order signal of constraint profitability.
+
+            2) How much visiting work was created the last time the constraint ran. The solver
+               remembers the lastVisitCount, and uses it to predict how much work the constraint will
+               generate next time. In practice this means we will keep re-running the one interesting
+               constraint until it shuts up.
+
+            3) Optional work predictors for some constraints. The constraint that shuffles the mutator
+               mark stack into the main SlotVisitor's mutator mark stack always knows exactly how much
+               work it will create.
+
+               The sum of (2) and (3) are used as a second-order signal of constraint profitability.
+
+            The constraint solver will always run all of the GreyedByExecution constraints at GC
+            start, since these double as the GC's roots. The constraint solver will always run all of
+            the GreyedByMarking constraints the first time that marking stalls. Other than that, the
+            solver will keep running constraints, sorted according to their likelihood to create work,
+            until either work is created or we run out of constraints to run. GC termination happens
+            when we run out of constraints to run.
+
+            This new infrastructure means that we have a much better chance of dealing with worst-case
+            DOM pathologies. If we can intelligently factor different evil DOM things into different
+            constraints with the right work predictions then this could reduce the cost of those DOM
+            things by a factor of N where N is the number of fixpoint iterations the GC typically
+            does. N is usually around 5-6 even for simple heaps.
+
+            My perf measurements say:
+
+            PLT3: 0.02% faster with 5.3% confidence.
+            JetStream: 0.15% faster with 17% confidence.
+            Speedometer: 0.58% faster with 82% confidence.
+
+            Here are the details from JetStream:
+
+            splay: 1.02173x faster with 0.996841 confidence
+            splay-latency: 1.0617x faster with 0.987462 confidence
+            towers.c: 1.01852x faster with 0.92128 confidence
+            crypto-md5: 1.06058x faster with 0.482363 confidence
+            score: 1.00152x faster with 0.16892 confidence
+
+            I think that Speedometer is legitimately benefiting from this change based on looking at
+            --logGC=true output. We are now spending less time reexecuting expensive constraints. I
+            think that JetStream/splay is also benefiting, because although the constraints it sees
+            are cheap, it spends 30% of its time in GC so even small improvements matter.
+
+            * CMakeLists.txt:
+            * JavaScriptCore.xcodeproj/project.pbxproj:
+            * dfg/DFGPlan.cpp:
+            (JSC::DFG::Plan::markCodeBlocks): Deleted.
+            (JSC::DFG::Plan::rememberCodeBlocks): Deleted.
+            * dfg/DFGPlan.h:
+            * dfg/DFGPlanInlines.h: Added.
+            (JSC::DFG::Plan::iterateCodeBlocksForGC):
+            * dfg/DFGWorklist.cpp:
+            (JSC::DFG::Worklist::markCodeBlocks): Deleted.
+            (JSC::DFG::Worklist::rememberCodeBlocks): Deleted.
+            (JSC::DFG::rememberCodeBlocks): Deleted.
+            * dfg/DFGWorklist.h:
+            * dfg/DFGWorklistInlines.h: Added.
+            (JSC::DFG::iterateCodeBlocksForGC):
+            (JSC::DFG::Worklist::iterateCodeBlocksForGC):
+            * heap/CodeBlockSet.cpp:
+            (JSC::CodeBlockSet::writeBarrierCurrentlyExecuting): Deleted.
+            * heap/CodeBlockSet.h:
+            (JSC::CodeBlockSet::iterate): Deleted.
+            * heap/CodeBlockSetInlines.h:
+            (JSC::CodeBlockSet::iterate):
+            (JSC::CodeBlockSet::iterateCurrentlyExecuting):
+            * heap/Heap.cpp:
+            (JSC::Heap::Heap):
+            (JSC::Heap::iterateExecutingAndCompilingCodeBlocks):
+            (JSC::Heap::iterateExecutingAndCompilingCodeBlocksWithoutHoldingLocks):
+            (JSC::Heap::assertSharedMarkStacksEmpty):
+            (JSC::Heap::markToFixpoint):
+            (JSC::Heap::endMarking):
+            (JSC::Heap::collectInThread):
+            (JSC::Heap::stopIfNecessarySlow):
+            (JSC::Heap::acquireAccessSlow):
+            (JSC::Heap::collectIfNecessaryOrDefer):
+            (JSC::Heap::buildConstraintSet):
+            (JSC::Heap::notifyIsSafeToCollect):
+            (JSC::Heap::ResumeTheWorldScope::ResumeTheWorldScope): Deleted.
+            (JSC::Heap::ResumeTheWorldScope::~ResumeTheWorldScope): Deleted.
+            (JSC::Heap::harvestWeakReferences): Deleted.
+            (JSC::Heap::visitConservativeRoots): Deleted.
+            (JSC::Heap::visitCompilerWorklistWeakReferences): Deleted.
+            * heap/Heap.h:
+            * heap/MarkingConstraint.cpp: Added.
+            (JSC::MarkingConstraint::MarkingConstraint):
+            (JSC::MarkingConstraint::~MarkingConstraint):
+            (JSC::MarkingConstraint::resetStats):
+            (JSC::MarkingConstraint::execute):
+            * heap/MarkingConstraint.h: Added.
+            (JSC::MarkingConstraint::index):
+            (JSC::MarkingConstraint::abbreviatedName):
+            (JSC::MarkingConstraint::name):
+            (JSC::MarkingConstraint::lastVisitCount):
+            (JSC::MarkingConstraint::quickWorkEstimate):
+            (JSC::MarkingConstraint::workEstimate):
+            (JSC::MarkingConstraint::volatility):
+            * heap/MarkingConstraintSet.cpp: Added.
+            (JSC::MarkingConstraintSet::ExecutionContext::ExecutionContext):
+            (JSC::MarkingConstraintSet::ExecutionContext::didVisitSomething):
+            (JSC::MarkingConstraintSet::ExecutionContext::shouldTimeOut):
+            (JSC::MarkingConstraintSet::ExecutionContext::drain):
+            (JSC::MarkingConstraintSet::ExecutionContext::didExecute):
+            (JSC::MarkingConstraintSet::ExecutionContext::execute):
+            (JSC::MarkingConstraintSet::MarkingConstraintSet):
+            (JSC::MarkingConstraintSet::~MarkingConstraintSet):
+            (JSC::MarkingConstraintSet::resetStats):
+            (JSC::MarkingConstraintSet::add):
+            (JSC::MarkingConstraintSet::executeBootstrap):
+            (JSC::MarkingConstraintSet::executeConvergence):
+            (JSC::MarkingConstraintSet::isWavefrontAdvancing):
+            (JSC::MarkingConstraintSet::executeConvergenceImpl):
+            (JSC::MarkingConstraintSet::executeAll):
+            * heap/MarkingConstraintSet.h: Added.
+            (JSC::MarkingConstraintSet::isWavefrontRetreating):
+            * heap/MutatorScheduler.cpp: Added.
+            (JSC::MutatorScheduler::MutatorScheduler):
+            (JSC::MutatorScheduler::~MutatorScheduler):
+            (JSC::MutatorScheduler::didStop):
+            (JSC::MutatorScheduler::willResume):
+            (JSC::MutatorScheduler::didExecuteConstraints):
+            (JSC::MutatorScheduler::log):
+            (JSC::MutatorScheduler::shouldStop):
+            (JSC::MutatorScheduler::shouldResume):
+            * heap/MutatorScheduler.h: Added.
+            * heap/OpaqueRootSet.h:
+            (JSC::OpaqueRootSet::add):
+            * heap/SlotVisitor.cpp:
+            (JSC::SlotVisitor::visitAsConstraint):
+            (JSC::SlotVisitor::drain):
+            (JSC::SlotVisitor::didReachTermination):
+            (JSC::SlotVisitor::hasWork):
+            (JSC::SlotVisitor::drainFromShared):
+            (JSC::SlotVisitor::drainInParallelPassively):
+            (JSC::SlotVisitor::addOpaqueRoot):
+            * heap/SlotVisitor.h:
+            (JSC::SlotVisitor::addToVisitCount):
+            * heap/SpaceTimeMutatorScheduler.cpp: Copied from Source/JavaScriptCore/heap/SpaceTimeScheduler.cpp.
+            (JSC::SpaceTimeMutatorScheduler::Snapshot::Snapshot):
+            (JSC::SpaceTimeMutatorScheduler::Snapshot::now):
+            (JSC::SpaceTimeMutatorScheduler::Snapshot::bytesAllocatedThisCycle):
+            (JSC::SpaceTimeMutatorScheduler::SpaceTimeMutatorScheduler):
+            (JSC::SpaceTimeMutatorScheduler::~SpaceTimeMutatorScheduler):
+            (JSC::SpaceTimeMutatorScheduler::state):
+            (JSC::SpaceTimeMutatorScheduler::beginCollection):
+            (JSC::SpaceTimeMutatorScheduler::didStop):
+            (JSC::SpaceTimeMutatorScheduler::willResume):
+            (JSC::SpaceTimeMutatorScheduler::didExecuteConstraints):
+            (JSC::SpaceTimeMutatorScheduler::timeToStop):
+            (JSC::SpaceTimeMutatorScheduler::timeToResume):
+            (JSC::SpaceTimeMutatorScheduler::log):
+            (JSC::SpaceTimeMutatorScheduler::endCollection):
+            (JSC::SpaceTimeMutatorScheduler::bytesAllocatedThisCycleImpl):
+            (JSC::SpaceTimeMutatorScheduler::bytesSinceBeginningOfCycle):
+            (JSC::SpaceTimeMutatorScheduler::maxHeadroom):
+            (JSC::SpaceTimeMutatorScheduler::headroomFullness):
+            (JSC::SpaceTimeMutatorScheduler::mutatorUtilization):
+            (JSC::SpaceTimeMutatorScheduler::collectorUtilization):
+            (JSC::SpaceTimeMutatorScheduler::elapsedInPeriod):
+            (JSC::SpaceTimeMutatorScheduler::phase):
+            (JSC::SpaceTimeMutatorScheduler::shouldBeResumed):
+            (JSC::SpaceTimeScheduler::Decision::targetMutatorUtilization): Deleted.
+            (JSC::SpaceTimeScheduler::Decision::targetCollectorUtilization): Deleted.
+            (JSC::SpaceTimeScheduler::Decision::elapsedInPeriod): Deleted.
+            (JSC::SpaceTimeScheduler::Decision::phase): Deleted.
+            (JSC::SpaceTimeScheduler::Decision::shouldBeResumed): Deleted.
+            (JSC::SpaceTimeScheduler::Decision::timeToResume): Deleted.
+            (JSC::SpaceTimeScheduler::Decision::timeToStop): Deleted.
+            (JSC::SpaceTimeScheduler::SpaceTimeScheduler): Deleted.
+            (JSC::SpaceTimeScheduler::snapPhase): Deleted.
+            (JSC::SpaceTimeScheduler::currentDecision): Deleted.
+            * heap/SpaceTimeMutatorScheduler.h: Copied from Source/JavaScriptCore/heap/SpaceTimeScheduler.h.
+            (JSC::SpaceTimeScheduler::Decision::operator bool): Deleted.
+            * heap/SpaceTimeScheduler.cpp: Removed.
+            * heap/SpaceTimeScheduler.h: Removed.
+            * heap/SynchronousStopTheWorldMutatorScheduler.cpp: Added.
+            (JSC::SynchronousStopTheWorldMutatorScheduler::SynchronousStopTheWorldMutatorScheduler):
+            (JSC::SynchronousStopTheWorldMutatorScheduler::~SynchronousStopTheWorldMutatorScheduler):
+            (JSC::SynchronousStopTheWorldMutatorScheduler::state):
+            (JSC::SynchronousStopTheWorldMutatorScheduler::beginCollection):
+            (JSC::SynchronousStopTheWorldMutatorScheduler::timeToStop):
+            (JSC::SynchronousStopTheWorldMutatorScheduler::timeToResume):
+            (JSC::SynchronousStopTheWorldMutatorScheduler::endCollection):
+            * heap/SynchronousStopTheWorldMutatorScheduler.h: Added.
+            * heap/VisitingTimeout.h: Added.
+            (JSC::VisitingTimeout::VisitingTimeout):
+            (JSC::VisitingTimeout::visitCount):
+            (JSC::VisitingTimeout::didVisitSomething):
+            (JSC::VisitingTimeout::shouldTimeOut):
+            * runtime/Options.h:
+
+2017-01-12  Matthew Hanson  &lt;matthew_hanson@apple.com&gt;
+
</ins><span class="cx">         Merge r210457. rdar://problem/27330808
</span><span class="cx"> 
</span><span class="cx">     2017-01-06  Michael Saboff  &lt;msaboff@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -127,6 +127,13 @@
</span><span class="cx">                 0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */; };
</span><span class="cx">                 0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */; };
</span><span class="cx">                 0F1E3A67153A21E2000F9456 /* DFGSilentRegisterSavePlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A65153A21DF000F9456 /* DFGSilentRegisterSavePlan.h */; };
</span><ins>+                0F1FB38E1E173A6500A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1FB38A1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp */; };
+                0F1FB38F1E173A6700A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB38B1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h */; };
+                0F1FB3901E173A6B00A9BE50 /* MutatorScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1FB38C1E173A6200A9BE50 /* MutatorScheduler.cpp */; };
+                0F1FB3931E177A7200A9BE50 /* VisitingTimeout.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB3921E177A6F00A9BE50 /* VisitingTimeout.h */; };
+                0F1FB3961E1AF7E100A9BE50 /* DFGPlanInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB3941E1AF7DF00A9BE50 /* DFGPlanInlines.h */; };
+                0F1FB3971E1AF7E300A9BE50 /* DFGWorklistInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB3951E1AF7DF00A9BE50 /* DFGWorklistInlines.h */; };
+                0F1FB3991E1F65FB00A9BE50 /* MutatorScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FB3981E1F65F900A9BE50 /* MutatorScheduler.h */; };
</ins><span class="cx">                 0F1FE51C1922A3BC006987C5 /* AbortReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1FE51B1922A3BC006987C5 /* AbortReason.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F20177F1DCADC3300EA5950 /* DFGFlowIndexing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F20177D1DCADC3000EA5950 /* DFGFlowIndexing.cpp */; };
</span><span class="cx">                 0F2017801DCADC3500EA5950 /* DFGFlowIndexing.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F20177E1DCADC3000EA5950 /* DFGFlowIndexing.h */; };
</span><span class="lines">@@ -455,6 +462,10 @@
</span><span class="cx">                 0F64B2791A7957B2006E4E66 /* CallEdge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F64B2771A7957B2006E4E66 /* CallEdge.cpp */; };
</span><span class="cx">                 0F64B27A1A7957B2006E4E66 /* CallEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F64B2781A7957B2006E4E66 /* CallEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F64EAF31C4ECD0600621E9B /* AirArgInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F64EAF21C4ECD0600621E9B /* AirArgInlines.h */; };
</span><ins>+                0F660E371E0517B90031462C /* MarkingConstraint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F660E331E0517B70031462C /* MarkingConstraint.cpp */; };
+                0F660E381E0517BB0031462C /* MarkingConstraint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F660E341E0517B70031462C /* MarkingConstraint.h */; };
+                0F660E391E0517BF0031462C /* MarkingConstraintSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F660E351E0517B70031462C /* MarkingConstraintSet.cpp */; };
+                0F660E3A1E0517C10031462C /* MarkingConstraintSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F660E361E0517B80031462C /* MarkingConstraintSet.h */; };
</ins><span class="cx">                 0F664CE81DA304EF00B00A11 /* CodeBlockSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F664CE71DA304ED00B00A11 /* CodeBlockSetInlines.h */; };
</span><span class="cx">                 0F666EC0183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F666EBE183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F666EC1183566F900D017F1 /* FullBytecodeLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F666EBF183566F900D017F1 /* FullBytecodeLiveness.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -753,8 +764,8 @@
</span><span class="cx">                 0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */; };
</span><span class="cx">                 0FDDBFB61666EEDA00C55FEF /* DFGVariableAccessDataDump.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */; };
</span><span class="cx">                 0FDE87F91DFD0C760064C390 /* CellContainer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDE87F81DFD0C6D0064C390 /* CellContainer.cpp */; };
</span><del>-                0FDE87FC1DFE6E510064C390 /* SpaceTimeScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDE87FB1DFE6E500064C390 /* SpaceTimeScheduler.h */; };
-                0FDE87FD1DFE6E540064C390 /* SpaceTimeScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDE87FA1DFE6E500064C390 /* SpaceTimeScheduler.cpp */; };
</del><ins>+                0FDE87FC1DFE6E510064C390 /* SpaceTimeMutatorScheduler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDE87FB1DFE6E500064C390 /* SpaceTimeMutatorScheduler.h */; };
+                0FDE87FD1DFE6E540064C390 /* SpaceTimeMutatorScheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDE87FA1DFE6E500064C390 /* SpaceTimeMutatorScheduler.cpp */; };
</ins><span class="cx">                 0FDF67D21D9C6D27001B9825 /* B3Kind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FDF67D11D9C6086001B9825 /* B3Kind.h */; };
</span><span class="cx">                 0FDF67D31D9C6D2A001B9825 /* B3Kind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDF67D01D9C6086001B9825 /* B3Kind.cpp */; };
</span><span class="cx">                 0FDF67D61D9DC440001B9825 /* AirKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDF67D41D9DC43E001B9825 /* AirKind.cpp */; };
</span><span class="lines">@@ -2551,6 +2562,13 @@
</span><span class="cx">                 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDoubleFormatState.h; path = dfg/DFGDoubleFormatState.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSlowPathGenerator.h; path = dfg/DFGSlowPathGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F1E3A65153A21DF000F9456 /* DFGSilentRegisterSavePlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSilentRegisterSavePlan.h; path = dfg/DFGSilentRegisterSavePlan.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F1FB38A1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SynchronousStopTheWorldMutatorScheduler.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F1FB38B1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SynchronousStopTheWorldMutatorScheduler.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F1FB38C1E173A6200A9BE50 /* MutatorScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MutatorScheduler.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F1FB3921E177A6F00A9BE50 /* VisitingTimeout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisitingTimeout.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F1FB3941E1AF7DF00A9BE50 /* DFGPlanInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPlanInlines.h; path = dfg/DFGPlanInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F1FB3951E1AF7DF00A9BE50 /* DFGWorklistInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGWorklistInlines.h; path = dfg/DFGWorklistInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F1FB3981E1F65F900A9BE50 /* MutatorScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MutatorScheduler.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F1FE51B1922A3BC006987C5 /* AbortReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbortReason.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F20177D1DCADC3000EA5950 /* DFGFlowIndexing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGFlowIndexing.cpp; path = dfg/DFGFlowIndexing.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F20177E1DCADC3000EA5950 /* DFGFlowIndexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFlowIndexing.h; path = dfg/DFGFlowIndexing.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2876,6 +2894,10 @@
</span><span class="cx">                 0F64B2771A7957B2006E4E66 /* CallEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallEdge.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F64B2781A7957B2006E4E66 /* CallEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallEdge.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F64EAF21C4ECD0600621E9B /* AirArgInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirArgInlines.h; path = b3/air/AirArgInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F660E331E0517B70031462C /* MarkingConstraint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkingConstraint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F660E341E0517B70031462C /* MarkingConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkingConstraint.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F660E351E0517B70031462C /* MarkingConstraintSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkingConstraintSet.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F660E361E0517B80031462C /* MarkingConstraintSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkingConstraintSet.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F664CE71DA304ED00B00A11 /* CodeBlockSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockSetInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F666EBE183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeLivenessAnalysisInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F666EBF183566F900D017F1 /* FullBytecodeLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FullBytecodeLiveness.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3185,8 +3207,8 @@
</span><span class="cx">                 0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableAccessDataDump.cpp; path = dfg/DFGVariableAccessDataDump.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessDataDump.h; path = dfg/DFGVariableAccessDataDump.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDE87F81DFD0C6D0064C390 /* CellContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CellContainer.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                0FDE87FA1DFE6E500064C390 /* SpaceTimeScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpaceTimeScheduler.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
-                0FDE87FB1DFE6E500064C390 /* SpaceTimeScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpaceTimeScheduler.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><ins>+                0FDE87FA1DFE6E500064C390 /* SpaceTimeMutatorScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpaceTimeMutatorScheduler.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FDE87FB1DFE6E500064C390 /* SpaceTimeMutatorScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpaceTimeMutatorScheduler.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FDF67D01D9C6086001B9825 /* B3Kind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3Kind.cpp; path = b3/B3Kind.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDF67D11D9C6086001B9825 /* B3Kind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3Kind.h; path = b3/B3Kind.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FDF67D41D9DC43E001B9825 /* AirKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirKind.cpp; path = b3/air/AirKind.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5735,8 +5757,14 @@
</span><span class="cx">                                 14D2F3D8139F4BE200491031 /* MarkedSpace.cpp */,
</span><span class="cx">                                 14D2F3D9139F4BE200491031 /* MarkedSpace.h */,
</span><span class="cx">                                 0F7C5FB91D8895050044F5E2 /* MarkedSpaceInlines.h */,
</span><ins>+                                0F660E331E0517B70031462C /* MarkingConstraint.cpp */,
+                                0F660E341E0517B70031462C /* MarkingConstraint.h */,
+                                0F660E351E0517B70031462C /* MarkingConstraintSet.cpp */,
+                                0F660E361E0517B80031462C /* MarkingConstraintSet.h */,
</ins><span class="cx">                                 142D6F0E13539A4100B02E86 /* MarkStack.cpp */,
</span><span class="cx">                                 142D6F0F13539A4100B02E86 /* MarkStack.h */,
</span><ins>+                                0F1FB38C1E173A6200A9BE50 /* MutatorScheduler.cpp */,
+                                0F1FB3981E1F65F900A9BE50 /* MutatorScheduler.h */,
</ins><span class="cx">                                 0FA762021DB9242300B7A2FD /* MutatorState.cpp */,
</span><span class="cx">                                 0FA762031DB9242300B7A2FD /* MutatorState.h */,
</span><span class="cx">                                 ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */,
</span><span class="lines">@@ -5745,14 +5773,17 @@
</span><span class="cx">                                 C225494215F7DBAA0065E898 /* SlotVisitor.cpp */,
</span><span class="cx">                                 14BA78F013AAB88F005B7C2C /* SlotVisitor.h */,
</span><span class="cx">                                 0FCB408515C0A3C30048932B /* SlotVisitorInlines.h */,
</span><del>-                                0FDE87FA1DFE6E500064C390 /* SpaceTimeScheduler.cpp */,
-                                0FDE87FB1DFE6E500064C390 /* SpaceTimeScheduler.h */,
</del><ins>+                                0FDE87FA1DFE6E500064C390 /* SpaceTimeMutatorScheduler.cpp */,
+                                0FDE87FB1DFE6E500064C390 /* SpaceTimeMutatorScheduler.h */,
</ins><span class="cx">                                 0F7CF9501DC027D70098CC12 /* StopIfNecessaryTimer.cpp */,
</span><span class="cx">                                 0F7CF9511DC027D70098CC12 /* StopIfNecessaryTimer.h */,
</span><span class="cx">                                 142E3132134FF0A600AFADB5 /* Strong.h */,
</span><span class="cx">                                 145722851437E140005FDE26 /* StrongInlines.h */,
</span><ins>+                                0F1FB38A1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp */,
+                                0F1FB38B1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h */,
</ins><span class="cx">                                 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */,
</span><span class="cx">                                 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */,
</span><ins>+                                0F1FB3921E177A6F00A9BE50 /* VisitingTimeout.h */,
</ins><span class="cx">                                 0F952A9F1DF7860700E06FBD /* VisitRaceKey.cpp */,
</span><span class="cx">                                 0F952AA01DF7860700E06FBD /* VisitRaceKey.h */,
</span><span class="cx">                                 1ACF7376171CA6FB00C9BB1E /* Weak.cpp */,
</span><span class="lines">@@ -6975,6 +7006,7 @@
</span><span class="cx">                                 0F2B9CDF19D0BA7D00B1D1B5 /* DFGPhiChildren.h */,
</span><span class="cx">                                 A78A9772179738B8009DF744 /* DFGPlan.cpp */,
</span><span class="cx">                                 A78A9773179738B8009DF744 /* DFGPlan.h */,
</span><ins>+                                0F1FB3941E1AF7DF00A9BE50 /* DFGPlanInlines.h */,
</ins><span class="cx">                                 DC00039019D8BE6F00023EB0 /* DFGPreciseLocalClobberize.h */,
</span><span class="cx">                                 0FBE0F6D16C1DB010082C5E8 /* DFGPredictionInjectionPhase.cpp */,
</span><span class="cx">                                 0FBE0F6E16C1DB010082C5E8 /* DFGPredictionInjectionPhase.h */,
</span><span class="lines">@@ -7063,6 +7095,7 @@
</span><span class="cx">                                 0FC97F3C18202119002C9B26 /* DFGWatchpointCollectionPhase.h */,
</span><span class="cx">                                 0FDB2CE5174830A2007B3C1B /* DFGWorklist.cpp */,
</span><span class="cx">                                 0FDB2CE6174830A2007B3C1B /* DFGWorklist.h */,
</span><ins>+                                0F1FB3951E1AF7DF00A9BE50 /* DFGWorklistInlines.h */,
</ins><span class="cx">                         );
</span><span class="cx">                         name = dfg;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="lines">@@ -7921,6 +7954,7 @@
</span><span class="cx">                                 0FB7F39815ED8E4600F167B2 /* ButterflyInlines.h in Headers */,
</span><span class="cx">                                 C2FCAE1117A9C24E0034C735 /* BytecodeBasicBlock.h in Headers */,
</span><span class="cx">                                 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */,
</span><ins>+                                0F1FB3931E177A7200A9BE50 /* VisitingTimeout.h in Headers */,
</ins><span class="cx">                                 969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */,
</span><span class="cx">                                 E328DAE81D38D005001A2529 /* BytecodeGeneratorification.h in Headers */,
</span><span class="cx">                                 E328DAE91D38D005001A2529 /* BytecodeGraph.h in Headers */,
</span><span class="lines">@@ -8451,6 +8485,7 @@
</span><span class="cx">                                 A1D793011B43864B004516F5 /* IntlNumberFormatPrototype.h in Headers */,
</span><span class="cx">                                 A125846F1B45A36000CC7F6C /* IntlNumberFormatPrototype.lut.h in Headers */,
</span><span class="cx">                                 A12BBFF21B044A8B00664B69 /* IntlObject.h in Headers */,
</span><ins>+                                0F1FB3971E1AF7E300A9BE50 /* DFGWorklistInlines.h in Headers */,
</ins><span class="cx">                                 708EBE241CE8F35800453146 /* IntlObjectInlines.h in Headers */,
</span><span class="cx">                                 860BD801148EA6F200112B2F /* Intrinsic.h in Headers */,
</span><span class="cx">                                 8B9F6D561D5912FA001C739F /* IterationKind.h in Headers */,
</span><span class="lines">@@ -8535,7 +8570,9 @@
</span><span class="cx">                                 0F2B66EF17B6B5AB00A7AE3F /* JSFloat32Array.h in Headers */,
</span><span class="cx">                                 0F2B66F017B6B5AB00A7AE3F /* JSFloat64Array.h in Headers */,
</span><span class="cx">                                 BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
</span><ins>+                                0F660E3A1E0517C10031462C /* MarkingConstraintSet.h in Headers */,
</ins><span class="cx">                                 A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
</span><ins>+                                0F660E381E0517BB0031462C /* MarkingConstraint.h in Headers */,
</ins><span class="cx">                                 70B7919C1C024A49002481E2 /* JSGeneratorFunction.h in Headers */,
</span><span class="cx">                                 0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
</span><span class="cx">                                 0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
</span><span class="lines">@@ -8647,6 +8684,7 @@
</span><span class="cx">                                 AD2FCBEB1DB58DAD00B3E736 /* JSWebAssemblyTable.h in Headers */,
</span><span class="cx">                                 1442566215EDE98D0066A49B /* JSWithScope.h in Headers */,
</span><span class="cx">                                 86E3C619167BABEE006D760A /* JSWrapperMap.h in Headers */,
</span><ins>+                                0F1FB38F1E173A6700A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h in Headers */,
</ins><span class="cx">                                 BC18C42E0E16F5CD00B34460 /* JSWrapperObject.h in Headers */,
</span><span class="cx">                                 BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */,
</span><span class="cx">                                 A72FFD64139985A800E5365A /* KeywordLookup.h in Headers */,
</span><span class="lines">@@ -8692,6 +8730,7 @@
</span><span class="cx">                                 863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */,
</span><span class="cx">                                 E32AB2441DCD75F400D7533A /* MacroAssemblerHelpers.h in Headers */,
</span><span class="cx">                                 86C568E111A213EE0007F7F0 /* MacroAssemblerMIPS.h in Headers */,
</span><ins>+                                0F1FB3961E1AF7E100A9BE50 /* DFGPlanInlines.h in Headers */,
</ins><span class="cx">                                 FE68C6371B90DE040042BCB3 /* MacroAssemblerPrinter.h in Headers */,
</span><span class="cx">                                 86AE64A9135E5E1C00963012 /* MacroAssemblerSH4.h in Headers */,
</span><span class="cx">                                 860161E40F3A83C100F84710 /* MacroAssemblerX86.h in Headers */,
</span><span class="lines">@@ -8875,7 +8914,7 @@
</span><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><del>-                                0FDE87FC1DFE6E510064C390 /* SpaceTimeScheduler.h in Headers */,
</del><ins>+                                0FDE87FC1DFE6E510064C390 /* SpaceTimeMutatorScheduler.h in Headers */,
</ins><span class="cx">                                 0FB7F39E15ED8E4600F167B2 /* SparseArrayValueMap.h in Headers */,
</span><span class="cx">                                 A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */,
</span><span class="cx">                                 0F5541B21613C1FB00CE3E25 /* SpecialPointer.h in Headers */,
</span><span class="lines">@@ -8908,6 +8947,7 @@
</span><span class="cx">                                 BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */,
</span><span class="cx">                                 BC9041480EB9250900FE26FA /* StructureTransitionTable.h in Headers */,
</span><span class="cx">                                 0F4A38FA1C8E13DF00190318 /* SuperSampler.h in Headers */,
</span><ins>+                                0F1FB3991E1F65FB00A9BE50 /* MutatorScheduler.h in Headers */,
</ins><span class="cx">                                 705B41AC1A6E501E00716757 /* Symbol.h in Headers */,
</span><span class="cx">                                 705B41AE1A6E501E00716757 /* SymbolConstructor.h in Headers */,
</span><span class="cx">                                 996B73271BDA08EF00331B84 /* SymbolConstructor.lut.h in Headers */,
</span><span class="lines">@@ -9715,6 +9755,7 @@
</span><span class="cx">                                 A7E5A3A71797432D00E893C0 /* CompilationResult.cpp in Sources */,
</span><span class="cx">                                 147F39C2107EC37600427A48 /* Completion.cpp in Sources */,
</span><span class="cx">                                 0F6FC750196110A800E1D02D /* ComplexGetStatus.cpp in Sources */,
</span><ins>+                                0F1FB38E1E173A6500A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp in Sources */,
</ins><span class="cx">                                 146B16D812EB5B59001BEC1B /* ConservativeRoots.cpp in Sources */,
</span><span class="cx">                                 A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
</span><span class="cx">                                 A5FD0079189B051000633231 /* ConsoleMessage.cpp in Sources */,
</span><span class="lines">@@ -9730,6 +9771,7 @@
</span><span class="cx">                                 147F39C4107EC37600427A48 /* DateConversion.cpp in Sources */,
</span><span class="cx">                                 147F39C5107EC37600427A48 /* DateInstance.cpp in Sources */,
</span><span class="cx">                                 147F39C6107EC37600427A48 /* DatePrototype.cpp in Sources */,
</span><ins>+                                0F660E391E0517BF0031462C /* MarkingConstraintSet.cpp in Sources */,
</ins><span class="cx">                                 14280823107EC02C0013E7B2 /* Debugger.cpp in Sources */,
</span><span class="cx">                                 149559EE0DDCDDF700648087 /* DebuggerCallFrame.cpp in Sources */,
</span><span class="cx">                                 A5FC84B31D1DDAD9006B5C46 /* DebuggerLocation.cpp in Sources */,
</span><span class="lines">@@ -10315,7 +10357,7 @@
</span><span class="cx">                                 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */,
</span><span class="cx">                                 0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */,
</span><span class="cx">                                 E49DC16B12EF293E00184A1F /* SourceProviderCache.cpp in Sources */,
</span><del>-                                0FDE87FD1DFE6E540064C390 /* SpaceTimeScheduler.cpp in Sources */,
</del><ins>+                                0FDE87FD1DFE6E540064C390 /* SpaceTimeMutatorScheduler.cpp in Sources */,
</ins><span class="cx">                                 0F0CD4C415F6B6BB0032F1C0 /* SparseArrayValueMap.cpp in Sources */,
</span><span class="cx">                                 0F5541B11613C1FB00CE3E25 /* SpecialPointer.cpp in Sources */,
</span><span class="cx">                                 0FD82E86141F3FF100179C94 /* SpeculatedType.cpp in Sources */,
</span><span class="lines">@@ -10325,6 +10367,7 @@
</span><span class="cx">                                 A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */,
</span><span class="cx">                                 14469DEB107EC7E700650446 /* StringConstructor.cpp in Sources */,
</span><span class="cx">                                 70EC0EC61AA0D7DA00B6AAFA /* StringIteratorPrototype.cpp in Sources */,
</span><ins>+                                0F1FB3901E173A6B00A9BE50 /* MutatorScheduler.cpp in Sources */,
</ins><span class="cx">                                 14469DEC107EC7E700650446 /* StringObject.cpp in Sources */,
</span><span class="cx">                                 14469DED107EC7E700650446 /* StringPrototype.cpp in Sources */,
</span><span class="cx">                                 9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */,
</span><span class="lines">@@ -10376,6 +10419,7 @@
</span><span class="cx">                                 0F24E55817F74EDB00ABB217 /* ValueRecovery.cpp in Sources */,
</span><span class="cx">                                 79EE0BFF1B4AFB85000385C9 /* VariableEnvironment.cpp in Sources */,
</span><span class="cx">                                 0F6C73501AC9F99F00BE1682 /* VariableWriteFireDetail.cpp in Sources */,
</span><ins>+                                0F660E371E0517B90031462C /* MarkingConstraint.cpp in Sources */,
</ins><span class="cx">                                 0FE0502C1AA9095600D33B33 /* VarOffset.cpp in Sources */,
</span><span class="cx">                                 0F20C2591A8013AB00DA3229 /* VirtualRegister.cpp in Sources */,
</span><span class="cx">                                 0F952AA21DF7860D00E06FBD /* VisitRaceKey.cpp in Sources */,
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlan.cpp (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlan.cpp        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlan.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2017 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">@@ -610,36 +610,6 @@
</span><span class="cx">     return CompilationKey(codeBlock-&gt;alternative(), mode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Plan::markCodeBlocks(SlotVisitor&amp; slotVisitor)
-{
-    if (!isKnownToBeLiveDuringGC())
-        return;
-    
-    // Compilation writes lots of values to a CodeBlock without performing
-    // an explicit barrier. So, we need to be pessimistic and assume that
-    // all our CodeBlocks must be visited during GC.
-
-    slotVisitor.appendUnbarriered(codeBlock);
-    slotVisitor.appendUnbarriered(codeBlock-&gt;alternative());
-    if (profiledDFGCodeBlock)
-        slotVisitor.appendUnbarriered(profiledDFGCodeBlock);
-}
-
-void Plan::rememberCodeBlocks(VM&amp; vm)
-{
-    if (!isKnownToBeLiveDuringGC())
-        return;
-    
-    // Compilation writes lots of values to a CodeBlock without performing
-    // an explicit barrier. So, we need to be pessimistic and assume that
-    // all our CodeBlocks must be visited during GC.
-
-    vm.heap.writeBarrier(codeBlock);
-    vm.heap.writeBarrier(codeBlock-&gt;alternative());
-    if (profiledDFGCodeBlock)
-        vm.heap.writeBarrier(profiledDFGCodeBlock);
-}
-
</del><span class="cx"> void Plan::checkLivenessAndVisitChildren(SlotVisitor&amp; visitor)
</span><span class="cx"> {
</span><span class="cx">     if (!isKnownToBeLiveDuringGC())
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGPlanh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlan.h (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlan.h        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlan.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2017 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">@@ -70,7 +70,8 @@
</span><span class="cx">     CompilationKey key();
</span><span class="cx">     
</span><span class="cx">     void markCodeBlocks(SlotVisitor&amp;);
</span><del>-    void rememberCodeBlocks(VM&amp;);
</del><ins>+    template&lt;typename Func&gt;
+    void iterateCodeBlocksForGC(const Func&amp;);
</ins><span class="cx">     void checkLivenessAndVisitChildren(SlotVisitor&amp;);
</span><span class="cx">     bool isKnownToBeLiveDuringGC();
</span><span class="cx">     void cancel();
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGPlanInlinesh"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlanInlines.h (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlanInlines.h                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGPlanInlines.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,49 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;DFGPlan.h&quot;
+
+namespace JSC { namespace DFG {
+
+template&lt;typename Func&gt;
+void Plan::iterateCodeBlocksForGC(const Func&amp; func)
+{
+    if (!isKnownToBeLiveDuringGC())
+        return;
+    
+    // Compilation writes lots of values to a CodeBlock without performing
+    // an explicit barrier. So, we need to be pessimistic and assume that
+    // all our CodeBlocks must be visited during GC.
+
+    func(codeBlock);
+    func(codeBlock-&gt;alternative());
+    if (profiledDFGCodeBlock)
+        func(profiledDFGCodeBlock);
+}
+
+} } // namespace JSC::DFG
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGWorklistcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklist.cpp (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklist.cpp        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklist.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -351,28 +351,6 @@
</span><span class="cx">     completeAllReadyPlansForVM(vm);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Worklist::markCodeBlocks(VM&amp; vm, SlotVisitor&amp; slotVisitor)
-{
-    LockHolder locker(*m_lock);
-    for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
-        Plan* plan = iter-&gt;value.get();
-        if (plan-&gt;vm != &amp;vm)
-            continue;
-        plan-&gt;markCodeBlocks(slotVisitor);
-    }
-}
-
-void Worklist::rememberCodeBlocks(VM&amp; vm)
-{
-    LockHolder locker(*m_lock);
-    for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
-        Plan* plan = iter-&gt;value.get();
-        if (plan-&gt;vm != &amp;vm)
-            continue;
-        plan-&gt;rememberCodeBlocks(vm);
-    }
-}
-
</del><span class="cx"> void Worklist::suspendAllThreads()
</span><span class="cx"> {
</span><span class="cx">     m_suspensionLock.lock();
</span><span class="lines">@@ -566,22 +544,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void markCodeBlocks(VM&amp; vm, SlotVisitor&amp; slotVisitor)
-{
-    for (unsigned i = DFG::numberOfWorklists(); i--;) {
-        if (DFG::Worklist* worklist = DFG::existingWorklistForIndexOrNull(i))
-            worklist-&gt;markCodeBlocks(vm, slotVisitor);
-    }
-}
-
-void rememberCodeBlocks(VM&amp; vm)
-{
-    for (unsigned i = DFG::numberOfWorklists(); i--;) {
-        if (DFG::Worklist* worklist = DFG::existingWorklistForIndexOrNull(i))
-            worklist-&gt;rememberCodeBlocks(vm);
-    }
-}
-
</del><span class="cx"> #else // ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><span class="cx"> void completeAllPlansForVM(VM&amp;)
</span><span class="lines">@@ -592,10 +554,6 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void rememberCodeBlocks(VM&amp;)
-{
-}
-
</del><span class="cx"> #endif // ENABLE(DFG_JIT)
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGWorklisth"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklist.h (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklist.h        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklist.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2014, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2017 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">@@ -57,8 +57,8 @@
</span><span class="cx">     // worklist-&gt;completeAllReadyPlansForVM(vm);
</span><span class="cx">     void completeAllPlansForVM(VM&amp;);
</span><span class="cx"> 
</span><del>-    void markCodeBlocks(VM&amp;, SlotVisitor&amp;);
-    void rememberCodeBlocks(VM&amp;);
</del><ins>+    template&lt;typename Func&gt;
+    void iterateCodeBlocksForGC(VM&amp;, const Func&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void waitUntilAllPlansForVMAreReady(VM&amp;);
</span><span class="cx">     State completeAllReadyPlansForVM(VM&amp;, CompilationKey = CompilationKey());
</span><span class="lines">@@ -168,7 +168,9 @@
</span><span class="cx"> 
</span><span class="cx"> void completeAllPlansForVM(VM&amp;);
</span><span class="cx"> void markCodeBlocks(VM&amp;, SlotVisitor&amp;);
</span><del>-void rememberCodeBlocks(VM&amp;);
</del><span class="cx"> 
</span><ins>+template&lt;typename Func&gt;
+void iterateCodeBlocksForGC(VM&amp;, const Func&amp;);
+
</ins><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoredfgDFGWorklistInlinesh"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklistInlines.h (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklistInlines.h                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/dfg/DFGWorklistInlines.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,66 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;DFGPlanInlines.h&quot;
+#include &quot;DFGWorklist.h&quot;
+
+namespace JSC { namespace DFG {
+
+#if ENABLE(DFG_JIT)
+
+template&lt;typename Func&gt;
+void iterateCodeBlocksForGC(VM&amp; vm, const Func&amp; func)
+{
+    for (unsigned i = DFG::numberOfWorklists(); i--;) {
+        if (DFG::Worklist* worklist = DFG::existingWorklistForIndexOrNull(i))
+            worklist-&gt;iterateCodeBlocksForGC(vm, func);
+    }
+}
+
+template&lt;typename Func&gt;
+void Worklist::iterateCodeBlocksForGC(VM&amp; vm, const Func&amp; func)
+{
+    LockHolder locker(*m_lock);
+    for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
+        Plan* plan = iter-&gt;value.get();
+        if (plan-&gt;vm != &amp;vm)
+            continue;
+        plan-&gt;iterateCodeBlocksForGC(func);
+    }
+}
+
+#else // ENABLE(DFG_JIT)
+
+template&lt;typename Func&gt;
+void iterateCodeBlocksForGC(VM&amp;, const Func&amp;)
+{
+}
+
+#endif // ENABLE(DFG_JIT)
+
+} } // namespace JSC::DFG
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapCodeBlockSetcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSet.cpp (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSet.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2017 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">@@ -32,8 +32,6 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-static const bool verbose = false;
-
</del><span class="cx"> CodeBlockSet::CodeBlockSet()
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -114,15 +112,6 @@
</span><span class="cx">     return m_oldCodeBlocks.contains(codeBlock) || m_newCodeBlocks.contains(codeBlock) || m_currentlyExecuting.contains(codeBlock);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void CodeBlockSet::writeBarrierCurrentlyExecuting(Heap* heap)
-{
-    LockHolder locker(&amp;m_lock);
-    if (verbose)
-        dataLog(&quot;Remembering &quot;, m_currentlyExecuting.size(), &quot; code blocks.\n&quot;);
-    for (CodeBlock* codeBlock : m_currentlyExecuting)
-        heap-&gt;writeBarrier(codeBlock);
-}
-
</del><span class="cx"> void CodeBlockSet::clearCurrentlyExecuting()
</span><span class="cx"> {
</span><span class="cx">     m_currentlyExecuting.clear();
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapCodeBlockSeth"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSet.h (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSet.h        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSet.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2014, 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2017 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">@@ -69,10 +69,6 @@
</span><span class="cx">     // by this set), and that have not been marked.
</span><span class="cx">     void deleteUnmarkedAndUnreferenced(CollectionScope);
</span><span class="cx">     
</span><del>-    // Add all currently executing CodeBlocks to the remembered set to be 
-    // re-scanned during the next collection.
-    void writeBarrierCurrentlyExecuting(Heap*);
-
</del><span class="cx">     void clearCurrentlyExecuting();
</span><span class="cx"> 
</span><span class="cx">     bool contains(const LockHolder&amp;, void* candidateCodeBlock);
</span><span class="lines">@@ -81,22 +77,10 @@
</span><span class="cx">     // Visits each CodeBlock in the heap until the visitor function returns true
</span><span class="cx">     // to indicate that it is done iterating, or until every CodeBlock has been
</span><span class="cx">     // visited.
</span><del>-    template&lt;typename Functor&gt; void iterate(const Functor&amp; functor)
-    {
-        LockHolder locker(m_lock);
-        for (auto&amp; codeBlock : m_oldCodeBlocks) {
-            bool done = functor(codeBlock);
-            if (done)
-                return;
-        }
-
-        for (auto&amp; codeBlock : m_newCodeBlocks) {
-            bool done = functor(codeBlock);
-            if (done)
-                return;
-        }
-    }
</del><ins>+    template&lt;typename Functor&gt; void iterate(const Functor&amp;);
</ins><span class="cx">     
</span><ins>+    template&lt;typename Functor&gt; void iterateCurrentlyExecuting(const Functor&amp;);
+    
</ins><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx"> 
</span><span class="cx"> private:
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapCodeBlockSetInlinesh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSetInlines.h (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSetInlines.h        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/CodeBlockSetInlines.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2016-2017 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">@@ -60,5 +60,30 @@
</span><span class="cx">     m_currentlyExecuting.add(codeBlock);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename Functor&gt;
+void CodeBlockSet::iterate(const Functor&amp; functor)
+{
+    LockHolder locker(m_lock);
+    for (auto&amp; codeBlock : m_oldCodeBlocks) {
+        bool done = functor(codeBlock);
+        if (done)
+            return;
+    }
+    
+    for (auto&amp; codeBlock : m_newCodeBlocks) {
+        bool done = functor(codeBlock);
+        if (done)
+            return;
+    }
+}
+
+template&lt;typename Functor&gt;
+void CodeBlockSet::iterateCurrentlyExecuting(const Functor&amp; functor)
+{
+    LockHolder locker(&amp;m_lock);
+    for (CodeBlock* codeBlock : m_currentlyExecuting)
+        functor(codeBlock);
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/heap/Heap.cpp (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/Heap.cpp        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/Heap.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -22,9 +22,9 @@
</span><span class="cx"> #include &quot;Heap.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><del>-#include &quot;CodeBlockSet.h&quot;
</del><ins>+#include &quot;CodeBlockSetInlines.h&quot;
</ins><span class="cx"> #include &quot;ConservativeRoots.h&quot;
</span><del>-#include &quot;DFGWorklist.h&quot;
</del><ins>+#include &quot;DFGWorklistInlines.h&quot;
</ins><span class="cx"> #include &quot;EdenGCActivityCallback.h&quot;
</span><span class="cx"> #include &quot;Exception.h&quot;
</span><span class="cx"> #include &quot;FullGCActivityCallback.h&quot;
</span><span class="lines">@@ -49,12 +49,14 @@
</span><span class="cx"> #include &quot;JSLock.h&quot;
</span><span class="cx"> #include &quot;JSVirtualMachineInternal.h&quot;
</span><span class="cx"> #include &quot;MarkedSpaceInlines.h&quot;
</span><ins>+#include &quot;MarkingConstraintSet.h&quot;
</ins><span class="cx"> #include &quot;PreventCollectionScope.h&quot;
</span><span class="cx"> #include &quot;SamplingProfiler.h&quot;
</span><span class="cx"> #include &quot;ShadowChicken.h&quot;
</span><del>-#include &quot;SpaceTimeScheduler.h&quot;
</del><ins>+#include &quot;SpaceTimeMutatorScheduler.h&quot;
</ins><span class="cx"> #include &quot;SuperSampler.h&quot;
</span><span class="cx"> #include &quot;StopIfNecessaryTimer.h&quot;
</span><ins>+#include &quot;SynchronousStopTheWorldMutatorScheduler.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">@@ -91,41 +93,6 @@
</span><span class="cx">     return maxPauseMS;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-} // anonymous namespace
-
-class Heap::ResumeTheWorldScope {
-public:
-    ResumeTheWorldScope(Heap&amp; heap)
-        : m_heap(heap)
-    {
-        if (!Options::useConcurrentGC())
-            return;
-        
-        if (Options::logGC()) {
-            double thisPauseMS = (MonotonicTime::now() - m_heap.m_stopTime).milliseconds();
-            dataLog(&quot;p=&quot;, thisPauseMS, &quot; ms (max &quot;, maxPauseMS(thisPauseMS), &quot;)...]\n&quot;);
-        }
-        
-        m_heap.resumeTheWorld();
-    }
-    
-    ~ResumeTheWorldScope()
-    {
-        if (!Options::useConcurrentGC())
-            return;
-        
-        m_heap.stopTheWorld();
-        
-        if (Options::logGC())
-            dataLog(&quot;[GC: &quot;);
-    }
-    
-private:
-    Heap&amp; m_heap;
-};
-
-namespace {
-
</del><span class="cx"> size_t minHeapSize(HeapType heapType, size_t ramSize)
</span><span class="cx"> {
</span><span class="cx">     if (heapType == LargeHeap) {
</span><span class="lines">@@ -316,11 +283,20 @@
</span><span class="cx">     , m_sharedCollectorMarkStack(std::make_unique&lt;MarkStackArray&gt;())
</span><span class="cx">     , m_sharedMutatorMarkStack(std::make_unique&lt;MarkStackArray&gt;())
</span><span class="cx">     , m_helperClient(&amp;heapHelperPool())
</span><ins>+    , m_scheduler(std::make_unique&lt;SpaceTimeMutatorScheduler&gt;(*this))
</ins><span class="cx">     , m_threadLock(Box&lt;Lock&gt;::create())
</span><span class="cx">     , m_threadCondition(AutomaticThreadCondition::create())
</span><span class="cx"> {
</span><span class="cx">     m_worldState.store(0);
</span><span class="cx">     
</span><ins>+    if (Options::useConcurrentGC())
+        m_scheduler = std::make_unique&lt;SpaceTimeMutatorScheduler&gt;(*this);
+    else {
+        // We simulate turning off concurrent GC by making the scheduler say that the world
+        // should always be stopped when the collector is running.
+        m_scheduler = std::make_unique&lt;SynchronousStopTheWorldMutatorScheduler&gt;();
+    }
+    
</ins><span class="cx">     if (Options::verifyHeap())
</span><span class="cx">         m_verifier = std::make_unique&lt;HeapVerifier&gt;(this, Options::numberOfGCCyclesToRecordForVerification());
</span><span class="cx">     
</span><span class="lines">@@ -479,12 +455,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::harvestWeakReferences()
-{
-    for (WeakReferenceHarvester* current = m_weakReferenceHarvesters.head(); current; current = current-&gt;next())
-        current-&gt;visitWeakReferences(*m_collectorSlotVisitor);
-}
-
</del><span class="cx"> void Heap::finalizeUnconditionalFinalizers()
</span><span class="cx"> {
</span><span class="cx">     while (m_unconditionalFinalizers.hasNext()) {
</span><span class="lines">@@ -511,6 +481,42 @@
</span><span class="cx">     DFG::completeAllPlansForVM(*m_vm);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename Func&gt;
+void Heap::iterateExecutingAndCompilingCodeBlocks(const Func&amp; func)
+{
+    m_codeBlocks-&gt;iterateCurrentlyExecuting(func);
+    DFG::iterateCodeBlocksForGC(*m_vm, func);
+}
+
+template&lt;typename Func&gt;
+void Heap::iterateExecutingAndCompilingCodeBlocksWithoutHoldingLocks(const Func&amp; func)
+{
+    Vector&lt;CodeBlock*, 256&gt; codeBlocks;
+    iterateExecutingAndCompilingCodeBlocks(
+        [&amp;] (CodeBlock* codeBlock) {
+            codeBlocks.append(codeBlock);
+        });
+    for (CodeBlock* codeBlock : codeBlocks)
+        func(codeBlock);
+}
+
+void Heap::assertSharedMarkStacksEmpty()
+{
+    bool ok = true;
+    
+    if (!m_sharedCollectorMarkStack-&gt;isEmpty()) {
+        dataLog(&quot;FATAL: Shared collector mark stack not empty! It has &quot;, m_sharedCollectorMarkStack-&gt;size(), &quot; elements.\n&quot;);
+        ok = false;
+    }
+    
+    if (!m_sharedMutatorMarkStack-&gt;isEmpty()) {
+        dataLog(&quot;FATAL: Shared mutator mark stack not empty! It has &quot;, m_sharedMutatorMarkStack-&gt;size(), &quot; elements.\n&quot;);
+        ok = false;
+    }
+    
+    RELEASE_ASSERT(ok);
+}
+
</ins><span class="cx"> void Heap::markToFixpoint(double gcStartTime)
</span><span class="cx"> {
</span><span class="cx">     TimingScope markToFixpointTimingScope(*this, &quot;Heap::markToFixpoint&quot;);
</span><span class="lines">@@ -560,133 +566,84 @@
</span><span class="cx">     SlotVisitor&amp; slotVisitor = *m_collectorSlotVisitor;
</span><span class="cx">     slotVisitor.didStartMarking();
</span><span class="cx"> 
</span><del>-    SpaceTimeScheduler scheduler(*this);
</del><ins>+    m_constraintSet-&gt;resetStats();
</ins><span class="cx">     
</span><ins>+    m_scheduler-&gt;beginCollection();
+    if (Options::logGC())
+        m_scheduler-&gt;log();
+    
+    // Wondering what m_constraintSet-&gt;executeXYZ does? It's running the constraints created by
+    // Heap::buildConstraintSet().
+    
+    m_constraintSet-&gt;executeBootstrap(slotVisitor, MonotonicTime::infinity());
+    m_scheduler-&gt;didExecuteConstraints();
+
+    // After this, we will almost certainly fall through all of the &quot;slotVisitor.isEmpty()&quot;
+    // checks because bootstrap would have put things into the visitor. So, we should fall
+    // through to draining.
+    
</ins><span class="cx">     for (unsigned iteration = 1; ; ++iteration) {
</span><span class="cx">         if (Options::logGC())
</span><del>-            dataLog(&quot;i#&quot;, iteration, &quot; &quot;);
-        {
-            TimingScope preConvergenceTimingScope(*this, &quot;Heap::markToFixpoint conservative scan&quot;);
-            m_objectSpace.prepareForConservativeScan();
-            ConservativeRoots conservativeRoots(*this);
-            SuperSamplerScope superSamplerScope(false);
-            gatherStackRoots(conservativeRoots);
-            gatherJSStackRoots(conservativeRoots);
-            gatherScratchBufferRoots(conservativeRoots);
-            visitConservativeRoots(conservativeRoots);
-        }
</del><ins>+            dataLog(&quot;i#&quot;, iteration, &quot; &quot;, slotVisitor.collectorMarkStack().size(), &quot;+&quot;, m_mutatorMarkStack-&gt;size() + slotVisitor.mutatorMarkStack().size(), &quot; b=&quot;, m_barriersExecuted, &quot; &quot;);
+        
+        if (slotVisitor.didReachTermination()) {
+            assertSharedMarkStacksEmpty();
</ins><span class="cx">             
</span><del>-        // Now we visit roots that don't get barriered, so each fixpoint iteration just revisits
-        // all of them.
-#if JSC_OBJC_API_ENABLED
-        scanExternalRememberedSet(*m_vm, slotVisitor);
-#endif
</del><ins>+            // FIXME: Take m_mutatorDidRun into account when scheduling constraints. Most likely,
+            // we don't have to execute root constraints again unless the mutator did run. At a
+            // minimum, we could use this for work estimates - but it's probably more than just an
+            // estimate.
+            // https://bugs.webkit.org/show_bug.cgi?id=166828
</ins><span class="cx">             
</span><del>-        if (m_vm-&gt;smallStrings.needsToBeVisited(*m_collectionScope))
-            m_vm-&gt;smallStrings.visitStrongReferences(slotVisitor);
</del><ins>+            // FIXME: We should take advantage of the fact that we could timeout. This only comes
+            // into play if we're executing constraints for the first time. But that will matter
+            // when we have deep stacks or a lot of DOM stuff.
+            // https://bugs.webkit.org/show_bug.cgi?id=166831
</ins><span class="cx">             
</span><del>-        for (auto&amp; pair : m_protectedValues)
-            slotVisitor.appendUnbarriered(pair.key);
</del><ins>+            bool executedEverything =
+                m_constraintSet-&gt;executeConvergence(slotVisitor, MonotonicTime::infinity());
+            if (executedEverything &amp;&amp; slotVisitor.isEmpty()) {
+                assertSharedMarkStacksEmpty();
+                break;
+            }
</ins><span class="cx">             
</span><del>-        if (m_markListSet &amp;&amp; m_markListSet-&gt;size())
-            MarkedArgumentBuffer::markLists(slotVisitor, *m_markListSet);
-            
-        slotVisitor.appendUnbarriered(m_vm-&gt;exception());
-        slotVisitor.appendUnbarriered(m_vm-&gt;lastException());
-            
-        m_handleSet.visitStrongHandles(slotVisitor);
-        m_handleStack.visit(slotVisitor);
-
-#if ENABLE(SAMPLING_PROFILER)
-        if (SamplingProfiler* samplingProfiler = m_vm-&gt;samplingProfiler()) {
-            LockHolder locker(samplingProfiler-&gt;getLock());
-            samplingProfiler-&gt;processUnverifiedStackTraces();
-            samplingProfiler-&gt;visit(slotVisitor);
-            if (Options::logGC() == GCLogging::Verbose)
-                dataLog(&quot;Sampling Profiler data:\n&quot;, slotVisitor);
</del><ins>+            m_scheduler-&gt;didExecuteConstraints();
</ins><span class="cx">         }
</span><del>-#endif // ENABLE(SAMPLING_PROFILER)
</del><span class="cx">         
</span><del>-        if (m_vm-&gt;typeProfiler())
-            m_vm-&gt;typeProfilerLog()-&gt;visit(slotVisitor);
-                
-        m_vm-&gt;shadowChicken().visitChildren(slotVisitor);
-                
-        m_jitStubRoutines-&gt;traceMarkedStubRoutines(slotVisitor);
-
-        slotVisitor.mergeOpaqueRootsIfNecessary();
-        for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
-            parallelVisitor-&gt;mergeOpaqueRootsIfNecessary();
-
-        m_objectSpace.visitWeakSets(slotVisitor);
-        harvestWeakReferences();
-        visitCompilerWorklistWeakReferences();
-        DFG::markCodeBlocks(*m_vm, slotVisitor);
-        bool shouldTerminate = slotVisitor.isEmpty() &amp;&amp; m_mutatorMarkStack-&gt;isEmpty();
-        
-        if (Options::logGC()) {
-            dataLog(slotVisitor.collectorMarkStack().size(), &quot;+&quot;, m_mutatorMarkStack-&gt;size() + slotVisitor.mutatorMarkStack().size(), &quot;, a=&quot;, m_bytesAllocatedThisCycle / 1024, &quot; kb, b=&quot;, m_barriersExecuted, &quot;, mu=&quot;, scheduler.currentDecision().targetMutatorUtilization(), &quot; &quot;);
</del><ins>+        {
+            ParallelModeEnabler enabler(slotVisitor);
+            slotVisitor.drainInParallel(m_scheduler-&gt;timeToResume());
</ins><span class="cx">         }
</span><span class="cx">         
</span><del>-        // We want to do this to conservatively ensure that we rescan any code blocks that are
-        // running right now. However, we need to be sure to do it *after* we mark the code block
-        // so that we know for sure if it really needs a barrier. Also, this has to happen after the
-        // fixpoint check - otherwise we might loop forever. Incidentally, we also want to do this
-        // at the end of GC so that anything at the end of the last GC gets barriered in the next
-        // GC.
-        m_codeBlocks-&gt;writeBarrierCurrentlyExecuting(this);
-        DFG::rememberCodeBlocks(*m_vm);
</del><ins>+        if (!m_scheduler-&gt;shouldResume())
+            continue;
</ins><span class="cx">         
</span><del>-        if (shouldTerminate)
-            break;
</del><ins>+        m_scheduler-&gt;willResume();
</ins><span class="cx">         
</span><del>-        // The SlotVisitor's mark stacks are accessed by the collector thread (i.e. this thread)
-        // without locks. That's why we double-buffer.
-        m_mutatorMarkStack-&gt;transferTo(slotVisitor.mutatorMarkStack());
</del><ins>+        if (Options::logGC()) {
+            double thisPauseMS = (MonotonicTime::now() - m_stopTime).milliseconds();
+            dataLog(&quot;p=&quot;, thisPauseMS, &quot; ms (max &quot;, maxPauseMS(thisPauseMS), &quot;)...]\n&quot;);
+        }
</ins><span class="cx">         
</span><del>-        if (Options::logGC() == GCLogging::Verbose)
-            dataLog(&quot;Live Weak Handles:\n&quot;, slotVisitor);
</del><ins>+        resumeTheWorld();
</ins><span class="cx">         
</span><span class="cx">         {
</span><del>-            TimingScope traceTimingScope(*this, &quot;Heap::markToFixpoint tracing&quot;);
</del><span class="cx">             ParallelModeEnabler enabler(slotVisitor);
</span><del>-            
-            if (Options::useCollectorTimeslicing()) {
-                scheduler.snapPhase();
-                
-                SlotVisitor::SharedDrainResult drainResult;
-                do {
-                    auto decision = scheduler.currentDecision();
-                    if (decision.shouldBeResumed()) {
-                        {
-                            ResumeTheWorldScope resumeTheWorldScope(*this);
-                            drainResult = slotVisitor.drainInParallelPassively(decision.timeToStop());
-                            if (drainResult == SlotVisitor::SharedDrainResult::Done) {
-                                // At this point we will stop. But maybe the scheduler does not want
-                                // that.
-                                Seconds scheduledIdle = decision.timeToStop() - MonotonicTime::now();
-                                // It's totally unclear what the value of collectPermittedIdleRatio
-                                // should be, other than it should be greater than 0. You could even
-                                // argue for it being greater than 1. We should tune it.
-                                sleep(scheduledIdle * Options::collectorPermittedIdleRatio());
-                            }
-                        }
-                        if (Options::logGC()) {
-                            Seconds wakeUpLatency = MonotonicTime::now() - decision.timeToStop();
-                            if (wakeUpLatency &gt;= 1_ms)
-                                dataLog(&quot;wul!=&quot;, wakeUpLatency.milliseconds(), &quot; ms &quot;);
-                        }
-                    } else
-                        drainResult = slotVisitor.drainInParallel(decision.timeToResume());
-                } while (drainResult != SlotVisitor::SharedDrainResult::Done);
-            } else {
-                // Disabling collector timeslicing is meant to be used together with
-                // --collectContinuously=true to maximize the opportunity for harmful races.
-                ResumeTheWorldScope resumeTheWorldScope(*this);
-                slotVisitor.drainInParallel();
-            }
</del><ins>+            slotVisitor.drainInParallelPassively(m_scheduler-&gt;timeToStop());
</ins><span class="cx">         }
</span><ins>+
+        stopTheWorld();
+        
+        if (Options::logGC())
+            dataLog(&quot;[GC: &quot;);
+        
+        m_scheduler-&gt;didStop();
+        
+        if (Options::logGC())
+            m_scheduler-&gt;log();
</ins><span class="cx">     }
</span><ins>+    
+    m_scheduler-&gt;endCollection();
</ins><span class="cx"> 
</span><span class="cx">     {
</span><span class="cx">         std::lock_guard&lt;Lock&gt; lock(m_markingMutex);
</span><span class="lines">@@ -694,6 +651,12 @@
</span><span class="cx">         m_markingConditionVariable.notifyAll();
</span><span class="cx">     }
</span><span class="cx">     m_helperClient.finish();
</span><ins>+
+    iterateExecutingAndCompilingCodeBlocks(
+        [&amp;] (CodeBlock* codeBlock) {
+            writeBarrier(codeBlock);
+        });
+        
</ins><span class="cx">     updateObjectCounts(gcStartTime);
</span><span class="cx">     endMarking();
</span><span class="cx"> }
</span><span class="lines">@@ -729,28 +692,8 @@
</span><span class="cx">     m_jitStubRoutines-&gt;clearMarks();
</span><span class="cx">     m_objectSpace.beginMarking();
</span><span class="cx">     setMutatorShouldBeFenced(true);
</span><del>-    m_barriersExecuted = 0;
</del><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::visitConservativeRoots(ConservativeRoots&amp; roots)
-{
-    m_collectorSlotVisitor-&gt;append(roots);
-
-    if (Options::logGC() == GCLogging::Verbose)
-        dataLog(&quot;Conservative Roots:\n&quot;, *m_collectorSlotVisitor);
-}
-
-void Heap::visitCompilerWorklistWeakReferences()
-{
-#if ENABLE(DFG_JIT)
-    for (unsigned i = DFG::numberOfWorklists(); i--;)
-        DFG::existingWorklistForIndex(i).visitWeakReferences(*m_collectorSlotVisitor);
-
-    if (Options::logGC() == GCLogging::Verbose)
-        dataLog(&quot;DFG Worklists:\n&quot;, *m_collectorSlotVisitor);
-#endif
-}
-
</del><span class="cx"> void Heap::removeDeadCompilerWorklistEntries()
</span><span class="cx"> {
</span><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="lines">@@ -850,8 +793,7 @@
</span><span class="cx">     for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
</span><span class="cx">         parallelVisitor-&gt;reset();
</span><span class="cx"> 
</span><del>-    RELEASE_ASSERT(m_sharedCollectorMarkStack-&gt;isEmpty());
-    RELEASE_ASSERT(m_sharedMutatorMarkStack-&gt;isEmpty());
</del><ins>+    assertSharedMarkStacksEmpty();
</ins><span class="cx">     m_weakReferenceHarvesters.removeAll();
</span><span class="cx">     
</span><span class="cx">     m_objectSpace.endMarking();
</span><span class="lines">@@ -1136,7 +1078,7 @@
</span><span class="cx">     
</span><span class="cx">     willStartCollection(scope);
</span><span class="cx">     collectImplTimingScope.setScope(*this);
</span><del>-        
</del><ins>+    
</ins><span class="cx">     gcStartTime = WTF::monotonicallyIncreasingTime();
</span><span class="cx">     if (m_verifier) {
</span><span class="cx">         // Verify that live objects from the last GC cycle haven't been corrupted by
</span><span class="lines">@@ -1146,11 +1088,11 @@
</span><span class="cx">         m_verifier-&gt;initializeGCCycle();
</span><span class="cx">         m_verifier-&gt;gatherLiveObjects(HeapVerifier::Phase::BeforeMarking);
</span><span class="cx">     }
</span><del>-        
</del><ins>+    
</ins><span class="cx">     prepareForMarking();
</span><del>-        
</del><ins>+    
</ins><span class="cx">     markToFixpoint(gcStartTime);
</span><del>-        
</del><ins>+    
</ins><span class="cx">     if (m_verifier) {
</span><span class="cx">         m_verifier-&gt;gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
</span><span class="cx">         m_verifier-&gt;verify(HeapVerifier::Phase::AfterMarking);
</span><span class="lines">@@ -1166,8 +1108,11 @@
</span><span class="cx">     finalizeUnconditionalFinalizers();
</span><span class="cx">     removeDeadCompilerWorklistEntries();
</span><span class="cx">     notifyIncrementalSweeper();
</span><del>-        
-    m_codeBlocks-&gt;writeBarrierCurrentlyExecuting(this);
</del><ins>+    
+    m_codeBlocks-&gt;iterateCurrentlyExecuting(
+        [&amp;] (CodeBlock* codeBlock) {
+            writeBarrier(codeBlock);
+        });
</ins><span class="cx">     m_codeBlocks-&gt;clearCurrentlyExecuting();
</span><span class="cx">         
</span><span class="cx">     m_objectSpace.prepareForAllocation();
</span><span class="lines">@@ -1248,6 +1193,8 @@
</span><span class="cx">     // - During collection cycle: it reinstates the last active block.
</span><span class="cx">     m_objectSpace.resumeAllocating();
</span><span class="cx">     
</span><ins>+    m_barriersExecuted = 0;
+    
</ins><span class="cx">     RELEASE_ASSERT(m_collectorBelievesThatTheWorldIsStopped);
</span><span class="cx">     m_collectorBelievesThatTheWorldIsStopped = false;
</span><span class="cx">     
</span><span class="lines">@@ -1354,6 +1301,7 @@
</span><span class="cx">     
</span><span class="cx">     handleGCDidJIT();
</span><span class="cx">     handleNeedFinalize();
</span><ins>+    m_mutatorDidRun = true;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool Heap::stopIfNecessarySlow(unsigned oldState)
</span><span class="lines">@@ -1366,7 +1314,7 @@
</span><span class="cx">         &amp;&amp; handleNeedFinalize(oldState))
</span><span class="cx">         return true;
</span><span class="cx">     
</span><del>-    if (!(oldState &amp; shouldStopBit)) {
</del><ins>+    if (!(oldState &amp; shouldStopBit) &amp;&amp; !m_scheduler-&gt;shouldStop()) {
</ins><span class="cx">         if (!(oldState &amp; stoppedBit))
</span><span class="cx">             return false;
</span><span class="cx">         m_worldState.compareExchangeStrong(oldState, oldState &amp; ~stoppedBit);
</span><span class="lines">@@ -1439,6 +1387,7 @@
</span><span class="cx">         if (m_worldState.compareExchangeWeak(oldState, newState)) {
</span><span class="cx">             handleGCDidJIT();
</span><span class="cx">             handleNeedFinalize();
</span><ins>+            m_mutatorDidRun = true;
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -2052,16 +2001,16 @@
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-bool Heap::collectIfNecessaryOrDefer(GCDeferralContext* deferralContext)
</del><ins>+void Heap::collectIfNecessaryOrDefer(GCDeferralContext* deferralContext)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
</span><span class="cx"> 
</span><span class="cx">     if (!m_isSafeToCollect)
</span><del>-        return false;
</del><ins>+        return;
</ins><span class="cx">     if (mutatorState() == MutatorState::HelpingGC)
</span><del>-        return false;
</del><ins>+        return;
</ins><span class="cx">     if (!Options::useGC())
</span><del>-        return false;
</del><ins>+        return;
</ins><span class="cx">     
</span><span class="cx">     if (mayNeedToStop()) {
</span><span class="cx">         if (deferralContext)
</span><span class="lines">@@ -2068,16 +2017,19 @@
</span><span class="cx">             deferralContext-&gt;m_shouldGC = true;
</span><span class="cx">         else if (isDeferred())
</span><span class="cx">             m_didDeferGCWork = true;
</span><del>-        else
</del><ins>+        else {
</ins><span class="cx">             stopIfNecessary();
</span><ins>+            // FIXME: Check if the scheduler wants us to stop.
+            // https://bugs.webkit.org/show_bug.cgi?id=166827
+        }
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (UNLIKELY(Options::gcMaxHeapSize())) {
</span><span class="cx">         if (m_bytesAllocatedThisCycle &lt;= Options::gcMaxHeapSize())
</span><del>-            return false;
</del><ins>+            return;
</ins><span class="cx">     } else {
</span><span class="cx">         if (m_bytesAllocatedThisCycle &lt;= m_maxEdenSize)
</span><del>-            return false;
</del><ins>+            return;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     if (deferralContext)
</span><span class="lines">@@ -2086,7 +2038,6 @@
</span><span class="cx">         m_didDeferGCWork = true;
</span><span class="cx">     else
</span><span class="cx">         collectAsync();
</span><del>-    return true;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::decrementDeferralDepthAndGCIfNeededSlow()
</span><span class="lines">@@ -2141,8 +2092,155 @@
</span><span class="cx"> }
</span><span class="cx"> #endif // USE(CF)
</span><span class="cx"> 
</span><ins>+void Heap::buildConstraintSet()
+{
+    m_constraintSet = std::make_unique&lt;MarkingConstraintSet&gt;();
+    
+    m_constraintSet-&gt;add(
+        &quot;Cs&quot;, &quot;Conservative Scan&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+            TimingScope preConvergenceTimingScope(*this, &quot;Constraint: conservative scan&quot;);
+            m_objectSpace.prepareForConservativeScan();
+            ConservativeRoots conservativeRoots(*this);
+            SuperSamplerScope superSamplerScope(false);
+            gatherStackRoots(conservativeRoots);
+            gatherJSStackRoots(conservativeRoots);
+            gatherScratchBufferRoots(conservativeRoots);
+            slotVisitor.append(conservativeRoots);
+        },
+        MarkingConstraint::GreyedByExecution);
+    
+    m_constraintSet-&gt;add(
+        &quot;Msr&quot;, &quot;Misc Small Roots&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+#if JSC_OBJC_API_ENABLED
+            scanExternalRememberedSet(*m_vm, slotVisitor);
+#endif
+
+            if (m_vm-&gt;smallStrings.needsToBeVisited(*m_collectionScope))
+                m_vm-&gt;smallStrings.visitStrongReferences(slotVisitor);
+            
+            for (auto&amp; pair : m_protectedValues)
+                slotVisitor.appendUnbarriered(pair.key);
+            
+            if (m_markListSet &amp;&amp; m_markListSet-&gt;size())
+                MarkedArgumentBuffer::markLists(slotVisitor, *m_markListSet);
+            
+            slotVisitor.appendUnbarriered(m_vm-&gt;exception());
+            slotVisitor.appendUnbarriered(m_vm-&gt;lastException());
+        },
+        MarkingConstraint::GreyedByExecution);
+    
+    m_constraintSet-&gt;add(
+        &quot;Sh&quot;, &quot;Strong Handles&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+            m_handleSet.visitStrongHandles(slotVisitor);
+            m_handleStack.visit(slotVisitor);
+        },
+        MarkingConstraint::GreyedByExecution);
+    
+    m_constraintSet-&gt;add(
+        &quot;D&quot;, &quot;Debugger&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+#if ENABLE(SAMPLING_PROFILER)
+            if (SamplingProfiler* samplingProfiler = m_vm-&gt;samplingProfiler()) {
+                LockHolder locker(samplingProfiler-&gt;getLock());
+                samplingProfiler-&gt;processUnverifiedStackTraces();
+                samplingProfiler-&gt;visit(slotVisitor);
+                if (Options::logGC() == GCLogging::Verbose)
+                    dataLog(&quot;Sampling Profiler data:\n&quot;, slotVisitor);
+            }
+#endif // ENABLE(SAMPLING_PROFILER)
+            
+            if (m_vm-&gt;typeProfiler())
+                m_vm-&gt;typeProfilerLog()-&gt;visit(slotVisitor);
+            
+            m_vm-&gt;shadowChicken().visitChildren(slotVisitor);
+        },
+        MarkingConstraint::GreyedByExecution);
+    
+    m_constraintSet-&gt;add(
+        &quot;Jsr&quot;, &quot;JIT Stub Routines&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+            m_jitStubRoutines-&gt;traceMarkedStubRoutines(slotVisitor);
+        },
+        MarkingConstraint::GreyedByExecution);
+    
+    m_constraintSet-&gt;add(
+        &quot;Ws&quot;, &quot;Weak Sets&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+            slotVisitor.mergeOpaqueRootsIfNecessary();
+            for (auto&amp; parallelVisitor : m_parallelSlotVisitors)
+                parallelVisitor-&gt;mergeOpaqueRootsIfNecessary();
+            
+            m_objectSpace.visitWeakSets(slotVisitor);
+        },
+        MarkingConstraint::GreyedByMarking);
+    
+    m_constraintSet-&gt;add(
+        &quot;Wrh&quot;, &quot;Weak Reference Harvesters&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+            for (WeakReferenceHarvester* current = m_weakReferenceHarvesters.head(); current; current = current-&gt;next())
+                current-&gt;visitWeakReferences(slotVisitor);
+        },
+        MarkingConstraint::GreyedByMarking);
+    
+#if ENABLE(DFG_JIT)
+    m_constraintSet-&gt;add(
+        &quot;Dw&quot;, &quot;DFG Worklists&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+            for (unsigned i = DFG::numberOfWorklists(); i--;)
+                DFG::existingWorklistForIndex(i).visitWeakReferences(slotVisitor);
+            
+            // FIXME: This is almost certainly unnecessary.
+            // https://bugs.webkit.org/show_bug.cgi?id=166829
+            DFG::iterateCodeBlocksForGC(
+                *m_vm,
+                [&amp;] (CodeBlock* codeBlock) {
+                    slotVisitor.appendUnbarriered(codeBlock);
+                });
+            
+            if (Options::logGC() == GCLogging::Verbose)
+                dataLog(&quot;DFG Worklists:\n&quot;, slotVisitor);
+        },
+        MarkingConstraint::GreyedByMarking);
+#endif
+    
+    m_constraintSet-&gt;add(
+        &quot;Cb&quot;, &quot;CodeBlocks&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+            iterateExecutingAndCompilingCodeBlocksWithoutHoldingLocks(
+                [&amp;] (CodeBlock* codeBlock) {
+                    // Visit the CodeBlock as a constraint only if it's black.
+                    if (Heap::isMarked(codeBlock)
+                        &amp;&amp; codeBlock-&gt;cellState() == CellState::PossiblyOldOrBlack)
+                        slotVisitor.visitAsConstraint(codeBlock);
+                });
+        },
+        MarkingConstraint::GreyedByExecution);
+    
+    m_constraintSet-&gt;add(
+        &quot;Mms&quot;, &quot;Mutator Mark Stack&quot;,
+        [this] (SlotVisitor&amp; slotVisitor, const VisitingTimeout&amp;) {
+            // Indicate to the fixpoint that we introduced work!
+            size_t size = m_mutatorMarkStack-&gt;size();
+            slotVisitor.addToVisitCount(size);
+            
+            if (Options::logGC())
+                dataLog(&quot;(&quot;, size, &quot;)&quot;);
+            
+            m_mutatorMarkStack-&gt;transferTo(slotVisitor.mutatorMarkStack());
+        },
+        [this] (SlotVisitor&amp;) -&gt; double {
+            return m_mutatorMarkStack-&gt;size();
+        },
+        MarkingConstraint::GreyedByExecution);
+}
+
</ins><span class="cx"> void Heap::notifyIsSafeToCollect()
</span><span class="cx"> {
</span><ins>+    buildConstraintSet();
+    
</ins><span class="cx">     m_isSafeToCollect = true;
</span><span class="cx">     
</span><span class="cx">     if (Options::collectContinuously()) {
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/heap/Heap.h (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/Heap.h        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/Heap.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -73,8 +73,10 @@
</span><span class="cx"> class LLIntOffsetsExtractor;
</span><span class="cx"> class MarkStackArray;
</span><span class="cx"> class MarkedArgumentBuffer;
</span><ins>+class MarkingConstraintSet;
+class MutatorScheduler;
</ins><span class="cx"> class SlotVisitor;
</span><del>-class SpaceTimeScheduler;
</del><ins>+class SpaceTimeMutatorScheduler;
</ins><span class="cx"> class StopIfNecessaryTimer;
</span><span class="cx"> class VM;
</span><span class="cx"> 
</span><span class="lines">@@ -201,7 +203,7 @@
</span><span class="cx">     // and this will wait for that backlog before running its GC and returning.
</span><span class="cx">     JS_EXPORT_PRIVATE void collectSync(std::optional&lt;CollectionScope&gt; = std::nullopt);
</span><span class="cx">     
</span><del>-    bool collectIfNecessaryOrDefer(GCDeferralContext* = nullptr); // Returns true if it did collect.
</del><ins>+    void collectIfNecessaryOrDefer(GCDeferralContext* = nullptr);
</ins><span class="cx"> 
</span><span class="cx">     void completeAllJITPlans();
</span><span class="cx">     
</span><span class="lines">@@ -375,7 +377,7 @@
</span><span class="cx">     friend class MarkedAllocator;
</span><span class="cx">     friend class MarkedBlock;
</span><span class="cx">     friend class SlotVisitor;
</span><del>-    friend class SpaceTimeScheduler;
</del><ins>+    friend class SpaceTimeMutatorScheduler;
</ins><span class="cx">     friend class IncrementalSweeper;
</span><span class="cx">     friend class HeapStatistics;
</span><span class="cx">     friend class VM;
</span><span class="lines">@@ -412,9 +414,6 @@
</span><span class="cx">     void stopTheWorld();
</span><span class="cx">     void resumeTheWorld();
</span><span class="cx">     
</span><del>-    class ResumeTheWorldScope;
-    friend class ResumeTheWorldScope;
-    
</del><span class="cx">     void stopTheMutator();
</span><span class="cx">     void resumeTheMutator();
</span><span class="cx">     
</span><span class="lines">@@ -454,7 +453,6 @@
</span><span class="cx">     void gatherJSStackRoots(ConservativeRoots&amp;);
</span><span class="cx">     void gatherScratchBufferRoots(ConservativeRoots&amp;);
</span><span class="cx">     void beginMarking();
</span><del>-    void visitConservativeRoots(ConservativeRoots&amp;);
</del><span class="cx">     void visitCompilerWorklistWeakReferences();
</span><span class="cx">     void removeDeadCompilerWorklistEntries();
</span><span class="cx">     void updateObjectCounts(double gcStartTime);
</span><span class="lines">@@ -498,6 +496,16 @@
</span><span class="cx">     JS_EXPORT_PRIVATE void writeBarrierOpaqueRootSlow(void*);
</span><span class="cx">     
</span><span class="cx">     void setMutatorShouldBeFenced(bool value);
</span><ins>+    
+    void buildConstraintSet();
+    
+    template&lt;typename Func&gt;
+    void iterateExecutingAndCompilingCodeBlocks(const Func&amp;);
+    
+    template&lt;typename Func&gt;
+    void iterateExecutingAndCompilingCodeBlocksWithoutHoldingLocks(const Func&amp;);
+    
+    void assertSharedMarkStacksEmpty();
</ins><span class="cx"> 
</span><span class="cx">     const HeapType m_heapType;
</span><span class="cx">     const size_t m_ramSize;
</span><span class="lines">@@ -534,6 +542,8 @@
</span><span class="cx">     
</span><span class="cx">     std::unique_ptr&lt;SlotVisitor&gt; m_collectorSlotVisitor;
</span><span class="cx">     std::unique_ptr&lt;MarkStackArray&gt; m_mutatorMarkStack;
</span><ins>+    
+    std::unique_ptr&lt;MarkingConstraintSet&gt; m_constraintSet;
</ins><span class="cx"> 
</span><span class="cx">     // We pool the slot visitors used by parallel marking threads. It's useful to be able to
</span><span class="cx">     // enumerate over them, and it's useful to have them cache some small amount of memory from
</span><span class="lines">@@ -616,6 +626,8 @@
</span><span class="cx">     size_t m_externalMemorySize { 0 };
</span><span class="cx"> #endif
</span><span class="cx">     
</span><ins>+    std::unique_ptr&lt;MutatorScheduler&gt; m_scheduler;
+    
</ins><span class="cx">     static const unsigned shouldStopBit = 1u &lt;&lt; 0u;
</span><span class="cx">     static const unsigned stoppedBit = 1u &lt;&lt; 1u;
</span><span class="cx">     static const unsigned hasAccessBit = 1u &lt;&lt; 2u;
</span><span class="lines">@@ -631,6 +643,7 @@
</span><span class="cx">     Ticket m_lastGrantedTicket { 0 };
</span><span class="cx">     bool m_threadShouldStop { false };
</span><span class="cx">     bool m_threadIsStopping { false };
</span><ins>+    bool m_mutatorDidRun { true };
</ins><span class="cx">     Box&lt;Lock&gt; m_threadLock;
</span><span class="cx">     RefPtr&lt;AutomaticThreadCondition&gt; m_threadCondition; // The mutator must not wait on this. It would cause a deadlock.
</span><span class="cx">     RefPtr&lt;AutomaticThread&gt; m_thread;
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapMarkingConstraintcpp"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraint.cpp (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraint.cpp                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraint.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;MarkingConstraint.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+MarkingConstraint::MarkingConstraint(
+    CString abbreviatedName, CString name,
+    ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt; executeFunction,
+    Volatility volatility)
+    : m_abbreviatedName(abbreviatedName)
+    , m_name(WTFMove(name))
+    , m_executeFunction(WTFMove(executeFunction))
+    , m_volatility(volatility)
+{
+}
+
+MarkingConstraint::MarkingConstraint(
+    CString abbreviatedName, CString name,
+    ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt; executeFunction,
+    ::Function&lt;double(SlotVisitor&amp;)&gt; quickWorkEstimateFunction,
+    Volatility volatility)
+    : m_abbreviatedName(abbreviatedName)
+    , m_name(WTFMove(name))
+    , m_executeFunction(WTFMove(executeFunction))
+    , m_quickWorkEstimateFunction(WTFMove(quickWorkEstimateFunction))
+    , m_volatility(volatility)
+{
+}
+
+MarkingConstraint::~MarkingConstraint()
+{
+}
+
+void MarkingConstraint::resetStats()
+{
+    m_lastVisitCount = 0;
+}
+
+void MarkingConstraint::execute(SlotVisitor&amp; visitor, bool&amp; didVisitSomething, MonotonicTime timeout)
+{
+    if (Options::logGC())
+        dataLog(abbreviatedName());
+    VisitingTimeout visitingTimeout(visitor, didVisitSomething, timeout);
+    m_executeFunction(visitor, visitingTimeout);
+    m_lastVisitCount = visitingTimeout.visitCount(visitor);
+    didVisitSomething = visitingTimeout.didVisitSomething(visitor);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapMarkingConstrainth"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraint.h (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraint.h                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraint.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,111 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;VisitingTimeout.h&quot;
+#include &lt;wtf/FastMalloc.h&gt;
+#include &lt;wtf/Function.h&gt;
+#include &lt;wtf/MonotonicTime.h&gt;
+#include &lt;wtf/Noncopyable.h&gt;
+#include &lt;wtf/text/CString.h&gt;
+
+namespace JSC {
+
+class MarkingConstraintSet;
+class SlotVisitor;
+
+class MarkingConstraint {
+    WTF_MAKE_NONCOPYABLE(MarkingConstraint);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    enum Volatility {
+        // FIXME: We could introduce a new kind of volatility called GreyedByResumption, which
+        // would mean running all of the times that GreyedByExecution runs except as a root in a
+        // full GC.
+        // https://bugs.webkit.org/show_bug.cgi?id=166830
+        
+        // The constraint needs to be reevaluated anytime the mutator runs: so at GC start and
+        // whenever the GC resuspends after a resumption. This is almost always something that
+        // you'd call a &quot;root&quot; in a traditional GC.
+        GreyedByExecution,
+        
+        // The constraint needs to be reevaluated any time any object is marked and anytime the
+        // mutator resumes.
+        GreyedByMarking
+    };
+    
+    MarkingConstraint(
+        CString abbreviatedName, CString name,
+        ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt;,
+        Volatility);
+    
+    MarkingConstraint(
+        CString abbreviatedName, CString name,
+        ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt;,
+        ::Function&lt;double(SlotVisitor&amp;)&gt;,
+        Volatility);
+    
+    ~MarkingConstraint();
+    
+    unsigned index() const { return m_index; }
+    
+    const char* abbreviatedName() const { return m_abbreviatedName.data(); }
+    const char* name() const { return m_name.data(); }
+    
+    void resetStats();
+    
+    size_t lastVisitCount() const { return m_lastVisitCount; }
+    
+    void execute(SlotVisitor&amp;, bool&amp; didVisitSomething, MonotonicTime timeout);
+    
+    double quickWorkEstimate(SlotVisitor&amp; visitor)
+    {
+        if (!m_quickWorkEstimateFunction)
+            return 0;
+        return m_quickWorkEstimateFunction(visitor);
+    }
+    
+    double workEstimate(SlotVisitor&amp; visitor)
+    {
+        return lastVisitCount() + quickWorkEstimate(visitor);
+    }
+    
+    Volatility volatility() const { return m_volatility; }
+    
+private:
+    friend class MarkingConstraintSet; // So it can set m_index.
+    
+    unsigned m_index { UINT_MAX };
+    CString m_abbreviatedName;
+    CString m_name;
+    ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp; timeout)&gt; m_executeFunction;
+    ::Function&lt;double(SlotVisitor&amp;)&gt; m_quickWorkEstimateFunction;
+    Volatility m_volatility;
+    size_t m_lastVisitCount { 0 };
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapMarkingConstraintSetcpp"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraintSet.cpp (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraintSet.cpp                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraintSet.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,239 @@
</span><ins>+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;MarkingConstraintSet.h&quot;
+
+#include &quot;Options.h&quot;
+#include &lt;wtf/TimeWithDynamicClockType.h&gt;
+
+namespace JSC {
+
+class MarkingConstraintSet::ExecutionContext {
+public:
+    ExecutionContext(MarkingConstraintSet&amp; set, SlotVisitor&amp; visitor, MonotonicTime timeout)
+        : m_set(set)
+        , m_visitor(visitor)
+        , m_timeout(timeout)
+    {
+    }
+    
+    bool didVisitSomething() const
+    {
+        return m_didVisitSomething;
+    }
+    
+    bool shouldTimeOut() const
+    {
+        return didVisitSomething() &amp;&amp; hasElapsed(m_timeout);
+    }
+    
+    // Returns false if it times out.
+    bool drain(BitVector&amp; unexecuted)
+    {
+        for (size_t index : unexecuted) {
+            execute(index);
+            unexecuted.clear(index);
+            if (shouldTimeOut())
+                return false;
+        }
+        return true;
+    }
+    
+    bool didExecute(size_t index) const { return m_executed.get(index); }
+
+    void execute(size_t index)
+    {
+        m_set.m_set[index]-&gt;execute(m_visitor, m_didVisitSomething, m_timeout);
+        m_executed.set(index);
+    }
+    
+private:
+    MarkingConstraintSet&amp; m_set;
+    SlotVisitor&amp; m_visitor;
+    MonotonicTime m_timeout;
+    BitVector m_executed;
+    bool m_didVisitSomething { false };
+};
+
+MarkingConstraintSet::MarkingConstraintSet()
+{
+}
+
+MarkingConstraintSet::~MarkingConstraintSet()
+{
+}
+
+void MarkingConstraintSet::resetStats()
+{
+    m_unexecutedRoots.clearAll();
+    m_unexecutedOutgrowths.clearAll();
+    for (auto&amp; constraint : m_set) {
+        constraint-&gt;resetStats();
+        switch (constraint-&gt;volatility()) {
+        case MarkingConstraint::GreyedByExecution:
+            m_unexecutedRoots.set(constraint-&gt;index());
+            break;
+        case MarkingConstraint::GreyedByMarking:
+            m_unexecutedOutgrowths.set(constraint-&gt;index());
+            break;
+        }
+    }
+}
+
+void MarkingConstraintSet::add(CString abbreviatedName, CString name, Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt; function, MarkingConstraint::Volatility volatility)
+{
+    add(std::make_unique&lt;MarkingConstraint&gt;(WTFMove(abbreviatedName), WTFMove(name), WTFMove(function), volatility));
+}
+
+void MarkingConstraintSet::add(
+    CString abbreviatedName, CString name,
+    Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt; executeFunction,
+    Function&lt;double(SlotVisitor&amp;)&gt; quickWorkEstimateFunction,
+    MarkingConstraint::Volatility volatility)
+{
+    add(std::make_unique&lt;MarkingConstraint&gt;(WTFMove(abbreviatedName), WTFMove(name), WTFMove(executeFunction), WTFMove(quickWorkEstimateFunction), volatility));
+}
+
+void MarkingConstraintSet::add(
+    std::unique_ptr&lt;MarkingConstraint&gt; constraint)
+{
+    constraint-&gt;m_index = m_set.size();
+    m_ordered.append(constraint.get());
+    if (constraint-&gt;volatility() == MarkingConstraint::GreyedByMarking)
+        m_outgrowths.append(constraint.get());
+    m_set.append(WTFMove(constraint));
+}
+
+bool MarkingConstraintSet::executeBootstrap(SlotVisitor&amp; visitor, MonotonicTime timeout)
+{
+    // Bootstrap means that we haven't done any object visiting yet. This means that we want to
+    // only execute root constraints (which also happens to be those that we say are greyed by
+    // resumption), since the other constraints are super unlikely to trigger without some object
+    // visiting. The expectation is that the caller will go straight to object visiting after
+    // this.
+    ExecutionContext executionContext(*this, visitor, timeout);
+    if (Options::logGC())
+        dataLog(&quot;boot:&quot;);
+    bool result = executionContext.drain(m_unexecutedRoots);
+    if (Options::logGC())
+        dataLog(&quot; &quot;);
+    return result;
+}
+
+bool MarkingConstraintSet::executeConvergence(SlotVisitor&amp; visitor, MonotonicTime timeout)
+{
+    bool result = executeConvergenceImpl(visitor, timeout);
+    if (Options::logGC())
+        dataLog(&quot; &quot;);
+    return result;
+}
+
+bool MarkingConstraintSet::isWavefrontAdvancing(SlotVisitor&amp; visitor)
+{
+    for (MarkingConstraint* outgrowth : m_outgrowths) {
+        if (outgrowth-&gt;workEstimate(visitor))
+            return true;
+    }
+    return false;
+}
+
+bool MarkingConstraintSet::executeConvergenceImpl(SlotVisitor&amp; visitor, MonotonicTime timeout)
+{
+    ExecutionContext executionContext(*this, visitor, timeout);
+    
+    if (Options::logGC())
+        dataLog(&quot;converge:&quot;);
+
+    // If there are any constraints that we have not executed at all during this cycle, then
+    // we should execute those now.
+    if (!executionContext.drain(m_unexecutedRoots))
+        return false;
+    if (!executionContext.drain(m_unexecutedOutgrowths))
+        return false;
+    
+    // We want to keep preferring the outgrowth constraints - the ones that need to be fixpointed
+    // even in a stop-the-world GC - until they stop producing. They have a tendency to go totally
+    // silent at some point during GC, at which point it makes sense not to run them again until
+    // the end. Outgrowths producing new information corresponds almost exactly to the wavefront
+    // advancing: it usually means that we are marking objects that should be marked based on
+    // other objects that we would have marked anyway. Once the wavefront is no longer advancing,
+    // we want to run mostly the root constraints (based on their predictions of how much work
+    // they will have) because at this point we are just trying to outpace the retreating
+    // wavefront.
+    //
+    // Note that this function (executeConvergenceImpl) only returns true if it runs all
+    // constraints. So, all we are controlling are the heuristics that say which constraints to
+    // run first. Choosing the constraints that are the most likely to produce means running fewer
+    // constraints before returning.
+    bool isWavefrontAdvancing = this-&gt;isWavefrontAdvancing(visitor);
+    
+    std::sort(
+        m_ordered.begin(), m_ordered.end(),
+        [&amp;] (MarkingConstraint* a, MarkingConstraint* b) -&gt; bool {
+            // Remember: return true if a should come before b.
+            if (a-&gt;volatility() != b-&gt;volatility()) {
+                if (isWavefrontAdvancing)
+                    return a-&gt;volatility() &gt; b-&gt;volatility(); // GreyedByMarking should come before GreyedByExecution.
+                else
+                    return a-&gt;volatility() &lt; b-&gt;volatility(); // GreyedByExecution should come before GreyedByMarking.
+            }
+            
+            return a-&gt;workEstimate(visitor) &gt; b-&gt;workEstimate(visitor);
+        });
+    
+    for (MarkingConstraint* constraint : m_ordered) {
+        size_t i = constraint-&gt;index();
+        
+        if (executionContext.didExecute(i))
+            continue;
+        executionContext.execute(i);
+        
+        // Once we're in convergence, it makes the most sense to let some marking happen anytime
+        // we find work.
+        // FIXME: Maybe this should execute all constraints until timeout? Not clear if that's
+        // better or worse. Maybe even better is this:
+        // - If the visitor is empty, keep running.
+        // - If the visitor is has at least N things, return.
+        // - Else run until timeout.
+        // https://bugs.webkit.org/show_bug.cgi?id=166832
+        if (executionContext.didVisitSomething())
+            return false;
+    }
+    
+    return true;
+}
+
+void MarkingConstraintSet::executeAll(SlotVisitor&amp; visitor)
+{
+    bool didVisitSomething = false;
+    for (auto&amp; constraint : m_set)
+        constraint-&gt;execute(visitor, didVisitSomething, MonotonicTime::infinity());
+    if (Options::logGC())
+        dataLog(&quot; &quot;);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapMarkingConstraintSeth"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraintSet.h (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraintSet.h                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/MarkingConstraintSet.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,90 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;MarkingConstraint.h&quot;
+#include &lt;wtf/BitVector.h&gt;
+#include &lt;wtf/Vector.h&gt;
+
+namespace JSC {
+
+class MarkingConstraintSet {
+public:
+    MarkingConstraintSet();
+    ~MarkingConstraintSet();
+    
+    void resetStats();
+    
+    void add(
+        CString abbreviatedName,
+        CString name,
+        ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt;,
+        MarkingConstraint::Volatility);
+    
+    void add(
+        CString abbreviatedName,
+        CString name,
+        ::Function&lt;void(SlotVisitor&amp;, const VisitingTimeout&amp;)&gt;,
+        ::Function&lt;double(SlotVisitor&amp;)&gt;,
+        MarkingConstraint::Volatility);
+    
+    void add(std::unique_ptr&lt;MarkingConstraint&gt;);
+    
+    // Assuming that the mark stacks are all empty, this will give you a guess as to whether or
+    // not the wavefront is advancing.
+    bool isWavefrontAdvancing(SlotVisitor&amp;);
+    bool isWavefrontRetreating(SlotVisitor&amp; visitor) { return !isWavefrontAdvancing(visitor); }
+    
+    // Executes only roots. Returns true if all roots have been executed. It's expected
+    // that you'll do some draining after this and then use executeConvergence().
+    bool executeBootstrap(SlotVisitor&amp;, MonotonicTime timeout = MonotonicTime::infinity());
+    
+    // Returns true if all constraints were executed. This assumes that you've alraedy
+    // visited roots and drained from there.
+    bool executeConvergence(
+        SlotVisitor&amp;,
+        MonotonicTime timeout = MonotonicTime::infinity());
+    
+    // Simply runs all constraints without any shenanigans.
+    void executeAll(SlotVisitor&amp;);
+    
+private:
+    class ExecutionContext;
+    friend class ExecutionContext;
+    
+    bool executeConvergenceImpl(SlotVisitor&amp;, MonotonicTime timeout);
+    
+    bool drain(SlotVisitor&amp;, MonotonicTime, BitVector&amp; unexecuted, BitVector&amp; executed, bool&amp; didVisitSomething);
+    
+    BitVector m_unexecutedRoots;
+    BitVector m_unexecutedOutgrowths;
+    Vector&lt;std::unique_ptr&lt;MarkingConstraint&gt;&gt; m_set;
+    Vector&lt;MarkingConstraint*&gt; m_ordered;
+    Vector&lt;MarkingConstraint*&gt; m_outgrowths;
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapMutatorSchedulercpp"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/heap/MutatorScheduler.cpp (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/MutatorScheduler.cpp                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/MutatorScheduler.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,68 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;MutatorScheduler.h&quot;
+
+#include &lt;wtf/TimeWithDynamicClockType.h&gt;
+
+namespace JSC {
+
+MutatorScheduler::MutatorScheduler()
+{
+}
+
+MutatorScheduler::~MutatorScheduler()
+{
+}
+
+void MutatorScheduler::didStop()
+{
+}
+
+void MutatorScheduler::willResume()
+{
+}
+
+void MutatorScheduler::didExecuteConstraints()
+{
+}
+
+void MutatorScheduler::log()
+{
+}
+
+bool MutatorScheduler::shouldStop()
+{
+    return hasElapsed(timeToStop());
+}
+
+bool MutatorScheduler::shouldResume()
+{
+    return hasElapsed(timeToResume());
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapMutatorSchedulerhfromrev210652branchessafari603branchSourceJavaScriptCoreheapSpaceTimeSchedulerh"></a>
<div class="copfile"><h4>Copied: branches/safari-603-branch/Source/JavaScriptCore/heap/MutatorScheduler.h (from rev 210652, branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.h) (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/MutatorScheduler.h                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/MutatorScheduler.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,67 @@
</span><ins>+/*
+ * Copyright (C) 2017 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 &lt;wtf/FastMalloc.h&gt;
+#include &lt;wtf/MonotonicTime.h&gt;
+#include &lt;wtf/Noncopyable.h&gt;
+
+namespace JSC {
+
+class MutatorScheduler {
+    WTF_MAKE_NONCOPYABLE(MutatorScheduler);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    enum State {
+        Normal, // Not collecting.
+        Stopped,
+        Resumed
+    };
+    
+    MutatorScheduler();
+    virtual ~MutatorScheduler();
+    
+    virtual State state() const = 0;
+    
+    virtual void beginCollection() = 0;
+    
+    virtual void didStop();
+    virtual void willResume();
+    virtual void didExecuteConstraints();
+    
+    virtual MonotonicTime timeToStop() = 0; // Call while resumed, to ask when to stop.
+    virtual MonotonicTime timeToResume() = 0; // Call while stopped, to ask when to resume.
+    
+    virtual void log();
+    
+    bool shouldStop(); // Call while resumed, to ask if we should stop now.
+    bool shouldResume(); // Call while stopped, to ask if we should resume now.
+    
+    virtual void endCollection() = 0;
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapOpaqueRootSeth"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/heap/OpaqueRootSet.h (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/OpaqueRootSet.h        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/OpaqueRootSet.h        2017-01-12 16:45:48 UTC (rev 210653)
</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-2017 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">@@ -59,11 +59,11 @@
</span><span class="cx">         m_containsLastQueriedRoot = false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void add(void* root)
</del><ins>+    bool add(void* root)
</ins><span class="cx">     {
</span><span class="cx">         if (root == m_lastQueriedRoot)
</span><span class="cx">             m_containsLastQueriedRoot = true;
</span><del>-        m_roots.add(root);
</del><ins>+        return m_roots.add(root).isNewEntry;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     int size() const
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/heap/SlotVisitor.cpp (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/SlotVisitor.cpp        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/SlotVisitor.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2017 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">@@ -347,6 +347,11 @@
</span><span class="cx">     SlotVisitor&amp; m_visitor;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+void SlotVisitor::visitAsConstraint(const JSCell* cell)
+{
+    m_isVisitingMutatorStack = true;
+    visitChildren(cell);
+}
</ins><span class="cx"> 
</span><span class="cx"> ALWAYS_INLINE void SlotVisitor::visitChildren(const JSCell* cell)
</span><span class="cx"> {
</span><span class="lines">@@ -461,7 +466,7 @@
</span><span class="cx">     
</span><span class="cx">     auto locker = holdLock(m_rightToRun);
</span><span class="cx">     
</span><del>-    while ((!m_collectorStack.isEmpty() || !m_mutatorStack.isEmpty()) &amp;&amp; !hasElapsed(timeout)) {
</del><ins>+    while (!hasElapsed(timeout)) {
</ins><span class="cx">         updateMutatorIsStopped(locker);
</span><span class="cx">         if (!m_collectorStack.isEmpty()) {
</span><span class="cx">             m_collectorStack.refill();
</span><span class="lines">@@ -476,7 +481,8 @@
</span><span class="cx">             m_isVisitingMutatorStack = true;
</span><span class="cx">             for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance(); m_mutatorStack.canRemoveLast() &amp;&amp; countdown--;)
</span><span class="cx">                 visitChildren(m_mutatorStack.removeLast());
</span><del>-        }
</del><ins>+        } else
+            break;
</ins><span class="cx">         m_rightToRun.safepoint();
</span><span class="cx">         donateKnownParallel();
</span><span class="cx">     }
</span><span class="lines">@@ -486,12 +492,18 @@
</span><span class="cx"> 
</span><span class="cx"> bool SlotVisitor::didReachTermination()
</span><span class="cx"> {
</span><ins>+    LockHolder locker(m_heap.m_markingMutex);
+    return isEmpty() &amp;&amp; didReachTermination(locker);
+}
+
+bool SlotVisitor::didReachTermination(const LockHolder&amp;)
+{
</ins><span class="cx">     return !m_heap.m_numberOfActiveParallelMarkers
</span><span class="cx">         &amp;&amp; m_heap.m_sharedCollectorMarkStack-&gt;isEmpty()
</span><span class="cx">         &amp;&amp; m_heap.m_sharedMutatorMarkStack-&gt;isEmpty();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool SlotVisitor::hasWork()
</del><ins>+bool SlotVisitor::hasWork(const LockHolder&amp;)
</ins><span class="cx"> {
</span><span class="cx">     return !m_heap.m_sharedCollectorMarkStack-&gt;isEmpty()
</span><span class="cx">         || !m_heap.m_sharedMutatorMarkStack-&gt;isEmpty();
</span><span class="lines">@@ -518,12 +530,12 @@
</span><span class="cx">                     if (hasElapsed(timeout))
</span><span class="cx">                         return SharedDrainResult::TimedOut;
</span><span class="cx">                     
</span><del>-                    if (didReachTermination()) {
</del><ins>+                    if (didReachTermination(locker)) {
</ins><span class="cx">                         m_heap.m_markingConditionVariable.notifyAll();
</span><span class="cx">                         return SharedDrainResult::Done;
</span><span class="cx">                     }
</span><span class="cx">                     
</span><del>-                    if (hasWork())
</del><ins>+                    if (hasWork(locker))
</ins><span class="cx">                         break;
</span><span class="cx">                     
</span><span class="cx">                     m_heap.m_markingConditionVariable.waitUntil(m_heap.m_markingMutex, timeout);
</span><span class="lines">@@ -534,13 +546,13 @@
</span><span class="cx">                 if (hasElapsed(timeout))
</span><span class="cx">                     return SharedDrainResult::TimedOut;
</span><span class="cx">                 
</span><del>-                if (didReachTermination())
</del><ins>+                if (didReachTermination(locker))
</ins><span class="cx">                     m_heap.m_markingConditionVariable.notifyAll();
</span><span class="cx"> 
</span><span class="cx">                 m_heap.m_markingConditionVariable.waitUntil(
</span><span class="cx">                     m_heap.m_markingMutex, timeout,
</span><del>-                    [this] {
-                        return hasWork()
</del><ins>+                    [&amp;] {
+                        return hasWork(locker)
</ins><span class="cx">                             || m_heap.m_parallelMarkersShouldExit;
</span><span class="cx">                     });
</span><span class="cx">                 
</span><span class="lines">@@ -589,7 +601,7 @@
</span><span class="cx">         if (hasElapsed(timeout))
</span><span class="cx">             return SharedDrainResult::TimedOut;
</span><span class="cx">         
</span><del>-        if (didReachTermination()) {
</del><ins>+        if (didReachTermination(locker)) {
</ins><span class="cx">             m_heap.m_markingConditionVariable.notifyAll();
</span><span class="cx">             return SharedDrainResult::Done;
</span><span class="cx">         }
</span><span class="lines">@@ -605,13 +617,13 @@
</span><span class="cx">     
</span><span class="cx">     if (Options::numberOfGCMarkers() == 1) {
</span><span class="cx">         // Put directly into the shared HashSet.
</span><del>-        m_heap.m_opaqueRoots.add(root);
</del><ins>+        m_visitCount += m_heap.m_opaqueRoots.add(root).isNewEntry;
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     // Put into the local set, but merge with the shared one every once in
</span><span class="cx">     // a while to make sure that the local sets don't grow too large.
</span><span class="cx">     mergeOpaqueRootsIfProfitable();
</span><del>-    m_opaqueRoots.add(root);
</del><ins>+    m_visitCount += m_opaqueRoots.add(root);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SlotVisitor::containsOpaqueRoot(void* root) const
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapSlotVisitorh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/heap/SlotVisitor.h (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/SlotVisitor.h        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/SlotVisitor.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011-2013, 2015-2016 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011-2017 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">@@ -103,6 +103,8 @@
</span><span class="cx"> 
</span><span class="cx">     size_t bytesVisited() const { return m_bytesVisited; }
</span><span class="cx">     size_t visitCount() const { return m_visitCount; }
</span><ins>+    
+    void addToVisitCount(size_t value) { m_visitCount += value; }
</ins><span class="cx"> 
</span><span class="cx">     void donate();
</span><span class="cx">     void drain(MonotonicTime timeout = MonotonicTime::infinity());
</span><span class="lines">@@ -151,6 +153,10 @@
</span><span class="cx">     void didRace(JSCell* cell, const char* reason) { didRace(VisitRaceKey(cell, reason)); }
</span><span class="cx">     void didNotRace(const VisitRaceKey&amp;);
</span><span class="cx">     void didNotRace(JSCell* cell, const char* reason) { didNotRace(VisitRaceKey(cell, reason)); }
</span><ins>+    
+    void visitAsConstraint(const JSCell*);
+    
+    bool didReachTermination();
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class ParallelModeEnabler;
</span><span class="lines">@@ -180,8 +186,8 @@
</span><span class="cx">     void donateKnownParallel();
</span><span class="cx">     void donateKnownParallel(MarkStackArray&amp; from, MarkStackArray&amp; to);
</span><span class="cx">     
</span><del>-    bool hasWork();
-    bool didReachTermination();
</del><ins>+    bool hasWork(const LockHolder&amp;);
+    bool didReachTermination(const LockHolder&amp;);
</ins><span class="cx"> 
</span><span class="cx">     MarkStackArray m_collectorStack;
</span><span class="cx">     MarkStackArray m_mutatorStack;
</span></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapSpaceTimeMutatorSchedulercpp"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeMutatorScheduler.cpp (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeMutatorScheduler.cpp                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeMutatorScheduler.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,221 @@
</span><ins>+/*
+ * Copyright (C) 2016-2017 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;SpaceTimeMutatorScheduler.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+// The scheduler will often make decisions based on state that is in flux. It will be fine so
+// long as multiple uses of the same value all see the same value. We wouldn't get this for free,
+// since our need to modularize the calculation results in a tendency to access the same mutable
+// field in Heap multiple times, and to access the current time multiple times.
+class SpaceTimeMutatorScheduler::Snapshot {
+public:
+    Snapshot(SpaceTimeMutatorScheduler&amp; scheduler)
+    {
+        m_now = MonotonicTime::now();
+        m_bytesAllocatedThisCycle = scheduler.bytesAllocatedThisCycleImpl();
+    }
+    
+    MonotonicTime now() const { return m_now; }
+    
+    double bytesAllocatedThisCycle() const { return m_bytesAllocatedThisCycle; }
+    
+private:
+    MonotonicTime m_now;
+    double m_bytesAllocatedThisCycle;
+};
+
+SpaceTimeMutatorScheduler::SpaceTimeMutatorScheduler(Heap&amp; heap)
+    : m_heap(heap)
+    , m_period(Seconds::fromMilliseconds(Options::concurrentGCPeriodMS()))
+{
+}
+
+SpaceTimeMutatorScheduler::~SpaceTimeMutatorScheduler()
+{
+}
+
+MutatorScheduler::State SpaceTimeMutatorScheduler::state() const
+{
+    return m_state;
+}
+
+void SpaceTimeMutatorScheduler::beginCollection()
+{
+    RELEASE_ASSERT(m_state == Normal);
+    m_state = Stopped;
+    m_startTime = MonotonicTime::now();
+
+    m_bytesAllocatedThisCycleAtTheBeginning = m_heap.m_bytesAllocatedThisCycle;
+    m_bytesAllocatedThisCycleAtTheEnd = 
+        Options::concurrentGCMaxHeadroom() *
+        std::max&lt;double&gt;(m_bytesAllocatedThisCycleAtTheBeginning, m_heap.m_maxEdenSize);
+}
+
+void SpaceTimeMutatorScheduler::didStop()
+{
+    RELEASE_ASSERT(m_state == Stopped || m_state == Resumed);
+    m_state = Stopped;
+}
+
+void SpaceTimeMutatorScheduler::willResume()
+{
+    RELEASE_ASSERT(m_state == Stopped || m_state == Resumed);
+    m_state = Resumed;
+}
+
+void SpaceTimeMutatorScheduler::didExecuteConstraints()
+{
+    // If we execute constraints, we want to forgive the GC for all of the time it had stopped the
+    // world for in this increment. This hack is empirically better than every other heuristic I
+    // tried, because it just means that the GC is happy to pause for longer when it's dealing
+    // with things that don't play well with concurrency.
+    // FIXME: The feels so wrong but benchmarks so good.
+    // https://bugs.webkit.org/show_bug.cgi?id=166833
+    m_startTime = MonotonicTime::now();
+}
+
+MonotonicTime SpaceTimeMutatorScheduler::timeToStop()
+{
+    switch (m_state) {
+    case Normal:
+        return MonotonicTime::infinity();
+    case Stopped:
+        return MonotonicTime::now();
+    case Resumed: {
+        Snapshot snapshot(*this);
+        if (!shouldBeResumed(snapshot))
+            return snapshot.now();
+        return snapshot.now() - elapsedInPeriod(snapshot) + m_period;
+    } }
+    
+    RELEASE_ASSERT_NOT_REACHED();
+    return MonotonicTime();
+}
+
+MonotonicTime SpaceTimeMutatorScheduler::timeToResume()
+{
+    switch (m_state) {
+    case Normal:
+    case Resumed:
+        return MonotonicTime::now();
+    case Stopped: {
+        Snapshot snapshot(*this);
+        if (shouldBeResumed(snapshot))
+            return snapshot.now();
+        return snapshot.now() - elapsedInPeriod(snapshot) + m_period * collectorUtilization(snapshot);
+    } }
+    
+    RELEASE_ASSERT_NOT_REACHED();
+    return MonotonicTime();
+}
+
+void SpaceTimeMutatorScheduler::log()
+{
+    ASSERT(Options::logGC());
+    Snapshot snapshot(*this);
+    dataLog(
+        &quot;a=&quot;, format(&quot;%.0lf&quot;, bytesSinceBeginningOfCycle(snapshot) / 1024), &quot; kb &quot;,
+        &quot;hf=&quot;, format(&quot;%.3lf&quot;, headroomFullness(snapshot)), &quot; &quot;,
+        &quot;mu=&quot;, format(&quot;%.3lf&quot;, mutatorUtilization(snapshot)), &quot; &quot;);
+}
+
+void SpaceTimeMutatorScheduler::endCollection()
+{
+    m_state = Normal;
+    m_startTime = MonotonicTime::now();
+}
+
+double SpaceTimeMutatorScheduler::bytesAllocatedThisCycleImpl()
+{
+    return m_heap.m_bytesAllocatedThisCycle;
+}
+
+double SpaceTimeMutatorScheduler::bytesSinceBeginningOfCycle(const Snapshot&amp; snapshot)
+{
+    return snapshot.bytesAllocatedThisCycle() - m_bytesAllocatedThisCycleAtTheBeginning;
+}
+
+double SpaceTimeMutatorScheduler::maxHeadroom()
+{
+    return m_bytesAllocatedThisCycleAtTheEnd - m_bytesAllocatedThisCycleAtTheBeginning;
+}
+
+double SpaceTimeMutatorScheduler::headroomFullness(const Snapshot&amp; snapshot)
+{
+    double result = bytesSinceBeginningOfCycle(snapshot) / maxHeadroom();
+
+    // headroomFullness can be NaN and other interesting things if
+    // bytesAllocatedThisCycleAtTheBeginning is zero. We see that in debug tests. This code
+    // defends against all floating point dragons.
+    
+    if (!(result &gt;= 0))
+        result = 0;
+    if (!(result &lt;= 1))
+        result = 1;
+
+    return result;
+}
+
+double SpaceTimeMutatorScheduler::mutatorUtilization(const Snapshot&amp; snapshot)
+{
+    double mutatorUtilization = 1 - headroomFullness(snapshot);
+    
+    // Scale the mutator utilization into the permitted window.
+    mutatorUtilization =
+        Options::minimumMutatorUtilization() +
+        mutatorUtilization * (
+            Options::maximumMutatorUtilization() -
+            Options::minimumMutatorUtilization());
+    
+    return mutatorUtilization;
+}
+
+double SpaceTimeMutatorScheduler::collectorUtilization(const Snapshot&amp; snapshot)
+{
+    return 1 - mutatorUtilization(snapshot);
+}
+
+Seconds SpaceTimeMutatorScheduler::elapsedInPeriod(const Snapshot&amp; snapshot)
+{
+    return (snapshot.now() - m_startTime) % m_period;
+}
+
+double SpaceTimeMutatorScheduler::phase(const Snapshot&amp; snapshot)
+{
+    return elapsedInPeriod(snapshot) / m_period;
+}
+
+bool SpaceTimeMutatorScheduler::shouldBeResumed(const Snapshot&amp; snapshot)
+{
+    return phase(snapshot) &gt; collectorUtilization(snapshot);
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapSpaceTimeMutatorSchedulerh"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeMutatorScheduler.h (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeMutatorScheduler.h                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeMutatorScheduler.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,86 @@
</span><ins>+/*
+ * Copyright (C) 2016-2017 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;MutatorScheduler.h&quot;
+#include &lt;wtf/Seconds.h&gt;
+
+namespace JSC {
+
+class Heap;
+
+// The JSC concurrent GC sometimes stops the world in order to stay ahead of it. These deliberate,
+// synthetic pauses ensure that the GC won't have to do one huge pause in order to catch up to the
+// retreating wavefront. The scheduler is called &quot;space-time&quot; because it links the amount of time
+// that the world is paused for to the amount of space that the world allocated since the GC cycle
+// began.
+
+class SpaceTimeMutatorScheduler : public MutatorScheduler {
+public:
+    SpaceTimeMutatorScheduler(Heap&amp;);
+    ~SpaceTimeMutatorScheduler();
+    
+    State state() const override;
+    
+    void beginCollection() override;
+    
+    void didStop() override;
+    void willResume() override;
+    void didExecuteConstraints() override;
+    
+    MonotonicTime timeToStop() override;
+    MonotonicTime timeToResume() override;
+    
+    void log() override;
+    
+    void endCollection() override;
+    
+private:
+    class Snapshot;
+    friend class Snapshot;
+    
+    double bytesAllocatedThisCycleImpl();
+    
+    double bytesSinceBeginningOfCycle(const Snapshot&amp;);
+    double maxHeadroom();
+    double headroomFullness(const Snapshot&amp;);
+    double mutatorUtilization(const Snapshot&amp;);
+    double collectorUtilization(const Snapshot&amp;);
+    Seconds elapsedInPeriod(const Snapshot&amp;);
+    double phase(const Snapshot&amp;);
+    bool shouldBeResumed(const Snapshot&amp;);
+    
+    Heap&amp; m_heap;
+    Seconds m_period;
+    State m_state { Normal };
+    
+    double m_bytesAllocatedThisCycleAtTheBeginning { 0 };
+    double m_bytesAllocatedThisCycleAtTheEnd { 0 };
+    MonotonicTime m_startTime;
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapSpaceTimeSchedulercpp"></a>
<div class="delfile"><h4>Deleted: branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.cpp (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.cpp        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,129 +0,0 @@
</span><del>-/*
- * 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;SpaceTimeScheduler.h&quot;
-
-#include &quot;JSCInlines.h&quot;
-
-namespace JSC {
-
-double SpaceTimeScheduler::Decision::targetMutatorUtilization() const
-{
-    double bytesSinceBeginningOfCycle =
-        m_bytesAllocatedThisCycle - m_scheduler-&gt;m_bytesAllocatedThisCycleAtTheBeginning;
-    
-    double maxHeadroom =
-        m_scheduler-&gt;m_bytesAllocatedThisCycleAtTheEnd - m_scheduler-&gt;m_bytesAllocatedThisCycleAtTheBeginning;
-    
-    double headroomFullness =
-        bytesSinceBeginningOfCycle / maxHeadroom;
-    
-    // headroomFullness can be NaN and other interesting things if
-    // bytesAllocatedThisCycleAtTheBeginning is zero. We see that in debug tests. This code
-    // defends against all floating point dragons.
-    
-    if (!(headroomFullness &gt;= 0))
-        headroomFullness = 0;
-    if (!(headroomFullness &lt;= 1))
-        headroomFullness = 1;
-    
-    double mutatorUtilization = 1 - headroomFullness;
-    
-    // Scale the mutator utilization into the permitted window.
-    mutatorUtilization =
-        Options::minimumMutatorUtilization() +
-        mutatorUtilization * (
-            Options::maximumMutatorUtilization() -
-            Options::minimumMutatorUtilization());
-    
-    return mutatorUtilization;
-}
-
-double SpaceTimeScheduler::Decision::targetCollectorUtilization() const
-{
-    return 1 - targetMutatorUtilization();
-}
-
-Seconds SpaceTimeScheduler::Decision::elapsedInPeriod() const
-{
-    return (m_now - m_scheduler-&gt;m_initialTime) % m_scheduler-&gt;m_period;
-}
-
-double SpaceTimeScheduler::Decision::phase() const
-{
-    return elapsedInPeriod() / m_scheduler-&gt;m_period;
-}
-
-bool SpaceTimeScheduler::Decision::shouldBeResumed() const
-{
-    if (Options::collectorShouldResumeFirst())
-        return phase() &lt;= targetMutatorUtilization();
-    return phase() &gt; targetCollectorUtilization();
-}
-
-MonotonicTime SpaceTimeScheduler::Decision::timeToResume() const
-{
-    ASSERT(!shouldBeResumed());
-    if (Options::collectorShouldResumeFirst())
-        return m_now - elapsedInPeriod() + m_scheduler-&gt;m_period;
-    return m_now - elapsedInPeriod() + m_scheduler-&gt;m_period * targetCollectorUtilization();
-}
-
-MonotonicTime SpaceTimeScheduler::Decision::timeToStop() const
-{
-    ASSERT(shouldBeResumed());
-    if (Options::collectorShouldResumeFirst())
-        return m_now - elapsedInPeriod() + m_scheduler-&gt;m_period * targetMutatorUtilization();
-    return m_now - elapsedInPeriod() + m_scheduler-&gt;m_period;
-}
-
-SpaceTimeScheduler::SpaceTimeScheduler(Heap&amp; heap)
-    : m_heap(heap)
-    , m_period(Seconds::fromMilliseconds(Options::concurrentGCPeriodMS()))
-    , m_bytesAllocatedThisCycleAtTheBeginning(heap.m_bytesAllocatedThisCycle)
-    , m_bytesAllocatedThisCycleAtTheEnd(
-        Options::concurrentGCMaxHeadroom() *
-        std::max&lt;double&gt;(m_bytesAllocatedThisCycleAtTheBeginning, heap.m_maxEdenSize))
-{
-    snapPhase();
-}
-
-void SpaceTimeScheduler::snapPhase()
-{
-    m_initialTime = MonotonicTime::now();
-}
-
-SpaceTimeScheduler::Decision SpaceTimeScheduler::currentDecision()
-{
-    Decision result;
-    result.m_scheduler = this;
-    result.m_bytesAllocatedThisCycle = m_heap.m_bytesAllocatedThisCycle;
-    result.m_now = MonotonicTime::now();
-    return result;
-}
-
-} // namespace JSC
-
</del></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapSpaceTimeSchedulerh"></a>
<div class="delfile"><h4>Deleted: branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.h (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.h        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -1,78 +0,0 @@
</span><del>-/*
- * 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 &lt;wtf/MonotonicTime.h&gt;
-#include &lt;wtf/Seconds.h&gt;
-
-namespace JSC {
-
-class Heap;
-
-class SpaceTimeScheduler {
-public:
-    class Decision {
-    public:
-        explicit operator bool() const { return !!m_scheduler; }
-        
-        double targetMutatorUtilization() const;
-        double targetCollectorUtilization() const;
-        Seconds elapsedInPeriod() const;
-        double phase() const;
-        bool shouldBeResumed() const;
-        MonotonicTime timeToResume() const;
-        MonotonicTime timeToStop() const;
-        
-    private:
-        friend class SpaceTimeScheduler;
-
-        SpaceTimeScheduler* m_scheduler { nullptr };
-        double m_bytesAllocatedThisCycle { 0 };
-        MonotonicTime m_now;
-    };
-    
-    // Construct the scheduler at the start of a GC cycle.
-    SpaceTimeScheduler(Heap&amp;);
-    
-    // Forces the next phase to start now.
-    void snapPhase();
-    
-    // Returns a snapshot of the current scheduling decision, which will be valid so long as
-    // SpaceTimeScheduler is live and you haven't called snapPhase().
-    Decision currentDecision();
-    
-private:
-    friend class Decision;
-
-    Heap&amp; m_heap;
-    Seconds m_period;
-    double m_bytesAllocatedThisCycleAtTheBeginning;
-    double m_bytesAllocatedThisCycleAtTheEnd;
-    MonotonicTime m_initialTime;
-};
-
-} // namespace JSC
-
</del></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapSynchronousStopTheWorldMutatorSchedulercpp"></a>
<div class="addfile"><h4>Added: branches/safari-603-branch/Source/JavaScriptCore/heap/SynchronousStopTheWorldMutatorScheduler.cpp (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/SynchronousStopTheWorldMutatorScheduler.cpp                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/SynchronousStopTheWorldMutatorScheduler.cpp        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,67 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;SynchronousStopTheWorldMutatorScheduler.h&quot;
+
+namespace JSC {
+
+SynchronousStopTheWorldMutatorScheduler::SynchronousStopTheWorldMutatorScheduler()
+{
+}
+
+SynchronousStopTheWorldMutatorScheduler::~SynchronousStopTheWorldMutatorScheduler()
+{
+}
+
+MutatorScheduler::State SynchronousStopTheWorldMutatorScheduler::state() const
+{
+    return m_state;
+}
+
+void SynchronousStopTheWorldMutatorScheduler::beginCollection()
+{
+    RELEASE_ASSERT(m_state == Normal);
+    m_state = Stopped;
+}
+
+MonotonicTime SynchronousStopTheWorldMutatorScheduler::timeToStop()
+{
+    return m_state == Normal ? MonotonicTime::infinity() : MonotonicTime::now();
+}
+
+MonotonicTime SynchronousStopTheWorldMutatorScheduler::timeToResume()
+{
+    return m_state == Normal ? MonotonicTime::now() : MonotonicTime::infinity();
+}
+
+void SynchronousStopTheWorldMutatorScheduler::endCollection()
+{
+    RELEASE_ASSERT(m_state == Stopped);
+    m_state = Normal;
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapSynchronousStopTheWorldMutatorSchedulerhfromrev210652branchessafari603branchSourceJavaScriptCoreheapSpaceTimeSchedulerh"></a>
<div class="copfile"><h4>Copied: branches/safari-603-branch/Source/JavaScriptCore/heap/SynchronousStopTheWorldMutatorScheduler.h (from rev 210652, branches/safari-603-branch/Source/JavaScriptCore/heap/SpaceTimeScheduler.h) (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/SynchronousStopTheWorldMutatorScheduler.h                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/SynchronousStopTheWorldMutatorScheduler.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;MutatorScheduler.h&quot;
+
+namespace JSC {
+
+// The JSC concurrent GC relies on stopping the world to stay ahead of the retreating wavefront.
+// It so happens that the same API can be reused to implement a non-concurrent GC mode, which we
+// use on platforms that don't support the GC's atomicity protocols. That means anything other
+// than X86-64 and ARM64. This scheduler is a drop-in replacement for the concurrent GC's
+// SpaceTimeMutatorScheduler. It tells the GC to never resume the world once the GC cycle begins.
+
+class SynchronousStopTheWorldMutatorScheduler : public MutatorScheduler {
+public:
+    SynchronousStopTheWorldMutatorScheduler();
+    ~SynchronousStopTheWorldMutatorScheduler();
+    
+    State state() const override;
+    
+    void beginCollection() override;
+    
+    MonotonicTime timeToStop() override;
+    MonotonicTime timeToResume() override;
+    
+    void endCollection() override;
+
+private:
+    State m_state { Normal };
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreheapVisitingTimeouthfromrev210652branchessafari603branchSourceJavaScriptCoreheapOpaqueRootSeth"></a>
<div class="copfile"><h4>Copied: branches/safari-603-branch/Source/JavaScriptCore/heap/VisitingTimeout.h (from rev 210652, branches/safari-603-branch/Source/JavaScriptCore/heap/OpaqueRootSet.h) (0 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/heap/VisitingTimeout.h                                (rev 0)
+++ branches/safari-603-branch/Source/JavaScriptCore/heap/VisitingTimeout.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -0,0 +1,68 @@
</span><ins>+/*
+ * Copyright (C) 2017 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;SlotVisitor.h&quot;
+#include &lt;wtf/MonotonicTime.h&gt;
+
+namespace JSC {
+
+class VisitingTimeout {
+public:
+    VisitingTimeout()
+    {
+    }
+    
+    VisitingTimeout(SlotVisitor&amp; visitor, bool didVisitSomething, MonotonicTime timeout)
+        : m_didVisitSomething(didVisitSomething)
+        , m_visitCountBefore(visitor.visitCount())
+        , m_timeout(timeout)
+    {
+    }
+    
+    size_t visitCount(SlotVisitor&amp; visitor) const
+    {
+        return visitor.visitCount() - m_visitCountBefore;
+    }
+
+    bool didVisitSomething(SlotVisitor&amp; visitor) const
+    {
+        return m_didVisitSomething || visitCount(visitor);
+    }
+    
+    bool shouldTimeOut(SlotVisitor&amp; visitor) const
+    {
+        return didVisitSomething(visitor) &amp;&amp; hasElapsed(m_timeout);
+    }
+    
+private:
+    bool m_didVisitSomething { false };
+    size_t m_visitCountBefore { 0 };
+    MonotonicTime m_timeout;
+};
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="branchessafari603branchSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: branches/safari-603-branch/Source/JavaScriptCore/runtime/Options.h (210652 => 210653)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-603-branch/Source/JavaScriptCore/runtime/Options.h        2017-01-12 16:45:39 UTC (rev 210652)
+++ branches/safari-603-branch/Source/JavaScriptCore/runtime/Options.h        2017-01-12 16:45:48 UTC (rev 210653)
</span><span class="lines">@@ -202,8 +202,6 @@
</span><span class="cx">     v(double, maximumMutatorUtilization, 0.7, Normal, nullptr) \
</span><span class="cx">     v(double, concurrentGCMaxHeadroom, 1.5, Normal, nullptr) \
</span><span class="cx">     v(double, concurrentGCPeriodMS, 2, Normal, nullptr) \
</span><del>-    v(bool, collectorShouldResumeFirst, false, Normal, nullptr) \
-    v(double, collectorPermittedIdleRatio, 0, Normal, nullptr) \
</del><span class="cx">     v(bool, scribbleFreeCells, false, Normal, nullptr) \
</span><span class="cx">     v(double, sizeClassProgression, 1.4, Normal, nullptr) \
</span><span class="cx">     v(unsigned, largeAllocationCutoff, 100000, Normal, nullptr) \
</span></span></pre>
</div>
</div>

</body>
</html>