<!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>[192525] 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/192525">192525</a></dd>
<dt>Author</dt> <dd>sbarati@apple.com</dd>
<dt>Date</dt> <dd>2015-11-17 12:52:26 -0800 (Tue, 17 Nov 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>FTLLazySlowPaths should be able to handle being passed the zero register as a location
https://bugs.webkit.org/show_bug.cgi?id=151193

Reviewed by Geoffrey Garen.

On arm64, SP and ZR are the same register number. The meaning
of the register number being SP or ZR is dependent on context of
the instruction and the register within the instruction. LLVM may
prove that a value is zero, or sometimes, we will lower a
value as a constant zero (for example, we might compile
CreateDirectArguments of an inlined call frame and we might know
that the arguments have a length of zero). LazySlowPaths should
be able to gracefully handle being passed a stackmap location
with a gpr value of SP by moving zero into another register
and replacing the location's register with the new register.
This way, no lazy slow path will ever have access to a location with a GPR
value of SP.  This patch makes this work by using a scratch register
allocator when we need to do this maneuver of moving zero into a scratch
register.  Inside FTLCompile, we track if we need to move zero into a register,
and if so, into which register. We actually emit the necessary
instructions to move zero into this register, and to spill reused
registers if necessary, while generating the code for the lazy slow
path itself.

* ftl/FTLCompile.cpp:
(JSC::FTL::mmAllocateDataSection):
* ftl/FTLDWARFRegister.cpp:
(JSC::FTL::DWARFRegister::reg):
* ftl/FTLLazySlowPath.cpp:
(JSC::FTL::LazySlowPath::LazySlowPath):
(JSC::FTL::LazySlowPath::generate):
* ftl/FTLLazySlowPath.h:
(JSC::FTL::LazySlowPath::createGenerator):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCompilecpp">trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLDWARFRegistercpp">trunk/Source/JavaScriptCore/ftl/FTLDWARFRegister.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLazySlowPathcpp">trunk/Source/JavaScriptCore/ftl/FTLLazySlowPath.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLazySlowPathh">trunk/Source/JavaScriptCore/ftl/FTLLazySlowPath.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (192524 => 192525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-11-17 20:24:12 UTC (rev 192524)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-11-17 20:52:26 UTC (rev 192525)
</span><span class="lines">@@ -1,3 +1,39 @@
</span><ins>+2015-11-17  Saam barati  &lt;sbarati@apple.com&gt;
+
+        FTLLazySlowPaths should be able to handle being passed the zero register as a location
+        https://bugs.webkit.org/show_bug.cgi?id=151193
+
+        Reviewed by Geoffrey Garen.
+
+        On arm64, SP and ZR are the same register number. The meaning
+        of the register number being SP or ZR is dependent on context of
+        the instruction and the register within the instruction. LLVM may
+        prove that a value is zero, or sometimes, we will lower a
+        value as a constant zero (for example, we might compile
+        CreateDirectArguments of an inlined call frame and we might know
+        that the arguments have a length of zero). LazySlowPaths should
+        be able to gracefully handle being passed a stackmap location
+        with a gpr value of SP by moving zero into another register
+        and replacing the location's register with the new register.
+        This way, no lazy slow path will ever have access to a location with a GPR
+        value of SP.  This patch makes this work by using a scratch register 
+        allocator when we need to do this maneuver of moving zero into a scratch
+        register.  Inside FTLCompile, we track if we need to move zero into a register,
+        and if so, into which register. We actually emit the necessary
+        instructions to move zero into this register, and to spill reused
+        registers if necessary, while generating the code for the lazy slow
+        path itself.
+
+        * ftl/FTLCompile.cpp:
+        (JSC::FTL::mmAllocateDataSection):
+        * ftl/FTLDWARFRegister.cpp:
+        (JSC::FTL::DWARFRegister::reg):
+        * ftl/FTLLazySlowPath.cpp:
+        (JSC::FTL::LazySlowPath::LazySlowPath):
+        (JSC::FTL::LazySlowPath::generate):
+        * ftl/FTLLazySlowPath.h:
+        (JSC::FTL::LazySlowPath::createGenerator):
+
</ins><span class="cx"> 2015-11-17  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [JSC] Support Doubles with B3's Mul.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCompilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp (192524 => 192525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-11-17 20:24:12 UTC (rev 192524)
+++ trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp        2015-11-17 20:52:26 UTC (rev 192525)
</span><span class="lines">@@ -922,10 +922,6 @@
</span><span class="cx">             for (unsigned i = 0; i &lt; iter-&gt;value.size(); ++i) {
</span><span class="cx">                 StackMaps::Record&amp; record = iter-&gt;value[i].record;
</span><span class="cx">                 RegisterSet usedRegisters = usedRegistersFor(record);
</span><del>-                Vector&lt;Location&gt; locations;
-                for (auto location : record.locations)
-                    locations.append(Location::forStackmaps(&amp;stackmaps, location));
-
</del><span class="cx">                 char* startOfIC =
</span><span class="cx">                     bitwise_cast&lt;char*&gt;(generatedFunction) + record.instructionOffset;
</span><span class="cx">                 CodeLocationLabel patchpoint((MacroAssemblerCodePtr(startOfIC)));
</span><span class="lines">@@ -933,9 +929,28 @@
</span><span class="cx">                 if (!exceptionTarget)
</span><span class="cx">                     exceptionTarget = state.finalizer-&gt;handleExceptionsLinkBuffer-&gt;entrypoint();
</span><span class="cx"> 
</span><ins>+                ScratchRegisterAllocator scratchAllocator(usedRegisters);
+                GPRReg newZero = InvalidGPRReg;
+                Vector&lt;Location&gt; locations;
+                for (auto stackmapLocation : record.locations) {
+                    FTL::Location location = Location::forStackmaps(&amp;stackmaps, stackmapLocation);
+                    if (isARM64()) {
+                        // If LLVM proves that something is zero, it may pass us the zero register (aka, the stack pointer). Our assembler
+                        // isn't prepared to handle this well. We need to move it into a different register if such a case arises.
+                        if (location.isGPR() &amp;&amp; location.gpr() == MacroAssembler::stackPointerRegister) {
+                            if (newZero == InvalidGPRReg) {
+                                newZero = scratchAllocator.allocateScratchGPR();
+                                usedRegisters.set(newZero);
+                            }
+                            location = FTL::Location::forRegister(DWARFRegister(static_cast&lt;uint16_t&gt;(newZero)), 0); // DWARF GPRs for arm64 are sensibly numbered.
+                        }
+                    }
+                    locations.append(location);
+                }
+
</ins><span class="cx">                 std::unique_ptr&lt;LazySlowPath&gt; lazySlowPath = std::make_unique&lt;LazySlowPath&gt;(
</span><span class="cx">                     patchpoint, exceptionTarget, usedRegisters, exceptionHandlerManager.procureCallSiteIndex(iter-&gt;value[i].index, codeOrigin),
</span><del>-                    descriptor.m_linker-&gt;run(locations));
</del><ins>+                    descriptor.m_linker-&gt;run(locations), newZero, scratchAllocator);
</ins><span class="cx"> 
</span><span class="cx">                 CCallHelpers::Label begin = slowPathJIT.label();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLDWARFRegistercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLDWARFRegister.cpp (192524 => 192525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLDWARFRegister.cpp        2015-11-17 20:24:12 UTC (rev 192524)
+++ trunk/Source/JavaScriptCore/ftl/FTLDWARFRegister.cpp        2015-11-17 20:52:26 UTC (rev 192525)
</span><span class="lines">@@ -55,7 +55,6 @@
</span><span class="cx">         case 7:
</span><span class="cx">             return X86Registers::esp;
</span><span class="cx">         default:
</span><del>-            RELEASE_ASSERT(m_dwarfRegNum &lt; 16);
</del><span class="cx">             // Registers r8..r15 are numbered sensibly.
</span><span class="cx">             return static_cast&lt;GPRReg&gt;(m_dwarfRegNum);
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLazySlowPathcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLazySlowPath.cpp (192524 => 192525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLazySlowPath.cpp        2015-11-17 20:24:12 UTC (rev 192524)
+++ trunk/Source/JavaScriptCore/ftl/FTLLazySlowPath.cpp        2015-11-17 20:52:26 UTC (rev 192525)
</span><span class="lines">@@ -35,12 +35,15 @@
</span><span class="cx"> 
</span><span class="cx"> LazySlowPath::LazySlowPath(
</span><span class="cx">     CodeLocationLabel patchpoint, CodeLocationLabel exceptionTarget,
</span><del>-    const RegisterSet&amp; usedRegisters, CallSiteIndex callSiteIndex, RefPtr&lt;Generator&gt; generator)
</del><ins>+    const RegisterSet&amp; usedRegisters, CallSiteIndex callSiteIndex, RefPtr&lt;Generator&gt; generator,
+    GPRReg newZeroReg, ScratchRegisterAllocator scratchRegisterAllocator)
</ins><span class="cx">     : m_patchpoint(patchpoint)
</span><span class="cx">     , m_exceptionTarget(exceptionTarget)
</span><span class="cx">     , m_usedRegisters(usedRegisters)
</span><span class="cx">     , m_callSiteIndex(callSiteIndex)
</span><span class="cx">     , m_generator(generator)
</span><ins>+    , m_newZeroValueRegister(newZeroReg)
+    , m_scratchRegisterAllocator(scratchRegisterAllocator)
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -59,11 +62,32 @@
</span><span class="cx">     CCallHelpers::JumpList exceptionJumps;
</span><span class="cx">     params.exceptionJumps = m_exceptionTarget ? &amp;exceptionJumps : nullptr;
</span><span class="cx">     params.lazySlowPath = this;
</span><ins>+
+    unsigned bytesSaved = m_scratchRegisterAllocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
+    // This is needed because LLVM may create a stackmap location that is the register SP.
+    // But on arm64, SP is also the same register number as ZR, so LLVM is telling us that it has
+    // proven something is zero. Our MASM isn't universally compatible with arm64's context dependent
+    // notion of SP meaning ZR. We just make things easier by ensuring we do the necessary move of zero
+    // into a non-SP register.
+    if (m_newZeroValueRegister != InvalidGPRReg)
+        jit.move(CCallHelpers::TrustedImm32(0), m_newZeroValueRegister);
+
</ins><span class="cx">     m_generator-&gt;run(jit, params);
</span><span class="cx"> 
</span><ins>+    CCallHelpers::Label doneLabel;
+    CCallHelpers::Jump jumpToEndOfPatchpoint;
+    if (bytesSaved) {
+        doneLabel = jit.label();
+        m_scratchRegisterAllocator.restoreReusedRegistersByPopping(jit, bytesSaved, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
+        jumpToEndOfPatchpoint = jit.jump();
+    }
+
</ins><span class="cx">     LinkBuffer linkBuffer(vm, jit, codeBlock, JITCompilationMustSucceed);
</span><del>-    linkBuffer.link(
-        params.doneJumps, m_patchpoint.labelAtOffset(MacroAssembler::maxJumpReplacementSize()));
</del><ins>+    if (bytesSaved) {
+        linkBuffer.link(params.doneJumps, linkBuffer.locationOf(doneLabel));
+        linkBuffer.link(jumpToEndOfPatchpoint, m_patchpoint.labelAtOffset(MacroAssembler::maxJumpReplacementSize()));
+    } else
+        linkBuffer.link(params.doneJumps, m_patchpoint.labelAtOffset(MacroAssembler::maxJumpReplacementSize()));
</ins><span class="cx">     if (m_exceptionTarget)
</span><span class="cx">         linkBuffer.link(exceptionJumps, m_exceptionTarget);
</span><span class="cx">     m_stub = FINALIZE_CODE_FOR(codeBlock, linkBuffer, (&quot;Lazy slow path call stub&quot;));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLazySlowPathh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLazySlowPath.h (192524 => 192525)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLazySlowPath.h        2015-11-17 20:24:12 UTC (rev 192524)
+++ trunk/Source/JavaScriptCore/ftl/FTLLazySlowPath.h        2015-11-17 20:52:26 UTC (rev 192525)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><span class="cx"> #include &quot;MacroAssemblerCodeRef.h&quot;
</span><span class="cx"> #include &quot;RegisterSet.h&quot;
</span><ins>+#include &quot;ScratchRegisterAllocator.h&quot;
</ins><span class="cx"> #include &lt;wtf/SharedTask.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace FTL {
</span><span class="lines">@@ -65,8 +66,8 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     LazySlowPath(
</span><del>-        CodeLocationLabel patchpoint, CodeLocationLabel exceptionTarget,
-        const RegisterSet&amp; usedRegisters, CallSiteIndex callSiteIndex, RefPtr&lt;Generator&gt;);
</del><ins>+        CodeLocationLabel patchpoint, CodeLocationLabel exceptionTarget, const RegisterSet&amp; usedRegisters,
+        CallSiteIndex, RefPtr&lt;Generator&gt;, GPRReg newZeroReg, ScratchRegisterAllocator);
</ins><span class="cx"> 
</span><span class="cx">     ~LazySlowPath();
</span><span class="cx"> 
</span><span class="lines">@@ -85,6 +86,8 @@
</span><span class="cx">     CallSiteIndex m_callSiteIndex;
</span><span class="cx">     MacroAssemblerCodeRef m_stub;
</span><span class="cx">     RefPtr&lt;Generator&gt; m_generator;
</span><ins>+    GPRReg m_newZeroValueRegister;
+    ScratchRegisterAllocator m_scratchRegisterAllocator;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre>
</div>
</div>

</body>
</html>