<!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 <matthew_hanson@apple.com>
</span><span class="cx">
</span><ins>+ Merge r210521. rdar://problem/29909896
+
+ 2017-01-08 Filip Pizlo <fpizlo@apple.com>
+
+ 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 <matthew_hanson@apple.com>
+
</ins><span class="cx"> Merge r210457. rdar://problem/27330808
</span><span class="cx">
</span><span class="cx"> 2017-01-06 Michael Saboff <msaboff@apple.com>
</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 = "<group>"; };
</span><span class="cx">                 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSlowPathGenerator.h; path = dfg/DFGSlowPathGenerator.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F1E3A65153A21DF000F9456 /* DFGSilentRegisterSavePlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSilentRegisterSavePlan.h; path = dfg/DFGSilentRegisterSavePlan.h; sourceTree = "<group>"; };
</span><ins>+                0F1FB38A1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SynchronousStopTheWorldMutatorScheduler.cpp; sourceTree = "<group>"; };
+                0F1FB38B1E173A6200A9BE50 /* SynchronousStopTheWorldMutatorScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SynchronousStopTheWorldMutatorScheduler.h; sourceTree = "<group>"; };
+                0F1FB38C1E173A6200A9BE50 /* MutatorScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MutatorScheduler.cpp; sourceTree = "<group>"; };
+                0F1FB3921E177A6F00A9BE50 /* VisitingTimeout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VisitingTimeout.h; sourceTree = "<group>"; };
+                0F1FB3941E1AF7DF00A9BE50 /* DFGPlanInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPlanInlines.h; path = dfg/DFGPlanInlines.h; sourceTree = "<group>"; };
+                0F1FB3951E1AF7DF00A9BE50 /* DFGWorklistInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGWorklistInlines.h; path = dfg/DFGWorklistInlines.h; sourceTree = "<group>"; };
+                0F1FB3981E1F65F900A9BE50 /* MutatorScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MutatorScheduler.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0F1FE51B1922A3BC006987C5 /* AbortReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbortReason.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F20177D1DCADC3000EA5950 /* DFGFlowIndexing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGFlowIndexing.cpp; path = dfg/DFGFlowIndexing.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F20177E1DCADC3000EA5950 /* DFGFlowIndexing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFlowIndexing.h; path = dfg/DFGFlowIndexing.h; sourceTree = "<group>"; };
</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 = "<group>"; };
</span><span class="cx">                 0F64B2781A7957B2006E4E66 /* CallEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallEdge.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F64EAF21C4ECD0600621E9B /* AirArgInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AirArgInlines.h; path = b3/air/AirArgInlines.h; sourceTree = "<group>"; };
</span><ins>+                0F660E331E0517B70031462C /* MarkingConstraint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkingConstraint.cpp; sourceTree = "<group>"; };
+                0F660E341E0517B70031462C /* MarkingConstraint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkingConstraint.h; sourceTree = "<group>"; };
+                0F660E351E0517B70031462C /* MarkingConstraintSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkingConstraintSet.cpp; sourceTree = "<group>"; };
+                0F660E361E0517B80031462C /* MarkingConstraintSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkingConstraintSet.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0F664CE71DA304ED00B00A11 /* CodeBlockSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockSetInlines.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F666EBE183566F900D017F1 /* BytecodeLivenessAnalysisInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeLivenessAnalysisInlines.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F666EBF183566F900D017F1 /* FullBytecodeLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FullBytecodeLiveness.h; sourceTree = "<group>"; };
</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 = "<group>"; };
</span><span class="cx">                 0FDDBFB31666EED500C55FEF /* DFGVariableAccessDataDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessDataDump.h; path = dfg/DFGVariableAccessDataDump.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FDE87F81DFD0C6D0064C390 /* CellContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CellContainer.cpp; sourceTree = "<group>"; };
</span><del>-                0FDE87FA1DFE6E500064C390 /* SpaceTimeScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpaceTimeScheduler.cpp; sourceTree = "<group>"; };
-                0FDE87FB1DFE6E500064C390 /* SpaceTimeScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpaceTimeScheduler.h; sourceTree = "<group>"; };
</del><ins>+                0FDE87FA1DFE6E500064C390 /* SpaceTimeMutatorScheduler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpaceTimeMutatorScheduler.cpp; sourceTree = "<group>"; };
+                0FDE87FB1DFE6E500064C390 /* SpaceTimeMutatorScheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpaceTimeMutatorScheduler.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0FDF67D01D9C6086001B9825 /* B3Kind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3Kind.cpp; path = b3/B3Kind.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0FDF67D11D9C6086001B9825 /* B3Kind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3Kind.h; path = b3/B3Kind.h; sourceTree = "<group>"; };
</span><span class="cx">                 0FDF67D41D9DC43E001B9825 /* AirKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AirKind.cpp; path = b3/air/AirKind.cpp; sourceTree = "<group>"; };
</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 = "<group>";
</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->alternative(), mode);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Plan::markCodeBlocks(SlotVisitor& 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->alternative());
- if (profiledDFGCodeBlock)
- slotVisitor.appendUnbarriered(profiledDFGCodeBlock);
-}
-
-void Plan::rememberCodeBlocks(VM& 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->alternative());
- if (profiledDFGCodeBlock)
- vm.heap.writeBarrier(profiledDFGCodeBlock);
-}
-
</del><span class="cx"> void Plan::checkLivenessAndVisitChildren(SlotVisitor& 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&);
</span><del>- void rememberCodeBlocks(VM&);
</del><ins>+ template<typename Func>
+ void iterateCodeBlocksForGC(const Func&);
</ins><span class="cx"> void checkLivenessAndVisitChildren(SlotVisitor&);
</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 "DFGPlan.h"
+
+namespace JSC { namespace DFG {
+
+template<typename Func>
+void Plan::iterateCodeBlocksForGC(const Func& 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->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& vm, SlotVisitor& slotVisitor)
-{
- LockHolder locker(*m_lock);
- for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
- Plan* plan = iter->value.get();
- if (plan->vm != &vm)
- continue;
- plan->markCodeBlocks(slotVisitor);
- }
-}
-
-void Worklist::rememberCodeBlocks(VM& vm)
-{
- LockHolder locker(*m_lock);
- for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
- Plan* plan = iter->value.get();
- if (plan->vm != &vm)
- continue;
- plan->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& vm, SlotVisitor& slotVisitor)
-{
- for (unsigned i = DFG::numberOfWorklists(); i--;) {
- if (DFG::Worklist* worklist = DFG::existingWorklistForIndexOrNull(i))
- worklist->markCodeBlocks(vm, slotVisitor);
- }
-}
-
-void rememberCodeBlocks(VM& vm)
-{
- for (unsigned i = DFG::numberOfWorklists(); i--;) {
- if (DFG::Worklist* worklist = DFG::existingWorklistForIndexOrNull(i))
- worklist->rememberCodeBlocks(vm);
- }
-}
-
</del><span class="cx"> #else // ENABLE(DFG_JIT)
</span><span class="cx">
</span><span class="cx"> void completeAllPlansForVM(VM&)
</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&)
-{
-}
-
</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->completeAllReadyPlansForVM(vm);
</span><span class="cx"> void completeAllPlansForVM(VM&);
</span><span class="cx">
</span><del>- void markCodeBlocks(VM&, SlotVisitor&);
- void rememberCodeBlocks(VM&);
</del><ins>+ template<typename Func>
+ void iterateCodeBlocksForGC(VM&, const Func&);
</ins><span class="cx">
</span><span class="cx"> void waitUntilAllPlansForVMAreReady(VM&);
</span><span class="cx"> State completeAllReadyPlansForVM(VM&, CompilationKey = CompilationKey());
</span><span class="lines">@@ -168,7 +168,9 @@
</span><span class="cx">
</span><span class="cx"> void completeAllPlansForVM(VM&);
</span><span class="cx"> void markCodeBlocks(VM&, SlotVisitor&);
</span><del>-void rememberCodeBlocks(VM&);
</del><span class="cx">
</span><ins>+template<typename Func>
+void iterateCodeBlocksForGC(VM&, const Func&);
+
</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 "DFGPlanInlines.h"
+#include "DFGWorklist.h"
+
+namespace JSC { namespace DFG {
+
+#if ENABLE(DFG_JIT)
+
+template<typename Func>
+void iterateCodeBlocksForGC(VM& vm, const Func& func)
+{
+ for (unsigned i = DFG::numberOfWorklists(); i--;) {
+ if (DFG::Worklist* worklist = DFG::existingWorklistForIndexOrNull(i))
+ worklist->iterateCodeBlocksForGC(vm, func);
+ }
+}
+
+template<typename Func>
+void Worklist::iterateCodeBlocksForGC(VM& vm, const Func& func)
+{
+ LockHolder locker(*m_lock);
+ for (PlanMap::iterator iter = m_plans.begin(); iter != m_plans.end(); ++iter) {
+ Plan* plan = iter->value.get();
+ if (plan->vm != &vm)
+ continue;
+ plan->iterateCodeBlocksForGC(func);
+ }
+}
+
+#else // ENABLE(DFG_JIT)
+
+template<typename Func>
+void iterateCodeBlocksForGC(VM&, const Func&)
+{
+}
+
+#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(&m_lock);
- if (verbose)
- dataLog("Remembering ", m_currentlyExecuting.size(), " code blocks.\n");
- for (CodeBlock* codeBlock : m_currentlyExecuting)
- heap->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&, 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<typename Functor> void iterate(const Functor& functor)
- {
- LockHolder locker(m_lock);
- for (auto& codeBlock : m_oldCodeBlocks) {
- bool done = functor(codeBlock);
- if (done)
- return;
- }
-
- for (auto& codeBlock : m_newCodeBlocks) {
- bool done = functor(codeBlock);
- if (done)
- return;
- }
- }
</del><ins>+ template<typename Functor> void iterate(const Functor&);
</ins><span class="cx">
</span><ins>+ template<typename Functor> void iterateCurrentlyExecuting(const Functor&);
+
</ins><span class="cx"> void dump(PrintStream&) 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<typename Functor>
+void CodeBlockSet::iterate(const Functor& functor)
+{
+ LockHolder locker(m_lock);
+ for (auto& codeBlock : m_oldCodeBlocks) {
+ bool done = functor(codeBlock);
+ if (done)
+ return;
+ }
+
+ for (auto& codeBlock : m_newCodeBlocks) {
+ bool done = functor(codeBlock);
+ if (done)
+ return;
+ }
+}
+
+template<typename Functor>
+void CodeBlockSet::iterateCurrentlyExecuting(const Functor& functor)
+{
+ LockHolder locker(&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 "Heap.h"
</span><span class="cx">
</span><span class="cx"> #include "CodeBlock.h"
</span><del>-#include "CodeBlockSet.h"
</del><ins>+#include "CodeBlockSetInlines.h"
</ins><span class="cx"> #include "ConservativeRoots.h"
</span><del>-#include "DFGWorklist.h"
</del><ins>+#include "DFGWorklistInlines.h"
</ins><span class="cx"> #include "EdenGCActivityCallback.h"
</span><span class="cx"> #include "Exception.h"
</span><span class="cx"> #include "FullGCActivityCallback.h"
</span><span class="lines">@@ -49,12 +49,14 @@
</span><span class="cx"> #include "JSLock.h"
</span><span class="cx"> #include "JSVirtualMachineInternal.h"
</span><span class="cx"> #include "MarkedSpaceInlines.h"
</span><ins>+#include "MarkingConstraintSet.h"
</ins><span class="cx"> #include "PreventCollectionScope.h"
</span><span class="cx"> #include "SamplingProfiler.h"
</span><span class="cx"> #include "ShadowChicken.h"
</span><del>-#include "SpaceTimeScheduler.h"
</del><ins>+#include "SpaceTimeMutatorScheduler.h"
</ins><span class="cx"> #include "SuperSampler.h"
</span><span class="cx"> #include "StopIfNecessaryTimer.h"
</span><ins>+#include "SynchronousStopTheWorldMutatorScheduler.h"
</ins><span class="cx"> #include "TypeProfilerLog.h"
</span><span class="cx"> #include "UnlinkedCodeBlock.h"
</span><span class="cx"> #include "VM.h"
</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& heap)
- : m_heap(heap)
- {
- if (!Options::useConcurrentGC())
- return;
-
- if (Options::logGC()) {
- double thisPauseMS = (MonotonicTime::now() - m_heap.m_stopTime).milliseconds();
- dataLog("p=", thisPauseMS, " ms (max ", maxPauseMS(thisPauseMS), ")...]\n");
- }
-
- m_heap.resumeTheWorld();
- }
-
- ~ResumeTheWorldScope()
- {
- if (!Options::useConcurrentGC())
- return;
-
- m_heap.stopTheWorld();
-
- if (Options::logGC())
- dataLog("[GC: ");
- }
-
-private:
- Heap& 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<MarkStackArray>())
</span><span class="cx"> , m_sharedMutatorMarkStack(std::make_unique<MarkStackArray>())
</span><span class="cx"> , m_helperClient(&heapHelperPool())
</span><ins>+ , m_scheduler(std::make_unique<SpaceTimeMutatorScheduler>(*this))
</ins><span class="cx"> , m_threadLock(Box<Lock>::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<SpaceTimeMutatorScheduler>(*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<SynchronousStopTheWorldMutatorScheduler>();
+ }
+
</ins><span class="cx"> if (Options::verifyHeap())
</span><span class="cx"> m_verifier = std::make_unique<HeapVerifier>(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->next())
- current->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<typename Func>
+void Heap::iterateExecutingAndCompilingCodeBlocks(const Func& func)
+{
+ m_codeBlocks->iterateCurrentlyExecuting(func);
+ DFG::iterateCodeBlocksForGC(*m_vm, func);
+}
+
+template<typename Func>
+void Heap::iterateExecutingAndCompilingCodeBlocksWithoutHoldingLocks(const Func& func)
+{
+ Vector<CodeBlock*, 256> codeBlocks;
+ iterateExecutingAndCompilingCodeBlocks(
+ [&] (CodeBlock* codeBlock) {
+ codeBlocks.append(codeBlock);
+ });
+ for (CodeBlock* codeBlock : codeBlocks)
+ func(codeBlock);
+}
+
+void Heap::assertSharedMarkStacksEmpty()
+{
+ bool ok = true;
+
+ if (!m_sharedCollectorMarkStack->isEmpty()) {
+ dataLog("FATAL: Shared collector mark stack not empty! It has ", m_sharedCollectorMarkStack->size(), " elements.\n");
+ ok = false;
+ }
+
+ if (!m_sharedMutatorMarkStack->isEmpty()) {
+ dataLog("FATAL: Shared mutator mark stack not empty! It has ", m_sharedMutatorMarkStack->size(), " elements.\n");
+ 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, "Heap::markToFixpoint");
</span><span class="lines">@@ -560,133 +566,84 @@
</span><span class="cx"> SlotVisitor& slotVisitor = *m_collectorSlotVisitor;
</span><span class="cx"> slotVisitor.didStartMarking();
</span><span class="cx">
</span><del>- SpaceTimeScheduler scheduler(*this);
</del><ins>+ m_constraintSet->resetStats();
</ins><span class="cx">
</span><ins>+ m_scheduler->beginCollection();
+ if (Options::logGC())
+ m_scheduler->log();
+
+ // Wondering what m_constraintSet->executeXYZ does? It's running the constraints created by
+ // Heap::buildConstraintSet().
+
+ m_constraintSet->executeBootstrap(slotVisitor, MonotonicTime::infinity());
+ m_scheduler->didExecuteConstraints();
+
+ // After this, we will almost certainly fall through all of the "slotVisitor.isEmpty()"
+ // 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("i#", iteration, " ");
- {
- TimingScope preConvergenceTimingScope(*this, "Heap::markToFixpoint conservative scan");
- m_objectSpace.prepareForConservativeScan();
- ConservativeRoots conservativeRoots(*this);
- SuperSamplerScope superSamplerScope(false);
- gatherStackRoots(conservativeRoots);
- gatherJSStackRoots(conservativeRoots);
- gatherScratchBufferRoots(conservativeRoots);
- visitConservativeRoots(conservativeRoots);
- }
</del><ins>+ dataLog("i#", iteration, " ", slotVisitor.collectorMarkStack().size(), "+", m_mutatorMarkStack->size() + slotVisitor.mutatorMarkStack().size(), " b=", m_barriersExecuted, " ");
+
+ 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->smallStrings.needsToBeVisited(*m_collectionScope))
- m_vm->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& pair : m_protectedValues)
- slotVisitor.appendUnbarriered(pair.key);
</del><ins>+ bool executedEverything =
+ m_constraintSet->executeConvergence(slotVisitor, MonotonicTime::infinity());
+ if (executedEverything && slotVisitor.isEmpty()) {
+ assertSharedMarkStacksEmpty();
+ break;
+ }
</ins><span class="cx">
</span><del>- if (m_markListSet && m_markListSet->size())
- MarkedArgumentBuffer::markLists(slotVisitor, *m_markListSet);
-
- slotVisitor.appendUnbarriered(m_vm->exception());
- slotVisitor.appendUnbarriered(m_vm->lastException());
-
- m_handleSet.visitStrongHandles(slotVisitor);
- m_handleStack.visit(slotVisitor);
-
-#if ENABLE(SAMPLING_PROFILER)
- if (SamplingProfiler* samplingProfiler = m_vm->samplingProfiler()) {
- LockHolder locker(samplingProfiler->getLock());
- samplingProfiler->processUnverifiedStackTraces();
- samplingProfiler->visit(slotVisitor);
- if (Options::logGC() == GCLogging::Verbose)
- dataLog("Sampling Profiler data:\n", slotVisitor);
</del><ins>+ m_scheduler->didExecuteConstraints();
</ins><span class="cx"> }
</span><del>-#endif // ENABLE(SAMPLING_PROFILER)
</del><span class="cx">
</span><del>- if (m_vm->typeProfiler())
- m_vm->typeProfilerLog()->visit(slotVisitor);
-
- m_vm->shadowChicken().visitChildren(slotVisitor);
-
- m_jitStubRoutines->traceMarkedStubRoutines(slotVisitor);
-
- slotVisitor.mergeOpaqueRootsIfNecessary();
- for (auto& parallelVisitor : m_parallelSlotVisitors)
- parallelVisitor->mergeOpaqueRootsIfNecessary();
-
- m_objectSpace.visitWeakSets(slotVisitor);
- harvestWeakReferences();
- visitCompilerWorklistWeakReferences();
- DFG::markCodeBlocks(*m_vm, slotVisitor);
- bool shouldTerminate = slotVisitor.isEmpty() && m_mutatorMarkStack->isEmpty();
-
- if (Options::logGC()) {
- dataLog(slotVisitor.collectorMarkStack().size(), "+", m_mutatorMarkStack->size() + slotVisitor.mutatorMarkStack().size(), ", a=", m_bytesAllocatedThisCycle / 1024, " kb, b=", m_barriersExecuted, ", mu=", scheduler.currentDecision().targetMutatorUtilization(), " ");
</del><ins>+ {
+ ParallelModeEnabler enabler(slotVisitor);
+ slotVisitor.drainInParallel(m_scheduler->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->writeBarrierCurrentlyExecuting(this);
- DFG::rememberCodeBlocks(*m_vm);
</del><ins>+ if (!m_scheduler->shouldResume())
+ continue;
</ins><span class="cx">
</span><del>- if (shouldTerminate)
- break;
</del><ins>+ m_scheduler->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->transferTo(slotVisitor.mutatorMarkStack());
</del><ins>+ if (Options::logGC()) {
+ double thisPauseMS = (MonotonicTime::now() - m_stopTime).milliseconds();
+ dataLog("p=", thisPauseMS, " ms (max ", maxPauseMS(thisPauseMS), ")...]\n");
+ }
</ins><span class="cx">
</span><del>- if (Options::logGC() == GCLogging::Verbose)
- dataLog("Live Weak Handles:\n", slotVisitor);
</del><ins>+ resumeTheWorld();
</ins><span class="cx">
</span><span class="cx"> {
</span><del>- TimingScope traceTimingScope(*this, "Heap::markToFixpoint tracing");
</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 >= 1_ms)
- dataLog("wul!=", wakeUpLatency.milliseconds(), " ms ");
- }
- } 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->timeToStop());
</ins><span class="cx"> }
</span><ins>+
+ stopTheWorld();
+
+ if (Options::logGC())
+ dataLog("[GC: ");
+
+ m_scheduler->didStop();
+
+ if (Options::logGC())
+ m_scheduler->log();
</ins><span class="cx"> }
</span><ins>+
+ m_scheduler->endCollection();
</ins><span class="cx">
</span><span class="cx"> {
</span><span class="cx"> std::lock_guard<Lock> 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(
+ [&] (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->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& roots)
-{
- m_collectorSlotVisitor->append(roots);
-
- if (Options::logGC() == GCLogging::Verbose)
- dataLog("Conservative Roots:\n", *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("DFG Worklists:\n", *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& parallelVisitor : m_parallelSlotVisitors)
</span><span class="cx"> parallelVisitor->reset();
</span><span class="cx">
</span><del>- RELEASE_ASSERT(m_sharedCollectorMarkStack->isEmpty());
- RELEASE_ASSERT(m_sharedMutatorMarkStack->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->initializeGCCycle();
</span><span class="cx"> m_verifier->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->gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
</span><span class="cx"> m_verifier->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->writeBarrierCurrentlyExecuting(this);
</del><ins>+
+ m_codeBlocks->iterateCurrentlyExecuting(
+ [&] (CodeBlock* codeBlock) {
+ writeBarrier(codeBlock);
+ });
</ins><span class="cx"> m_codeBlocks->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"> && handleNeedFinalize(oldState))
</span><span class="cx"> return true;
</span><span class="cx">
</span><del>- if (!(oldState & shouldStopBit)) {
</del><ins>+ if (!(oldState & shouldStopBit) && !m_scheduler->shouldStop()) {
</ins><span class="cx"> if (!(oldState & stoppedBit))
</span><span class="cx"> return false;
</span><span class="cx"> m_worldState.compareExchangeStrong(oldState, oldState & ~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->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 <= Options::gcMaxHeapSize())
</span><del>- return false;
</del><ins>+ return;
</ins><span class="cx"> } else {
</span><span class="cx"> if (m_bytesAllocatedThisCycle <= 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<MarkingConstraintSet>();
+
+ m_constraintSet->add(
+ "Cs", "Conservative Scan",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+ TimingScope preConvergenceTimingScope(*this, "Constraint: conservative scan");
+ m_objectSpace.prepareForConservativeScan();
+ ConservativeRoots conservativeRoots(*this);
+ SuperSamplerScope superSamplerScope(false);
+ gatherStackRoots(conservativeRoots);
+ gatherJSStackRoots(conservativeRoots);
+ gatherScratchBufferRoots(conservativeRoots);
+ slotVisitor.append(conservativeRoots);
+ },
+ MarkingConstraint::GreyedByExecution);
+
+ m_constraintSet->add(
+ "Msr", "Misc Small Roots",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+#if JSC_OBJC_API_ENABLED
+ scanExternalRememberedSet(*m_vm, slotVisitor);
+#endif
+
+ if (m_vm->smallStrings.needsToBeVisited(*m_collectionScope))
+ m_vm->smallStrings.visitStrongReferences(slotVisitor);
+
+ for (auto& pair : m_protectedValues)
+ slotVisitor.appendUnbarriered(pair.key);
+
+ if (m_markListSet && m_markListSet->size())
+ MarkedArgumentBuffer::markLists(slotVisitor, *m_markListSet);
+
+ slotVisitor.appendUnbarriered(m_vm->exception());
+ slotVisitor.appendUnbarriered(m_vm->lastException());
+ },
+ MarkingConstraint::GreyedByExecution);
+
+ m_constraintSet->add(
+ "Sh", "Strong Handles",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+ m_handleSet.visitStrongHandles(slotVisitor);
+ m_handleStack.visit(slotVisitor);
+ },
+ MarkingConstraint::GreyedByExecution);
+
+ m_constraintSet->add(
+ "D", "Debugger",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+#if ENABLE(SAMPLING_PROFILER)
+ if (SamplingProfiler* samplingProfiler = m_vm->samplingProfiler()) {
+ LockHolder locker(samplingProfiler->getLock());
+ samplingProfiler->processUnverifiedStackTraces();
+ samplingProfiler->visit(slotVisitor);
+ if (Options::logGC() == GCLogging::Verbose)
+ dataLog("Sampling Profiler data:\n", slotVisitor);
+ }
+#endif // ENABLE(SAMPLING_PROFILER)
+
+ if (m_vm->typeProfiler())
+ m_vm->typeProfilerLog()->visit(slotVisitor);
+
+ m_vm->shadowChicken().visitChildren(slotVisitor);
+ },
+ MarkingConstraint::GreyedByExecution);
+
+ m_constraintSet->add(
+ "Jsr", "JIT Stub Routines",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+ m_jitStubRoutines->traceMarkedStubRoutines(slotVisitor);
+ },
+ MarkingConstraint::GreyedByExecution);
+
+ m_constraintSet->add(
+ "Ws", "Weak Sets",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+ slotVisitor.mergeOpaqueRootsIfNecessary();
+ for (auto& parallelVisitor : m_parallelSlotVisitors)
+ parallelVisitor->mergeOpaqueRootsIfNecessary();
+
+ m_objectSpace.visitWeakSets(slotVisitor);
+ },
+ MarkingConstraint::GreyedByMarking);
+
+ m_constraintSet->add(
+ "Wrh", "Weak Reference Harvesters",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+ for (WeakReferenceHarvester* current = m_weakReferenceHarvesters.head(); current; current = current->next())
+ current->visitWeakReferences(slotVisitor);
+ },
+ MarkingConstraint::GreyedByMarking);
+
+#if ENABLE(DFG_JIT)
+ m_constraintSet->add(
+ "Dw", "DFG Worklists",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+ 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,
+ [&] (CodeBlock* codeBlock) {
+ slotVisitor.appendUnbarriered(codeBlock);
+ });
+
+ if (Options::logGC() == GCLogging::Verbose)
+ dataLog("DFG Worklists:\n", slotVisitor);
+ },
+ MarkingConstraint::GreyedByMarking);
+#endif
+
+ m_constraintSet->add(
+ "Cb", "CodeBlocks",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+ iterateExecutingAndCompilingCodeBlocksWithoutHoldingLocks(
+ [&] (CodeBlock* codeBlock) {
+ // Visit the CodeBlock as a constraint only if it's black.
+ if (Heap::isMarked(codeBlock)
+ && codeBlock->cellState() == CellState::PossiblyOldOrBlack)
+ slotVisitor.visitAsConstraint(codeBlock);
+ });
+ },
+ MarkingConstraint::GreyedByExecution);
+
+ m_constraintSet->add(
+ "Mms", "Mutator Mark Stack",
+ [this] (SlotVisitor& slotVisitor, const VisitingTimeout&) {
+ // Indicate to the fixpoint that we introduced work!
+ size_t size = m_mutatorMarkStack->size();
+ slotVisitor.addToVisitCount(size);
+
+ if (Options::logGC())
+ dataLog("(", size, ")");
+
+ m_mutatorMarkStack->transferTo(slotVisitor.mutatorMarkStack());
+ },
+ [this] (SlotVisitor&) -> double {
+ return m_mutatorMarkStack->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<CollectionScope> = 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&);
</span><span class="cx"> void gatherScratchBufferRoots(ConservativeRoots&);
</span><span class="cx"> void beginMarking();
</span><del>- void visitConservativeRoots(ConservativeRoots&);
</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<typename Func>
+ void iterateExecutingAndCompilingCodeBlocks(const Func&);
+
+ template<typename Func>
+ void iterateExecutingAndCompilingCodeBlocksWithoutHoldingLocks(const Func&);
+
+ 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<SlotVisitor> m_collectorSlotVisitor;
</span><span class="cx"> std::unique_ptr<MarkStackArray> m_mutatorMarkStack;
</span><ins>+
+ std::unique_ptr<MarkingConstraintSet> 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<MutatorScheduler> m_scheduler;
+
</ins><span class="cx"> static const unsigned shouldStopBit = 1u << 0u;
</span><span class="cx"> static const unsigned stoppedBit = 1u << 1u;
</span><span class="cx"> static const unsigned hasAccessBit = 1u << 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<Lock> m_threadLock;
</span><span class="cx"> RefPtr<AutomaticThreadCondition> m_threadCondition; // The mutator must not wait on this. It would cause a deadlock.
</span><span class="cx"> RefPtr<AutomaticThread> 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 "config.h"
+#include "MarkingConstraint.h"
+
+#include "JSCInlines.h"
+
+namespace JSC {
+
+MarkingConstraint::MarkingConstraint(
+ CString abbreviatedName, CString name,
+ ::Function<void(SlotVisitor&, const VisitingTimeout&)> executeFunction,
+ Volatility volatility)
+ : m_abbreviatedName(abbreviatedName)
+ , m_name(WTFMove(name))
+ , m_executeFunction(WTFMove(executeFunction))
+ , m_volatility(volatility)
+{
+}
+
+MarkingConstraint::MarkingConstraint(
+ CString abbreviatedName, CString name,
+ ::Function<void(SlotVisitor&, const VisitingTimeout&)> executeFunction,
+ ::Function<double(SlotVisitor&)> 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& visitor, bool& 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 "VisitingTimeout.h"
+#include <wtf/FastMalloc.h>
+#include <wtf/Function.h>
+#include <wtf/MonotonicTime.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/text/CString.h>
+
+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 "root" 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<void(SlotVisitor&, const VisitingTimeout&)>,
+ Volatility);
+
+ MarkingConstraint(
+ CString abbreviatedName, CString name,
+ ::Function<void(SlotVisitor&, const VisitingTimeout&)>,
+ ::Function<double(SlotVisitor&)>,
+ 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&, bool& didVisitSomething, MonotonicTime timeout);
+
+ double quickWorkEstimate(SlotVisitor& visitor)
+ {
+ if (!m_quickWorkEstimateFunction)
+ return 0;
+ return m_quickWorkEstimateFunction(visitor);
+ }
+
+ double workEstimate(SlotVisitor& 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<void(SlotVisitor&, const VisitingTimeout& timeout)> m_executeFunction;
+ ::Function<double(SlotVisitor&)> 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 "config.h"
+#include "MarkingConstraintSet.h"
+
+#include "Options.h"
+#include <wtf/TimeWithDynamicClockType.h>
+
+namespace JSC {
+
+class MarkingConstraintSet::ExecutionContext {
+public:
+ ExecutionContext(MarkingConstraintSet& set, SlotVisitor& visitor, MonotonicTime timeout)
+ : m_set(set)
+ , m_visitor(visitor)
+ , m_timeout(timeout)
+ {
+ }
+
+ bool didVisitSomething() const
+ {
+ return m_didVisitSomething;
+ }
+
+ bool shouldTimeOut() const
+ {
+ return didVisitSomething() && hasElapsed(m_timeout);
+ }
+
+ // Returns false if it times out.
+ bool drain(BitVector& 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]->execute(m_visitor, m_didVisitSomething, m_timeout);
+ m_executed.set(index);
+ }
+
+private:
+ MarkingConstraintSet& m_set;
+ SlotVisitor& 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& constraint : m_set) {
+ constraint->resetStats();
+ switch (constraint->volatility()) {
+ case MarkingConstraint::GreyedByExecution:
+ m_unexecutedRoots.set(constraint->index());
+ break;
+ case MarkingConstraint::GreyedByMarking:
+ m_unexecutedOutgrowths.set(constraint->index());
+ break;
+ }
+ }
+}
+
+void MarkingConstraintSet::add(CString abbreviatedName, CString name, Function<void(SlotVisitor&, const VisitingTimeout&)> function, MarkingConstraint::Volatility volatility)
+{
+ add(std::make_unique<MarkingConstraint>(WTFMove(abbreviatedName), WTFMove(name), WTFMove(function), volatility));
+}
+
+void MarkingConstraintSet::add(
+ CString abbreviatedName, CString name,
+ Function<void(SlotVisitor&, const VisitingTimeout&)> executeFunction,
+ Function<double(SlotVisitor&)> quickWorkEstimateFunction,
+ MarkingConstraint::Volatility volatility)
+{
+ add(std::make_unique<MarkingConstraint>(WTFMove(abbreviatedName), WTFMove(name), WTFMove(executeFunction), WTFMove(quickWorkEstimateFunction), volatility));
+}
+
+void MarkingConstraintSet::add(
+ std::unique_ptr<MarkingConstraint> constraint)
+{
+ constraint->m_index = m_set.size();
+ m_ordered.append(constraint.get());
+ if (constraint->volatility() == MarkingConstraint::GreyedByMarking)
+ m_outgrowths.append(constraint.get());
+ m_set.append(WTFMove(constraint));
+}
+
+bool MarkingConstraintSet::executeBootstrap(SlotVisitor& 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("boot:");
+ bool result = executionContext.drain(m_unexecutedRoots);
+ if (Options::logGC())
+ dataLog(" ");
+ return result;
+}
+
+bool MarkingConstraintSet::executeConvergence(SlotVisitor& visitor, MonotonicTime timeout)
+{
+ bool result = executeConvergenceImpl(visitor, timeout);
+ if (Options::logGC())
+ dataLog(" ");
+ return result;
+}
+
+bool MarkingConstraintSet::isWavefrontAdvancing(SlotVisitor& visitor)
+{
+ for (MarkingConstraint* outgrowth : m_outgrowths) {
+ if (outgrowth->workEstimate(visitor))
+ return true;
+ }
+ return false;
+}
+
+bool MarkingConstraintSet::executeConvergenceImpl(SlotVisitor& visitor, MonotonicTime timeout)
+{
+ ExecutionContext executionContext(*this, visitor, timeout);
+
+ if (Options::logGC())
+ dataLog("converge:");
+
+ // 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->isWavefrontAdvancing(visitor);
+
+ std::sort(
+ m_ordered.begin(), m_ordered.end(),
+ [&] (MarkingConstraint* a, MarkingConstraint* b) -> bool {
+ // Remember: return true if a should come before b.
+ if (a->volatility() != b->volatility()) {
+ if (isWavefrontAdvancing)
+ return a->volatility() > b->volatility(); // GreyedByMarking should come before GreyedByExecution.
+ else
+ return a->volatility() < b->volatility(); // GreyedByExecution should come before GreyedByMarking.
+ }
+
+ return a->workEstimate(visitor) > b->workEstimate(visitor);
+ });
+
+ for (MarkingConstraint* constraint : m_ordered) {
+ size_t i = constraint->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& visitor)
+{
+ bool didVisitSomething = false;
+ for (auto& constraint : m_set)
+ constraint->execute(visitor, didVisitSomething, MonotonicTime::infinity());
+ if (Options::logGC())
+ dataLog(" ");
+}
+
+} // 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 "MarkingConstraint.h"
+#include <wtf/BitVector.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class MarkingConstraintSet {
+public:
+ MarkingConstraintSet();
+ ~MarkingConstraintSet();
+
+ void resetStats();
+
+ void add(
+ CString abbreviatedName,
+ CString name,
+ ::Function<void(SlotVisitor&, const VisitingTimeout&)>,
+ MarkingConstraint::Volatility);
+
+ void add(
+ CString abbreviatedName,
+ CString name,
+ ::Function<void(SlotVisitor&, const VisitingTimeout&)>,
+ ::Function<double(SlotVisitor&)>,
+ MarkingConstraint::Volatility);
+
+ void add(std::unique_ptr<MarkingConstraint>);
+
+ // 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&);
+ bool isWavefrontRetreating(SlotVisitor& 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&, 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&,
+ MonotonicTime timeout = MonotonicTime::infinity());
+
+ // Simply runs all constraints without any shenanigans.
+ void executeAll(SlotVisitor&);
+
+private:
+ class ExecutionContext;
+ friend class ExecutionContext;
+
+ bool executeConvergenceImpl(SlotVisitor&, MonotonicTime timeout);
+
+ bool drain(SlotVisitor&, MonotonicTime, BitVector& unexecuted, BitVector& executed, bool& didVisitSomething);
+
+ BitVector m_unexecutedRoots;
+ BitVector m_unexecutedOutgrowths;
+ Vector<std::unique_ptr<MarkingConstraint>> m_set;
+ Vector<MarkingConstraint*> m_ordered;
+ Vector<MarkingConstraint*> 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 "config.h"
+#include "MutatorScheduler.h"
+
+#include <wtf/TimeWithDynamicClockType.h>
+
+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 <wtf/FastMalloc.h>
+#include <wtf/MonotonicTime.h>
+#include <wtf/Noncopyable.h>
+
+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& 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()) && !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() && 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() && didReachTermination(locker);
+}
+
+bool SlotVisitor::didReachTermination(const LockHolder&)
+{
</ins><span class="cx"> return !m_heap.m_numberOfActiveParallelMarkers
</span><span class="cx"> && m_heap.m_sharedCollectorMarkStack->isEmpty()
</span><span class="cx"> && m_heap.m_sharedMutatorMarkStack->isEmpty();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-bool SlotVisitor::hasWork()
</del><ins>+bool SlotVisitor::hasWork(const LockHolder&)
</ins><span class="cx"> {
</span><span class="cx"> return !m_heap.m_sharedCollectorMarkStack->isEmpty()
</span><span class="cx"> || !m_heap.m_sharedMutatorMarkStack->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>+ [&] {
+ 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&);
</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& from, MarkStackArray& to);
</span><span class="cx">
</span><del>- bool hasWork();
- bool didReachTermination();
</del><ins>+ bool hasWork(const LockHolder&);
+ bool didReachTermination(const LockHolder&);
</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 "config.h"
+#include "SpaceTimeMutatorScheduler.h"
+
+#include "JSCInlines.h"
+
+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& 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& 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<double>(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(
+ "a=", format("%.0lf", bytesSinceBeginningOfCycle(snapshot) / 1024), " kb ",
+ "hf=", format("%.3lf", headroomFullness(snapshot)), " ",
+ "mu=", format("%.3lf", mutatorUtilization(snapshot)), " ");
+}
+
+void SpaceTimeMutatorScheduler::endCollection()
+{
+ m_state = Normal;
+ m_startTime = MonotonicTime::now();
+}
+
+double SpaceTimeMutatorScheduler::bytesAllocatedThisCycleImpl()
+{
+ return m_heap.m_bytesAllocatedThisCycle;
+}
+
+double SpaceTimeMutatorScheduler::bytesSinceBeginningOfCycle(const Snapshot& snapshot)
+{
+ return snapshot.bytesAllocatedThisCycle() - m_bytesAllocatedThisCycleAtTheBeginning;
+}
+
+double SpaceTimeMutatorScheduler::maxHeadroom()
+{
+ return m_bytesAllocatedThisCycleAtTheEnd - m_bytesAllocatedThisCycleAtTheBeginning;
+}
+
+double SpaceTimeMutatorScheduler::headroomFullness(const Snapshot& 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 >= 0))
+ result = 0;
+ if (!(result <= 1))
+ result = 1;
+
+ return result;
+}
+
+double SpaceTimeMutatorScheduler::mutatorUtilization(const Snapshot& 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& snapshot)
+{
+ return 1 - mutatorUtilization(snapshot);
+}
+
+Seconds SpaceTimeMutatorScheduler::elapsedInPeriod(const Snapshot& snapshot)
+{
+ return (snapshot.now() - m_startTime) % m_period;
+}
+
+double SpaceTimeMutatorScheduler::phase(const Snapshot& snapshot)
+{
+ return elapsedInPeriod(snapshot) / m_period;
+}
+
+bool SpaceTimeMutatorScheduler::shouldBeResumed(const Snapshot& snapshot)
+{
+ return phase(snapshot) > 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 "MutatorScheduler.h"
+#include <wtf/Seconds.h>
+
+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 "space-time" 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&);
+ ~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&);
+ double maxHeadroom();
+ double headroomFullness(const Snapshot&);
+ double mutatorUtilization(const Snapshot&);
+ double collectorUtilization(const Snapshot&);
+ Seconds elapsedInPeriod(const Snapshot&);
+ double phase(const Snapshot&);
+ bool shouldBeResumed(const Snapshot&);
+
+ Heap& 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 "config.h"
-#include "SpaceTimeScheduler.h"
-
-#include "JSCInlines.h"
-
-namespace JSC {
-
-double SpaceTimeScheduler::Decision::targetMutatorUtilization() const
-{
- double bytesSinceBeginningOfCycle =
- m_bytesAllocatedThisCycle - m_scheduler->m_bytesAllocatedThisCycleAtTheBeginning;
-
- double maxHeadroom =
- m_scheduler->m_bytesAllocatedThisCycleAtTheEnd - m_scheduler->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 >= 0))
- headroomFullness = 0;
- if (!(headroomFullness <= 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->m_initialTime) % m_scheduler->m_period;
-}
-
-double SpaceTimeScheduler::Decision::phase() const
-{
- return elapsedInPeriod() / m_scheduler->m_period;
-}
-
-bool SpaceTimeScheduler::Decision::shouldBeResumed() const
-{
- if (Options::collectorShouldResumeFirst())
- return phase() <= targetMutatorUtilization();
- return phase() > targetCollectorUtilization();
-}
-
-MonotonicTime SpaceTimeScheduler::Decision::timeToResume() const
-{
- ASSERT(!shouldBeResumed());
- if (Options::collectorShouldResumeFirst())
- return m_now - elapsedInPeriod() + m_scheduler->m_period;
- return m_now - elapsedInPeriod() + m_scheduler->m_period * targetCollectorUtilization();
-}
-
-MonotonicTime SpaceTimeScheduler::Decision::timeToStop() const
-{
- ASSERT(shouldBeResumed());
- if (Options::collectorShouldResumeFirst())
- return m_now - elapsedInPeriod() + m_scheduler->m_period * targetMutatorUtilization();
- return m_now - elapsedInPeriod() + m_scheduler->m_period;
-}
-
-SpaceTimeScheduler::SpaceTimeScheduler(Heap& heap)
- : m_heap(heap)
- , m_period(Seconds::fromMilliseconds(Options::concurrentGCPeriodMS()))
- , m_bytesAllocatedThisCycleAtTheBeginning(heap.m_bytesAllocatedThisCycle)
- , m_bytesAllocatedThisCycleAtTheEnd(
- Options::concurrentGCMaxHeadroom() *
- std::max<double>(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 <wtf/MonotonicTime.h>
-#include <wtf/Seconds.h>
-
-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&);
-
- // 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& 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 "config.h"
+#include "SynchronousStopTheWorldMutatorScheduler.h"
+
+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 "MutatorScheduler.h"
+
+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 "SlotVisitor.h"
+#include <wtf/MonotonicTime.h>
+
+namespace JSC {
+
+class VisitingTimeout {
+public:
+ VisitingTimeout()
+ {
+ }
+
+ VisitingTimeout(SlotVisitor& visitor, bool didVisitSomething, MonotonicTime timeout)
+ : m_didVisitSomething(didVisitSomething)
+ , m_visitCountBefore(visitor.visitCount())
+ , m_timeout(timeout)
+ {
+ }
+
+ size_t visitCount(SlotVisitor& visitor) const
+ {
+ return visitor.visitCount() - m_visitCountBefore;
+ }
+
+ bool didVisitSomething(SlotVisitor& visitor) const
+ {
+ return m_didVisitSomething || visitCount(visitor);
+ }
+
+ bool shouldTimeOut(SlotVisitor& visitor) const
+ {
+ return didVisitSomething(visitor) && 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>