<!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>[188986] branches/jsc-tailcall/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/188986">188986</a></dd>
<dt>Author</dt> <dd>msaboff@apple.com</dd>
<dt>Date</dt> <dd>2015-08-26 13:43:35 -0700 (Wed, 26 Aug 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>jsc-tailcall: Integrate FTL OSR entry / exit and exceptions handling of callee save registers with other tiers
https://bugs.webkit.org/show_bug.cgi?id=148099

Reviewed by Basile Clement.

Turned off register preservation thunks for outgoing calls from FTL generated code.
Handled callee saves registers for DFG to FTL OSR entry.
Fxed the FTL OSR exit compiler to restore the callee saves from an FTL function to
either the baseline call frame for callee saves the baseline handles or directly to
the callee save register itself.

* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::setUpCallFromFTL):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCompile.cpp:
(JSC::FTL::fixFunctionBasedOnStackMaps):
* ftl/FTLOSRExitCompiler.cpp:
(JSC::FTL::compileStub):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesjsctailcallSourceJavaScriptCoreChangeLog">branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorebytecodeCallLinkInfoh">branches/jsc-tailcall/Source/JavaScriptCore/bytecode/CallLinkInfo.h</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">branches/jsc-tailcall/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCoreftlFTLCompilecpp">branches/jsc-tailcall/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCoreftlFTLOSRExitCompilercpp">branches/jsc-tailcall/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesjsctailcallSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog (188985 => 188986)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog        2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog        2015-08-26 20:43:35 UTC (rev 188986)
</span><span class="lines">@@ -1,5 +1,27 @@
</span><span class="cx"> 2015-08-26  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        jsc-tailcall: Integrate FTL OSR entry / exit and exceptions handling of callee save registers with other tiers
+        https://bugs.webkit.org/show_bug.cgi?id=148099
+
+        Reviewed by Basile Clement.
+
+        Turned off register preservation thunks for outgoing calls from FTL generated code.
+        Handled callee saves registers for DFG to FTL OSR entry.
+        Fxed the FTL OSR exit compiler to restore the callee saves from an FTL function to
+        either the baseline call frame for callee saves the baseline handles or directly to
+        the callee save register itself.
+
+        * bytecode/CallLinkInfo.h:
+        (JSC::CallLinkInfo::setUpCallFromFTL):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::fixFunctionBasedOnStackMaps):
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::compileStub):
+
+2015-08-26  Michael Saboff  &lt;msaboff@apple.com&gt;
+
</ins><span class="cx">         Unreviewed build fix for release builds after r188937.
</span><span class="cx"> 
</span><span class="cx">         * jit/CallFrameShuffler.cpp:
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorebytecodeCallLinkInfoh"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/bytecode/CallLinkInfo.h (188985 => 188986)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-08-26 20:43:35 UTC (rev 188986)
</span><span class="lines">@@ -161,7 +161,7 @@
</span><span class="cx">         CodeLocationNearCall callReturnLocation, CodeLocationDataLabelPtr hotPathBegin,
</span><span class="cx">         CodeLocationNearCall hotPathOther, unsigned calleeGPR)
</span><span class="cx">     {
</span><del>-        m_registerPreservationMode = static_cast&lt;unsigned&gt;(MustPreserveRegisters);
</del><ins>+        m_registerPreservationMode = static_cast&lt;unsigned&gt;(RegisterPreservationNotRequired);
</ins><span class="cx">         m_callType = callType;
</span><span class="cx">         m_codeOrigin = codeOrigin;
</span><span class="cx">         m_callReturnLocation = callReturnLocation;
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (188985 => 188986)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-08-26 20:43:35 UTC (rev 188986)
</span><span class="lines">@@ -4818,6 +4818,7 @@
</span><span class="cx">             TrustedImm32(m_stream-&gt;size()));
</span><span class="cx">         appendCallSetResult(triggerOSREntryNow, tempGPR);
</span><span class="cx">         MacroAssembler::Jump dontEnter = m_jit.branchTestPtr(MacroAssembler::Zero, tempGPR);
</span><ins>+        m_jit.emitRestoreCalleeSaves();
</ins><span class="cx">         m_jit.jump(tempGPR);
</span><span class="cx">         dontEnter.link(&amp;m_jit);
</span><span class="cx">         silentFillAllRegisters(tempGPR);
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/ftl/FTLCompile.cpp (188985 => 188986)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-08-26 20:43:35 UTC (rev 188986)
</span><span class="lines">@@ -366,12 +366,14 @@
</span><span class="cx">         
</span><span class="cx">         // At this point it's perfectly fair to just blow away all state and restore the
</span><span class="cx">         // JS JIT view of the universe.
</span><ins>+        checkJIT.copyCalleeSavesToVMCalleeSavesBuffer();
</ins><span class="cx">         checkJIT.move(MacroAssembler::TrustedImmPtr(&amp;vm), GPRInfo::argumentGPR0);
</span><span class="cx">         checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
</span><span class="cx">         MacroAssembler::Call callLookupExceptionHandler = checkJIT.call();
</span><span class="cx">         checkJIT.jumpToExceptionHandler();
</span><span class="cx"> 
</span><span class="cx">         stackOverflowException = checkJIT.label();
</span><ins>+        checkJIT.copyCalleeSavesToVMCalleeSavesBuffer();
</ins><span class="cx">         checkJIT.move(MacroAssembler::TrustedImmPtr(&amp;vm), GPRInfo::argumentGPR0);
</span><span class="cx">         checkJIT.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR1);
</span><span class="cx">         MacroAssembler::Call callLookupExceptionHandlerFromCallerFrame = checkJIT.call();
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCoreftlFTLOSRExitCompilercpp"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp (188985 => 188986)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-08-26 20:38:42 UTC (rev 188985)
+++ branches/jsc-tailcall/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp        2015-08-26 20:43:35 UTC (rev 188986)
</span><span class="lines">@@ -404,10 +404,12 @@
</span><span class="cx">     jit.add32(GPRInfo::regT3, GPRInfo::regT2);
</span><span class="cx">     arityIntact.link(&amp;jit);
</span><span class="cx"> 
</span><ins>+    CodeBlock* baselineCodeBlock = jit.baselineCodeBlockFor(exit.m_codeOrigin);
+
</ins><span class="cx">     // First set up SP so that our data doesn't get clobbered by signals.
</span><span class="cx">     unsigned conservativeStackDelta =
</span><span class="cx">         registerPreservationOffset() +
</span><del>-        exit.m_values.numberOfLocals() * sizeof(Register) +
</del><ins>+        (exit.m_values.numberOfLocals() + baselineCodeBlock-&gt;calleeSaveSpaceAsVirtualRegisters()) * sizeof(Register) +
</ins><span class="cx">         maxFrameExtentForSlowPathCall;
</span><span class="cx">     conservativeStackDelta = WTF::roundUpToMultipleOf(
</span><span class="cx">         stackAlignmentBytes(), conservativeStackDelta);
</span><span class="lines">@@ -429,67 +431,44 @@
</span><span class="cx">     jit.store64(GPRInfo::regT0, GPRInfo::regT1);
</span><span class="cx">     jit.addPtr(MacroAssembler::TrustedImm32(sizeof(Register)), GPRInfo::regT1);
</span><span class="cx">     jit.branchTest32(MacroAssembler::NonZero, GPRInfo::regT2).linkTo(loop, &amp;jit);
</span><del>-    
-    // At this point regT1 points to where we would save our registers. Save them here.
-    ptrdiff_t currentOffset = 0;
</del><ins>+
+    RegisterAtOffsetList* baselineCalleeSaves = baselineCodeBlock-&gt;calleeSaveRegisters();
+
</ins><span class="cx">     for (Reg reg = Reg::first(); reg &lt;= Reg::last(); reg = reg.next()) {
</span><del>-        if (!toSave.get(reg))
</del><ins>+        if (!toSave.get(reg) || !reg.isGPR())
</ins><span class="cx">             continue;
</span><del>-        currentOffset += sizeof(Register);
</del><span class="cx">         unsigned unwindIndex = codeBlock-&gt;calleeSaveRegisters()-&gt;indexOf(reg);
</span><ins>+        RegisterAtOffset* baselineRegisterOffset = baselineCalleeSaves-&gt;find(reg);
+
</ins><span class="cx">         if (unwindIndex == UINT_MAX) {
</span><span class="cx">             // The FTL compilation didn't preserve this register. This means that it also
</span><span class="cx">             // didn't use the register. So its value at the beginning of OSR exit should be
</span><span class="cx">             // preserved by the thunk. Luckily, we saved all registers into the register
</span><span class="cx">             // scratch buffer, so we can restore them from there.
</span><del>-            jit.load64(registerScratch + offsetOfReg(reg), GPRInfo::regT0);
</del><ins>+            jit.load64(registerScratch + offsetOfReg(reg), reg.gpr());
</ins><span class="cx">         } else {
</span><span class="cx">             // The FTL compilation preserved the register. Its new value is therefore
</span><span class="cx">             // irrelevant, but we can get the value that was preserved by using the unwind
</span><span class="cx">             // data. We've already copied all unwind-able preserved registers into the unwind
</span><span class="cx">             // scratch buffer, so we can get it from there.
</span><del>-            jit.load64(unwindScratch + unwindIndex, GPRInfo::regT0);
</del><ins>+            jit.load64(unwindScratch + unwindIndex, reg.gpr());
</ins><span class="cx">         }
</span><del>-        jit.store64(GPRInfo::regT0, AssemblyHelpers::Address(GPRInfo::regT1, currentOffset));
</del><ins>+
+        if (baselineRegisterOffset)
+            jit.store64(reg.gpr(), MacroAssembler::Address(MacroAssembler::framePointerRegister, baselineRegisterOffset-&gt;offset()));
</ins><span class="cx">     }
</span><del>-    
-    // We need to make sure that we return into the register restoration thunk. This works
-    // differently depending on whether or not we had arity issues.
-    MacroAssembler::Jump arityIntactForReturnPC = jit.branch32(
-        MacroAssembler::GreaterThanOrEqual,
-        CCallHelpers::payloadFor(JSStack::ArgumentCount),
-        MacroAssembler::TrustedImm32(codeBlock-&gt;numParameters()));
-    
-    // The return PC in the call frame header points at exactly the right arity restoration
-    // thunk. We don't want to change that. But the arity restoration thunk's frame has a
-    // return PC and we want to reroute that to our register restoration thunk. The arity
-    // restoration's return PC just just below regT1, and the register restoration's return PC
-    // is right at regT1.
-    jit.loadPtr(MacroAssembler::Address(GPRInfo::regT1, -static_cast&lt;ptrdiff_t&gt;(sizeof(Register))), GPRInfo::regT0);
-    jit.storePtr(GPRInfo::regT0, GPRInfo::regT1);
-    jit.storePtr(
-        MacroAssembler::TrustedImmPtr(vm-&gt;getCTIStub(registerRestorationThunkGenerator).code().executableAddress()),
-        MacroAssembler::Address(GPRInfo::regT1, -static_cast&lt;ptrdiff_t&gt;(sizeof(Register))));
-    
-    MacroAssembler::Jump arityReturnPCReady = jit.jump();
</del><ins>+    size_t baselineVirtualRegistersForCalleeSaves = baselineCodeBlock-&gt;calleeSaveSpaceAsVirtualRegisters();
</ins><span class="cx"> 
</span><del>-    arityIntactForReturnPC.link(&amp;jit);
-    
-    jit.loadPtr(MacroAssembler::Address(MacroAssembler::framePointerRegister, CallFrame::returnPCOffset()), GPRInfo::regT0);
-    jit.storePtr(GPRInfo::regT0, GPRInfo::regT1);
-    jit.storePtr(
-        MacroAssembler::TrustedImmPtr(vm-&gt;getCTIStub(registerRestorationThunkGenerator).code().executableAddress()),
-        MacroAssembler::Address(MacroAssembler::framePointerRegister, CallFrame::returnPCOffset()));
-    
-    arityReturnPCReady.link(&amp;jit);
-    
</del><span class="cx">     // Now get state out of the scratch buffer and place it back into the stack. The values are
</span><span class="cx">     // already reboxed so we just move them.
</span><span class="cx">     for (unsigned index = exit.m_values.size(); index--;) {
</span><del>-        int operand = exit.m_values.operandForIndex(index);
-        
</del><ins>+        VirtualRegister reg = exit.m_values.virtualRegisterForIndex(index);
+
+        if (reg.isLocal() &amp;&amp; reg.toLocal() &lt; static_cast&lt;int&gt;(baselineVirtualRegistersForCalleeSaves))
+            continue;
+
</ins><span class="cx">         jit.load64(scratch + index, GPRInfo::regT0);
</span><del>-        jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(static_cast&lt;VirtualRegister&gt;(operand)));
</del><ins>+        jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(reg));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     handleExitCounts(jit, exit);
</span></span></pre>
</div>
</div>

</body>
</html>