⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 179887 in webkit


Ignore:
Timestamp:
Feb 10, 2015, 3:16:36 PM (12 years ago)
Author:
fpizlo@apple.com
Message:

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):

Location:
trunk/Source/JavaScriptCore
Files:
1 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r179882 r179887  
     12015-02-10  Filip Pizlo  <fpizlo@apple.com>
     2
     3        op_call_varargs should only load the length once
     4        https://bugs.webkit.org/show_bug.cgi?id=141440
     5        rdar://problem/19761683
     6
     7        Reviewed by Michael Saboff.
     8       
     9        Refactors the pair of calls that set up the varargs frame so that the first call returns the
     10        length, and the second call uses the length returned by the first one. It turns out that this
     11        gave me an opportunity to shorten a lot of the code.
     12
     13        * interpreter/Interpreter.cpp:
     14        (JSC::sizeFrameForVarargs):
     15        (JSC::loadVarargs):
     16        (JSC::setupVarargsFrame):
     17        (JSC::setupVarargsFrameAndSetThis):
     18        * interpreter/Interpreter.h:
     19        (JSC::calleeFrameForVarargs):
     20        * jit/CCallHelpers.h:
     21        (JSC::CCallHelpers::setupArgumentsWithExecState):
     22        * jit/JIT.h:
     23        * jit/JITCall.cpp:
     24        (JSC::JIT::compileSetupVarargsFrame):
     25        * jit/JITCall32_64.cpp:
     26        (JSC::JIT::compileSetupVarargsFrame):
     27        * jit/JITInlines.h:
     28        (JSC::JIT::callOperation):
     29        * jit/JITOperations.cpp:
     30        * jit/JITOperations.h:
     31        * jit/SetupVarargsFrame.cpp:
     32        (JSC::emitSetVarargsFrame):
     33        (JSC::emitSetupVarargsFrameFastCase):
     34        * jit/SetupVarargsFrame.h:
     35        * llint/LLIntSlowPaths.cpp:
     36        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     37        * runtime/Arguments.cpp:
     38        (JSC::Arguments::copyToArguments):
     39        * runtime/Arguments.h:
     40        * runtime/JSArray.cpp:
     41        (JSC::JSArray::copyToArguments):
     42        * runtime/JSArray.h:
     43        * runtime/VM.h:
     44        * tests/stress/call-varargs-length-effects.js: Added.
     45        (foo):
     46        (bar):
     47
    1482015-02-10  Michael Saboff  <msaboff@apple.com>
    249
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r179862 r179887  
    11/*
    2  * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2009, 2010, 2012, 2013, 2014, 2015 Apple Inc. All rights reserved.
    33 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
    44 *
     
    135135}
    136136
    137 CallFrame* sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset)
    138 {
    139     if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
    140         unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
    141         if (argumentCountIncludingThis > firstVarArgOffset)
    142             argumentCountIncludingThis -= firstVarArgOffset;
    143         else
    144             argumentCountIncludingThis = 1;
    145         unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
    146         CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    147         if (argumentCountIncludingThis > Arguments::MaxArguments + 1 || !stack->ensureCapacityFor(newCallFrame->registers())) {
    148             throwStackOverflowError(callFrame);
    149             return 0;
    150         }
    151         return newCallFrame;
    152     }
    153 
    154     if (arguments.isUndefinedOrNull()) {
    155         unsigned argumentCountIncludingThis = 1;
    156         unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(),  numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
    157         CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    158         if (!stack->ensureCapacityFor(newCallFrame->registers())) {
    159             throwStackOverflowError(callFrame);
    160             return 0;
    161         }
    162         return newCallFrame;
    163     }
    164 
    165     if (!arguments.isObject()) {
     137unsigned sizeFrameForVarargs(CallFrame* callFrame, JSStack* stack, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset)
     138{
     139    unsigned length;
     140    if (!arguments)
     141        length = callFrame->argumentCount();
     142    else if (arguments.isUndefinedOrNull())
     143        length = 0;
     144    else if (!arguments.isObject()) {
    166145        callFrame->vm().throwException(callFrame, createInvalidParameterError(callFrame, "Function.prototype.apply", arguments));
    167146        return 0;
    168     }
    169 
    170     if (asObject(arguments)->classInfo() == Arguments::info()) {
    171         Arguments* argsObject = asArguments(arguments);
    172         unsigned argCount = argsObject->length(callFrame);
    173         if (argCount >= firstVarArgOffset)
    174             argCount -= firstVarArgOffset;
    175         else
    176             argCount = 0;
    177         unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numUsedStackSlots + argCount + 1 + JSStack::CallFrameHeaderSize);
    178         CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    179         if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
    180             throwStackOverflowError(callFrame);
    181             return 0;
    182         }
    183         return newCallFrame;
    184     }
    185 
    186     if (isJSArray(arguments)) {
    187         JSArray* array = asArray(arguments);
    188         unsigned argCount = array->length();
    189         if (argCount >= firstVarArgOffset)
    190             argCount -= firstVarArgOffset;
    191         else
    192             argCount = 0;
    193         unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numUsedStackSlots + argCount + 1 + JSStack::CallFrameHeaderSize);
    194         CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    195         if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
    196             throwStackOverflowError(callFrame);
    197             return 0;
    198         }
    199         return newCallFrame;
    200     }
    201 
    202     JSObject* argObject = asObject(arguments);
    203     unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
    204     if (argCount >= firstVarArgOffset)
    205         argCount -= firstVarArgOffset;
     147    } else if (asObject(arguments)->classInfo() == Arguments::info())
     148        length = asArguments(arguments)->length(callFrame);
     149    else if (isJSArray(arguments))
     150        length = asArray(arguments)->length();
    206151    else
    207         argCount = 0;
    208     unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numUsedStackSlots + argCount + 1 + JSStack::CallFrameHeaderSize);
    209     CallFrame* newCallFrame = CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
    210     if (argCount > Arguments::MaxArguments || !stack->ensureCapacityFor(newCallFrame->registers())) {
     152        length = asObject(arguments)->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
     153   
     154    if (length >= firstVarArgOffset)
     155        length -= firstVarArgOffset;
     156    else
     157        length = 0;
     158   
     159    CallFrame* calleeFrame = calleeFrameForVarargs(callFrame, numUsedStackSlots, length + 1);
     160    if (length > Arguments::MaxArguments || !stack->ensureCapacityFor(calleeFrame->registers())) {
    211161        throwStackOverflowError(callFrame);
    212162        return 0;
    213163    }
    214     return newCallFrame;
    215 }
    216 
    217 void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, VirtualRegister countDest, JSValue arguments, uint32_t firstVarArgOffset)
     164   
     165    return length;
     166}
     167
     168void loadVarargs(CallFrame* callFrame, VirtualRegister firstElementDest, JSValue arguments, uint32_t offset, uint32_t length)
    218169{
    219170    if (!arguments) { // f.apply(x, arguments), with arguments unmodified.
    220         unsigned argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
    221         if (argumentCountIncludingThis > firstVarArgOffset)
    222             argumentCountIncludingThis -= firstVarArgOffset;
    223         else
    224             argumentCountIncludingThis = 1;
    225         callFrame->r(countDest).payload() = argumentCountIncludingThis;
    226         for (size_t i = firstVarArgOffset; i < callFrame->argumentCount(); ++i)
    227             callFrame->r(firstElementDest + i - firstVarArgOffset) = callFrame->argumentAfterCapture(i);
     171        for (size_t i = 0; i < length; ++i)
     172            callFrame->r(firstElementDest + i) = callFrame->argumentAfterCapture(i + offset);
    228173        return;
    229174    }
    230175   
    231     if (arguments.isUndefinedOrNull()) {
    232         callFrame->r(countDest).payload() = 1;
     176    if (arguments.isUndefinedOrNull())
    233177        return;
    234     }
    235178   
    236179    if (asObject(arguments)->classInfo() == Arguments::info()) {
    237         Arguments* argsObject = asArguments(arguments);
    238         unsigned argCount = argsObject->length(callFrame);
    239         if (argCount >= firstVarArgOffset) {
    240             argCount -= firstVarArgOffset;
    241             callFrame->r(countDest).payload() = argCount + 1;
    242             argsObject->copyToArguments(callFrame, firstElementDest, argCount, firstVarArgOffset);
    243         } else
    244             callFrame->r(countDest).payload() = 1;
     180        asArguments(arguments)->copyToArguments(callFrame, firstElementDest, offset, length);
    245181        return;
    246182    }
    247183   
    248184    if (isJSArray(arguments)) {
    249         JSArray* array = asArray(arguments);
    250         unsigned argCount = array->length();
    251         if (argCount >= firstVarArgOffset) {
    252             argCount -= firstVarArgOffset;
    253             callFrame->r(countDest).payload() = argCount + 1;
    254             array->copyToArguments(callFrame, firstElementDest, argCount, firstVarArgOffset);
    255         } else
    256             callFrame->r(countDest).payload() = 1;
     185        asArray(arguments)->copyToArguments(callFrame, firstElementDest, offset, length);
    257186        return;
    258187    }
    259188   
    260     JSObject* argObject = asObject(arguments);
    261     unsigned argCount = argObject->get(callFrame, callFrame->propertyNames().length).toUInt32(callFrame);
    262     if (argCount >= firstVarArgOffset) {
    263         argCount -= firstVarArgOffset;
    264         callFrame->r(countDest).payload() = argCount + 1;
    265     } else
    266         callFrame->r(countDest).payload() = 1;
    267 
    268     for (size_t i = 0; i < argCount; ++i) {
    269         callFrame->r(firstElementDest + i) = asObject(arguments)->get(callFrame, i + firstVarArgOffset);
     189    for (unsigned i = 0; i < length; ++i) {
     190        callFrame->r(firstElementDest + i) = asObject(arguments)->get(callFrame, i + offset);
    270191        if (UNLIKELY(callFrame->vm().exception()))
    271192            return;
     
    273194}
    274195
    275 void setupVarargsFrame(CallFrame* callFrame, CallFrame* newCallFrame, JSValue arguments, uint32_t firstVarArgOffset)
     196void setupVarargsFrame(CallFrame* callFrame, CallFrame* newCallFrame, JSValue arguments, uint32_t offset, uint32_t length)
    276197{
    277198    VirtualRegister calleeFrameOffset(newCallFrame - callFrame);
     
    280201        callFrame,
    281202        calleeFrameOffset + CallFrame::argumentOffset(0),
    282         calleeFrameOffset + JSStack::ArgumentCount,
    283         arguments, firstVarArgOffset);
    284 }
    285 
    286 void setupVarargsFrameAndSetThis(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset)
    287 {
    288     setupVarargsFrame(callFrame, newCallFrame, arguments, firstVarArgOffset);
     203        arguments, offset, length);
     204   
     205    newCallFrame->setArgumentCountIncludingThis(length + 1);
     206}
     207
     208void setupVarargsFrameAndSetThis(CallFrame* callFrame, CallFrame* newCallFrame, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length)
     209{
     210    setupVarargsFrame(callFrame, newCallFrame, arguments, firstVarArgOffset, length);
    289211    newCallFrame->setThisValue(thisValue);
    290212}
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.h

    r179862 r179887  
    11/*
    2  * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2013, 2015 Apple Inc. All rights reserved.
    33 * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
    44 *
     
    4040#include "Opcode.h"
    4141#include "SourceProvider.h"
     42#include "StackAlignment.h"
    4243
    4344#include <wtf/HashMap.h>
     
    299300
    300301    JSValue eval(CallFrame*);
    301     CallFrame* sizeFrameForVarargs(CallFrame* exec, JSStack*, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset);
    302     void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, VirtualRegister countDest, JSValue source, uint32_t offset);
    303     void setupVarargsFrame(CallFrame* execCaller, CallFrame* execCallee, JSValue arguments, uint32_t firstVarArgOffset);
    304     void setupVarargsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset);
     302
     303    inline CallFrame* calleeFrameForVarargs(CallFrame* callFrame, unsigned numUsedStackSlots, unsigned argumentCountIncludingThis)
     304    {
     305        unsigned paddedCalleeFrameOffset = WTF::roundUpToMultipleOf(
     306            stackAlignmentRegisters(),
     307            numUsedStackSlots + argumentCountIncludingThis + JSStack::CallFrameHeaderSize);
     308        return CallFrame::create(callFrame->registers() - paddedCalleeFrameOffset);
     309    }
     310
     311    unsigned sizeFrameForVarargs(CallFrame* exec, JSStack*, JSValue arguments, unsigned numUsedStackSlots, uint32_t firstVarArgOffset);
     312    void loadVarargs(CallFrame* execCaller, VirtualRegister firstElementDest, JSValue source, uint32_t offset, uint32_t length);
     313    void setupVarargsFrame(CallFrame* execCaller, CallFrame* execCallee, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
     314    void setupVarargsFrameAndSetThis(CallFrame* execCaller, CallFrame* execCallee, JSValue thisValue, JSValue arguments, uint32_t firstVarArgOffset, uint32_t length);
    305315   
    306316} // namespace JSC
  • trunk/Source/JavaScriptCore/jit/CCallHelpers.h

    r175766 r179887  
    434434        addCallArgument(arg3);
    435435        addCallArgument(arg4);
     436    }
     437
     438    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4, GPRReg arg5)
     439    {
     440        resetCallArguments();
     441        addCallArgument(GPRInfo::callFrameRegister);
     442        addCallArgument(arg1);
     443        addCallArgument(arg2);
     444        addCallArgument(arg3);
     445        addCallArgument(arg4);
     446        addCallArgument(arg5);
    436447    }
    437448
     
    13821393    }
    13831394
     1395    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, GPRReg arg3, TrustedImm32 arg4, GPRReg arg5)
     1396    {
     1397        poke(arg4, POKE_ARGUMENT_OFFSET);
     1398        setupArgumentsWithExecState(arg1, arg2, arg3);
     1399    }
     1400
    13841401    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, TrustedImmPtr arg2, GPRReg arg3,  GPRReg arg4)
    13851402    {
     
    15241541   
    15251542    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, TrustedImmPtr arg4)
     1543    {
     1544        poke(arg4, POKE_ARGUMENT_OFFSET);
     1545        setupArgumentsWithExecState(arg1, arg2, arg3);
     1546    }
     1547
     1548    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4)
    15261549    {
    15271550        poke(arg4, POKE_ARGUMENT_OFFSET);
     
    17671790        setupThreeStubArgsGPR<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, GPRInfo::argumentGPR3>(arg1, arg2, arg3);
    17681791        move(arg4, GPRInfo::argumentGPR4);
     1792        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
     1793    }
     1794
     1795    ALWAYS_INLINE void setupArgumentsWithExecState(GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4)
     1796    {
     1797        setupThreeStubArgsGPR<GPRInfo::argumentGPR1, GPRInfo::argumentGPR2, GPRInfo::argumentGPR4>(arg1, arg2, arg4);
     1798        move(arg3, GPRInfo::argumentGPR3);
    17691799        move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
    17701800    }
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r179862 r179887  
    680680        MacroAssembler::Call callOperation(C_JITOperation_ESt, Structure*);
    681681        MacroAssembler::Call callOperation(C_JITOperation_EZ, int32_t);
    682         MacroAssembler::Call callOperation(F_JITOperation_EJZZ, GPRReg, int32_t, int32_t);
     682        MacroAssembler::Call callOperation(Z_JITOperation_EJZZ, GPRReg, int32_t, int32_t);
    683683        MacroAssembler::Call callOperation(J_JITOperation_E, int);
    684684        MacroAssembler::Call callOperation(J_JITOperation_EAapJ, int, ArrayAllocationProfile*, GPRReg);
     
    731731        MacroAssembler::Call callOperation(V_JITOperation_EJIdJJ, RegisterID, const Identifier*, RegisterID, RegisterID);
    732732#if USE(JSVALUE64)
    733         MacroAssembler::Call callOperation(F_JITOperation_EFJZ, RegisterID, RegisterID, int32_t);
     733        MacroAssembler::Call callOperation(F_JITOperation_EFJZZ, RegisterID, RegisterID, int32_t, RegisterID);
    734734        MacroAssembler::Call callOperation(V_JITOperation_ESsiJJI, StructureStubInfo*, RegisterID, RegisterID, StringImpl*);
    735735#else
     
    746746        MacroAssembler::Call callOperationWithCallFrameRollbackOnException(Z_JITOperation_E);
    747747#if USE(JSVALUE32_64)
    748         MacroAssembler::Call callOperation(F_JITOperation_EFJZ, RegisterID, RegisterID, RegisterID, int32_t);
    749         MacroAssembler::Call callOperation(F_JITOperation_EJZZ, GPRReg, GPRReg, int32_t, int32_t);
     748        MacroAssembler::Call callOperation(F_JITOperation_EFJZZ, RegisterID, RegisterID, RegisterID, int32_t, RegisterID);
     749        MacroAssembler::Call callOperation(Z_JITOperation_EJZZ, GPRReg, GPRReg, int32_t, int32_t);
    750750        MacroAssembler::Call callOperation(J_JITOperation_EAapJ, int, ArrayAllocationProfile*, GPRReg, GPRReg);
    751751        MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg, GPRReg);
  • trunk/Source/JavaScriptCore/jit/JITCall.cpp

    r179862 r179887  
    8181    emitGetVirtualRegister(arguments, regT1);
    8282    callOperation(operationSizeFrameForVarargs, regT1, -firstFreeRegister, firstVarArgOffset);
    83     move(returnValueGPR, stackPointerRegister);
    84     emitGetVirtualRegister(arguments, regT1);
    85     callOperation(operationSetupVarargsFrame, returnValueGPR, regT1, firstVarArgOffset);
     83    move(TrustedImm32(-firstFreeRegister), regT1);
     84    emitSetVarargsFrame(*this, returnValueGPR, false, regT1, regT1);
     85    addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 5 * sizeof(void*)))), regT1, stackPointerRegister);
     86    emitGetVirtualRegister(arguments, regT2);
     87    callOperation(operationSetupVarargsFrame, regT1, regT2, firstVarArgOffset, regT0);
    8688    move(returnValueGPR, regT1);
    8789
  • trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp

    r179862 r179887  
    141141    emitLoad(arguments, regT1, regT0);
    142142    callOperation(operationSizeFrameForVarargs, regT1, regT0, -firstFreeRegister, firstVarArgOffset);
    143     // This is spectacularly dirty. We want to pass four arguments to operationSetupVarargsFrame. On x86-32 we
    144     // will pass them on the stack. We want four stack slots, or 16 bytes. Extending the stack by 8 bytes
    145     // over where we planned on pointing the FP gives us enough room. The reason is that the FP gives an
    146     // extra CallerFrameAndPC bytes beyond where SP should point prior to the call. So if we just did
    147     // move(returnValueGPR, stackPointerRegister), we'd have enough room for passing two args, or 8
    148     // bytes - except that we'd have a misaligned stack. So if we subtract *another* CallerFrameAndPC
    149     // bytes, we are up to 16 bytes of spare room *and* we have an aligned stack. Gross, but correct!
    150     addPtr(TrustedImm32(-sizeof(CallerFrameAndPC)), returnValueGPR, stackPointerRegister);
    151     emitLoad(arguments, regT2, regT1);
    152     callOperation(operationSetupVarargsFrame, returnValueGPR, regT2, regT1, firstVarArgOffset);
     143    move(TrustedImm32(-firstFreeRegister), regT1);
     144    emitSetVarargsFrame(*this, returnValueGPR, false, regT1, regT1);
     145    addPtr(TrustedImm32(-(sizeof(CallerFrameAndPC) + WTF::roundUpToMultipleOf(stackAlignmentBytes(), 6 * sizeof(void*)))), regT1, stackPointerRegister);
     146    emitLoad(arguments, regT2, regT4);
     147    callOperation(operationSetupVarargsFrame, regT1, regT2, regT4, firstVarArgOffset, regT0);
    153148    move(returnValueGPR, regT1);
    154149
  • trunk/Source/JavaScriptCore/jit/JITInlines.h

    r179862 r179887  
    370370
    371371#if USE(JSVALUE64)
    372 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EJZZ operation, GPRReg arg1, int32_t arg2, int32_t arg3)
     372ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJZZ operation, GPRReg arg1, int32_t arg2, int32_t arg3)
    373373{
    374374    setupArgumentsWithExecState(arg1, TrustedImm32(arg2), TrustedImm32(arg3));
     
    376376}
    377377
    378 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZ operation, GPRReg arg1, GPRReg arg2, int32_t arg3)
    379 {
    380     setupArgumentsWithExecState(arg1, arg2, TrustedImm32(arg3));
     378ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZZ operation, GPRReg arg1, GPRReg arg2, int32_t arg3, GPRReg arg4)
     379{
     380    setupArgumentsWithExecState(arg1, arg2, TrustedImm32(arg3), arg4);
    381381    return appendCallWithExceptionCheck(operation);
    382382}
     
    517517}
    518518
    519 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EJZZ operation, GPRReg arg1Tag, GPRReg arg1Payload, int32_t arg2, int32_t arg3)
     519ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(Z_JITOperation_EJZZ operation, GPRReg arg1Tag, GPRReg arg1Payload, int32_t arg2, int32_t arg3)
    520520{
    521521    setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, TrustedImm32(arg2), TrustedImm32(arg3));
     
    523523}
    524524
    525 ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, int32_t arg3)
    526 {
    527     setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, TrustedImm32(arg3));
     525ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(F_JITOperation_EFJZZ operation, GPRReg arg1, GPRReg arg2Tag, GPRReg arg2Payload, int32_t arg3, GPRReg arg4)
     526{
     527    setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag, TrustedImm32(arg3), arg4);
    528528    return appendCallWithExceptionCheck(operation);
    529529}
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r179862 r179887  
    16051605}
    16061606
    1607 CallFrame* JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset)
     1607int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset)
    16081608{
    16091609    VM& vm = exec->vm();
     
    16111611    JSStack* stack = &exec->interpreter()->stack();
    16121612    JSValue arguments = JSValue::decode(encodedArguments);
    1613     CallFrame* newCallFrame = sizeFrameForVarargs(exec, stack, arguments, numUsedStackSlots, firstVarArgOffset);
    1614     return newCallFrame;
    1615 }
    1616 
    1617 CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
     1613    return sizeFrameForVarargs(exec, stack, arguments, numUsedStackSlots, firstVarArgOffset);
     1614}
     1615
     1616CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedArguments, int32_t firstVarArgOffset, int32_t length)
    16181617{
    16191618    VM& vm = exec->vm();
    16201619    NativeCallFrameTracer tracer(&vm, exec);
    16211620    JSValue arguments = JSValue::decode(encodedArguments);
    1622     setupVarargsFrame(exec, newCallFrame, arguments, firstVarArgOffset);
     1621    setupVarargsFrame(exec, newCallFrame, arguments, firstVarArgOffset, length);
    16231622    return newCallFrame;
    16241623}
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r179862 r179887  
    8888*/
    8989
    90 typedef CallFrame* JIT_OPERATION (*F_JITOperation_EFJZ)(ExecState*, CallFrame*, EncodedJSValue, int32_t);
    91 typedef CallFrame* JIT_OPERATION (*F_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t);
     90typedef CallFrame* JIT_OPERATION (*F_JITOperation_EFJZZ)(ExecState*, CallFrame*, EncodedJSValue, int32_t, int32_t);
    9291typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_E)(ExecState*);
    9392typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EA)(ExecState*, JSArray*);
     
    152151typedef int32_t JIT_OPERATION (*Z_JITOperation_E)(ExecState*);
    153152typedef int32_t JIT_OPERATION (*Z_JITOperation_EC)(ExecState*, JSCell*);
     153typedef int32_t JIT_OPERATION (*Z_JITOperation_EJZZ)(ExecState*, EncodedJSValue, int32_t, int32_t);
    154154typedef size_t JIT_OPERATION (*S_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
    155155typedef size_t JIT_OPERATION (*S_JITOperation_EJ)(ExecState*, EncodedJSValue);
     
    310310JSCell* JIT_OPERATION operationGetPNames(ExecState*, JSObject*) WTF_INTERNAL;
    311311EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState*, EncodedJSValue, EncodedJSValue proto) WTF_INTERNAL;
    312 CallFrame* JIT_OPERATION operationSizeFrameForVarargs(ExecState*, EncodedJSValue arguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset) WTF_INTERNAL;
    313 CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState*, CallFrame*, EncodedJSValue arguments, int32_t firstVarArgOffset) WTF_INTERNAL;
     312int32_t JIT_OPERATION operationSizeFrameForVarargs(ExecState*, EncodedJSValue arguments, int32_t numUsedStackSlots, int32_t firstVarArgOffset) WTF_INTERNAL;
     313CallFrame* JIT_OPERATION operationSetupVarargsFrame(ExecState*, CallFrame*, EncodedJSValue arguments, int32_t firstVarArgOffset, int32_t length) WTF_INTERNAL;
    314314EncodedJSValue JIT_OPERATION operationToObject(ExecState*, EncodedJSValue) WTF_INTERNAL;
    315315
  • trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.cpp

    r179862 r179887  
    3535namespace JSC {
    3636
     37void emitSetVarargsFrame(CCallHelpers& jit, GPRReg lengthGPR, bool lengthIncludesThis, GPRReg numUsedSlotsGPR, GPRReg resultGPR)
     38{
     39    jit.move(numUsedSlotsGPR, resultGPR);
     40    jit.addPtr(lengthGPR, resultGPR);
     41    jit.addPtr(CCallHelpers::TrustedImm32(JSStack::CallFrameHeaderSize + (lengthIncludesThis? 0 : 1)), resultGPR);
     42   
     43    // resultGPR now has the required frame size in Register units
     44    // Round resultGPR to next multiple of stackAlignmentRegisters()
     45    jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentRegisters() - 1), resultGPR);
     46    jit.andPtr(CCallHelpers::TrustedImm32(~(stackAlignmentRegisters() - 1)), resultGPR);
     47   
     48    // Now resultGPR has the right stack frame offset in Register units.
     49    jit.negPtr(resultGPR);
     50    jit.lshiftPtr(CCallHelpers::Imm32(3), resultGPR);
     51    jit.addPtr(GPRInfo::callFrameRegister, resultGPR);
     52}
     53
    3754void emitSetupVarargsFrameFastCase(CCallHelpers& jit, GPRReg numUsedSlotsGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, GPRReg scratchGPR3, int inlineStackOffset, unsigned firstVarArgOffset, CCallHelpers::JumpList& slowCase)
    3855{
     
    4966    }
    5067    slowCase.append(jit.branch32(CCallHelpers::Above, scratchGPR1, CCallHelpers::TrustedImm32(Arguments::MaxArguments + 1)));
    51     // scratchGPR1: argumentCountIncludingThis
    52     jit.move(numUsedSlotsGPR, scratchGPR2);
    53     jit.addPtr(scratchGPR1, scratchGPR2);
    54     jit.addPtr(CCallHelpers::TrustedImm32(JSStack::CallFrameHeaderSize), scratchGPR2);
    55     // scratchGPR2 now has the required frame size in Register units
    56     // Round scratchGPR2 to next multiple of stackAlignmentRegisters()
    57     jit.addPtr(CCallHelpers::TrustedImm32(stackAlignmentRegisters() - 1), scratchGPR2);
    58     jit.andPtr(CCallHelpers::TrustedImm32(~(stackAlignmentRegisters() - 1)), scratchGPR2);
    59 
    60     jit.negPtr(scratchGPR2);
    61     jit.lshiftPtr(CCallHelpers::Imm32(3), scratchGPR2);
    62     jit.addPtr(GPRInfo::callFrameRegister, scratchGPR2);
    63     // scratchGPR2: newCallFrame
     68   
     69    emitSetVarargsFrame(jit, scratchGPR1, true, numUsedSlotsGPR, scratchGPR2);
    6470
    6571    slowCase.append(jit.branchPtr(CCallHelpers::Above, CCallHelpers::AbsoluteAddress(jit.vm()->addressOfStackLimit()), scratchGPR2));
  • trunk/Source/JavaScriptCore/jit/SetupVarargsFrame.h

    r179862 r179887  
    3434namespace JSC {
    3535
     36void emitSetVarargsFrame(CCallHelpers&, GPRReg lengthGPR, bool lengthIncludesThis, GPRReg numUsedSlotsGPR, GPRReg resultGPR);
     37
    3638// Assumes that SP refers to the last in-use stack location, and after this returns SP will point to
    3739// the newly created frame plus the native header. scratchGPR2 may be the same as numUsedSlotsGPR.
    38 void emitSetupVarargsFrameFastCase(CCallHelpers& jit, GPRReg numUsedSlotsGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, GPRReg scratchGPR3, int inlineStackOffset, unsigned firstVarArgOffset, CCallHelpers::JumpList& slowCase);
     40void emitSetupVarargsFrameFastCase(CCallHelpers&, GPRReg numUsedSlotsGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, GPRReg scratchGPR3, int inlineStackOffset, unsigned firstVarArgOffset, CCallHelpers::JumpList& slowCase);
    3941
    4042} // namespace JSC
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r179862 r179887  
    11651165    // - Set up a call frame while respecting the variable arguments.
    11661166   
    1167     ExecState* execCallee = sizeFrameForVarargs(exec, &vm.interpreter->stack(),
    1168         LLINT_OP_C(4).jsValue(), -pc[5].u.operand, pc[6].u.operand);
     1167    unsigned numUsedStackSlots = -pc[5].u.operand;
     1168    unsigned length = sizeFrameForVarargs(exec, &vm.interpreter->stack(),
     1169        LLINT_OP_C(4).jsValue(), numUsedStackSlots, pc[6].u.operand);
    11691170    LLINT_CALL_CHECK_EXCEPTION(exec, exec);
    11701171   
     1172    ExecState* execCallee = calleeFrameForVarargs(exec, numUsedStackSlots, length + 1);
     1173    vm.varargsLength = length;
    11711174    vm.newCallFrameReturnValue = execCallee;
    11721175
     
    11851188    ExecState* execCallee = vm.newCallFrameReturnValue;
    11861189
    1187     setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand);
     1190    setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand, vm.varargsLength);
    11881191    LLINT_CALL_CHECK_EXCEPTION(exec, exec);
    11891192   
     
    12061209    ExecState* execCallee = vm.newCallFrameReturnValue;
    12071210   
    1208     setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand);
     1211    setupVarargsFrameAndSetThis(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand, vm.varargsLength);
    12091212    LLINT_CALL_CHECK_EXCEPTION(exec, exec);
    12101213   
  • trunk/Source/JavaScriptCore/runtime/Arguments.cpp

    r179862 r179887  
    8888static EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState*);
    8989
    90 void Arguments::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, uint32_t copyLength, int32_t firstVarArgOffset)
    91 {
    92     uint32_t length = copyLength + firstVarArgOffset;
    93 
    94     if (UNLIKELY(m_overrodeLength)) {
    95         length = min(get(exec, exec->propertyNames().length).toUInt32(exec), length);
    96         for (unsigned i = firstVarArgOffset; i < length; i++)
    97             exec->r(firstElementDest + i - firstVarArgOffset) = get(exec, i);
    98         return;
    99     }
    100     ASSERT(length == this->length(exec));
    101     for (size_t i = firstVarArgOffset; i < length; ++i) {
    102         if (JSValue value = tryGetArgument(i))
    103             exec->r(firstElementDest + i - firstVarArgOffset) = value;
     90void Arguments::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length)
     91{
     92    for (unsigned i = 0; i < length; ++i) {
     93        if (JSValue value = tryGetArgument(i + offset))
     94            exec->r(firstElementDest + i) = value;
    10495        else {
    105             exec->r(firstElementDest + i - firstVarArgOffset) = get(exec, i);
     96            exec->r(firstElementDest + i) = get(exec, i + offset);
    10697            if (UNLIKELY(exec->vm().exception()))
    10798                return;
  • trunk/Source/JavaScriptCore/runtime/Arguments.h

    r179862 r179887  
    8585    }
    8686       
    87     void copyToArguments(ExecState*, VirtualRegister firstElementDest, uint32_t copyLength, int32_t firstArgumentOffset);
     87    void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
    8888    void tearOff(CallFrame*);
    8989    void tearOff(CallFrame*, InlineCallFrame*);
  • trunk/Source/JavaScriptCore/runtime/JSArray.cpp

    r179862 r179887  
    15711571}
    15721572
    1573 void JSArray::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, uint32_t copyLength, int32_t firstVarArgOffset)
    1574 {
    1575     unsigned i = firstVarArgOffset;
     1573void JSArray::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length)
     1574{
     1575    unsigned i = offset;
    15761576    WriteBarrier<Unknown>* vector;
    15771577    unsigned vectorEnd;
    1578     unsigned length = copyLength + firstVarArgOffset;
     1578    length += offset; // We like to think of the length as being our length, rather than the output length.
    15791579    ASSERT(length == this->length());
    15801580    switch (indexingType()) {
     
    16031603            if (v != v)
    16041604                break;
    1605             exec->r(firstElementDest + i - firstVarArgOffset) = JSValue(JSValue::EncodeAsDouble, v);
     1605            exec->r(firstElementDest + i - offset) = JSValue(JSValue::EncodeAsDouble, v);
    16061606        }
    16071607        break;
     
    16281628        if (!v)
    16291629            break;
    1630         exec->r(firstElementDest + i - firstVarArgOffset) = v.get();
     1630        exec->r(firstElementDest + i - offset) = v.get();
    16311631    }
    16321632   
    16331633    for (; i < length; ++i) {
    1634         exec->r(firstElementDest + i - firstVarArgOffset) = get(exec, i);
     1634        exec->r(firstElementDest + i - offset) = get(exec, i);
    16351635        if (UNLIKELY(exec->vm().exception()))
    16361636            return;
  • trunk/Source/JavaScriptCore/runtime/JSArray.h

    r179862 r179887  
    133133
    134134    JS_EXPORT_PRIVATE void fillArgList(ExecState*, MarkedArgumentBuffer&);
    135     JS_EXPORT_PRIVATE void copyToArguments(ExecState*, VirtualRegister firstElementDest, uint32_t length, int32_t firstVarArgOffset);
     135    JS_EXPORT_PRIVATE void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
    136136
    137137    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r179609 r179887  
    411411
    412412    JSValue hostCallReturnValue;
     413    unsigned varargsLength;
    413414    ExecState* newCallFrameReturnValue;
    414415    VMEntryFrame* vmEntryFrameForThrow;
Note: See TracChangeset for help on using the changeset viewer.