<!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>[194092] 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/194092">194092</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-12-14 20:52:55 -0800 (Mon, 14 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>FTL B3 should account for localsOffset
https://bugs.webkit.org/show_bug.cgi?id=152288

Reviewed by Saam Barati.

The DFG will build up some data structures that expect to know about offsets from FP. Those data
structures may slide by some offset when the low-level compiler (either LLVM or B3) does stack
allocation. So, the LLVM FTL modifies those data structures based on the real offset that it gets
from LLVM's stackmaps. The B3 code needs to do the same.

I had previously vowed to never put more stuff into FTLB3Compile.cpp, because I didn't want it to
look like FTLCompile.cpp. Up until now, I was successful because I used lambdas installed by
FTLLower. But in this case, I actually think that having code that just does this explicitly in
FTLB3Compile.cpp is least confusing. There is no particular place in FTLLower that would want to
care about this, and we need to ensure that we do this fixup before we run any of the stackmap
generators. In other words, it needs to happen before we call B3::generate(). The ordering
constraints seem like a good reason to have this done explicitly rather than through lambdas.

I wrote a test. The test was failing in trunk because the B3 meaning of anchor().value() is
different from the LLVM meaning. This caused breakage when we used this idiom:

    ValueFromBlock foo = m_out.anchor(things);
    ...(foo.value()) // we were expecting that foo.value() == things

I never liked this idiom to begin with, so instead of trying to change B3's anchor(), I changed
the idiom to:

    LValue fooValue = things;
    ValueFromBlock foo = m_out.anchor(fooValue);
    ...(fooValue)

This is probably a good idea, since eventually we want B3's anchor() to just return the
UpsilonValue*. To get there, we want to eliminate any situations where code assumes that
ValueFromBlock is an actual object and not just a typedef for a pointer.

