<!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>[210971] trunk/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/210971">210971</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2017-01-20 10:10:55 -0800 (Fri, 20 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>We should flash a safepoint before each DFG/FTL phase
https://bugs.webkit.org/show_bug.cgi?id=167234

Reviewed by Filip Pizlo.

The recent GC changes caused us to regress Kraken because of a
longstanding issue that happened to be hit with higher frequency because
of a change in timing between when a particular GC was happening and
when a particular FTL compilation was happening. The regression is caused
by the GC was waiting for a large function to make it through the DFG portion
of an FTL compilation. This was taking 20ms-30ms and started happened during a
particular test with much higher frequency.

This means that anytime the GC waits for this compilation, the test ran at least
~20ms slower because the GC waits for the compiler threads the mutator is stopped.

It's good that we have such an easily reproducible case of this performance
issue because it will effect many real JS programs, especially ones with
large functions that get hot.

The most straight forward solution to fix this is to flash a safepoint before
each phase, allowing the GC to suspend the compiler if needed. In my testing,
this progresses Kraken in the browser, and doesn't regress anything else. This
solution also makes the most sense. I did some analysis on the compilation time
of this function that took ~20-30ms to pass through the DFG phases, and
the phase times were mostly evenly distributed. Some took longer than others,
but no phase was longer than 3ms. Most were in the 0.25ms to 1.5ms range.

* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGSafepoint.cpp:
(JSC::DFG::Safepoint::begin):
* runtime/Options.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlancpp">trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafepointcpp">trunk/Source/JavaScriptCore/dfg/DFGSafepoint.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeOptionsh">trunk/Source/JavaScriptCore/runtime/Options.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (210970 => 210971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-01-20 18:09:30 UTC (rev 210970)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-01-20 18:10:55 UTC (rev 210971)
</span><span class="lines">@@ -1,3 +1,39 @@
</span><ins>+2017-01-20  Saam Barati  &lt;sbarati@apple.com&gt;
+
+        We should flash a safepoint before each DFG/FTL phase
+        https://bugs.webkit.org/show_bug.cgi?id=167234
+
+        Reviewed by Filip Pizlo.
+
+        The recent GC changes caused us to regress Kraken because of a
+        longstanding issue that happened to be hit with higher frequency because
+        of a change in timing between when a particular GC was happening and 
+        when a particular FTL compilation was happening. The regression is caused
+        by the GC was waiting for a large function to make it through the DFG portion
+        of an FTL compilation. This was taking 20ms-30ms and started happened during a
+        particular test with much higher frequency.
+        
+        This means that anytime the GC waits for this compilation, the test ran at least
+        ~20ms slower because the GC waits for the compiler threads the mutator is stopped.
+        
+        It's good that we have such an easily reproducible case of this performance
+        issue because it will effect many real JS programs, especially ones with
+        large functions that get hot.
+        
+        The most straight forward solution to fix this is to flash a safepoint before
+        each phase, allowing the GC to suspend the compiler if needed. In my testing,
+        this progresses Kraken in the browser, and doesn't regress anything else. This
+        solution also makes the most sense. I did some analysis on the compilation time
+        of this function that took ~20-30ms to pass through the DFG phases, and
+        the phase times were mostly evenly distributed. Some took longer than others,
+        but no phase was longer than 3ms. Most were in the 0.25ms to 1.5ms range.
+
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+        * dfg/DFGSafepoint.cpp:
+        (JSC::DFG::Safepoint::begin):
+        * runtime/Options.h:
+
</ins><span class="cx"> 2017-01-20  Skachkov Oleksandr  &lt;gskachkov@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Super property access in base class constructor doesn't work
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (210970 => 210971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2017-01-20 18:09:30 UTC (rev 210970)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2017-01-20 18:10:55 UTC (rev 210971)
</span><span class="lines">@@ -254,6 +254,22 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     codeBlock-&gt;setCalleeSaveRegisters(RegisterSet::dfgCalleeSaveRegisters());
</span><ins>+
+    bool changed = false;
+
+#define RUN_PHASE(phase)                                         \
+    do {                                                         \
+        if (Options::safepointBeforeEachPhase()) {               \
+            Safepoint::Result safepointResult;                   \
+            {                                                    \
+                GraphSafepoint safepoint(dfg, safepointResult);  \
+            }                                                    \
+            if (safepointResult.didGetCancelled())               \
+                return CancelPath;                               \
+        }                                                        \
+        changed |= phase(dfg);                                   \
+    } while (false);                                             \
+
</ins><span class="cx">     
</span><span class="cx">     // By this point the DFG bytecode parser will have potentially mutated various tables
</span><span class="cx">     // in the CodeBlock. This is a good time to perform an early shrink, which is more
</span><span class="lines">@@ -269,16 +285,16 @@
</span><span class="cx">         dfg.dump();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    performLiveCatchVariablePreservationPhase(dfg);
</del><ins>+    RUN_PHASE(performLiveCatchVariablePreservationPhase);
</ins><span class="cx"> 
</span><span class="cx">     if (Options::useMaximalFlushInsertionPhase())
</span><del>-        performMaximalFlushInsertion(dfg);
</del><ins>+        RUN_PHASE(performMaximalFlushInsertion);
</ins><span class="cx">     
</span><del>-    performCPSRethreading(dfg);
-    performUnification(dfg);
-    performPredictionInjection(dfg);
</del><ins>+    RUN_PHASE(performCPSRethreading);
+    RUN_PHASE(performUnification);
+    RUN_PHASE(performPredictionInjection);
</ins><span class="cx">     
</span><del>-    performStaticExecutionCountEstimation(dfg);
</del><ins>+    RUN_PHASE(performStaticExecutionCountEstimation);
</ins><span class="cx">     
</span><span class="cx">     if (mode == FTLForOSREntryMode) {
</span><span class="cx">         bool result = performOSREntrypointCreation(dfg);
</span><span class="lines">@@ -286,18 +302,18 @@
</span><span class="cx">             finalizer = std::make_unique&lt;FailedFinalizer&gt;(*this);
</span><span class="cx">             return FailPath;
</span><span class="cx">         }
</span><del>-        performCPSRethreading(dfg);
</del><ins>+        RUN_PHASE(performCPSRethreading);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (validationEnabled())
</span><span class="cx">         validate(dfg);
</span><span class="cx">     
</span><del>-    performBackwardsPropagation(dfg);
-    performPredictionPropagation(dfg);
-    performFixup(dfg);
-    performStructureRegistration(dfg);
-    performInvalidationPointInjection(dfg);
-    performTypeCheckHoisting(dfg);
</del><ins>+    RUN_PHASE(performBackwardsPropagation);
+    RUN_PHASE(performPredictionPropagation);
+    RUN_PHASE(performFixup);
+    RUN_PHASE(performStructureRegistration);
+    RUN_PHASE(performInvalidationPointInjection);
+    RUN_PHASE(performTypeCheckHoisting);
</ins><span class="cx">     
</span><span class="cx">     dfg.m_fixpointState = FixpointNotConverged;
</span><span class="cx">     
</span><span class="lines">@@ -309,18 +325,18 @@
</span><span class="cx">     if (validationEnabled())
</span><span class="cx">         validate(dfg);
</span><span class="cx">         
</span><del>-    performStrengthReduction(dfg);
-    performCPSRethreading(dfg);
-    performCFA(dfg);
-    performConstantFolding(dfg);
-    bool changed = false;
-    changed |= performCFGSimplification(dfg);
-    changed |= performLocalCSE(dfg);
</del><ins>+    RUN_PHASE(performStrengthReduction);
+    RUN_PHASE(performCPSRethreading);
+    RUN_PHASE(performCFA);
+    RUN_PHASE(performConstantFolding);
+    changed = false;
+    RUN_PHASE(performCFGSimplification);
+    RUN_PHASE(performLocalCSE);
</ins><span class="cx">     
</span><span class="cx">     if (validationEnabled())
</span><span class="cx">         validate(dfg);
</span><span class="cx">     
</span><del>-    performCPSRethreading(dfg);
</del><ins>+    RUN_PHASE(performCPSRethreading);
</ins><span class="cx">     if (!isFTL(mode)) {
</span><span class="cx">         // Only run this if we're not FTLing, because currently for a LoadVarargs that is forwardable and
</span><span class="cx">         // in a non-varargs inlined call frame, this will generate ForwardVarargs while the FTL
</span><span class="lines">@@ -341,11 +357,11 @@
</span><span class="cx">         // ArgumentsEliminationPhase does everything that this phase does, and it doesn't introduce this
</span><span class="cx">         // pathology.
</span><span class="cx">         
</span><del>-        changed |= performVarargsForwarding(dfg); // Do this after CFG simplification and CPS rethreading.
</del><ins>+        RUN_PHASE(performVarargsForwarding); // Do this after CFG simplification and CPS rethreading.
</ins><span class="cx">     }
</span><span class="cx">     if (changed) {
</span><del>-        performCFA(dfg);
-        performConstantFolding(dfg);
</del><ins>+        RUN_PHASE(performCFA);
+        RUN_PHASE(performConstantFolding);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // If we're doing validation, then run some analyses, to give them an opportunity
</span><span class="lines">@@ -360,17 +376,17 @@
</span><span class="cx">     case DFGMode: {
</span><span class="cx">         dfg.m_fixpointState = FixpointConverged;
</span><span class="cx">     
</span><del>-        performTierUpCheckInjection(dfg);
</del><ins>+        RUN_PHASE(performTierUpCheckInjection);
</ins><span class="cx"> 
</span><del>-        performFastStoreBarrierInsertion(dfg);
-        performStoreBarrierClustering(dfg);
-        performCleanUp(dfg);
-        performCPSRethreading(dfg);
-        performDCE(dfg);
-        performPhantomInsertion(dfg);
-        performStackLayout(dfg);
-        performVirtualRegisterAllocation(dfg);
-        performWatchpointCollection(dfg);
</del><ins>+        RUN_PHASE(performFastStoreBarrierInsertion);
+        RUN_PHASE(performStoreBarrierClustering);
+        RUN_PHASE(performCleanUp);
+        RUN_PHASE(performCPSRethreading);
+        RUN_PHASE(performDCE);
+        RUN_PHASE(performPhantomInsertion);
+        RUN_PHASE(performStackLayout);
+        RUN_PHASE(performVirtualRegisterAllocation);
+        RUN_PHASE(performWatchpointCollection);
</ins><span class="cx">         dumpAndVerifyGraph(dfg, &quot;Graph after optimization:&quot;);
</span><span class="cx">         
</span><span class="cx">         JITCompiler dataFlowJIT(dfg);
</span><span class="lines">@@ -390,37 +406,37 @@
</span><span class="cx">             return FailPath;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        performCleanUp(dfg); // Reduce the graph size a bit.
-        performCriticalEdgeBreaking(dfg);
</del><ins>+        RUN_PHASE(performCleanUp); // Reduce the graph size a bit.
+        RUN_PHASE(performCriticalEdgeBreaking);
</ins><span class="cx">         if (Options::createPreHeaders())
</span><del>-            performLoopPreHeaderCreation(dfg);
-        performCPSRethreading(dfg);
-        performSSAConversion(dfg);
-        performSSALowering(dfg);
</del><ins>+            RUN_PHASE(performLoopPreHeaderCreation);
+        RUN_PHASE(performCPSRethreading);
+        RUN_PHASE(performSSAConversion);
+        RUN_PHASE(performSSALowering);
</ins><span class="cx">         
</span><span class="cx">         // Ideally, these would be run to fixpoint with the object allocation sinking phase.
</span><del>-        performArgumentsElimination(dfg);
</del><ins>+        RUN_PHASE(performArgumentsElimination);
</ins><span class="cx">         if (Options::usePutStackSinking())
</span><del>-            performPutStackSinking(dfg);
</del><ins>+            RUN_PHASE(performPutStackSinking);
</ins><span class="cx">         
</span><del>-        performConstantHoisting(dfg);
-        performGlobalCSE(dfg);
-        performLivenessAnalysis(dfg);
-        performCFA(dfg);
-        performConstantFolding(dfg);
-        performCleanUp(dfg); // Reduce the graph size a lot.
</del><ins>+        RUN_PHASE(performConstantHoisting);
+        RUN_PHASE(performGlobalCSE);
+        RUN_PHASE(performLivenessAnalysis);
+        RUN_PHASE(performCFA);
+        RUN_PHASE(performConstantFolding);
+        RUN_PHASE(performCleanUp); // Reduce the graph size a lot.
</ins><span class="cx">         changed = false;
</span><del>-        changed |= performStrengthReduction(dfg);
</del><ins>+        RUN_PHASE(performStrengthReduction);
</ins><span class="cx">         if (Options::useObjectAllocationSinking()) {
</span><del>-            changed |= performCriticalEdgeBreaking(dfg);
-            changed |= performObjectAllocationSinking(dfg);
</del><ins>+            RUN_PHASE(performCriticalEdgeBreaking);
+            RUN_PHASE(performObjectAllocationSinking);
</ins><span class="cx">         }
</span><span class="cx">         if (changed) {
</span><span class="cx">             // State-at-tail and state-at-head will be invalid if we did strength reduction since
</span><span class="cx">             // it might increase live ranges.
</span><del>-            performLivenessAnalysis(dfg);
-            performCFA(dfg);
-            performConstantFolding(dfg);
</del><ins>+            RUN_PHASE(performLivenessAnalysis);
+            RUN_PHASE(performCFA);
+            RUN_PHASE(performConstantFolding);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         // Currently, this relies on pre-headers still being valid. That precludes running CFG
</span><span class="lines">@@ -428,9 +444,9 @@
</span><span class="cx">         // wrong with running LICM earlier, if we wanted to put other CFG transforms above this point.
</span><span class="cx">         // Alternatively, we could run loop pre-header creation after SSA conversion - but if we did that
</span><span class="cx">         // then we'd need to do some simple SSA fix-up.
</span><del>-        performLivenessAnalysis(dfg);
-        performCFA(dfg);
-        performLICM(dfg);
</del><ins>+        RUN_PHASE(performLivenessAnalysis);
+        RUN_PHASE(performCFA);
+        RUN_PHASE(performLICM);
</ins><span class="cx"> 
</span><span class="cx">         // FIXME: Currently: IntegerRangeOptimization *must* be run after LICM.
</span><span class="cx">         //
</span><span class="lines">@@ -439,29 +455,29 @@
</span><span class="cx">         // by IntegerRangeOptimization.
</span><span class="cx">         //
</span><span class="cx">         // Ideally, the dependencies should be explicit. See https://bugs.webkit.org/show_bug.cgi?id=157534.
</span><del>-        performLivenessAnalysis(dfg);
-        performIntegerRangeOptimization(dfg);
</del><ins>+        RUN_PHASE(performLivenessAnalysis);
+        RUN_PHASE(performIntegerRangeOptimization);
</ins><span class="cx">         
</span><del>-        performCleanUp(dfg);
-        performIntegerCheckCombining(dfg);
-        performGlobalCSE(dfg);
</del><ins>+        RUN_PHASE(performCleanUp);
+        RUN_PHASE(performIntegerCheckCombining);
+        RUN_PHASE(performGlobalCSE);
</ins><span class="cx">         
</span><span class="cx">         // At this point we're not allowed to do any further code motion because our reasoning
</span><span class="cx">         // about code motion assumes that it's OK to insert GC points in random places.
</span><span class="cx">         dfg.m_fixpointState = FixpointConverged;
</span><span class="cx">         
</span><del>-        performLivenessAnalysis(dfg);
-        performCFA(dfg);
-        performGlobalStoreBarrierInsertion(dfg);
-        performStoreBarrierClustering(dfg);
</del><ins>+        RUN_PHASE(performLivenessAnalysis);
+        RUN_PHASE(performCFA);
+        RUN_PHASE(performGlobalStoreBarrierInsertion);
+        RUN_PHASE(performStoreBarrierClustering);
</ins><span class="cx">         if (Options::useMovHintRemoval())
</span><del>-            performMovHintRemoval(dfg);
-        performCleanUp(dfg);
-        performDCE(dfg); // We rely on this to kill dead code that won't be recognized as dead by B3.
-        performStackLayout(dfg);
-        performLivenessAnalysis(dfg);
-        performOSRAvailabilityAnalysis(dfg);
-        performWatchpointCollection(dfg);
</del><ins>+            RUN_PHASE(performMovHintRemoval);
+        RUN_PHASE(performCleanUp);
+        RUN_PHASE(performDCE); // We rely on this to kill dead code that won't be recognized as dead by B3.
+        RUN_PHASE(performStackLayout);
+        RUN_PHASE(performLivenessAnalysis);
+        RUN_PHASE(performOSRAvailabilityAnalysis);
+        RUN_PHASE(performWatchpointCollection);
</ins><span class="cx">         
</span><span class="cx">         if (FTL::canCompile(dfg) == FTL::CannotCompile) {
</span><span class="cx">             finalizer = std::make_unique&lt;FailedFinalizer&gt;(*this);
</span><span class="lines">@@ -521,6 +537,8 @@
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         return FailPath;
</span><span class="cx">     }
</span><ins>+
+#undef RUN_PHASE
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool Plan::isStillValid()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafepointcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafepoint.cpp (210970 => 210971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafepoint.cpp        2017-01-20 18:09:30 UTC (rev 210970)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafepoint.cpp        2017-01-20 18:10:55 UTC (rev 210971)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014, 2016 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">@@ -80,7 +80,7 @@
</span><span class="cx">     if (ThreadData* data = m_plan.threadData) {
</span><span class="cx">         RELEASE_ASSERT(!data-&gt;m_safepoint);
</span><span class="cx">         data-&gt;m_safepoint = this;
</span><del>-        data-&gt;m_rightToRun.unlock();
</del><ins>+        data-&gt;m_rightToRun.unlockFairly();
</ins><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeOptionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Options.h (210970 => 210971)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Options.h        2017-01-20 18:09:30 UTC (rev 210970)
+++ trunk/Source/JavaScriptCore/runtime/Options.h        2017-01-20 18:10:55 UTC (rev 210971)
</span><span class="lines">@@ -158,6 +158,7 @@
</span><span class="cx">     v(bool, dumpB3GraphAtEachPhase, false, Normal, &quot;dumps the B3 graph at each phase of compilation&quot;) \
</span><span class="cx">     v(bool, dumpAirGraphAtEachPhase, false, Normal, &quot;dumps the Air graph at each phase of compilation&quot;) \
</span><span class="cx">     v(bool, verboseDFGByteCodeParsing, false, Normal, nullptr) \
</span><ins>+    v(bool, safepointBeforeEachPhase, true, Normal, nullptr) \
</ins><span class="cx">     v(bool, verboseCompilation, false, Normal, nullptr) \
</span><span class="cx">     v(bool, verboseFTLCompilation, false, Normal, nullptr) \
</span><span class="cx">     v(bool, logCompilationChanges, false, Normal, nullptr) \
</span></span></pre>
</div>
</div>

</body>
</html>