<!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>[184511] 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/184511">184511</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2015-05-18 13:45:34 -0700 (Mon, 18 May 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>[JSC] When entering a CheckTierUp without OSREntry, force the CheckTierUp for the outer loops with OSR Entry
https://bugs.webkit.org/show_bug.cgi?id=145092
Reviewed by Filip Pizlo.
When we have a hot loop without OSR Entry inside a slower loop that support OSR Entry,
we get the inside loop driving the tierUpCounter and we have very little chance of
doing a CheckTierUp on the outer loop. In turn, this give almost no opportunity to tier
up in the outer loop and OSR Enter there.
This patches changes CheckTierUp to force its outer loops to do a CheckTierUp themselves.
To do that, CheckTierUp sets a flag "nestedTriggerIsSet" to force the outer loop to
enter their CheckTierUp regardless of the tier-up counter.
* bytecode/ExecutionCounter.cpp:
(JSC::ExecutionCounter<countingVariant>::setThreshold):
This is somewhat unrelated. This assertion is incorrect because it relies on
m_counter, which changes on an other thread.
I have hit it a couple of times with this patch because we are a bit more aggressive
on CheckTierUp. What happens is:
1) ExecutionCounter<countingVariant>::checkIfThresholdCrossedAndSet() first checks
hasCrossedThreshold(), and it is false.
2) On the main thread, the hot loops keeps running and the counter becomes large
enough to cross the threshold.
3) ExecutionCounter<countingVariant>::checkIfThresholdCrossedAndSet() runs the next
test, setThreshold(), where the assertion is. Since the counter is now large enough,
the assertion fails.
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGJITCode.h:
I used a uint8_t instead of a boolean to make the code generation clearer
in DFGSpeculativeJIT64.
* dfg/DFGNodeType.h:
* dfg/DFGOperations.cpp:
* dfg/DFGOperations.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
This is a bit annoying: we have the NaturalLoops analysis that provides us
everything we need to know about loops, but the TierUpCheck are conservative
and set on LoopHint.
To make the two work together, we first find all the CheckTierUp that cannot
OSR enter and we keep a list of all the natural loops containing them.
Then we do a second pass over the LoopHints, get their NaturalLoop, and check
if it contains a loop that cannot OSR enter.
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGTierUpCheckInjectionPhase.cpp:
(JSC::DFG::TierUpCheckInjectionPhase::run):
(JSC::DFG::TierUpCheckInjectionPhase::canOSREnterAtLoopHint):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeExecutionCountercpp">trunk/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCodeh">trunk/Source/JavaScriptCore/dfg/DFGJITCode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationscpp">trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOperationsh">trunk/Source/JavaScriptCore/dfg/DFGOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGTierUpCheckInjectionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -1,3 +1,74 @@
</span><ins>+2015-05-18 Benjamin Poulain <benjamin@webkit.org>
+
+ [JSC] When entering a CheckTierUp without OSREntry, force the CheckTierUp for the outer loops with OSR Entry
+ https://bugs.webkit.org/show_bug.cgi?id=145092
+
+ Reviewed by Filip Pizlo.
+
+ When we have a hot loop without OSR Entry inside a slower loop that support OSR Entry,
+ we get the inside loop driving the tierUpCounter and we have very little chance of
+ doing a CheckTierUp on the outer loop. In turn, this give almost no opportunity to tier
+ up in the outer loop and OSR Enter there.
+
+ This patches changes CheckTierUp to force its outer loops to do a CheckTierUp themselves.
+
+ To do that, CheckTierUp sets a flag "nestedTriggerIsSet" to force the outer loop to
+ enter their CheckTierUp regardless of the tier-up counter.
+
+ * bytecode/ExecutionCounter.cpp:
+ (JSC::ExecutionCounter<countingVariant>::setThreshold):
+ This is somewhat unrelated. This assertion is incorrect because it relies on
+ m_counter, which changes on an other thread.
+
+ I have hit it a couple of times with this patch because we are a bit more aggressive
+ on CheckTierUp. What happens is:
+ 1) ExecutionCounter<countingVariant>::checkIfThresholdCrossedAndSet() first checks
+ hasCrossedThreshold(), and it is false.
+ 2) On the main thread, the hot loops keeps running and the counter becomes large
+ enough to cross the threshold.
+ 3) ExecutionCounter<countingVariant>::checkIfThresholdCrossedAndSet() runs the next
+ test, setThreshold(), where the assertion is. Since the counter is now large enough,
+ the assertion fails.
+
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+
+ * dfg/DFGJITCode.h:
+ I used a uint8_t instead of a boolean to make the code generation clearer
+ in DFGSpeculativeJIT64.
+
+ * dfg/DFGNodeType.h:
+ * dfg/DFGOperations.cpp:
+ * dfg/DFGOperations.h:
+
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ This is a bit annoying: we have the NaturalLoops analysis that provides us
+ everything we need to know about loops, but the TierUpCheck are conservative
+ and set on LoopHint.
+
+ To make the two work together, we first find all the CheckTierUp that cannot
+ OSR enter and we keep a list of all the natural loops containing them.
+
+ Then we do a second pass over the LoopHints, get their NaturalLoop, and check
+ if it contains a loop that cannot OSR enter.
+
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGTierUpCheckInjectionPhase.cpp:
+ (JSC::DFG::TierUpCheckInjectionPhase::run):
+ (JSC::DFG::TierUpCheckInjectionPhase::canOSREnterAtLoopHint):
+
</ins><span class="cx"> 2015-05-18 Filip Pizlo <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> Add a Int-or-Boolean speculation to Branch
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeExecutionCountercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -136,8 +136,6 @@
</span><span class="cx"> return false;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- ASSERT(!m_activeThreshold || !hasCrossedThreshold(codeBlock));
-
</del><span class="cx"> // Compute the true total count.
</span><span class="cx"> double trueTotalCount = count();
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -2271,6 +2271,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case CheckTierUpAndOSREnter:
</span><ins>+ case CheckTierUpWithNestedTriggerAndOSREnter:
</ins><span class="cx"> case LoopHint:
</span><span class="cx"> case ZombieHint:
</span><span class="cx"> break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -286,6 +286,7 @@
</span><span class="cx"> case CheckTierUpInLoop:
</span><span class="cx"> case CheckTierUpAtReturn:
</span><span class="cx"> case CheckTierUpAndOSREnter:
</span><ins>+ case CheckTierUpWithNestedTriggerAndOSREnter:
</ins><span class="cx"> case LoopHint:
</span><span class="cx"> case Breakpoint:
</span><span class="cx"> case ProfileWillCall:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -159,6 +159,7 @@
</span><span class="cx"> case CheckTierUpInLoop:
</span><span class="cx"> case CheckTierUpAtReturn:
</span><span class="cx"> case CheckTierUpAndOSREnter:
</span><ins>+ case CheckTierUpWithNestedTriggerAndOSREnter:
</ins><span class="cx"> case LoopHint:
</span><span class="cx"> case StoreBarrier:
</span><span class="cx"> case InvalidationPoint:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -1084,6 +1084,7 @@
</span><span class="cx"> case CheckTierUpInLoop:
</span><span class="cx"> case CheckTierUpAtReturn:
</span><span class="cx"> case CheckTierUpAndOSREnter:
</span><ins>+ case CheckTierUpWithNestedTriggerAndOSREnter:
</ins><span class="cx"> case InvalidationPoint:
</span><span class="cx"> case CheckArray:
</span><span class="cx"> case CheckInBounds:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCode.h (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCode.h        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCode.h        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -120,6 +120,7 @@
</span><span class="cx"> DFG::VariableEventStream variableEventStream;
</span><span class="cx"> DFG::MinifiedGraph minifiedDFG;
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><ins>+ uint8_t nestedTriggerIsSet { 0 };
</ins><span class="cx"> UpperTierExecutionCounter tierUpCounter;
</span><span class="cx"> RefPtr<CodeBlock> osrEntryBlock;
</span><span class="cx"> unsigned osrEntryRetry;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -91,6 +91,7 @@
</span><span class="cx"> /* Tier-up checks from the DFG to the FTL. */\
</span><span class="cx"> macro(CheckTierUpInLoop, NodeMustGenerate) \
</span><span class="cx"> macro(CheckTierUpAndOSREnter, NodeMustGenerate) \
</span><ins>+ macro(CheckTierUpWithNestedTriggerAndOSREnter, NodeMustGenerate) \
</ins><span class="cx"> macro(CheckTierUpAtReturn, NodeMustGenerate) \
</span><span class="cx"> \
</span><span class="cx"> /* Get the value of a local variable, without linking into the VariableAccessData */\
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -1351,7 +1351,7 @@
</span><span class="cx"> Operands<JSValue>(), ToFTLDeferredCompilationCallback::create(codeBlock));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JIT_OPERATION triggerTierUpNow(ExecState* exec)
</del><ins>+static void triggerTierUpNowCommon(ExecState* exec, bool inLoop)
</ins><span class="cx"> {
</span><span class="cx"> VM* vm = &exec->vm();
</span><span class="cx"> NativeCallFrameTracer tracer(vm, exec);
</span><span class="lines">@@ -1370,10 +1370,22 @@
</span><span class="cx"> *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
</span><span class="cx"> jitCode->tierUpCounter, "\n");
</span><span class="cx"> }
</span><del>-
</del><ins>+ if (inLoop)
+ jitCode->nestedTriggerIsSet = 1;
+
</ins><span class="cx"> triggerFTLReplacementCompile(vm, codeBlock, jitCode);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void JIT_OPERATION triggerTierUpNow(ExecState* exec)
+{
+ triggerTierUpNowCommon(exec, false);
+}
+
+void JIT_OPERATION triggerTierUpNowInLoop(ExecState* exec)
+{
+ triggerTierUpNowCommon(exec, true);
+}
+
</ins><span class="cx"> char* JIT_OPERATION triggerOSREntryNow(
</span><span class="cx"> ExecState* exec, int32_t bytecodeIndex, int32_t streamIndex)
</span><span class="cx"> {
</span><span class="lines">@@ -1388,6 +1400,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> JITCode* jitCode = codeBlock->jitCode()->dfg();
</span><ins>+ jitCode->nestedTriggerIsSet = 0;
</ins><span class="cx">
</span><span class="cx"> if (Options::verboseOSR()) {
</span><span class="cx"> dataLog(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOperations.h (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGOperations.h        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -148,6 +148,7 @@
</span><span class="cx">
</span><span class="cx"> #if ENABLE(FTL_JIT)
</span><span class="cx"> void JIT_OPERATION triggerTierUpNow(ExecState*) WTF_INTERNAL;
</span><ins>+void JIT_OPERATION triggerTierUpNowInLoop(ExecState*) WTF_INTERNAL;
</ins><span class="cx"> char* JIT_OPERATION triggerOSREntryNow(ExecState*, int32_t bytecodeIndex, int32_t streamIndex) WTF_INTERNAL;
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -540,6 +540,7 @@
</span><span class="cx"> case CheckTierUpInLoop:
</span><span class="cx"> case CheckTierUpAtReturn:
</span><span class="cx"> case CheckTierUpAndOSREnter:
</span><ins>+ case CheckTierUpWithNestedTriggerAndOSREnter:
</ins><span class="cx"> case InvalidationPoint:
</span><span class="cx"> case CheckInBounds:
</span><span class="cx"> case ValueToInt32:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -246,6 +246,7 @@
</span><span class="cx"> case CheckTierUpInLoop:
</span><span class="cx"> case CheckTierUpAtReturn:
</span><span class="cx"> case CheckTierUpAndOSREnter:
</span><ins>+ case CheckTierUpWithNestedTriggerAndOSREnter:
</ins><span class="cx"> case LoopHint:
</span><span class="cx"> case StoreBarrier:
</span><span class="cx"> case InvalidationPoint:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -4610,6 +4610,7 @@
</span><span class="cx"> case CheckTierUpInLoop:
</span><span class="cx"> case CheckTierUpAtReturn:
</span><span class="cx"> case CheckTierUpAndOSREnter:
</span><ins>+ case CheckTierUpWithNestedTriggerAndOSREnter:
</ins><span class="cx"> case Int52Rep:
</span><span class="cx"> case FiatInt52:
</span><span class="cx"> case Int52Constant:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -4635,7 +4635,7 @@
</span><span class="cx">
</span><span class="cx"> silentSpillAllRegisters(InvalidGPRReg);
</span><span class="cx"> m_jit.setupArgumentsExecState();
</span><del>- appendCall(triggerTierUpNow);
</del><ins>+ appendCall(triggerTierUpNowInLoop);
</ins><span class="cx"> silentFillAllRegisters(InvalidGPRReg);
</span><span class="cx">
</span><span class="cx"> done.link(&m_jit);
</span><span class="lines">@@ -4657,17 +4657,24 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- case CheckTierUpAndOSREnter: {
</del><ins>+ case CheckTierUpAndOSREnter:
+ case CheckTierUpWithNestedTriggerAndOSREnter: {
</ins><span class="cx"> ASSERT(!node->origin.semantic.inlineCallFrame);
</span><span class="cx">
</span><span class="cx"> GPRTemporary temp(this);
</span><span class="cx"> GPRReg tempGPR = temp.gpr();
</span><ins>+
+ MacroAssembler::Jump forceOSREntry;
+ if (op == CheckTierUpWithNestedTriggerAndOSREnter)
+ forceOSREntry = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->nestedTriggerIsSet));
</ins><span class="cx">
</span><span class="cx"> MacroAssembler::Jump done = m_jit.branchAdd32(
</span><span class="cx"> MacroAssembler::Signed,
</span><span class="cx"> TrustedImm32(Options::ftlTierUpCounterIncrementForLoop()),
</span><span class="cx"> MacroAssembler::AbsoluteAddress(&m_jit.jitCode()->tierUpCounter.m_counter));
</span><del>-
</del><ins>+
+ if (forceOSREntry.isSet())
+ forceOSREntry.link(&m_jit);
</ins><span class="cx"> silentSpillAllRegisters(tempGPR);
</span><span class="cx"> m_jit.setupArgumentsWithExecState(
</span><span class="cx"> TrustedImm32(node->origin.semantic.bytecodeIndex),
</span><span class="lines">@@ -4685,6 +4692,7 @@
</span><span class="cx"> case CheckTierUpInLoop:
</span><span class="cx"> case CheckTierUpAtReturn:
</span><span class="cx"> case CheckTierUpAndOSREnter:
</span><ins>+ case CheckTierUpWithNestedTriggerAndOSREnter:
</ins><span class="cx"> DFG_CRASH(m_jit.graph(), node, "Unexpected tier-up node");
</span><span class="cx"> break;
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGTierUpCheckInjectionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp (184510 => 184511)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp        2015-05-18 20:41:54 UTC (rev 184510)
+++ trunk/Source/JavaScriptCore/dfg/DFGTierUpCheckInjectionPhase.cpp        2015-05-18 20:45:34 UTC (rev 184511)
</span><span class="lines">@@ -60,6 +60,13 @@
</span><span class="cx">
</span><span class="cx"> if (!Options::enableOSREntryToFTL())
</span><span class="cx"> level = FTL::CanCompile;
</span><ins>+
+ // First we find all the loops that contain a LoopHint for which we cannot OSR enter.
+ // We use that information to decide if we need CheckTierUpAndOSREnter or CheckTierUpWithNestedTriggerAndOSREnter.
+ NaturalLoops& naturalLoops = m_graph.m_naturalLoops;
+ naturalLoops.computeIfNecessary(m_graph);
+
+ HashSet<const NaturalLoop*> loopsContainingLoopHintWithoutOSREnter = findLoopsContainingLoopHintWithoutOSREnter(naturalLoops, level);
</ins><span class="cx">
</span><span class="cx"> InsertionSet insertionSet(m_graph);
</span><span class="cx"> for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
</span><span class="lines">@@ -71,35 +78,16 @@
</span><span class="cx"> Node* node = block->at(nodeIndex);
</span><span class="cx"> if (node->op() != LoopHint)
</span><span class="cx"> continue;
</span><del>-
- // We only put OSR checks for the first LoopHint in the block. Note that
- // more than one LoopHint could happen in cases where we did a lot of CFG
- // simplification in the bytecode parser, but it should be very rare.
-
</del><ins>+
</ins><span class="cx"> NodeOrigin origin = node->origin;
</span><del>-
- if (level != FTL::CanCompileAndOSREnter || origin.semantic.inlineCallFrame) {
- insertionSet.insertNode(
- nodeIndex + 1, SpecNone, CheckTierUpInLoop, origin);
- break;
- }
-
- bool isAtTop = true;
- for (unsigned subNodeIndex = nodeIndex; subNodeIndex--;) {
- if (!block->at(subNodeIndex)->isSemanticallySkippable()) {
- isAtTop = false;
- break;
- }
- }
-
- if (!isAtTop) {
- insertionSet.insertNode(
- nodeIndex + 1, SpecNone, CheckTierUpInLoop, origin);
- break;
- }
-
- insertionSet.insertNode(
- nodeIndex + 1, SpecNone, CheckTierUpAndOSREnter, origin);
</del><ins>+ if (canOSREnterAtLoopHint(level, block, nodeIndex)) {
+ const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block);
+ if (loop && loopsContainingLoopHintWithoutOSREnter.contains(loop))
+ insertionSet.insertNode(nodeIndex + 1, SpecNone, CheckTierUpWithNestedTriggerAndOSREnter, origin);
+ else
+ insertionSet.insertNode(nodeIndex + 1, SpecNone, CheckTierUpAndOSREnter, origin);
+ } else
+ insertionSet.insertNode(nodeIndex + 1, SpecNone, CheckTierUpInLoop, origin);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -119,6 +107,49 @@
</span><span class="cx"> return false;
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span><span class="cx"> }
</span><ins>+
+private:
+#if ENABLE(FTL_JIT)
+ bool canOSREnterAtLoopHint(FTL::CapabilityLevel level, const BasicBlock* block, unsigned nodeIndex)
+ {
+ Node* node = block->at(nodeIndex);
+ ASSERT(node->op() == LoopHint);
+
+ NodeOrigin origin = node->origin;
+ if (level != FTL::CanCompileAndOSREnter || origin.semantic.inlineCallFrame)
+ return false;
+
+ // We only put OSR checks for the first LoopHint in the block. Note that
+ // more than one LoopHint could happen in cases where we did a lot of CFG
+ // simplification in the bytecode parser, but it should be very rare.
+ for (unsigned subNodeIndex = nodeIndex; subNodeIndex--;) {
+ if (!block->at(subNodeIndex)->isSemanticallySkippable())
+ return false;
+ }
+ return true;
+ }
+
+ HashSet<const NaturalLoop*> findLoopsContainingLoopHintWithoutOSREnter(const NaturalLoops& naturalLoops, FTL::CapabilityLevel level)
+ {
+ HashSet<const NaturalLoop*> loopsContainingLoopHintWithoutOSREnter;
+ for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
+ for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
+ Node* node = block->at(nodeIndex);
+ if (node->op() != LoopHint)
+ continue;
+
+ if (!canOSREnterAtLoopHint(level, block, nodeIndex)) {
+ const NaturalLoop* loop = naturalLoops.innerMostLoopOf(block);
+ while (loop) {
+ loopsContainingLoopHintWithoutOSREnter.add(loop);
+ loop = naturalLoops.innerMostOuterLoop(*loop);
+ }
+ }
+ }
+ }
+ return loopsContainingLoopHintWithoutOSREnter;
+ }
+#endif
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> bool performTierUpCheckInjection(Graph& graph)
</span></span></pre>
</div>
</div>
</body>
</html>