<!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>[179887] 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/179887">179887</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-02-10 15:16:36 -0800 (Tue, 10 Feb 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>op_call_varargs should only load the length once
https://bugs.webkit.org/show_bug.cgi?id=141440
rdar://problem/19761683

Reviewed by Michael Saboff.
        
Refactors the pair of calls that set up the varargs frame so that the first call returns the
length, and the second call uses the length returned by the first one. It turns out that this
gave me an opportunity to shorten a lot of the code.

* interpreter/Interpreter.cpp:
(JSC::sizeFrameForVarargs):
(JSC::loadVarargs):
(JSC::setupVarargsFrame):
(JSC::setupVarargsFrameAndSetThis):
* interpreter/Interpreter.h:
(JSC::calleeFrameForVarargs):
* jit/CCallHelpers.h:
(JSC::CCallHelpers::setupArgumentsWithExecState):
* jit/JIT.h:
* jit/JITCall.cpp:
(JSC::JIT::compileSetupVarargsFrame):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileSetupVarargsFrame):
* jit/JITInlines.h:
(JSC::JIT::callOperation):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/SetupVarargsFrame.cpp:
(JSC::emitSetVarargsFrame):
(JSC::emitSetupVarargsFrameFastCase):
* jit/SetupVarargsFrame.h:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/Arguments.cpp:
(JSC::Arguments::copyToArguments):
* runtime/Arguments.h:
* runtime/JSArray.cpp:
(JSC::JSArray::copyToArguments):
* runtime/JSArray.h:
* runtime/VM.h:
* tests/stress/call-varargs-length-effects.js: Added.
(foo):
(bar):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpretercpp">trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterInterpreterh">trunk/Source/JavaScriptCore/interpreter/Interpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitCCallHelpersh">trunk/Source/JavaScriptCore/jit/CCallHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCallcpp">trunk/Source/JavaScriptCore/jit/JITCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCall32_64cpp">trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlinesh">trunk/Source/JavaScriptCore/jit/JITInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitSetupVarargsFramecpp">trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitSetupVarargsFrameh">trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArgumentscpp">trunk/Source/JavaScriptCore/runtime/Arguments.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArgumentsh">trunk/Source/JavaScriptCore/runtime/Arguments.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArraycpp">trunk/Source/JavaScriptCore/runtime/JSArray.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArrayh">trunk/Source/JavaScriptCore/runtime/JSArray.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresscallvarargslengtheffectsjs">trunk/Source/JavaScriptCore/tests/stress/call-varargs-length-effects.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -1,3 +1,50 @@
</span><ins>+2015-02-10  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        op_call_varargs should only load the length once
+        https://bugs.webkit.org/show_bug.cgi?id=141440
+        rdar://problem/19761683
+
+        Reviewed by Michael Saboff.
+        
+        Refactors the pair of calls that set up the varargs frame so that the first call returns the
+        length, and the second call uses the length returned by the first one. It turns out that this
+        gave me an opportunity to shorten a lot of the code.
+
+        * interpreter/Interpreter.cpp:
+        (JSC::sizeFrameForVarargs):
+        (JSC::loadVarargs):
+        (JSC::setupVarargsFrame):
+        (JSC::setupVarargsFrameAndSetThis):
+        * interpreter/Interpreter.h:
+        (JSC::calleeFrameForVarargs):
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::setupArgumentsWithExecState):
+        * jit/JIT.h:
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileSetupVarargsFrame):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::compileSetupVarargsFrame):
+        * jit/JITInlines.h:
+        (JSC::JIT::callOperation):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * jit/SetupVarargsFrame.cpp:
+        (JSC::emitSetVarargsFrame):
+        (JSC::emitSetupVarargsFrameFastCase):
+        * jit/SetupVarargsFrame.h:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/Arguments.cpp:
+        (JSC::Arguments::copyToArguments):
+        * runtime/Arguments.h:
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::copyToArguments):
+        * runtime/JSArray.h:
+        * runtime/VM.h:
+        * tests/stress/call-varargs-length-effects.js: Added.
+        (foo):
+        (bar):
+
</ins><span class="cx"> 2015-02-10  Michael Saboff  &lt;msaboff@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Crash in JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2008 Cameron Zwarich &lt;cwzwarich@uwaterloo.ca&gt;
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -134,158 +134,80 @@
</span><span class="cx">     return interpreter-&gt;execute(eval, callFrame, thisValue, callerScopeChain);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CallFrame* sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset)
</del><ins>+unsigned sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset)
</ins><span class="cx"> {
</span><del>-    if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
-        unsigned argumentCountIncludingThis = callFrame-&gt;argumentCountIncludingThis();
-        if (argumentCountIncludingThis &gt; firstVarArgOffset)
-            argumentCountIncludingThis -= firstVarArgOffset;
-        else
-            argumentCountIncludingThis = 1;
-        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
-        CallFrame* newCallFrame = CallFrame::create(callFrame-&gt;registers() - paddedCalleeFrameOffset);
-        if (argumentCountIncludingThis &gt; Arguments::MaxArguments + 1 || !stack-&gt;ensureCapacityFor(newCallFrame-&gt;registers())) {
-            throwStackOverflowError(callFrame);
-            return 0;
-        }
-        return newCallFrame;
-    }
-
-    if (arguments.isUndefinedOrNull()) {
-        unsigned argumentCountIncludingThis = 1;
-        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(),  numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
-        CallFrame* newCallFrame = CallFrame::create(callFrame-&gt;registers() - paddedCalleeFrameOffset);
-        if (!stack-&gt;ensureCapacityFor(newCallFrame-&gt;registers())) {
-            throwStackOverflowError(callFrame);
-            return 0;
-        }
-        return newCallFrame;
-    }
-
-    if (!arguments.isObject()) {
</del><ins>+    unsigned length;
+    if (!arguments)
+        length = callFrame-&gt;argumentCount();
+    else if (arguments.isUndefinedOrNull())
+        length = 0;
+    else if (!arguments.isObject()) {
</ins><span class="cx">         callFrame-&gt;vm().throwException(callFrame, createInvalidParameterError(callFrame, &quot;Function.prototype.apply&quot;, arguments));
</span><span class="cx">         return 0;
</span><del>-    }
-
-    if (asObject(arguments)-&gt;classInfo() == Arguments::info()) {
-        Arguments* argsObject = asArguments(arguments);
-        unsigned argCount = argsObject-&gt;length(callFrame);
-        if (argCount &gt;= firstVarArgOffset)
-            argCount -= firstVarArgOffset;
-        else
-            argCount = 0;
-        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numUsedStackSlots + argCount + 1 + JSStack::CallFrameHeaderSize);
-        CallFrame* newCallFrame = CallFrame::create(callFrame-&gt;registers() - paddedCalleeFrameOffset);
-        if (argCount &gt; Arguments::MaxArguments || !stack-&gt;ensureCapacityFor(newCallFrame-&gt;registers())) {
-            throwStackOverflowError(callFrame);
-            return 0;
-        }
-        return newCallFrame;
-    }
-
-    if (isJSArray(arguments)) {
-        JSArray* array = asArray(arguments);
-        unsigned argCount = array-&gt;length();
-        if (argCount &gt;= firstVarArgOffset)
-            argCount -= firstVarArgOffset;
-        else
-            argCount = 0;
-        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numUsedStackSlots + argCount + 1 + JSStack::CallFrameHeaderSize);
-        CallFrame* newCallFrame = CallFrame::create(callFrame-&gt;registers() - paddedCalleeFrameOffset);
-        if (argCount &gt; Arguments::MaxArguments || !stack-&gt;ensureCapacityFor(newCallFrame-&gt;registers())) {
-            throwStackOverflowError(callFrame);
-            return 0;
-        }
-        return newCallFrame;
-    }
-
-    JSObject* argObject = asObject(arguments);
-    unsigned argCount = argObject-&gt;get(callFrame, callFrame-&gt;propertyNames().length).toUInt32(callFrame);
-    if (argCount &gt;= firstVarArgOffset)
-        argCount -= firstVarArgOffset;
</del><ins>+    } else if (asObject(arguments)-&gt;classInfo() == Arguments::info())
+        length = asArguments(arguments)-&gt;length(callFrame);
+    else if (isJSArray(arguments))
+        length = asArray(arguments)-&gt;length();
</ins><span class="cx">     else
</span><del>-        argCount = 0;
-    unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numUsedStackSlots + argCount + 1 + JSStack::CallFrameHeaderSize);
-    CallFrame* newCallFrame = CallFrame::create(callFrame-&gt;registers() - paddedCalleeFrameOffset);
-    if (argCount &gt; Arguments::MaxArguments || !stack-&gt;ensureCapacityFor(newCallFrame-&gt;registers())) {
</del><ins>+        length = asObject(arguments)-&gt;get(callFrame, callFrame-&gt;propertyNames().length).toUInt32(callFrame);
+    
+    if (length &gt;= firstVarArgOffset)
+        length -= firstVarArgOffset;
+    else
+        length = 0;
+    
+    CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1);
+    if (length &gt; Arguments::MaxArguments || !stack-&gt;ensureCapacityFor(calleeFrame-&gt;registers())) {
</ins><span class="cx">         throwStackOverflowError(callFrame);
</span><span class="cx">         return 0;
</span><span class="cx">     }
</span><del>-    return newCallFrame;
</del><ins>+    
+    return length;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, VirtualRegister countDest, JSValue arguments, uint32_t firstVarArgOffset)
</del><ins>+void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, JSValue arguments, uint32_t offset, uint32_t length)
</ins><span class="cx"> {
</span><span class="cx">     if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
</span><del>-        unsigned argumentCountIncludingThis = callFrame-&gt;argumentCountIncludingThis();
-        if (argumentCountIncludingThis &gt; firstVarArgOffset)
-            argumentCountIncludingThis -= firstVarArgOffset;
-        else
-            argumentCountIncludingThis = 1;
-        callFrame-&gt;r(countDest).payload() = argumentCountIncludingThis;
-        for (size_t i = firstVarArgOffset; i &lt; callFrame-&gt;argumentCount(); ++i)
-            callFrame-&gt;r(firstElementDest + i - firstVarArgOffset) = callFrame-&gt;argumentAfterCapture(i);
</del><ins>+        for (size_t i = 0; i &lt; length; ++i)
+            callFrame-&gt;r(firstElementDest + i) = callFrame-&gt;argumentAfterCapture(i + offset);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (arguments.isUndefinedOrNull()) {
-        callFrame-&gt;r(countDest).payload() = 1;
</del><ins>+    if (arguments.isUndefinedOrNull())
</ins><span class="cx">         return;
</span><del>-    }
</del><span class="cx">     
</span><span class="cx">     if (asObject(arguments)-&gt;classInfo() == Arguments::info()) {
</span><del>-        Arguments* argsObject = asArguments(arguments);
-        unsigned argCount = argsObject-&gt;length(callFrame);
-        if (argCount &gt;= firstVarArgOffset) {
-            argCount -= firstVarArgOffset;
-            callFrame-&gt;r(countDest).payload() = argCount + 1;
-            argsObject-&gt;copyToArguments(callFrame, firstElementDest, argCount, firstVarArgOffset);
-        } else
-            callFrame-&gt;r(countDest).payload() = 1;
</del><ins>+        asArguments(arguments)-&gt;copyToArguments(callFrame, firstElementDest, offset, length);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     if (isJSArray(arguments)) {
</span><del>-        JSArray* array = asArray(arguments);
-        unsigned argCount = array-&gt;length();
-        if (argCount &gt;= firstVarArgOffset) {
-            argCount -= firstVarArgOffset;
-            callFrame-&gt;r(countDest).payload() = argCount + 1;
-            array-&gt;copyToArguments(callFrame, firstElementDest, argCount, firstVarArgOffset);
-        } else
-            callFrame-&gt;r(countDest).payload() = 1;
</del><ins>+        asArray(arguments)-&gt;copyToArguments(callFrame, firstElementDest, offset, length);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    JSObject* argObject = asObject(arguments);
-    unsigned argCount = argObject-&gt;get(callFrame, callFrame-&gt;propertyNames().length).toUInt32(callFrame);
-    if (argCount &gt;= firstVarArgOffset) {
-        argCount -= firstVarArgOffset;
-        callFrame-&gt;r(countDest).payload() = argCount + 1;
-    } else
-        callFrame-&gt;r(countDest).payload() = 1;
-
-    for (size_t i = 0; i &lt; argCount; ++i) {
-        callFrame-&gt;r(firstElementDest + i) = asObject(arguments)-&gt;get(callFrame, i + firstVarArgOffset);
</del><ins>+    for (unsigned i = 0; i &lt; length; ++i) {
+        callFrame-&gt;r(firstElementDest + i) = asObject(arguments)-&gt;get(callFrame, i + offset);
</ins><span class="cx">         if (UNLIKELY(callFrame-&gt;vm().exception()))
</span><span class="cx">             return;
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void setupVarargsFrame(CallFrame* callFrame, CallFrame* newCallFrame, JSValue arguments, uint32_t firstVarArgOffset)
</del><ins>+void setupVarargsFrame(CallFrame* callFrame, CallFrame* newCallFrame, JSValue arguments, uint32_t offset, uint32_t length)
</ins><span class="cx"> {
</span><span class="cx">     VirtualRegister calleeFrameOffset(newCallFrame - callFrame);
</span><span class="cx">     
</span><span class="cx">     loadVarargs(
</span><span class="cx">         callFrame,
</span><span class="cx">         calleeFrameOffset + CallFrame::argumentOffset(0),
</span><del>-        calleeFrameOffset + JSStack::ArgumentCount,
-        arguments, firstVarArgOffset);
</del><ins>+        arguments, offset, length);
+    
+    newCallFrame-&gt;setArgumentCountIncludingThis(length + 1);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void setupVarargsFrameAndSetThis(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset)
</del><ins>+void setupVarargsFrameAndSetThis(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length)
</ins><span class="cx"> {
</span><del>-    setupVarargsFrame(callFrame, newCallFrame, arguments, firstVarArgOffset);
</del><ins>+    setupVarargsFrame(callFrame, newCallFrame, arguments, firstVarArgOffset, length);
</ins><span class="cx">     newCallFrame-&gt;setThisValue(thisValue);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/Interpreter.h (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/interpreter/Interpreter.h        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2013, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
</span><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> #include &quot;LLIntData.h&quot;
</span><span class="cx"> #include &quot;Opcode.h&quot;
</span><span class="cx"> #include &quot;SourceProvider.h&quot;
</span><ins>+#include &quot;StackAlignment.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> #include &lt;wtf/HashMap.h&gt;
</span><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><span class="lines">@@ -298,10 +299,19 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     JSValue eval(CallFrame*);
</span><del>-    CallFrame* sizeFrameForVarargs(CallFrame* exec, JSStack*, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset);
-    void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, VirtualRegister countDest, JSValue source, uint32_t offset);
-    void setupVarargsFrame(CallFrame* execCaller, CallFrame* execCallee, JSValue arguments, uint32_t firstVarArgOffset);
-    void setupVarargsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset);
</del><ins>+
+    inline CallFrame* calleeFrameForVarargs(CallFrame* callFrame, unsigned numUsedStackSlots, unsigned argumentCountIncludingThis)
+    {
+        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(
+            stackAlignmentRegisters(),
+            numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
+        return CallFrame::create(callFrame-&gt;registers() - paddedCalleeFrameOffset);
+    }
+
+    unsigned sizeFrameForVarargs(CallFrame* exec, JSStack*, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset);
+    void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, JSValue source, uint32_t offset, uint32_t length);
+    void setupVarargsFrame(CallFrame* execCaller, CallFrame* execCallee, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
+    void setupVarargsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
</ins><span class="cx">     
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitCCallHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/CCallHelpers.h (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/jit/CCallHelpers.h        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -435,6 +435,17 @@
</span><span class="cx">         addCallArgument(arg4);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4, GPRReg arg5)
+    {
+        resetCallArguments();
+        addCallArgument(GPRInfo::callFrameRegister);
+        addCallArgument(arg1);
+        addCallArgument(arg2);
+        addCallArgument(arg3);
+        addCallArgument(arg4);
+        addCallArgument(arg5);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE void setupArgumentsWithExecState(TrustedImm32 arg1, TrustedImmPtr arg2, GPRReg arg3)
</span><span class="cx">     {
</span><span class="cx">         resetCallArguments();
</span><span class="lines">@@ -1381,6 +1392,12 @@
</span><span class="cx">         setupArgumentsWithExecState(arg1, arg2, arg3);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4, GPRReg arg5)
+    {
+        poke(arg4, POKE_ARGUMENT_OFFSET);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, GPRReg arg3,  GPRReg arg4)
</span><span class="cx">     {
</span><span class="cx">         poke(arg4, POKE_ARGUMENT_OFFSET);
</span><span class="lines">@@ -1528,6 +1545,12 @@
</span><span class="cx">         setupArgumentsWithExecState(arg1, arg2, arg3);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4)
+    {
+        poke(arg4, POKE_ARGUMENT_OFFSET);
+        setupArgumentsWithExecState(arg1, arg2, arg3);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4, GPRReg arg5)
</span><span class="cx">     {
</span><span class="cx">         poke(arg5, POKE_ARGUMENT_OFFSET + 1);
</span><span class="lines">@@ -1769,6 +1792,13 @@
</span><span class="cx">         move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4)
+    {
+        setupThreeStubArgsGPR&lt;GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, GPRInfo::argumentGPR4&gt;(arg1, arg2, arg4);
+        move(arg3, GPRInfo::argumentGPR3);
+        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+    }
+
</ins><span class="cx">     ALWAYS_INLINE void setupArguments(GPRReg arg1, TrustedImmPtr arg2, GPRReg arg3, GPRReg arg4, TrustedImmPtr arg5)
</span><span class="cx">     {
</span><span class="cx">         setupThreeStubArgsGPR&lt;GPRInfo::argumentGPR0, GPRInfo::argumentGPR2, GPRInfo::argumentGPR3&gt;(arg1, arg3, arg4);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -679,7 +679,7 @@
</span><span class="cx">         MacroAssembler::Call callOperation(C_JITOperation_EL, TrustedImmPtr);
</span><span class="cx">         MacroAssembler::Call callOperation(C_JITOperation_ESt, Structure*);
</span><span class="cx">         MacroAssembler::Call callOperation(C_JITOperation_EZ, int32_t);
</span><del>-        MacroAssembler::Call callOperation(F_JITOperation_EJZZ, GPRReg, int32_t, int32_t);
</del><ins>+        MacroAssembler::Call callOperation(Z_JITOperation_EJZZ, GPRReg, int32_t, int32_t);
</ins><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_E, int);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EAapJ, int, ArrayAllocationProfile*, GPRReg);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EAapJcpZ, int, ArrayAllocationProfile*, GPRReg, int32_t);
</span><span class="lines">@@ -730,7 +730,7 @@
</span><span class="cx"> #endif
</span><span class="cx">         MacroAssembler::Call callOperation(V_JITOperation_EJIdJJ, RegisterID, const Identifier*, RegisterID, RegisterID);
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-        MacroAssembler::Call callOperation(F_JITOperation_EFJZ, RegisterID, RegisterID, int32_t);
</del><ins>+        MacroAssembler::Call callOperation(F_JITOperation_EFJZZ, RegisterID, RegisterID, int32_t, RegisterID);
</ins><span class="cx">         MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, StringImpl*);
</span><span class="cx"> #else
</span><span class="cx">         MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, RegisterID, RegisterID, StringImpl*);
</span><span class="lines">@@ -745,8 +745,8 @@
</span><span class="cx">         MacroAssembler::Call callOperationWithCallFrameRollbackOnException(V_JITOperation_ECb, CodeBlock*);
</span><span class="cx">         MacroAssembler::Call callOperationWithCallFrameRollbackOnException(Z_JITOperation_E);
</span><span class="cx"> #if USE(JSVALUE32_64)
</span><del>-        MacroAssembler::Call callOperation(F_JITOperation_EFJZ, RegisterID, RegisterID, RegisterID, int32_t);
-        MacroAssembler::Call callOperation(F_JITOperation_EJZZ, GPRReg, GPRReg, int32_t, int32_t);
</del><ins>+        MacroAssembler::Call callOperation(F_JITOperation_EFJZZ, RegisterID, RegisterID, RegisterID, int32_t, RegisterID);
+        MacroAssembler::Call callOperation(Z_JITOperation_EJZZ, GPRReg, GPRReg, int32_t, int32_t);
</ins><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EAapJ, int, ArrayAllocationProfile*, GPRReg, GPRReg);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg, GPRReg);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJIdc, int, GPRReg, GPRReg, const Identifier*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall.cpp (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -80,9 +80,11 @@
</span><span class="cx"> 
</span><span class="cx">     emitGetVirtualRegister(arguments, regT1);
</span><span class="cx">     callOperation(operationSizeFrameForVarargs, regT1, -firstFreeRegister, firstVarArgOffset);
</span><del>-    move(returnValueGPR, stackPointerRegister);
-    emitGetVirtualRegister(arguments, regT1);
-    callOperation(operationSetupVarargsFrame, returnValueGPR, regT1, firstVarArgOffset);
</del><ins>+    move(TrustedImm32(-firstFreeRegister), regT1);
+    emitSetVarargsFrame(*this, returnValueGPR, false, regT1, regT1);
+    addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)))), regT1, stackPointerRegister);
+    emitGetVirtualRegister(arguments, regT2);
+    callOperation(operationSetupVarargsFrame, regT1, regT2, firstVarArgOffset, regT0);
</ins><span class="cx">     move(returnValueGPR, regT1);
</span><span class="cx"> 
</span><span class="cx">     if (canOptimize)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -140,16 +140,11 @@
</span><span class="cx"> 
</span><span class="cx">     emitLoad(arguments, regT1, regT0);
</span><span class="cx">     callOperation(operationSizeFrameForVarargs, regT1, regT0, -firstFreeRegister, firstVarArgOffset);
</span><del>-    // This is spectacularly dirty. We want to pass four arguments to operationSetupVarargsFrame. On x86-32 we
-    // will pass them on the stack. We want four stack slots, or 16 bytes. Extending the stack by 8 bytes
-    // over where we planned on pointing the FP gives us enough room. The reason is that the FP gives an
-    // extra CallerFrameAndPC bytes beyond where SP should point prior to the call. So if we just did
-    // move(returnValueGPR, stackPointerRegister), we'd have enough room for passing two args, or 8
-    // bytes - except that we'd have a misaligned stack. So if we subtract *another* CallerFrameAndPC
-    // bytes, we are up to 16 bytes of spare room *and* we have an aligned stack. Gross, but correct!
-    addPtr(TrustedImm32(-sizeof(CallerFrameAndPC)), returnValueGPR, stackPointerRegister);
-    emitLoad(arguments, regT2, regT1);
-    callOperation(operationSetupVarargsFrame, returnValueGPR, regT2, regT1, firstVarArgOffset);
</del><ins>+    move(TrustedImm32(-firstFreeRegister), regT1);
+    emitSetVarargsFrame(*this, returnValueGPR, false, regT1, regT1);
+    addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 6 * sizeof(void*)))), regT1, stackPointerRegister);
+    emitLoad(arguments, regT2, regT4);
+    callOperation(operationSetupVarargsFrame, regT1, regT2, regT4, firstVarArgOffset, regT0);
</ins><span class="cx">     move(returnValueGPR, regT1);
</span><span class="cx"> 
</span><span class="cx">     if (canOptimize)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlines.h (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -369,15 +369,15 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EJZZ operation, GPRReg arg1, int32_t arg2, int32_t arg3)
</del><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJZZ operation, GPRReg arg1, int32_t arg2, int32_t arg3)
</ins><span class="cx"> {
</span><span class="cx">     setupArgumentsWithExecState(arg1, TrustedImm32(arg2), TrustedImm32(arg3));
</span><span class="cx">     return appendCallWithExceptionCheck(operation);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZ operation, GPRReg arg1, GPRReg arg2, int32_t arg3)
</del><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZZ operation, GPRReg arg1, GPRReg arg2, int32_t arg3, GPRReg arg4)
</ins><span class="cx"> {
</span><del>-    setupArgumentsWithExecState(arg1, arg2, TrustedImm32(arg3));
</del><ins>+    setupArgumentsWithExecState(arg1, arg2, TrustedImm32(arg3), arg4);
</ins><span class="cx">     return appendCallWithExceptionCheck(operation);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -516,15 +516,15 @@
</span><span class="cx">     return appendCall(operation);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EJZZ operation, GPRReg arg1Tag, GPRReg arg1Payload, int32_t arg2, int32_t arg3)
</del><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJZZ operation, GPRReg arg1Tag, GPRReg arg1Payload, int32_t arg2, int32_t arg3)
</ins><span class="cx"> {
</span><span class="cx">     setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImm32(arg2), TrustedImm32(arg3));
</span><span class="cx">     return appendCallWithExceptionCheck(operation);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, int32_t arg3)
</del><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZZ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, int32_t arg3, GPRReg arg4)
</ins><span class="cx"> {
</span><del>-    setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, TrustedImm32(arg3));
</del><ins>+    setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, TrustedImm32(arg3), arg4);
</ins><span class="cx">     return appendCallWithExceptionCheck(operation);
</span><span class="cx"> }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -1604,22 +1604,21 @@
</span><span class="cx">     return JSValue::encode(jsBoolean(result));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CallFrame* JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset)
</del><ins>+int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(&amp;vm, exec);
</span><span class="cx">     JSStack* stack = &amp;exec-&gt;interpreter()-&gt;stack();
</span><span class="cx">     JSValue arguments = JSValue::decode(encodedArguments);
</span><del>-    CallFrame* newCallFrame = sizeFrameForVarargs(exec, stack, arguments, numUsedStackSlots, firstVarArgOffset);
-    return newCallFrame;
</del><ins>+    return sizeFrameForVarargs(exec, stack, arguments, numUsedStackSlots, firstVarArgOffset);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
</del><ins>+CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset, int32_t length)
</ins><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="cx">     NativeCallFrameTracer tracer(&amp;vm, exec);
</span><span class="cx">     JSValue arguments = JSValue::decode(encodedArguments);
</span><del>-    setupVarargsFrame(exec, newCallFrame, arguments, firstVarArgOffset);
</del><ins>+    setupVarargsFrame(exec, newCallFrame, arguments, firstVarArgOffset, length);
</ins><span class="cx">     return newCallFrame;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -87,8 +87,7 @@
</span><span class="cx">     Z: int32_t
</span><span class="cx"> */
</span><span class="cx"> 
</span><del>-typedef CallFrame* JIT_OPERATION (*F_JITOperation_EFJZ)(ExecState*, CallFrame*, EncodedJSValue, int32_t);
-typedef CallFrame* JIT_OPERATION (*F_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t);
</del><ins>+typedef CallFrame* JIT_OPERATION (*F_JITOperation_EFJZZ)(ExecState*, CallFrame*, EncodedJSValue, int32_t, int32_t);
</ins><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_E)(ExecState*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EA)(ExecState*, JSArray*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EAZ)(ExecState*, JSArray*, int32_t);
</span><span class="lines">@@ -151,6 +150,7 @@
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_D)(double);
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_E)(ExecState*);
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_EC)(ExecState*, JSCell*);
</span><ins>+typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t);
</ins><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EJ)(ExecState*, EncodedJSValue);
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
</span><span class="lines">@@ -309,8 +309,8 @@
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationDeleteById(ExecState*, EncodedJSValue base, const Identifier*) WTF_INTERNAL;
</span><span class="cx"> JSCell* JIT_OPERATION operationGetPNames(ExecState*, JSObject*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState*, EncodedJSValue, EncodedJSValue proto) WTF_INTERNAL;
</span><del>-CallFrame* JIT_OPERATION operationSizeFrameForVarargs(ExecState*, EncodedJSValue arguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset) WTF_INTERNAL;
-CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState*, CallFrame*, EncodedJSValue arguments, int32_t firstVarArgOffset) WTF_INTERNAL;
</del><ins>+int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState*, EncodedJSValue arguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset) WTF_INTERNAL;
+CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState*, CallFrame*, EncodedJSValue arguments, int32_t firstVarArgOffset, int32_t length) WTF_INTERNAL;
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationToObject(ExecState*, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> 
</span><span class="cx"> char* JIT_OPERATION operationSwitchCharWithUnknownKeyType(ExecState*, EncodedJSValue key, size_t tableIndex) WTF_INTERNAL;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitSetupVarargsFramecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -34,6 +34,23 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+void emitSetVarargsFrame(CCallHelpers&amp; jit, GPRReg lengthGPR, bool lengthIncludesThis, GPRReg numUsedSlotsGPR, GPRReg resultGPR)
+{
+    jit.move(numUsedSlotsGPR, resultGPR);
+    jit.addPtr(lengthGPR, resultGPR);
+    jit.addPtr(CCallHelpers::TrustedImm32(JSStack::CallFrameHeaderSize + (lengthIncludesThis? 0 : 1)), resultGPR);
+    
+    // resultGPR now has the required frame size in Register units
+    // Round resultGPR to next multiple of stackAlignmentRegisters()
+    jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentRegisters() - 1), resultGPR);
+    jit.andPtr(CCallHelpers::TrustedImm32(~(stackAlignmentRegisters() - 1)), resultGPR);
+    
+    // Now resultGPR has the right stack frame offset in Register units.
+    jit.negPtr(resultGPR);
+    jit.lshiftPtr(CCallHelpers::Imm32(3), resultGPR);
+    jit.addPtr(GPRInfo::callFrameRegister, resultGPR);
+}
+
</ins><span class="cx"> void emitSetupVarargsFrameFastCase(CCallHelpers&amp; jit, GPRReg numUsedSlotsGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, GPRReg scratchGPR3, int inlineStackOffset, unsigned firstVarArgOffset, CCallHelpers::JumpList&amp; slowCase)
</span><span class="cx"> {
</span><span class="cx">     CCallHelpers::JumpList end;
</span><span class="lines">@@ -48,20 +65,9 @@
</span><span class="cx">         endVarArgs.link(&amp;jit);
</span><span class="cx">     }
</span><span class="cx">     slowCase.append(jit.branch32(CCallHelpers::Above, scratchGPR1, CCallHelpers::TrustedImm32(Arguments::MaxArguments + 1)));
</span><del>-    // scratchGPR1: argumentCountIncludingThis
-    jit.move(numUsedSlotsGPR, scratchGPR2);
-    jit.addPtr(scratchGPR1, scratchGPR2);
-    jit.addPtr(CCallHelpers::TrustedImm32(JSStack::CallFrameHeaderSize), scratchGPR2);
-    // scratchGPR2 now has the required frame size in Register units
-    // Round scratchGPR2 to next multiple of stackAlignmentRegisters()
-    jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentRegisters() - 1), scratchGPR2);
-    jit.andPtr(CCallHelpers::TrustedImm32(~(stackAlignmentRegisters() - 1)), scratchGPR2);
</del><ins>+    
+    emitSetVarargsFrame(jit, scratchGPR1, true, numUsedSlotsGPR, scratchGPR2);
</ins><span class="cx"> 
</span><del>-    jit.negPtr(scratchGPR2);
-    jit.lshiftPtr(CCallHelpers::Imm32(3), scratchGPR2);
-    jit.addPtr(GPRInfo::callFrameRegister, scratchGPR2);
-    // scratchGPR2: newCallFrame
-
</del><span class="cx">     slowCase.append(jit.branchPtr(CCallHelpers::Above, CCallHelpers::AbsoluteAddress(jit.vm()-&gt;addressOfStackLimit()), scratchGPR2));
</span><span class="cx"> 
</span><span class="cx">     // Initialize ArgumentCount.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitSetupVarargsFrameh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.h (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.h        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.h        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -33,9 +33,11 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+void emitSetVarargsFrame(CCallHelpers&amp;, GPRReg lengthGPR, bool lengthIncludesThis, GPRReg numUsedSlotsGPR, GPRReg resultGPR);
+
</ins><span class="cx"> // Assumes that SP refers to the last in-use stack location, and after this returns SP will point to
</span><span class="cx"> // the newly created frame plus the native header. scratchGPR2 may be the same as numUsedSlotsGPR.
</span><del>-void emitSetupVarargsFrameFastCase(CCallHelpers&amp; jit, GPRReg numUsedSlotsGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, GPRReg scratchGPR3, int inlineStackOffset, unsigned firstVarArgOffset, CCallHelpers::JumpList&amp; slowCase);
</del><ins>+void emitSetupVarargsFrameFastCase(CCallHelpers&amp;, GPRReg numUsedSlotsGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, GPRReg scratchGPR3, int inlineStackOffset, unsigned firstVarArgOffset, CCallHelpers::JumpList&amp; slowCase);
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -1164,10 +1164,13 @@
</span><span class="cx">     // This needs to:
</span><span class="cx">     // - Set up a call frame while respecting the variable arguments.
</span><span class="cx">     
</span><del>-    ExecState* execCallee = sizeFrameForVarargs(exec, &amp;vm.interpreter-&gt;stack(),
-        LLINT_OP_C(4).jsValue(), -pc[5].u.operand, pc[6].u.operand);
</del><ins>+    unsigned numUsedStackSlots = -pc[5].u.operand;
+    unsigned length = sizeFrameForVarargs(exec, &amp;vm.interpreter-&gt;stack(),
+        LLINT_OP_C(4).jsValue(), numUsedStackSlots, pc[6].u.operand);
</ins><span class="cx">     LLINT_CALL_CHECK_EXCEPTION(exec, exec);
</span><span class="cx">     
</span><ins>+    ExecState* execCallee = calleeFrameForVarargs(exec, numUsedStackSlots, length + 1);
+    vm.varargsLength = length;
</ins><span class="cx">     vm.newCallFrameReturnValue = execCallee;
</span><span class="cx"> 
</span><span class="cx">     LLINT_RETURN_CALLEE_FRAME(execCallee);
</span><span class="lines">@@ -1184,7 +1187,7 @@
</span><span class="cx">     
</span><span class="cx">     ExecState* execCallee = vm.newCallFrameReturnValue;
</span><span class="cx"> 
</span><del>-    setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand);
</del><ins>+    setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand, vm.varargsLength);
</ins><span class="cx">     LLINT_CALL_CHECK_EXCEPTION(exec, exec);
</span><span class="cx">     
</span><span class="cx">     execCallee-&gt;uncheckedR(JSStack::Callee) = calleeAsValue;
</span><span class="lines">@@ -1205,7 +1208,7 @@
</span><span class="cx">     
</span><span class="cx">     ExecState* execCallee = vm.newCallFrameReturnValue;
</span><span class="cx">     
</span><del>-    setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand);
</del><ins>+    setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand, vm.varargsLength);
</ins><span class="cx">     LLINT_CALL_CHECK_EXCEPTION(exec, exec);
</span><span class="cx">     
</span><span class="cx">     execCallee-&gt;uncheckedR(JSStack::Callee) = calleeAsValue;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.cpp (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.cpp        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.cpp        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -87,22 +87,13 @@
</span><span class="cx">     
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState*);
</span><span class="cx"> 
</span><del>-void Arguments::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, uint32_t copyLength, int32_t firstVarArgOffset)
</del><ins>+void Arguments::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length)
</ins><span class="cx"> {
</span><del>-    uint32_t length = copyLength + firstVarArgOffset;
-
-    if (UNLIKELY(m_overrodeLength)) {
-        length = min(get(exec, exec-&gt;propertyNames().length).toUInt32(exec), length);
-        for (unsigned i = firstVarArgOffset; i &lt; length; i++)
-            exec-&gt;r(firstElementDest + i - firstVarArgOffset) = get(exec, i);
-        return;
-    }
-    ASSERT(length == this-&gt;length(exec));
-    for (size_t i = firstVarArgOffset; i &lt; length; ++i) {
-        if (JSValue value = tryGetArgument(i))
-            exec-&gt;r(firstElementDest + i - firstVarArgOffset) = value;
</del><ins>+    for (unsigned i = 0; i &lt; length; ++i) {
+        if (JSValue value = tryGetArgument(i + offset))
+            exec-&gt;r(firstElementDest + i) = value;
</ins><span class="cx">         else {
</span><del>-            exec-&gt;r(firstElementDest + i - firstVarArgOffset) = get(exec, i);
</del><ins>+            exec-&gt;r(firstElementDest + i) = get(exec, i + offset);
</ins><span class="cx">             if (UNLIKELY(exec-&gt;vm().exception()))
</span><span class="cx">                 return;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.h (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.h        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.h        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx">         return m_numArguments; 
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    void copyToArguments(ExecState*, VirtualRegister firstElementDest, uint32_t copyLength, int32_t firstArgumentOffset);
</del><ins>+    void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
</ins><span class="cx">     void tearOff(CallFrame*);
</span><span class="cx">     void tearOff(CallFrame*, InlineCallFrame*);
</span><span class="cx">     void tearOffForCloning(CallFrame*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArraycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArray.cpp (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArray.cpp        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/runtime/JSArray.cpp        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -1570,12 +1570,12 @@
</span><span class="cx">         args.append(get(exec, i));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JSArray::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, uint32_t copyLength, int32_t firstVarArgOffset)
</del><ins>+void JSArray::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length)
</ins><span class="cx"> {
</span><del>-    unsigned i = firstVarArgOffset;
</del><ins>+    unsigned i = offset;
</ins><span class="cx">     WriteBarrier&lt;Unknown&gt;* vector;
</span><span class="cx">     unsigned vectorEnd;
</span><del>-    unsigned length = copyLength + firstVarArgOffset;
</del><ins>+    length += offset; // We like to think of the length as being our length, rather than the output length.
</ins><span class="cx">     ASSERT(length == this-&gt;length());
</span><span class="cx">     switch (indexingType()) {
</span><span class="cx">     case ArrayClass:
</span><span class="lines">@@ -1602,7 +1602,7 @@
</span><span class="cx">             double v = m_butterfly-&gt;contiguousDouble()[i];
</span><span class="cx">             if (v != v)
</span><span class="cx">                 break;
</span><del>-            exec-&gt;r(firstElementDest + i - firstVarArgOffset) = JSValue(JSValue::EncodeAsDouble, v);
</del><ins>+            exec-&gt;r(firstElementDest + i - offset) = JSValue(JSValue::EncodeAsDouble, v);
</ins><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -1627,11 +1627,11 @@
</span><span class="cx">         WriteBarrier&lt;Unknown&gt;&amp; v = vector[i];
</span><span class="cx">         if (!v)
</span><span class="cx">             break;
</span><del>-        exec-&gt;r(firstElementDest + i - firstVarArgOffset) = v.get();
</del><ins>+        exec-&gt;r(firstElementDest + i - offset) = v.get();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     for (; i &lt; length; ++i) {
</span><del>-        exec-&gt;r(firstElementDest + i - firstVarArgOffset) = get(exec, i);
</del><ins>+        exec-&gt;r(firstElementDest + i - offset) = get(exec, i);
</ins><span class="cx">         if (UNLIKELY(exec-&gt;vm().exception()))
</span><span class="cx">             return;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArray.h (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArray.h        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/runtime/JSArray.h        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -132,7 +132,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE void fillArgList(ExecState*, MarkedArgumentBuffer&amp;);
</span><del>-    JS_EXPORT_PRIVATE void copyToArguments(ExecState*, VirtualRegister firstElementDest, uint32_t length, int32_t firstVarArgOffset);
</del><ins>+    JS_EXPORT_PRIVATE void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
</ins><span class="cx"> 
</span><span class="cx">     static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (179886 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2015-02-10 23:07:47 UTC (rev 179886)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -410,6 +410,7 @@
</span><span class="cx">     const ClassInfo* const jsFinalObjectClassInfo;
</span><span class="cx"> 
</span><span class="cx">     JSValue hostCallReturnValue;
</span><ins>+    unsigned varargsLength;
</ins><span class="cx">     ExecState* newCallFrameReturnValue;
</span><span class="cx">     VMEntryFrame* vmEntryFrameForThrow;
</span><span class="cx">     ExecState* callFrameForThrow;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresscallvarargslengtheffectsjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/call-varargs-length-effects.js (0 => 179887)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/call-varargs-length-effects.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/call-varargs-length-effects.js        2015-02-10 23:16:36 UTC (rev 179887)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+function foo() { return arguments.length; }
+
+var o = {};
+o[0] = 42;
+var callCount = 0;
+o.__defineGetter__(&quot;length&quot;, function() {
+    callCount++;
+    return 1;
+});
+
+function bar() {
+    callCount = 0;
+    var result = foo.apply(this, o);
+    if (result != 1)
+        throw &quot;Error: bad result: &quot; + result;
+    if (callCount != 1)
+        throw &quot;Error: bad call count: &quot; + callCount;
+}
+
+noInline(foo);
+noInline(bar);
+
+for (var i = 0; i &lt; 10000; ++i)
+    bar();
</ins></span></pre>
</div>
</div>

</body>
</html>