Changeset 192814 in webkit


Ignore:
Timestamp:
Nov 30, 2015 12:36:54 PM (8 years ago)
Author:
sbarati@apple.com
Message:

implement op_get_rest_length so that we can allocate the rest array with the right size from the start
https://bugs.webkit.org/show_bug.cgi?id=151467

Reviewed by Geoffrey Garen and Mark Lam.

This patch implements op_get_rest_length which returns the length
that the rest parameter array will be. We're implementing this because
it might be a constant value in the presence of inlining in the DFG.
We will take advantage of this optimization opportunity in a future patch:
https://bugs.webkit.org/show_bug.cgi?id=151454
to emit better code for op_copy_rest.

op_get_rest_length has two operands:
1) a destination
2) A constant indicating the number of parameters to skip when copying the rest array.

op_get_rest_length lowers to a JSConstant node when we're inlined
and not a varargs call (in this case, we statically know the arguments
length). When that condition isn't met, we lower op_get_rest_length to
GetRestArray. GetRestArray produces its result as an int32.

  • bytecode/BytecodeList.json:
  • bytecode/BytecodeUseDef.h:

(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitNewArray):
(JSC::BytecodeGenerator::emitNewArrayWithSize):
(JSC::BytecodeGenerator::emitNewFunction):
(JSC::BytecodeGenerator::emitExpectedFunctionSnippet):
(JSC::BytecodeGenerator::emitRestParameter):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::RestParameterNode::emit):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCapabilities.cpp:

(JSC::DFG::capabilityLevel):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGDoesGC.cpp:

(JSC::DFG::doesGC):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGMayExit.cpp:

(JSC::DFG::mayExit):

  • dfg/DFGNode.h:

(JSC::DFG::Node::numberOfArgumentsToSkip):

  • dfg/DFGNodeType.h:
  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileCopyRest):
(JSC::DFG::SpeculativeJIT::compileGetRestLength):
(JSC::DFG::SpeculativeJIT::compileNotifyWrite):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::callOperation):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCopyRest):
(JSC::FTL::DFG::LowerDFGToLLVM::compileGetRestLength):
(JSC::FTL::DFG::LowerDFGToLLVM::compileNewObject):

  • jit/JIT.cpp:

(JSC::JIT::privateCompileMainPass):

  • jit/JIT.h:
  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_copy_rest):
(JSC::JIT::emit_op_get_rest_length):

  • llint/LowLevelInterpreter.asm:
  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

