<!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>[187618] 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/187618">187618</a></dd>
<dt>Author</dt> <dd>basile_clement@apple.com</dd>
<dt>Date</dt> <dd>2015-07-30 16:19:30 -0700 (Thu, 30 Jul 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>jsc-tailcall: Don't waste stack space when arity fixup was performed
https://bugs.webkit.org/show_bug.cgi?id=147447

Reviewed by Michael Saboff.

When doing a tail call, we overwrite an amount of stack space based on
the number of arguments in the call frame. If we entered the tail
caller by performing an arity fixup, this is incorrect and leads to
wasted stack space - we must use the CodeBlock's number of parameters
instead in that case.

This patch is also moving the prepareForTailCall() function from
jit/ThunkGenerators.h to the place where it should have always been,
namely jit/CCallHelpers.h

* jit/CCallHelpers.h:
(JSC::CCallHelpers::prepareForTailCallSlow):
* jit/JITCall.cpp:
(JSC::JIT::compileOpCall):
* jit/Repatch.cpp:
(JSC::linkPolymorphicCall):
* jit/ThunkGenerators.cpp:
(JSC::slowPathFor):
(JSC::virtualThunkFor):
* jit/ThunkGenerators.h:
* tests/stress/tail-call-no-stack-overflow.js:
(strictLoopArityFixup):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesjsctailcallSourceJavaScriptCoreChangeLog">branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorejitCCallHelpersh">branches/jsc-tailcall/Source/JavaScriptCore/jit/CCallHelpers.h</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorejitJITCallcpp">branches/jsc-tailcall/Source/JavaScriptCore/jit/JITCall.cpp</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorejitJITCall32_64cpp">branches/jsc-tailcall/Source/JavaScriptCore/jit/JITCall32_64.cpp</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorejitRepatchcpp">branches/jsc-tailcall/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorejitThunkGeneratorscpp">branches/jsc-tailcall/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCorejitThunkGeneratorsh">branches/jsc-tailcall/Source/JavaScriptCore/jit/ThunkGenerators.h</a></li>
<li><a href="#branchesjsctailcallSourceJavaScriptCoretestsstresstailcallnostackoverflowjs">branches/jsc-tailcall/Source/JavaScriptCore/tests/stress/tail-call-no-stack-overflow.js</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 (187617 => 187618)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog        2015-07-30 23:17:45 UTC (rev 187617)
+++ branches/jsc-tailcall/Source/JavaScriptCore/ChangeLog        2015-07-30 23:19:30 UTC (rev 187618)
</span><span class="lines">@@ -1,5 +1,35 @@
</span><span class="cx"> 2015-07-30  Basile Clement  &lt;basile_clement@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        jsc-tailcall: Don't waste stack space when arity fixup was performed
+        https://bugs.webkit.org/show_bug.cgi?id=147447
+
+        Reviewed by Michael Saboff.
+
+        When doing a tail call, we overwrite an amount of stack space based on
+        the number of arguments in the call frame. If we entered the tail
+        caller by performing an arity fixup, this is incorrect and leads to
+        wasted stack space - we must use the CodeBlock's number of parameters
+        instead in that case.
+
+        This patch is also moving the prepareForTailCall() function from
+        jit/ThunkGenerators.h to the place where it should have always been,
+        namely jit/CCallHelpers.h
+
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::prepareForTailCallSlow):
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileOpCall):
+        * jit/Repatch.cpp:
+        (JSC::linkPolymorphicCall):
+        * jit/ThunkGenerators.cpp:
+        (JSC::slowPathFor):
+        (JSC::virtualThunkFor):
+        * jit/ThunkGenerators.h:
+        * tests/stress/tail-call-no-stack-overflow.js:
+        (strictLoopArityFixup):
+
+2015-07-30  Basile Clement  &lt;basile_clement@apple.com&gt;
+
</ins><span class="cx">         jsc-tailcall: We should consider a tail call as an exit in the LLInt for the purpose of switching to the JIT
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=147449
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorejitCCallHelpersh"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/jit/CCallHelpers.h (187617 => 187618)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/jit/CCallHelpers.h        2015-07-30 23:17:45 UTC (rev 187617)
+++ branches/jsc-tailcall/Source/JavaScriptCore/jit/CCallHelpers.h        2015-07-30 23:19:30 UTC (rev 187618)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;AssemblyHelpers.h&quot;
</span><span class="cx"> #include &quot;GPRInfo.h&quot;
</span><ins>+#include &quot;StackAlignment.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -2020,6 +2021,70 @@
</span><span class="cx">         loadPtr(&amp;vm()-&gt;targetMachinePCForThrow, GPRInfo::regT1);
</span><span class="cx">         jump(GPRInfo::regT1);
</span><span class="cx">     }
</span><ins>+
+    void prepareForTailCallSlow(const TempRegisterSet&amp; usedRegisters = { RegisterSet::specialRegisters() })
+    {
+        GPRReg temp1 = usedRegisters.getFreeGPR(0);
+        GPRReg temp2 = usedRegisters.getFreeGPR(1);
+        ASSERT(temp2 != InvalidGPRReg);
+
+        subPtr(TrustedImm32(sizeof(CallerFrameAndPC)), stackPointerRegister);
+        loadPtr(Address(GPRInfo::callFrameRegister), temp1);
+        storePtr(temp1, Address(stackPointerRegister));
+        loadPtr(Address(GPRInfo::callFrameRegister, sizeof(void*)), temp1);
+        storePtr(temp1, Address(stackPointerRegister, sizeof(void*)));
+
+        // Now stackPointerRegister points to a valid call frame for the callee
+        // and callFrameRegister points to our own call frame.
+        // We now slide the callee's call frame over our own call frame,
+        // starting with the top to avoid unwanted overwrites
+
+        // Move the callFrameRegister to the top of our (trashed) call frame
+        load32(Address(GPRInfo::callFrameRegister, JSStack::ArgumentCount * static_cast&lt;int&gt;(sizeof(Register)) + PayloadOffset),
+            temp1);
+
+        // We need to use the number of parameters instead of the argument count in case of arity fixup
+        loadPtr(Address(GPRInfo::callFrameRegister, JSStack::CodeBlock * static_cast&lt;int&gt;(sizeof(Register))), temp2);
+        load32(Address(temp2, CodeBlock::offsetOfNumParameters()), temp2);
+        MacroAssembler::Jump argumentCountWasNotFixedUp = branch32(BelowOrEqual, temp2, temp1);
+        move(temp2, temp1);
+        argumentCountWasNotFixedUp.link(this);
+
+        add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), temp1);
+        and32(TrustedImm32(-stackAlignmentRegisters()), temp1);
+        mul32(TrustedImm32(sizeof(Register)), temp1, temp1);
+        addPtr(temp1, GPRInfo::callFrameRegister);
+
+        // Compute the call frame size of the callee's call frame
+        load32(Address(stackPointerRegister, JSStack::ArgumentCount * static_cast&lt;int&gt;(sizeof(Register)) + PayloadOffset),
+            temp2);
+        add32(TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), temp2);
+        and32(TrustedImm32(-stackAlignmentRegisters()), temp2);
+
+#if USE(JSVALUE32_64)
+        COMPILE_ASSERT(sizeof(void*) * 2 == sizeof(Register), Register_is_two_pointers_sized);
+        lshift32(TrustedImm32(1), temp2);
+#endif
+
+        // Do the sliding
+        MacroAssembler::Label copyLoop(label());
+
+        subPtr(TrustedImm32(sizeof(void*)), GPRInfo::callFrameRegister);
+        sub32(TrustedImm32(1), temp2);
+        loadPtr(BaseIndex(stackPointerRegister, temp2, MacroAssembler::timesPtr()), temp1);
+        storePtr(temp1, Address(GPRInfo::callFrameRegister));
+
+        branchTest32(MacroAssembler::NonZero, temp2).linkTo(copyLoop, this);
+
+        emitFunctionEpilogue();
+    }
+
+    void prepareForTailCallSlow(GPRReg calleeGPR)
+    {
+        TempRegisterSet usedRegisters { RegisterSet::specialRegisters() };
+        usedRegisters.set(calleeGPR);
+        prepareForTailCallSlow(usedRegisters);
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/jit/JITCall.cpp (187617 => 187618)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/jit/JITCall.cpp        2015-07-30 23:17:45 UTC (rev 187617)
+++ branches/jsc-tailcall/Source/JavaScriptCore/jit/JITCall.cpp        2015-07-30 23:19:30 UTC (rev 187618)
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx">     m_callCompilationInfo[callLinkInfoIndex].callLinkInfo = info;
</span><span class="cx"> 
</span><span class="cx">     if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
</span><del>-        prepareForTailCall(*this);
</del><ins>+        prepareForTailCallSlow();
</ins><span class="cx">         m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall();
</span><span class="cx">         // We must never come back here
</span><span class="cx">         breakpoint();
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/jit/JITCall32_64.cpp (187617 => 187618)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-07-30 23:17:45 UTC (rev 187617)
+++ branches/jsc-tailcall/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-07-30 23:19:30 UTC (rev 187618)
</span><span class="lines">@@ -276,7 +276,7 @@
</span><span class="cx"> 
</span><span class="cx">     checkStackPointerAlignment();
</span><span class="cx">     if (opcodeID == op_tail_call || opcodeID == op_tail_call_varargs) {
</span><del>-        prepareForTailCall(*this);
</del><ins>+        prepareForTailCallSlow();
</ins><span class="cx">         m_callCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedTailCall();
</span><span class="cx">         // We must never come back here
</span><span class="cx">         breakpoint();
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/jit/Repatch.cpp (187617 => 187618)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/jit/Repatch.cpp        2015-07-30 23:17:45 UTC (rev 187617)
+++ branches/jsc-tailcall/Source/JavaScriptCore/jit/Repatch.cpp        2015-07-30 23:19:30 UTC (rev 187618)
</span><span class="lines">@@ -1881,7 +1881,7 @@
</span><span class="cx">                 CCallHelpers::Address(fastCountsBaseGPR, caseIndex * sizeof(uint32_t)));
</span><span class="cx">         }
</span><span class="cx">         if (CallLinkInfo::isTailCallType(callLinkInfo.callType())) {
</span><del>-            prepareForTailCall(stubJit);
</del><ins>+            stubJit.prepareForTailCallSlow();
</ins><span class="cx">             calls[caseIndex].call = stubJit.nearTailCall();
</span><span class="cx">         } else
</span><span class="cx">             calls[caseIndex].call = stubJit.nearCall();
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/jit/ThunkGenerators.cpp (187617 => 187618)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-07-30 23:17:45 UTC (rev 187617)
+++ branches/jsc-tailcall/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-07-30 23:19:30 UTC (rev 187618)
</span><span class="lines">@@ -102,9 +102,7 @@
</span><span class="cx">     CCallHelpers::Jump doNotTrash = jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::returnValueGPR2);
</span><span class="cx"> 
</span><span class="cx">     jit.preserveReturnAddressAfterCall(GPRInfo::nonPreservedNonReturnGPR);
</span><del>-    jit.move(GPRInfo::returnValueGPR, GPRInfo::regT4); // FIXME
-    prepareForTailCall(jit);
-    jit.jump(GPRInfo::regT4);
</del><ins>+    jit.prepareForTailCallSlow(GPRInfo::returnValueGPR);
</ins><span class="cx"> 
</span><span class="cx">     doNotTrash.link(&amp;jit);
</span><span class="cx">     jit.jump(GPRInfo::returnValueGPR);
</span><span class="lines">@@ -195,7 +193,7 @@
</span><span class="cx">     emitPointerValidation(jit, GPRInfo::regT4);
</span><span class="cx">     if (CallLinkInfo::isTailCallType(callLinkInfo.callType())) {
</span><span class="cx">         jit.preserveReturnAddressAfterCall(GPRInfo::regT0);
</span><del>-        prepareForTailCall(jit);
</del><ins>+        jit.prepareForTailCallSlow(GPRInfo::regT4);
</ins><span class="cx">     }
</span><span class="cx">     jit.jump(GPRInfo::regT4);
</span><span class="cx"> 
</span><span class="lines">@@ -461,51 +459,6 @@
</span><span class="cx">     return FINALIZE_CODE(patchBuffer, (&quot;unreachable thunk&quot;));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void prepareForTailCall(CCallHelpers&amp; jit)
-{
-    jit.subPtr(CCallHelpers::TrustedImm32(sizeof(CallerFrameAndPC)), JSInterfaceJIT::stackPointerRegister);
-    jit.loadPtr(CCallHelpers::Address(JSInterfaceJIT::callFrameRegister), JSInterfaceJIT::regT1);
-    jit.storePtr(JSInterfaceJIT::regT1, CCallHelpers::Address(JSInterfaceJIT::stackPointerRegister));
-    jit.loadPtr(CCallHelpers::Address(JSInterfaceJIT::callFrameRegister, sizeof(void*)), JSInterfaceJIT::regT1);
-    jit.storePtr(JSInterfaceJIT::regT1, CCallHelpers::Address(JSInterfaceJIT::stackPointerRegister, sizeof(void*)));
-
-    // Now stackPointerRegister points to a valid call frame for the callee
-    // and callFrameRegister points to our own call frame.
-    // We now slide the callee's call frame over our own call frame,
-    // starting with the top to avoid unwanted overwrites
-
-    // Move the callFrameRegister to the top of our (trashed) call frame
-    jit.load32(CCallHelpers::Address(JSInterfaceJIT::callFrameRegister, JSStack::ArgumentCount * static_cast&lt;int&gt;(sizeof(Register)) + PayloadOffset),
-        JSInterfaceJIT::regT1);
-    jit.add32(CCallHelpers::TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), JSInterfaceJIT::regT1);
-    jit.and32(CCallHelpers::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::regT1);
-    jit.mul32(CCallHelpers::TrustedImm32(sizeof(Register)), JSInterfaceJIT::regT1, JSInterfaceJIT::regT1);
-    jit.addPtr(JSInterfaceJIT::regT1, JSInterfaceJIT::callFrameRegister);
-
-    // Compute the call frame size of the callee's call frame
-    jit.load32(CCallHelpers::Address(JSInterfaceJIT::stackPointerRegister, JSStack::ArgumentCount * static_cast&lt;int&gt;(sizeof(Register)) + PayloadOffset),
-        JSInterfaceJIT::regT2);
-    jit.add32(CCallHelpers::TrustedImm32(stackAlignmentRegisters() + JSStack::CallFrameHeaderSize - 1), JSInterfaceJIT::regT2);
-    jit.and32(CCallHelpers::TrustedImm32(-stackAlignmentRegisters()), JSInterfaceJIT::regT2);
-
-#if USE(JSVALUE32_64)
-    COMPILE_ASSERT(sizeof(void*) * 2 == sizeof(Register), Register_is_two_pointers_sized);
-    jit.lshift32(CCallHelpers::TrustedImm32(1), JSInterfaceJIT::regT2);
-#endif
-
-    // Do the sliding
-    MacroAssembler::Label copyLoop(jit.label());
-
-    jit.subPtr(CCallHelpers::TrustedImm32(sizeof(void*)), JSInterfaceJIT::callFrameRegister);
-    jit.sub32(CCallHelpers::TrustedImm32(1), JSInterfaceJIT::regT2);
-    jit.loadPtr(CCallHelpers::BaseIndex(JSInterfaceJIT::stackPointerRegister, JSInterfaceJIT::regT2, MacroAssembler::timesPtr()), JSInterfaceJIT::regT1);
-    jit.storePtr(JSInterfaceJIT::regT1, CCallHelpers::Address(JSInterfaceJIT::callFrameRegister));
-
-    jit.branchTest32(MacroAssembler::NonZero, JSInterfaceJIT::regT2).linkTo(copyLoop, &amp;jit);
-
-    jit.emitFunctionEpilogue();
-}
-
</del><span class="cx"> MacroAssemblerCodeRef baselineGetterReturnThunkGenerator(VM* vm)
</span><span class="cx"> {
</span><span class="cx">     JSInterfaceJIT jit(vm);
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCorejitThunkGeneratorsh"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/jit/ThunkGenerators.h (187617 => 187618)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-07-30 23:17:45 UTC (rev 187617)
+++ branches/jsc-tailcall/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-07-30 23:19:30 UTC (rev 187618)
</span><span class="lines">@@ -49,8 +49,6 @@
</span><span class="cx"> MacroAssemblerCodeRef arityFixupGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef unreachableGenerator(VM*);
</span><span class="cx"> 
</span><del>-void prepareForTailCall(CCallHelpers&amp; jit);
-
</del><span class="cx"> MacroAssemblerCodeRef baselineGetterReturnThunkGenerator(VM* vm);
</span><span class="cx"> MacroAssemblerCodeRef baselineSetterReturnThunkGenerator(VM* vm);
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesjsctailcallSourceJavaScriptCoretestsstresstailcallnostackoverflowjs"></a>
<div class="modfile"><h4>Modified: branches/jsc-tailcall/Source/JavaScriptCore/tests/stress/tail-call-no-stack-overflow.js (187617 => 187618)</h4>
<pre class="diff"><span>
<span class="info">--- branches/jsc-tailcall/Source/JavaScriptCore/tests/stress/tail-call-no-stack-overflow.js        2015-07-30 23:17:45 UTC (rev 187617)
+++ branches/jsc-tailcall/Source/JavaScriptCore/tests/stress/tail-call-no-stack-overflow.js        2015-07-30 23:19:30 UTC (rev 187618)
</span><span class="lines">@@ -24,5 +24,14 @@
</span><span class="cx">         return strictLoop(n - 1);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+function strictLoopArityFixup(n, dummy) {
+    &quot;use strict&quot;;
+    if (n &gt; 0)
+        return strictLoopArityFixup(n - 1);
+}
+
</ins><span class="cx"> shouldThrow(function () { sloppyLoop(100000); }, 'RangeError: Maximum call stack size exceeded.');
</span><ins>+
+// These should not throw
</ins><span class="cx"> strictLoop(100000);
</span><ins>+strictLoopArityFixup(100000);
</ins></span></pre>
</div>
</div>

</body>
</html>