* ftl/FTLB3Compile.cpp:
(JSC::FTL::compile):
* ftl/FTLB3Output.cpp:
(JSC::FTL::Output::appendTo):
(JSC::FTL::Output::lockedStackSlot):
* ftl/FTLB3Output.h:
(JSC::FTL::Output::framePointer):
(JSC::FTL::Output::constBool):
(JSC::FTL::Output::constInt32):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::lower):
(JSC::FTL::DFG::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
(JSC::FTL::DFG::LowerDFGToLLVM::compileGetByVal):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCreateDirectArguments):
(JSC::FTL::DFG::LowerDFGToLLVM::compileStringCharAt):
(JSC::FTL::DFG::LowerDFGToLLVM::compileForwardVarargs):
(JSC::FTL::DFG::LowerDFGToLLVM::compileHasIndexedProperty):
(JSC::FTL::DFG::LowerDFGToLLVM::allocateJSArray):
(JSC::FTL::DFG::LowerDFGToLLVM::sensibleDoubleToInt32):
* ftl/FTLState.h:
(JSC::FTL::verboseCompilationEnabled):
* tests/stress/ftl-function-dot-arguments-with-callee-saves.js: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Compilecpp">trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Outputcpp">trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLB3Outputh">trunk/Source/JavaScriptCore/ftl/FTLB3Output.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLStateh">trunk/Source/JavaScriptCore/ftl/FTLState.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressftlfunctiondotargumentswithcalleesavesjs">trunk/Source/JavaScriptCore/tests/stress/ftl-function-dot-arguments-with-callee-saves.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (194091 => 194092)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-12-15 04:43:03 UTC (rev 194091)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-12-15 04:52:55 UTC (rev 194092)
</span><span class="lines">@@ -1,3 +1,63 @@
</span><ins>+2015-12-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        FTL B3 should account for localsOffset
+        https://bugs.webkit.org/show_bug.cgi?id=152288
+
+        Reviewed by Saam Barati.
+
+        The DFG will build up some data structures that expect to know about offsets from FP. Those data
+        structures may slide by some offset when the low-level compiler (either LLVM or B3) does stack
+        allocation. So, the LLVM FTL modifies those data structures based on the real offset that it gets
+        from LLVM's stackmaps. The B3 code needs to do the same.
+
+        I had previously vowed to never put more stuff into FTLB3Compile.cpp, because I didn't want it to
+        look like FTLCompile.cpp. Up until now, I was successful because I used lambdas installed by
+        FTLLower. But in this case, I actually think that having code that just does this explicitly in
+        FTLB3Compile.cpp is least confusing. There is no particular place in FTLLower that would want to
+        care about this, and we need to ensure that we do this fixup before we run any of the stackmap
+        generators. In other words, it needs to happen before we call B3::generate(). The ordering
+        constraints seem like a good reason to have this done explicitly rather than through lambdas.
+
+        I wrote a test. The test was failing in trunk because the B3 meaning of anchor().value() is
+        different from the LLVM meaning. This caused breakage when we used this idiom:
+
+            ValueFromBlock foo = m_out.anchor(things);
+            ...(foo.value()) // we were expecting that foo.value() == things
+
+        I never liked this idiom to begin with, so instead of trying to change B3's anchor(), I changed
+        the idiom to:
+
+            LValue fooValue = things;
+            ValueFromBlock foo = m_out.anchor(fooValue);
+            ...(fooValue)
+
+        This is probably a good idea, since eventually we want B3's anchor() to just return the
+        UpsilonValue*. To get there, we want to eliminate any situations where code assumes that
+        ValueFromBlock is an actual object and not just a typedef for a pointer.
+
+        * ftl/FTLB3Compile.cpp:
+        (JSC::FTL::compile):
+        * ftl/FTLB3Output.cpp:
+        (JSC::FTL::Output::appendTo):
+        (JSC::FTL::Output::lockedStackSlot):
+        * ftl/FTLB3Output.h:
+        (JSC::FTL::Output::framePointer):
+        (JSC::FTL::Output::constBool):
+        (JSC::FTL::Output::constInt32):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::lower):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileGetIndexedPropertyStorage):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileGetByVal):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileCreateDirectArguments):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileStringCharAt):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileForwardVarargs):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileHasIndexedProperty):
+        (JSC::FTL::DFG::LowerDFGToLLVM::allocateJSArray):
+        (JSC::FTL::DFG::LowerDFGToLLVM::sensibleDoubleToInt32):
+        * ftl/FTLState.h:
+        (JSC::FTL::verboseCompilationEnabled):
+        * tests/stress/ftl-function-dot-arguments-with-callee-saves.js: Added.
+
</ins><span class="cx"> 2015-12-14  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Math.random should have an intrinsic thunk and it should be later handled as a DFG Node
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Compilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp (194091 => 194092)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2015-12-15 04:43:03 UTC (rev 194091)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Compile.cpp        2015-12-15 04:52:55 UTC (rev 194092)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;B3Generate.h&quot;
</span><span class="cx"> #include &quot;B3ProcedureInlines.h&quot;
</span><ins>+#include &quot;B3StackSlotValue.h&quot;
</ins><span class="cx"> #include &quot;CodeBlockWithJITType.h&quot;
</span><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><span class="cx"> #include &quot;DFGCommon.h&quot;
</span><span class="lines">@@ -80,6 +81,34 @@
</span><span class="cx">     ASSERT(!(state.proc-&gt;frameSize() % sizeof(EncodedJSValue)));
</span><span class="cx">     state.jitCode-&gt;common.frameRegisterCount = state.proc-&gt;frameSize() / sizeof(EncodedJSValue);
</span><span class="cx"> 
</span><ins>+    int localsOffset =
+        state.capturedValue-&gt;offsetFromFP() / sizeof(EncodedJSValue) + graph.m_nextMachineLocal;
+    for (unsigned i = graph.m_inlineVariableData.size(); i--;) {
+        InlineCallFrame* inlineCallFrame = graph.m_inlineVariableData[i].inlineCallFrame;
+        
+        if (inlineCallFrame-&gt;argumentCountRegister.isValid())
+            inlineCallFrame-&gt;argumentCountRegister += localsOffset;
+        
+        for (unsigned argument = inlineCallFrame-&gt;arguments.size(); argument-- &gt; 1;) {
+            inlineCallFrame-&gt;arguments[argument] =
+                inlineCallFrame-&gt;arguments[argument].withLocalsOffset(localsOffset);
+        }
+        
+        if (inlineCallFrame-&gt;isClosureCall) {
+            inlineCallFrame-&gt;calleeRecovery =
+                inlineCallFrame-&gt;calleeRecovery.withLocalsOffset(localsOffset);
+        }
+
+        if (graph.hasDebuggerEnabled())
+            codeBlock-&gt;setScopeRegister(codeBlock-&gt;scopeRegister() + localsOffset);
+    }
+    for (OSRExitDescriptor&amp; descriptor : state.jitCode-&gt;osrExitDescriptors) {
+        for (unsigned i = descriptor.m_values.size(); i--;)
+            descriptor.m_values[i] = descriptor.m_values[i].withLocalsOffset(localsOffset);
+        for (ExitTimeObjectMaterialization* materialization : descriptor.m_materializations)
+            materialization-&gt;accountForLocalsOffset(localsOffset);
+    }
+
</ins><span class="cx">     CCallHelpers jit(&amp;vm, codeBlock);
</span><span class="cx">     B3::generate(*state.proc, jit);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Outputcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp (194091 => 194092)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp        2015-12-15 04:43:03 UTC (rev 194091)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Output.cpp        2015-12-15 04:52:55 UTC (rev 194092)
</span><span class="lines">@@ -59,7 +59,7 @@
</span><span class="cx">     m_block = block;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-LValue Output::lockedStackSlot(size_t bytes)
</del><ins>+B3::StackSlotValue* Output::lockedStackSlot(size_t bytes)
</ins><span class="cx"> {
</span><span class="cx">     return m_block-&gt;appendNew&lt;B3::StackSlotValue&gt;(m_proc, origin(), bytes, B3::StackSlotKind::Locked);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLB3Outputh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLB3Output.h (194091 => 194092)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2015-12-15 04:43:03 UTC (rev 194091)
+++ trunk/Source/JavaScriptCore/ftl/FTLB3Output.h        2015-12-15 04:52:55 UTC (rev 194092)
</span><span class="lines">@@ -103,7 +103,7 @@
</span><span class="cx"> 
</span><span class="cx">     LValue framePointer() { return m_block-&gt;appendNew&lt;B3::Value&gt;(m_proc, B3::FramePointer, origin()); }
</span><span class="cx"> 
</span><del>-    LValue lockedStackSlot(size_t bytes);
</del><ins>+    B3::StackSlotValue* lockedStackSlot(size_t bytes);
</ins><span class="cx"> 
</span><span class="cx">     LValue constBool(bool value) { return m_block-&gt;appendNew&lt;B3::Const32Value&gt;(m_proc, origin(), value); }
</span><span class="cx">     LValue constInt32(int32_t value) { return m_block-&gt;appendNew&lt;B3::Const32Value&gt;(m_proc, origin(), value); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (194091 => 194092)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-12-15 04:43:03 UTC (rev 194091)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-12-15 04:52:55 UTC (rev 194092)
</span><span class="lines">@@ -187,9 +187,9 @@
</span><span class="cx"> 
</span><span class="cx"> #if FTL_USES_B3
</span><span class="cx">         size_t sizeOfCaptured = sizeof(JSValue) * m_graph.m_nextMachineLocal;
</span><del>-        LValue capturedBase = m_out.lockedStackSlot(sizeOfCaptured);
</del><ins>+        B3::StackSlotValue* capturedBase = m_out.lockedStackSlot(sizeOfCaptured);
</ins><span class="cx">         m_captured = m_out.add(capturedBase, m_out.constIntPtr(sizeOfCaptured));
</span><del>-        m_ftlState.capturedValue = m_captured;
</del><ins>+        m_ftlState.capturedValue = capturedBase;
</ins><span class="cx"> #else // FTL_USES_B3
</span><span class="cx">         LValue capturedAlloca = m_out.alloca(arrayType(m_out.int64, m_graph.m_nextMachineLocal));
</span><span class="cx">         
</span><span class="lines">@@ -2633,12 +2633,12 @@
</span><span class="cx">         if (m_node-&gt;arrayMode().type() == Array::String) {
</span><span class="cx">             LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;GetIndexedPropertyStorage String slow case&quot;));
</span><span class="cx">             LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;GetIndexedPropertyStorage String continuation&quot;));
</span><ins>+
+            LValue fastResultValue = m_out.loadPtr(cell, m_heaps.JSString_value);
+            ValueFromBlock fastResult = m_out.anchor(fastResultValue);
</ins><span class="cx">             
</span><del>-            ValueFromBlock fastResult = m_out.anchor(
-                m_out.loadPtr(cell, m_heaps.JSString_value));
-            
</del><span class="cx">             m_out.branch(
</span><del>-                m_out.notNull(fastResult.value()), usually(continuation), rarely(slowPath));
</del><ins>+                m_out.notNull(fastResultValue), usually(continuation), rarely(slowPath));
</ins><span class="cx">             
</span><span class="cx">             LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
</span><span class="cx">             
</span><span class="lines">@@ -2793,11 +2793,11 @@
</span><span class="cx">                 rarely(slowCase), usually(fastCase));
</span><span class="cx">             
</span><span class="cx">             LBasicBlock lastNext = m_out.appendTo(fastCase, slowCase);
</span><del>-            
-            ValueFromBlock fastResult = m_out.anchor(
-                m_out.load64(baseIndex(heap, storage, index, m_node-&gt;child2())));
</del><ins>+
+            LValue fastResultValue = m_out.load64(baseIndex(heap, storage, index, m_node-&gt;child2()));
+            ValueFromBlock fastResult = m_out.anchor(fastResultValue);
</ins><span class="cx">             m_out.branch(
</span><del>-                m_out.isZero64(fastResult.value()), rarely(slowCase), usually(continuation));
</del><ins>+                m_out.isZero64(fastResultValue), rarely(slowCase), usually(continuation));
</ins><span class="cx">             
</span><span class="cx">             m_out.appendTo(slowCase, continuation);
</span><span class="cx">             ValueFromBlock slowResult = m_out.anchor(
</span><span class="lines">@@ -3677,18 +3677,20 @@
</span><span class="cx">             
</span><span class="cx">             LBasicBlock loop = FTL_NEW_BLOCK(m_out, (&quot;CreateDirectArguments loop body&quot;));
</span><span class="cx">             LBasicBlock end = FTL_NEW_BLOCK(m_out, (&quot;CreateDirectArguments loop end&quot;));
</span><del>-            
</del><ins>+
</ins><span class="cx">             ValueFromBlock originalLength;
</span><span class="cx">             if (minCapacity) {
</span><span class="cx">                 LValue capacity = m_out.select(
</span><span class="cx">                     m_out.aboveOrEqual(length.value, m_out.constInt32(minCapacity)),
</span><span class="cx">                     length.value,
</span><span class="cx">                     m_out.constInt32(minCapacity));
</span><del>-                originalLength = m_out.anchor(m_out.zeroExtPtr(capacity));
</del><ins>+                LValue originalLengthValue = m_out.zeroExtPtr(capacity);
+                originalLength = m_out.anchor(originalLengthValue);
</ins><span class="cx">                 m_out.jump(loop);
</span><span class="cx">             } else {
</span><del>-                originalLength = m_out.anchor(m_out.zeroExtPtr(length.value));
-                m_out.branch(m_out.isNull(originalLength.value()), unsure(end), unsure(loop));
</del><ins>+                LValue originalLengthValue = m_out.zeroExtPtr(length.value);
+                originalLength = m_out.anchor(originalLengthValue);
+                m_out.branch(m_out.isNull(originalLengthValue), unsure(end), unsure(loop));
</ins><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             lastNext = m_out.appendTo(loop, end);
</span><span class="lines">@@ -4256,13 +4258,14 @@
</span><span class="cx">         m_out.jump(bitsContinuation);
</span><span class="cx">             
</span><span class="cx">         m_out.appendTo(is16Bit, bigCharacter);
</span><del>-            
-        ValueFromBlock char16Bit = m_out.anchor(
-            m_out.load16ZeroExt32(m_out.baseIndex(
</del><ins>+
+        LValue char16BitValue = m_out.load16ZeroExt32(
+            m_out.baseIndex(
</ins><span class="cx">                 m_heaps.characters16, storage, m_out.zeroExtPtr(index),
</span><del>-                provenValue(m_node-&gt;child2()))));
</del><ins>+                provenValue(m_node-&gt;child2())));
+        ValueFromBlock char16Bit = m_out.anchor(char16BitValue);
</ins><span class="cx">         m_out.branch(
</span><del>-            m_out.aboveOrEqual(char16Bit.value(), m_out.constInt32(0x100)),
</del><ins>+            m_out.aboveOrEqual(char16BitValue, m_out.constInt32(0x100)),
</ins><span class="cx">             rarely(bigCharacter), usually(bitsContinuation));
</span><span class="cx">             
</span><span class="cx">         m_out.appendTo(bigCharacter, bitsContinuation);
</span><span class="lines">@@ -4270,7 +4273,7 @@
</span><span class="cx">         Vector&lt;ValueFromBlock, 4&gt; results;
</span><span class="cx">         results.append(m_out.anchor(vmCall(
</span><span class="cx">             m_out.int64, m_out.operation(operationSingleCharacterString),
</span><del>-            m_callFrame, char16Bit.value())));
</del><ins>+            m_callFrame, char16BitValue)));
</ins><span class="cx">         m_out.jump(continuation);
</span><span class="cx">             
</span><span class="cx">         m_out.appendTo(bitsContinuation, slowPath);
</span><span class="lines">@@ -5141,9 +5144,10 @@
</span><span class="cx">         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;ForwardVarargs continuation&quot;));
</span><span class="cx">         
</span><span class="cx">         LValue lengthAsPtr = m_out.zeroExtPtr(length);
</span><del>-        ValueFromBlock loopBound = m_out.anchor(m_out.constIntPtr(data-&gt;mandatoryMinimum));
</del><ins>+        LValue loopBoundValue = m_out.constIntPtr(data-&gt;mandatoryMinimum);
+        ValueFromBlock loopBound = m_out.anchor(loopBoundValue);
</ins><span class="cx">         m_out.branch(
</span><del>-            m_out.above(loopBound.value(), lengthAsPtr), unsure(undefinedLoop), unsure(mainLoopEntry));
</del><ins>+            m_out.above(loopBoundValue, lengthAsPtr), unsure(undefinedLoop), unsure(mainLoopEntry));
</ins><span class="cx">         
</span><span class="cx">         LBasicBlock lastNext = m_out.appendTo(undefinedLoop, mainLoopEntry);
</span><span class="cx">         LValue previousIndex = m_out.phi(m_out.intPtr, loopBound);
</span><span class="lines">@@ -5158,7 +5162,7 @@
</span><span class="cx">         
</span><span class="cx">         m_out.appendTo(mainLoopEntry, mainLoop);
</span><span class="cx">         loopBound = m_out.anchor(lengthAsPtr);
</span><del>-        m_out.branch(m_out.notNull(loopBound.value()), unsure(mainLoop), unsure(continuation));
</del><ins>+        m_out.branch(m_out.notNull(lengthAsPtr), unsure(mainLoop), unsure(continuation));
</ins><span class="cx">         
</span><span class="cx">         m_out.appendTo(mainLoop, continuation);
</span><span class="cx">         previousIndex = m_out.phi(m_out.intPtr, loopBound);
</span><span class="lines">@@ -5800,10 +5804,11 @@
</span><span class="cx">             } else
</span><span class="cx">                 m_out.jump(checkHole);
</span><span class="cx"> 
</span><del>-            LBasicBlock lastNext = m_out.appendTo(checkHole, slowCase); 
-            ValueFromBlock checkHoleResult = m_out.anchor(
-                m_out.notZero64(m_out.load64(baseIndex(heap, storage, index, m_node-&gt;child2()))));
-            m_out.branch(checkHoleResult.value(), usually(continuation), rarely(slowCase));
</del><ins>+            LBasicBlock lastNext = m_out.appendTo(checkHole, slowCase);
+            LValue checkHoleResultValue =
+                m_out.notZero64(m_out.load64(baseIndex(heap, storage, index, m_node-&gt;child2())));
+            ValueFromBlock checkHoleResult = m_out.anchor(checkHoleResultValue);
+            m_out.branch(checkHoleResultValue, usually(continuation), rarely(slowCase));
</ins><span class="cx"> 
</span><span class="cx">             m_out.appendTo(slowCase, continuation);
</span><span class="cx">             ValueFromBlock slowResult = m_out.anchor(m_out.equal(
</span><span class="lines">@@ -5836,8 +5841,9 @@
</span><span class="cx"> 
</span><span class="cx">             LBasicBlock lastNext = m_out.appendTo(checkHole, slowCase);
</span><span class="cx">             LValue doubleValue = m_out.loadDouble(baseIndex(heap, storage, index, m_node-&gt;child2()));
</span><del>-            ValueFromBlock checkHoleResult = m_out.anchor(m_out.doubleEqual(doubleValue, doubleValue));
-            m_out.branch(checkHoleResult.value(), usually(continuation), rarely(slowCase));
</del><ins>+            LValue checkHoleResultValue = m_out.doubleEqual(doubleValue, doubleValue);
+            ValueFromBlock checkHoleResult = m_out.anchor(checkHoleResultValue);
+            m_out.branch(checkHoleResultValue, usually(continuation), rarely(slowCase));
</ins><span class="cx">             
</span><span class="cx">             m_out.appendTo(slowCase, continuation);
</span><span class="cx">             ValueFromBlock slowResult = m_out.anchor(m_out.equal(
</span><span class="lines">@@ -7201,7 +7207,7 @@
</span><span class="cx">             });
</span><span class="cx">         ValueFromBlock slowArray = m_out.anchor(slowArrayValue);
</span><span class="cx">         ValueFromBlock slowButterfly = m_out.anchor(
</span><del>-            m_out.loadPtr(slowArray.value(), m_heaps.JSObject_butterfly));
</del><ins>+            m_out.loadPtr(slowArrayValue, m_heaps.JSObject_butterfly));
</ins><span class="cx"> 
</span><span class="cx">         m_out.jump(continuation);
</span><span class="cx">         
</span><span class="lines">@@ -7981,11 +7987,11 @@
</span><span class="cx">     {
</span><span class="cx">         LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;sensible doubleToInt32 slow path&quot;));
</span><span class="cx">         LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;sensible doubleToInt32 continuation&quot;));
</span><del>-        
-        ValueFromBlock fastResult = m_out.anchor(
-            m_out.sensibleDoubleToInt(doubleValue));
</del><ins>+
+        LValue fastResultValue = m_out.sensibleDoubleToInt(doubleValue);
+        ValueFromBlock fastResult = m_out.anchor(fastResultValue);
</ins><span class="cx">         m_out.branch(
</span><del>-            m_out.equal(fastResult.value(), m_out.constInt32(0x80000000)),
</del><ins>+            m_out.equal(fastResultValue, m_out.constInt32(0x80000000)),
</ins><span class="cx">             rarely(slowPath), usually(continuation));
</span><span class="cx">         
</span><span class="cx">         LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLStateh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLState.h (194091 => 194092)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLState.h        2015-12-15 04:43:03 UTC (rev 194091)
+++ trunk/Source/JavaScriptCore/ftl/FTLState.h        2015-12-15 04:52:55 UTC (rev 194092)
</span><span class="lines">@@ -42,8 +42,15 @@
</span><span class="cx"> #include &quot;FTLStackMaps.h&quot;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> 
</span><del>-namespace JSC { namespace FTL {
</del><ins>+namespace JSC {
</ins><span class="cx"> 
</span><ins>+namespace B3 {
+class PatchpointValue;
+class StackSlotValue;
+} // namespace B3
+
+namespace FTL {
+
</ins><span class="cx"> inline bool verboseCompilationEnabled()
</span><span class="cx"> {
</span><span class="cx">     return DFG::verboseCompilationEnabled(DFG::FTLMode);
</span><span class="lines">@@ -75,11 +82,11 @@
</span><span class="cx">     GeneratedFunction generatedFunction;
</span><span class="cx">     JITFinalizer* finalizer;
</span><span class="cx"> #if FTL_USES_B3
</span><del>-    LValue handleStackOverflowExceptionValue { nullptr };
-    LValue handleExceptionValue { nullptr };
-    LValue capturedValue { nullptr };
-    LValue varargsSpillSlotsValue { nullptr };
-    LValue exceptionHandlingSpillSlotValue { nullptr };
</del><ins>+    B3::PatchpointValue* handleStackOverflowExceptionValue { nullptr };
+    B3::PatchpointValue* handleExceptionValue { nullptr };
+    B3::StackSlotValue* capturedValue { nullptr };
+    B3::StackSlotValue* varargsSpillSlotsValue { nullptr };
+    B3::StackSlotValue* exceptionHandlingSpillSlotValue { nullptr };
</ins><span class="cx"> #else // FTL_USES_B3
</span><span class="cx">     unsigned handleStackOverflowExceptionStackmapID { UINT_MAX };
</span><span class="cx">     unsigned handleExceptionStackmapID { UINT_MAX };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressftlfunctiondotargumentswithcalleesavesjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/ftl-function-dot-arguments-with-callee-saves.js (0 => 194092)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/ftl-function-dot-arguments-with-callee-saves.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/ftl-function-dot-arguments-with-callee-saves.js        2015-12-15 04:52:55 UTC (rev 194092)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+function baz() {
+    return foo.arguments;
+}
+
+noInline(baz);
+
+function foo() {
+    return baz();
+}
+
+function bar(o, i) {
+    var x = o.f;
+    return [foo(1, 2, 3), x];
+}
+
+noInline(bar);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var a = bar({f:42});
+    if (a.length != 2 || a[0].length != 3 || a[0][0] != 1 || a[0][1] != 2 || a[0][2] != 3 || a[1] != 42)
+        throw &quot;Error: bad result: &quot; + a;
+}
+
</ins></span></pre>
</div>
</div>

</body>
</html>