Location:
trunk/Source/JavaScriptCore
Files:
33 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r192812 r192814  
     12015-11-30  Saam barati  <sbarati@apple.com>
     2
     3        implement op_get_rest_length so that we can allocate the rest array with the right size from the start
     4        https://bugs.webkit.org/show_bug.cgi?id=151467
     5
     6        Reviewed by Geoffrey Garen and Mark Lam.
     7
     8        This patch implements op_get_rest_length which returns the length
     9        that the rest parameter array will be. We're implementing this because
     10        it might be a constant value in the presence of inlining in the DFG.
     11        We will take advantage of this optimization opportunity in a future patch:
     12        https://bugs.webkit.org/show_bug.cgi?id=151454
     13        to emit better code for op_copy_rest.
     14
     15        op_get_rest_length has two operands:
     16        1) a destination
     17        2) A constant indicating the number of parameters to skip when copying the rest array.
     18
     19        op_get_rest_length lowers to a JSConstant node when we're inlined
     20        and not a varargs call (in this case, we statically know the arguments
     21        length). When that condition isn't met, we lower op_get_rest_length to
     22        GetRestArray. GetRestArray produces its result as an int32.
     23
     24        * bytecode/BytecodeList.json:
     25        * bytecode/BytecodeUseDef.h:
     26        (JSC::computeUsesForBytecodeOffset):
     27        (JSC::computeDefsForBytecodeOffset):
     28        * bytecode/CodeBlock.cpp:
     29        (JSC::CodeBlock::dumpBytecode):
     30        * bytecompiler/BytecodeGenerator.cpp:
     31        (JSC::BytecodeGenerator::emitNewArray):
     32        (JSC::BytecodeGenerator::emitNewArrayWithSize):
     33        (JSC::BytecodeGenerator::emitNewFunction):
     34        (JSC::BytecodeGenerator::emitExpectedFunctionSnippet):
     35        (JSC::BytecodeGenerator::emitRestParameter):
     36        * bytecompiler/BytecodeGenerator.h:
     37        * bytecompiler/NodesCodegen.cpp:
     38        (JSC::RestParameterNode::emit):
     39        * dfg/DFGAbstractInterpreterInlines.h:
     40        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     41        * dfg/DFGByteCodeParser.cpp:
     42        (JSC::DFG::ByteCodeParser::parseBlock):
     43        * dfg/DFGCapabilities.cpp:
     44        (JSC::DFG::capabilityLevel):
     45        * dfg/DFGClobberize.h:
     46        (JSC::DFG::clobberize):
     47        * dfg/DFGDoesGC.cpp:
     48        (JSC::DFG::doesGC):
     49        * dfg/DFGFixupPhase.cpp:
     50        (JSC::DFG::FixupPhase::fixupNode):
     51        * dfg/DFGMayExit.cpp:
     52        (JSC::DFG::mayExit):
     53        * dfg/DFGNode.h:
     54        (JSC::DFG::Node::numberOfArgumentsToSkip):
     55        * dfg/DFGNodeType.h:
     56        * dfg/DFGOperations.cpp:
     57        * dfg/DFGOperations.h:
     58        * dfg/DFGPredictionPropagationPhase.cpp:
     59        (JSC::DFG::PredictionPropagationPhase::propagate):
     60        * dfg/DFGSafeToExecute.h:
     61        (JSC::DFG::safeToExecute):
     62        * dfg/DFGSpeculativeJIT.cpp:
     63        (JSC::DFG::SpeculativeJIT::compileCopyRest):
     64        (JSC::DFG::SpeculativeJIT::compileGetRestLength):
     65        (JSC::DFG::SpeculativeJIT::compileNotifyWrite):
     66        * dfg/DFGSpeculativeJIT.h:
     67        (JSC::DFG::SpeculativeJIT::callOperation):
     68        * dfg/DFGSpeculativeJIT32_64.cpp:
     69        (JSC::DFG::SpeculativeJIT::compile):
     70        * dfg/DFGSpeculativeJIT64.cpp:
     71        (JSC::DFG::SpeculativeJIT::compile):
     72        * ftl/FTLCapabilities.cpp:
     73        (JSC::FTL::canCompile):
     74        * ftl/FTLLowerDFGToLLVM.cpp:
     75        (JSC::FTL::DFG::LowerDFGToLLVM::compileNode):
     76        (JSC::FTL::DFG::LowerDFGToLLVM::compileCopyRest):
     77        (JSC::FTL::DFG::LowerDFGToLLVM::compileGetRestLength):
     78        (JSC::FTL::DFG::LowerDFGToLLVM::compileNewObject):
     79        * jit/JIT.cpp:
     80        (JSC::JIT::privateCompileMainPass):
     81        * jit/JIT.h:
     82        * jit/JITOpcodes.cpp:
     83        (JSC::JIT::emit_op_copy_rest):
     84        (JSC::JIT::emit_op_get_rest_length):
     85        * llint/LowLevelInterpreter.asm:
     86        * llint/LowLevelInterpreter32_64.asm:
     87        * llint/LowLevelInterpreter64.asm:
     88        * runtime/CommonSlowPaths.cpp:
     89        (JSC::SLOW_PATH_DECL):
     90
    1912015-11-30  Filip Pizlo  <fpizlo@apple.com>
    292
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r192671 r192814  
    130130            { "name" : "op_load_arrowfunction_this", "length" : 2 },
    131131            { "name" : "op_assert", "length" : 3 },
    132             { "name" : "op_copy_rest", "length": 3 }
     132            { "name" : "op_copy_rest", "length": 4 },
     133            { "name" : "op_get_rest_length", "length": 3 }
    133134        ]
    134135    },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r192671 r192814  
    5454    case op_create_direct_arguments:
    5555    case op_create_out_of_band_arguments:
     56    case op_get_rest_length:
    5657        return;
    5758    case op_assert:
     
    7172    case op_jneq_null:
    7273    case op_dec:
    73     case op_inc:
    74     case op_copy_rest: {
     74    case op_inc: {
    7575        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    7676        return;
     
    8383    case op_jngreater:
    8484    case op_jngreatereq:
    85     case op_jless: {
     85    case op_jless:
     86    case op_copy_rest: {
    8687        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    8788        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
     
    378379    case op_del_by_val:
    379380    case op_unsigned:
    380     case op_get_from_arguments: {
     381    case op_get_from_arguments:
     382    case op_get_rest_length: {
    381383        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
    382384        return;
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r192671 r192814  
    784784        case op_copy_rest: {
    785785            int r0 = (++it)->u.operand;
     786            int r1 = (++it)->u.operand;
     787            unsigned argumentOffset = (++it)->u.unsignedValue;
    786788            printLocationAndOp(out, exec, location, it, "copy_rest");
     789            out.printf("%s, %s, ", registerName(r0).data(), registerName(r1).data());
     790            out.printf("ArgumentsOffset: %u", argumentOffset);
     791            break;
     792        }
     793        case op_get_rest_length: {
     794            int r0 = (++it)->u.operand;
     795            printLocationAndOp(out, exec, location, it, "get_rest_length");
    787796            out.printf("%s, ", registerName(r0).data());
    788797            unsigned argumentOffset = (++it)->u.unsignedValue;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r192671 r192814  
    24722472}
    24732473
     2474RegisterID* BytecodeGenerator::emitNewArrayWithSize(RegisterID* dst, RegisterID* length)
     2475{
     2476    emitOpcode(op_new_array_with_size);
     2477    instructions().append(dst->index());
     2478    instructions().append(length->index());
     2479    instructions().append(newArrayAllocationProfile());
     2480
     2481    return dst;
     2482}
     2483
    24742484RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionMetadataNode* function)
    24752485{
     
    26012611       
    26022612        if (dst != ignoredResult()) {
    2603             if (callArguments.argumentCountIncludingThis() == 2) {
    2604                 emitOpcode(op_new_array_with_size);
    2605                 instructions().append(dst->index());
    2606                 instructions().append(callArguments.argumentRegister(0)->index());
    2607                 instructions().append(newArrayAllocationProfile());
    2608             } else {
     2613            if (callArguments.argumentCountIncludingThis() == 2)
     2614                emitNewArrayWithSize(dst, callArguments.argumentRegister(0));
     2615            else {
    26092616                ASSERT(callArguments.argumentCountIncludingThis() == 1);
    26102617                emitOpcode(op_new_array);
     
    38343841RegisterID* BytecodeGenerator::emitRestParameter(RegisterID* result, unsigned numParametersToSkip)
    38353842{
    3836     emitNewArray(result, nullptr, 0);
     3843    RefPtr<RegisterID> restArrayLength = newTemporary();
     3844    emitOpcode(op_get_rest_length);
     3845    instructions().append(restArrayLength->index());
     3846    instructions().append(numParametersToSkip);
     3847
     3848    emitNewArrayWithSize(result, restArrayLength.get());
    38373849
    38383850    emitOpcode(op_copy_rest);
    38393851    instructions().append(result->index());
     3852    instructions().append(restArrayLength->index());
    38403853    instructions().append(numParametersToSkip);
    38413854
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r192671 r192814  
    498498        RegisterID* emitNewObject(RegisterID* dst);
    499499        RegisterID* emitNewArray(RegisterID* dst, ElementNode*, unsigned length); // stops at first elision
     500        RegisterID* emitNewArrayWithSize(RegisterID* dst, RegisterID* length);
    500501
    501502        RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r192768 r192814  
    34843484    }
    34853485
    3486     RefPtr<RegisterID> restParameterArray = generator.emitRestParameter(generator.newTemporary(), m_numParametersToSkip);
     3486    RefPtr<RegisterID> restParameterArray = generator.newTemporary();
     3487    generator.emitRestParameter(restParameterArray.get(), m_numParametersToSkip);
    34873488    generator.emitProfileType(restParameterArray.get(), var, m_divotStart, m_divotEnd);
    34883489    RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var);
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r192671 r192814  
    17611761       
    17621762    case GetArgumentCount:
     1763        forNode(node).setType(SpecInt32);
     1764        break;
     1765       
     1766    case GetRestLength:
    17631767        forNode(node).setType(SpecInt32);
    17641768        break;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r192671 r192814  
    33323332        }
    33333333
     3334        case op_get_rest_length: {
     3335            InlineCallFrame* inlineCallFrame = this->inlineCallFrame();
     3336            Node* length;
     3337            if (inlineCallFrame && !inlineCallFrame->isVarargs()) {
     3338                unsigned argumentsLength = inlineCallFrame->arguments.size() - 1;
     3339                unsigned numParamsToSkip = currentInstruction[2].u.unsignedValue;
     3340                JSValue restLength;
     3341                if (argumentsLength <= numParamsToSkip)
     3342                    restLength = jsNumber(0);
     3343                else
     3344                    restLength = jsNumber(argumentsLength - numParamsToSkip);
     3345
     3346                length = jsConstant(restLength);
     3347            } else
     3348                length = addToGraph(GetRestLength, OpInfo(currentInstruction[2].u.unsignedValue));
     3349            set(VirtualRegister(currentInstruction[1].u.operand), length);
     3350            NEXT_OPCODE(op_get_rest_length);
     3351        }
     3352
    33343353        case op_copy_rest: {
    33353354            noticeArgumentsUse();
    3336             addToGraph(CopyRest,
    3337                 OpInfo(currentInstruction[2].u.unsignedValue), get(VirtualRegister(currentInstruction[1].u.operand)));
     3355            Node* array = get(VirtualRegister(currentInstruction[1].u.operand));
     3356            Node* arrayLength = get(VirtualRegister(currentInstruction[2].u.operand));
     3357            addToGraph(CopyRest, OpInfo(currentInstruction[3].u.unsignedValue),
     3358                array, arrayLength);
    33383359            NEXT_OPCODE(op_copy_rest);
    33393360        }
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r192671 r192814  
    221221    case op_catch:
    222222    case op_copy_rest:
     223    case op_get_rest_length:
    223224        return CanCompileAndInline;
    224225
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r192671 r192814  
    429429        def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, JSStack::ArgumentCount)), LazyNode(node));
    430430        return;
     431
     432    case GetRestLength:
     433        read(Stack);
     434        return;
    431435       
    432436    case GetLocal:
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r192671 r192814  
    5151    case GetCallee:
    5252    case GetArgumentCount:
     53    case GetRestLength:
    5354    case GetLocal:
    5455    case SetLocal:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r192671 r192814  
    13711371        case CopyRest: {
    13721372            fixEdge<KnownCellUse>(node->child1());
     1373            fixEdge<KnownInt32Use>(node->child2());
    13731374            break;
    13741375        }
     
    13821383        case GetCallee:
    13831384        case GetArgumentCount:
     1385        case GetRestLength:
    13841386        case Flush:
    13851387        case PhantomLocal:
  • trunk/Source/JavaScriptCore/dfg/DFGMayExit.cpp

    r189070 r192814  
    114114    case GetCallee:
    115115    case GetArgumentCount:
     116    case GetRestLength:
    116117    case GetScope:
    117118    case PhantomLocal:
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r192671 r192814  
    21622162    unsigned numberOfArgumentsToSkip()
    21632163    {
    2164         ASSERT(op() == CopyRest);
     2164        ASSERT(op() == CopyRest || op() == GetRestLength);
    21652165        return static_cast<unsigned>(m_opInfo);
    21662166    }
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r192671 r192814  
    263263    macro(NewTypedArray, NodeResultJS | NodeMustGenerate) \
    264264    macro(NewRegexp, NodeResultJS) \
     265    /* Rest Parameter */\
     266    macro(GetRestLength, NodeResultInt32) \
    265267    macro(CopyRest, NodeMustGenerate) \
    266268    \
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r192671 r192814  
    819819}
    820820
    821 void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned numberOfArguments)
    822 {
    823     RELEASE_ASSERT(numberOfArguments > numberOfParamsToSkip); // We should only call this from JIT code when this condition is true.
     821void JIT_OPERATION operationCopyRest(ExecState* exec, JSCell* arrayAsCell, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize)
     822{
     823    ASSERT(arraySize);
    824824    JSArray* array = jsCast<JSArray*>(arrayAsCell);
    825     unsigned arraySize = numberOfArguments - numberOfParamsToSkip;
     825    ASSERT(arraySize == array->length());
    826826    array->setLength(exec, arraySize);
    827827    for (unsigned i = 0; i < arraySize; i++)
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r192671 r192814  
    104104JSCell* JIT_OPERATION operationCreateClonedArgumentsDuringExit(ExecState*, InlineCallFrame*, JSFunction*, int32_t argumentCount);
    105105JSCell* JIT_OPERATION operationCreateClonedArguments(ExecState*, Structure*, Register* argumentStart, int32_t length, JSFunction* callee);
    106 void JIT_OPERATION operationCopyRest(ExecState*, JSCell*, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned argumentsCount);
     106void JIT_OPERATION operationCopyRest(ExecState*, JSCell*, Register* argumentStart, unsigned numberOfParamsToSkip, unsigned arraySize);
    107107double JIT_OPERATION operationFModOnInts(int32_t, int32_t) WTF_INTERNAL;
    108108size_t JIT_OPERATION operationObjectIsObject(ExecState*, JSGlobalObject*, JSCell*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r192671 r192814  
    216216           
    217217        case GetArgumentCount: {
     218            changed |= setPrediction(SpecInt32);
     219            break;
     220        }
     221
     222        case GetRestLength: {
    218223            changed |= setPrediction(SpecInt32);
    219224            break;
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r192671 r192814  
    141141    case GetCallee:
    142142    case GetArgumentCount:
     143    case GetRestLength:
    143144    case GetLocal:
    144145    case SetLocal:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r192795 r192814  
    53535353
    53545354    SpeculateCellOperand array(this, node->child1());
     5355    GPRTemporary argumentsStart(this);
     5356    SpeculateStrictInt32Operand arrayLength(this, node->child2());
     5357
    53555358    GPRReg arrayGPR = array.gpr();
    5356 
    5357     GPRTemporary argumentsLength(this);
    5358     GPRReg argumentsLengthGPR = argumentsLength.gpr();
    5359 
    5360     GPRTemporary argumentsStart(this);
    53615359    GPRReg argumentsStartGPR = argumentsStart.gpr();
    5362 
    5363     emitGetLength(node->origin.semantic, argumentsLengthGPR);
    5364     CCallHelpers::Jump done = m_jit.branch32(MacroAssembler::LessThanOrEqual, argumentsLengthGPR, TrustedImm32(node->numberOfArgumentsToSkip()));
     5360    GPRReg arrayLengthGPR = arrayLength.gpr();
     5361
     5362    CCallHelpers::Jump done = m_jit.branch32(MacroAssembler::Equal, arrayLengthGPR, TrustedImm32(0));
    53655363
    53665364    emitGetArgumentStart(node->origin.semantic, argumentsStartGPR);
    5367     silentSpillAllRegisters(argumentsLengthGPR, argumentsStartGPR);
    5368     // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:number of arguments
    5369     callOperation(operationCopyRest, arrayGPR, argumentsStartGPR, TrustedImm32(node->numberOfArgumentsToSkip()), argumentsLengthGPR);
    5370     silentFillAllRegisters(argumentsLengthGPR);
     5365    silentSpillAllRegisters(argumentsStartGPR);
     5366    // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length
     5367    callOperation(operationCopyRest, arrayGPR, argumentsStartGPR, Imm32(node->numberOfArgumentsToSkip()), arrayLengthGPR);
     5368    silentFillAllRegisters(argumentsStartGPR);
    53715369    m_jit.exceptionCheck();
    53725370
     
    53745372
    53755373    noResult(node);
     5374}
     5375
     5376void SpeculativeJIT::compileGetRestLength(Node* node)
     5377{
     5378    ASSERT(node->op() == GetRestLength);
     5379
     5380    GPRTemporary result(this);
     5381    GPRReg resultGPR = result.gpr();
     5382
     5383    emitGetLength(node->origin.semantic, resultGPR);
     5384    CCallHelpers::Jump hasNonZeroLength = m_jit.branch32(MacroAssembler::Above, resultGPR, Imm32(node->numberOfArgumentsToSkip()));
     5385    m_jit.move(TrustedImm32(0), resultGPR);
     5386    CCallHelpers::Jump done = m_jit.jump();
     5387    hasNonZeroLength.link(&m_jit);
     5388    if (node->numberOfArgumentsToSkip())
     5389        m_jit.sub32(TrustedImm32(node->numberOfArgumentsToSkip()), resultGPR);
     5390    done.link(&m_jit);
     5391    int32Result(resultGPR, node);
    53765392}
    53775393
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r192671 r192814  
    12221222    }
    12231223
    1224     JITCompiler::Call callOperation(V_JITOperation_ECRUiUi operation, GPRReg arg1, GPRReg arg2, TrustedImm32 arg3, GPRReg arg4)
    1225     {
    1226         m_jit.setupArgumentsWithExecState(arg1, arg2, arg3, arg4);
     1224    JITCompiler::Call callOperation(V_JITOperation_ECRUiUi operation, GPRReg arg1, GPRReg arg2, Imm32 arg3, GPRReg arg4)
     1225    {
     1226        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3.asTrustedImm32(), arg4);
    12271227        return appendCall(operation);
    12281228    }
     
    22462246    void compileCreateClonedArguments(Node*);
    22472247    void compileCopyRest(Node*);
     2248    void compileGetRestLength(Node*);
    22482249    void compileNotifyWrite(Node*);
    22492250    bool compileRegExpExec(Node*);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r192671 r192814  
    44444444    }
    44454445
     4446    case GetRestLength: {
     4447        compileGetRestLength(node);
     4448        break;
     4449    }
     4450
    44464451    case NewFunction:
    44474452    case NewArrowFunction:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r192671 r192814  
    38283828        break;
    38293829    }
     3830
     3831    case GetRestLength: {
     3832        compileGetRestLength(node);
     3833        break;
     3834    }
    38303835       
    38313836    case GetScope:
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r192671 r192814  
    212212    case PutSetterByVal:
    213213    case CopyRest:
     214    case GetRestLength:
    214215        // These are OK.
    215216        break;
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r192671 r192814  
    970970        case CopyRest:
    971971            compileCopyRest();
     972            break;
     973        case GetRestLength:
     974            compileGetRestLength();
    972975            break;
    973976
     
    36463649        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("FillRestParameter continuation"));
    36473650
     3651        LValue arrayLength = lowInt32(m_node->child2());
     3652
     3653        m_out.branch(
     3654            m_out.equal(arrayLength, m_out.constInt32(0)),
     3655            unsure(continuation), unsure(doCopyRest));
     3656           
     3657        LBasicBlock lastNext = m_out.appendTo(doCopyRest, continuation);
     3658        // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:array length
    36483659        LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip());
    3649         LValue numberOfArguments = getArgumentsLength().value;
    3650 
    3651         m_out.branch(
    3652             m_out.above(numberOfArguments, numberOfArgumentsToSkip),
    3653             unsure(doCopyRest), unsure(continuation));
    3654            
    3655         LBasicBlock lastNext = m_out.appendTo(doCopyRest, continuation);
    3656         // Arguments: 0:exec, 1:JSCell* array, 2:arguments start, 3:number of arguments to skip, 4:number of arguments
    36573660        vmCall(
    36583661            m_out.voidType,m_out.operation(operationCopyRest), m_callFrame, lowCell(m_node->child1()),
    3659             getArgumentsStart(), numberOfArgumentsToSkip, numberOfArguments);
     3662            getArgumentsStart(), numberOfArgumentsToSkip, arrayLength);
    36603663        m_out.jump(continuation);
    36613664
    36623665        m_out.appendTo(continuation, lastNext);
     3666    }
     3667
     3668    void compileGetRestLength()
     3669    {
     3670        LBasicBlock nonZeroLength = FTL_NEW_BLOCK(m_out, ("GetRestLength non zero"));
     3671        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetRestLength continuation"));
     3672       
     3673        ValueFromBlock zeroLengthResult = m_out.anchor(m_out.constInt32(0));
     3674
     3675        LValue numberOfArgumentsToSkip = m_out.constInt32(m_node->numberOfArgumentsToSkip());
     3676        LValue argumentsLength = getArgumentsLength().value;
     3677        m_out.branch(m_out.above(argumentsLength, numberOfArgumentsToSkip),
     3678            unsure(nonZeroLength), unsure(continuation));
     3679       
     3680        LBasicBlock lastNext = m_out.appendTo(nonZeroLength, continuation);
     3681        ValueFromBlock nonZeroLengthResult = m_out.anchor(m_out.sub(argumentsLength, numberOfArgumentsToSkip));
     3682        m_out.jump(continuation);
     3683       
     3684        m_out.appendTo(continuation, lastNext);
     3685        setInt32(m_out.phi(m_out.int32, zeroLengthResult, nonZeroLengthResult));
    36633686    }
    36643687   
  • trunk/Source/JavaScriptCore/jit/JIT.cpp

    r192671 r192814  
    213213        DEFINE_OP(op_create_out_of_band_arguments)
    214214        DEFINE_OP(op_copy_rest)
     215        DEFINE_OP(op_get_rest_length)
    215216        DEFINE_OP(op_check_tdz)
    216217        DEFINE_OP(op_assert)
  • trunk/Source/JavaScriptCore/jit/JIT.h

    r192671 r192814  
    492492        void emit_op_create_out_of_band_arguments(Instruction*);
    493493        void emit_op_copy_rest(Instruction*);
     494        void emit_op_get_rest_length(Instruction*);
    494495        void emit_op_check_tdz(Instruction*);
    495496        void emit_op_assert(Instruction*);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r192671 r192814  
    14061406}
    14071407
     1408void JIT::emit_op_get_rest_length(Instruction* currentInstruction)
     1409{
     1410    int dst = currentInstruction[1].u.operand;
     1411    unsigned numParamsToSkip = currentInstruction[2].u.unsignedValue;
     1412    load32(payloadFor(JSStack::ArgumentCount), regT0);
     1413    sub32(TrustedImm32(1), regT0);
     1414    Jump zeroLength = branch32(LessThanOrEqual, regT0, Imm32(numParamsToSkip));
     1415    sub32(Imm32(numParamsToSkip), regT0);
     1416#if USE(JSVALUE64)
     1417    boxInt32(regT0, JSValueRegs(regT0));
     1418#endif
     1419    Jump done = jump();
     1420
     1421    zeroLength.link(this);
     1422#if USE(JSVALUE64)
     1423    move(TrustedImm64(JSValue::encode(jsNumber(0))), regT0);
     1424#else
     1425    move(TrustedImm32(0), regT0);
     1426#endif
     1427
     1428    done.link(this);
     1429#if USE(JSVALUE64)
     1430    emitPutVirtualRegister(dst, regT0);
     1431#else
     1432    move(TrustedImm32(JSValue::Int32Tag), regT1);
     1433    emitPutVirtualRegister(dst, JSValueRegs(regT1, regT0));
     1434#endif
     1435}
     1436
    14081437} // namespace JSC
    14091438
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r192671 r192814  
    16791679    traceExecution()
    16801680    callSlowPath(_slow_path_copy_rest)
    1681     dispatch(3)
     1681    dispatch(4)
    16821682
    16831683
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r192125 r192814  
    24312431    storei t0, PayloadOffset[cfr, t1, 8]
    24322432    dispatch(2)
     2433
     2434
     2435_llint_op_get_rest_length:
     2436    traceExecution()
     2437    loadi PayloadOffset + ArgumentCount[cfr], t0
     2438    subi 1, t0
     2439    loadisFromInstruction(2, t1)
     2440    bilteq t0, t1, .storeZero
     2441    subi t1, t0
     2442    jmp .finish
     2443.storeZero:
     2444    move 0, t0
     2445.finish:
     2446    loadisFromInstruction(1, t1)
     2447    storei t0, PayloadOffset[cfr, t1, 8]
     2448    storei Int32Tag, TagOffset[cfr, t1, 8]
     2449    dispatch(3)
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r192125 r192814  
    22992299    storeq t0, [cfr, t1, 8]
    23002300    dispatch(2)
     2301
     2302
     2303_llint_op_get_rest_length:
     2304    traceExecution()
     2305    loadi PayloadOffset + ArgumentCount[cfr], t0
     2306    subi 1, t0
     2307    loadisFromInstruction(2, t1)
     2308    bilteq t0, t1, .storeZero
     2309    subi t1, t0
     2310    jmp .boxUp
     2311.storeZero:
     2312    move 0, t0
     2313.boxUp:
     2314    orq tagTypeNumber, t0
     2315    loadisFromInstruction(1, t1)
     2316    storeq t0, [cfr, t1, 8]
     2317    dispatch(3)
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r192671 r192814  
    705705{
    706706    BEGIN();
    707     unsigned numParamsToSkip = pc[2].u.unsignedValue;
    708     unsigned numArgumentsToFunction = exec->argumentCount();
    709     if (numArgumentsToFunction <= numParamsToSkip)
     707    unsigned arraySize = OP_C(2).jsValue().asUInt32();
     708    if (!arraySize) {
     709        ASSERT(!jsCast<JSArray*>(OP(1).jsValue())->length());
    710710        END();
    711 
     711    }
    712712    JSArray* array = jsCast<JSArray*>(OP(1).jsValue());
    713     unsigned arraySize = numArgumentsToFunction - numParamsToSkip;
    714     array->setLength(exec, arraySize);
     713    ASSERT(arraySize == array->length());
     714    unsigned numParamsToSkip = pc[3].u.unsignedValue;
    715715    for (unsigned i = 0; i < arraySize; i++)
    716716        array->putDirectIndex(exec, i, exec->uncheckedArgument(i + numParamsToSkip));
Note: See TracChangeset for help on using the changeset viewer.