Changeset 118112 in webkit


Ignore:
Timestamp:
May 22, 2012, 8:48:52 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG should support op_get_argument_by_val and op_get_arguments_length
https://bugs.webkit.org/show_bug.cgi?id=85911

Reviewed by Oliver Hunt.

Merged r116467 from dfgopt.

This adds a simple and relatively conservative implementation of op_get_argument_by_val
and op_get_arguments_length. We can optimize these later. For now it's great to have
the additional coverage.

This patch appears to be perf-neutral.

  • dfg/DFGAbstractState.cpp:

(JSC::DFG::AbstractState::execute):

  • dfg/DFGAssemblyHelpers.h:

(JSC::DFG::AssemblyHelpers::addressFor):
(JSC::DFG::AssemblyHelpers::tagFor):
(JSC::DFG::AssemblyHelpers::payloadFor):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGCapabilities.h:

(JSC::DFG::canCompileOpcode):
(JSC::DFG::canInlineOpcode):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasHeapPrediction):

  • dfg/DFGNodeType.h:

(DFG):

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

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

  • dfg/DFGSpeculativeJIT.h:

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

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • jit/JITOpcodes.cpp:

(JSC::JIT::emit_op_get_argument_by_val):

  • jit/JITOpcodes32_64.cpp:

(JSC::JIT::emit_op_get_argument_by_val):

  • llint/LowLevelInterpreter32_64.asm:
  • llint/LowLevelInterpreter64.asm:
Location:
trunk/Source/JavaScriptCore
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r118102 r118112  
     12012-05-08  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG should support op_get_argument_by_val and op_get_arguments_length
     4        https://bugs.webkit.org/show_bug.cgi?id=85911
     5
     6        Reviewed by Oliver Hunt.
     7       
     8        Merged r116467 from dfgopt.
     9       
     10        This adds a simple and relatively conservative implementation of op_get_argument_by_val
     11        and op_get_arguments_length. We can optimize these later. For now it's great to have
     12        the additional coverage.
     13       
     14        This patch appears to be perf-neutral.
     15
     16        * dfg/DFGAbstractState.cpp:
     17        (JSC::DFG::AbstractState::execute):
     18        * dfg/DFGAssemblyHelpers.h:
     19        (JSC::DFG::AssemblyHelpers::addressFor):
     20        (JSC::DFG::AssemblyHelpers::tagFor):
     21        (JSC::DFG::AssemblyHelpers::payloadFor):
     22        * dfg/DFGByteCodeParser.cpp:
     23        (JSC::DFG::ByteCodeParser::parseBlock):
     24        * dfg/DFGCapabilities.h:
     25        (JSC::DFG::canCompileOpcode):
     26        (JSC::DFG::canInlineOpcode):
     27        * dfg/DFGNode.h:
     28        (JSC::DFG::Node::hasHeapPrediction):
     29        * dfg/DFGNodeType.h:
     30        (DFG):
     31        * dfg/DFGOperations.cpp:
     32        * dfg/DFGOperations.h:
     33        * dfg/DFGPredictionPropagationPhase.cpp:
     34        (JSC::DFG::PredictionPropagationPhase::propagate):
     35        * dfg/DFGSpeculativeJIT.h:
     36        (JSC::DFG::SpeculativeJIT::callOperation):
     37        (SpeculativeJIT):
     38        * dfg/DFGSpeculativeJIT32_64.cpp:
     39        (JSC::DFG::SpeculativeJIT::compile):
     40        * dfg/DFGSpeculativeJIT64.cpp:
     41        (JSC::DFG::SpeculativeJIT::compile):
     42        * jit/JITOpcodes.cpp:
     43        (JSC::JIT::emit_op_get_argument_by_val):
     44        * jit/JITOpcodes32_64.cpp:
     45        (JSC::JIT::emit_op_get_argument_by_val):
     46        * llint/LowLevelInterpreter32_64.asm:
     47        * llint/LowLevelInterpreter64.asm:
     48
    1492012-05-07  Filip Pizlo  <fpizlo@apple.com>
    250
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractState.cpp

    r118102 r118112  
    10691069        break;
    10701070       
     1071    case GetMyArgumentsLength:
     1072        // This potentially clobbers all structures if the arguments object had a getter
     1073        // installed on the length property.
     1074        clobberStructures(indexInBlock);
     1075        // We currently make no guarantee about what this returns because it does not
     1076        // speculate that the length property is actually a length.
     1077        forNode(nodeIndex).makeTop();
     1078        break;
     1079       
     1080    case GetMyArgumentByVal:
     1081        // This potentially clobbers all structures if the property we're accessing has
     1082        // a getter. We don't speculate against this.
     1083        clobberStructures(indexInBlock);
     1084        // But we do speculate that the index is an integer.
     1085        forNode(node.child1()).filter(PredictInt32);
     1086        // And the result is unknown.
     1087        forNode(nodeIndex).makeTop();
     1088        break;
     1089       
    10711090    case NewFunction:
    10721091    case NewFunctionExpression:
  • trunk/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h

    r117729 r118112  
    135135        return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register));
    136136    }
     137    static Address addressFor(int operand)
     138    {
     139        return addressFor(static_cast<VirtualRegister>(operand));
     140    }
    137141
    138142    static Address tagFor(VirtualRegister virtualRegister)
     
    140144        return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
    141145    }
     146    static Address tagFor(int operand)
     147    {
     148        return tagFor(static_cast<VirtualRegister>(operand));
     149    }
    142150
    143151    static Address payloadFor(VirtualRegister virtualRegister)
    144152    {
    145153        return Address(GPRInfo::callFrameRegister, virtualRegister * sizeof(Register) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
     154    }
     155    static Address payloadFor(int operand)
     156    {
     157        return payloadFor(static_cast<VirtualRegister>(operand));
    146158    }
    147159
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r118102 r118112  
    23882388        }
    23892389           
     2390        case op_get_arguments_length: {
     2391            set(currentInstruction[1].u.operand, addToGraph(GetMyArgumentsLength));
     2392            NEXT_OPCODE(op_get_arguments_length);
     2393        }
     2394           
     2395        case op_get_argument_by_val: {
     2396            set(currentInstruction[1].u.operand,
     2397                addToGraph(
     2398                    GetMyArgumentByVal, OpInfo(0), OpInfo(getPrediction()),
     2399                    get(currentInstruction[3].u.operand)));
     2400            NEXT_OPCODE(op_get_argument_by_val);
     2401        }
     2402           
    23902403        case op_new_func: {
    23912404            if (!currentInstruction[3].u.operand) {
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.h

    r118102 r118112  
    168168    case op_new_func:
    169169    case op_new_func_exp:
     170    case op_get_argument_by_val:
     171    case op_get_arguments_length:
    170172        return true;
    171173       
     
    203205    case op_create_arguments:
    204206    case op_tear_off_arguments:
     207    case op_get_argument_by_val:
     208    case op_get_arguments_length:
    205209        return false;
    206210       
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r118030 r118112  
    513513        case GetByIdFlush:
    514514        case GetByVal:
     515        case GetMyArgumentByVal:
    515516        case Call:
    516517        case Construct:
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r118102 r118112  
    196196    macro(CreateArguments, NodeResultJS) \
    197197    macro(TearOffArguments, NodeMustGenerate) \
     198    macro(GetMyArgumentsLength, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
     199    macro(GetMyArgumentByVal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
    198200    \
    199201    /* Nodes for creating functions. */\
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r118102 r118112  
    10651065    ASSERT(exec->codeBlock()->usesArguments() && !exec->codeBlock()->needsFullScopeChain());
    10661066    asArguments(argumentsCell)->tearOff(exec);
     1067}
     1068
     1069EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState* exec)
     1070{
     1071    Identifier ident(&exec->globalData(), "length");
     1072    JSValue baseValue = exec->uncheckedR(exec->codeBlock()->argumentsRegister()).jsValue();
     1073    PropertySlot slot(baseValue);
     1074    return JSValue::encode(baseValue.get(exec, ident, slot));
     1075}
     1076
     1077EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState* exec, int32_t index)
     1078{
     1079    return JSValue::encode(
     1080        exec->uncheckedR(exec->codeBlock()->argumentsRegister()).jsValue().get(exec, index));
    10671081}
    10681082
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r118102 r118112  
    6161    G: GlobalResolveInfo*
    6262*/
     63typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_E)(ExecState*);
    6364typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EA)(ExecState*, JSArray*);
    6465typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*);
     
    7677typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPS)(ExecState*, void*, size_t);
    7778typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESS)(ExecState*, size_t, size_t);
     79typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EZ)(ExecState*, int32_t);
    7880typedef JSCell* DFG_OPERATION (*C_DFGOperation_E)(ExecState*);
    7981typedef JSCell* DFG_OPERATION (*C_DFGOperation_EC)(ExecState*, JSCell*);
     
    158160void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*, int32_t unmodifiedArgumentsRegister);
    159161void DFG_OPERATION operationTearOffArguments(ExecState*, JSCell*);
     162EncodedJSValue DFG_OPERATION operationGetArgumentsLength(ExecState*);
     163EncodedJSValue DFG_OPERATION operationGetArgumentByVal(ExecState*, int32_t);
    160164JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*);
    161165JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*);
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r118102 r118112  
    438438        }
    439439           
     440        case GetMyArgumentByVal: {
     441            changed |= mergePrediction(node.getHeapPrediction());
     442            changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt);
     443            break;
     444        }
     445           
     446        case GetMyArgumentsLength: {
     447            changed |= setPrediction(PredictInt32);
     448            break;
     449        }
     450           
    440451        case GetPropertyStorage:
    441452        case GetIndexedPropertyStorage: {
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r118102 r118112  
    12121212    // decision as to how to fill the regsiters to setupArguments* methods.
    12131213#if USE(JSVALUE64)
     1214    JITCompiler::Call callOperation(J_DFGOperation_E operation, GPRReg result)
     1215    {
     1216        m_jit.setupArgumentsExecState();
     1217        return appendCallWithExceptionCheckSetResult(operation, result);
     1218    }
    12141219    JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg result, void* pointer)
    12151220    {
     
    12701275    }
    12711276    JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg result, GPRReg arg1)
     1277    {
     1278        m_jit.setupArgumentsWithExecState(arg1);
     1279        return appendCallWithExceptionCheckSetResult(operation, result);
     1280    }
     1281    JITCompiler::Call callOperation(J_DFGOperation_EZ operation, GPRReg result, GPRReg arg1)
    12721282    {
    12731283        m_jit.setupArgumentsWithExecState(arg1);
     
    14321442        return call;
    14331443    }
     1444    JITCompiler::Call callOperation(J_DFGOperation_E operation, GPRReg resultTag, GPRReg resultPayload)
     1445    {
     1446        m_jit.setupArgumentsExecState();
     1447        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     1448    }
    14341449    JITCompiler::Call callOperation(J_DFGOperation_EP operation, GPRReg resultTag, GPRReg resultPayload, void* pointer)
    14351450    {
     
    15071522        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
    15081523    }
     1524    JITCompiler::Call callOperation(J_DFGOperation_EZ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1)
     1525    {
     1526        m_jit.setupArgumentsWithExecState(arg1);
     1527        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     1528    }
    15091529    JITCompiler::Call callOperation(C_DFGOperation_E operation, GPRReg result)
    15101530    {
     
    16521672#undef EABI_32BIT_DUMMY_ARG
    16531673   
     1674    template<typename FunctionType>
     1675    JITCompiler::Call callOperation(
     1676        FunctionType operation, JSValueRegs result)
     1677    {
     1678        return callOperation(operation, result.tagGPR(), result.payloadGPR());
     1679    }
    16541680    template<typename FunctionType, typename ArgumentType1>
    16551681    JITCompiler::Call callOperation(
     
    19992025    void compileGetCharCodeAt(Node&);
    20002026    void compileGetByValOnString(Node&);
     2027
    20012028    void compileGetByValOnArguments(Node&);
    20022029    void compileGetArgumentsLength(Node&);
     2030   
    20032031    void compileValueToInt32(Node&);
    20042032    void compileUInt32ToNumber(Node&);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r118102 r118112  
    38093809    }
    38103810       
     3811    case GetMyArgumentsLength: {
     3812        GPRTemporary resultPayload(this);
     3813        GPRTemporary resultTag(this);
     3814        GPRReg resultPayloadGPR = resultPayload.gpr();
     3815        GPRReg resultTagGPR = resultTag.gpr();
     3816       
     3817        JITCompiler::Jump created = m_jit.branch32(
     3818            JITCompiler::NotEqual,
     3819            JITCompiler::tagFor(m_jit.codeBlock()->argumentsRegister()),
     3820            TrustedImm32(JSValue::EmptyValueTag));
     3821       
     3822        m_jit.load32(JITCompiler::payloadFor(RegisterFile::ArgumentCount), resultPayloadGPR);
     3823        m_jit.sub32(TrustedImm32(1), resultPayloadGPR);
     3824        m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
     3825       
     3826        // FIXME: the slow path generator should perform a forward speculation that the
     3827        // result is an integer. For now we postpone the speculation by having this return
     3828        // a JSValue.
     3829       
     3830        addSlowPathGenerator(
     3831            slowPathCall(
     3832                created, this, operationGetArgumentsLength,
     3833                JSValueRegs(resultTagGPR, resultPayloadGPR)));
     3834       
     3835        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
     3836        break;
     3837    }
     3838       
     3839    case GetMyArgumentByVal: {
     3840        SpeculateStrictInt32Operand index(this, node.child1());
     3841        GPRTemporary resultPayload(this);
     3842        GPRTemporary resultTag(this);
     3843        GPRReg indexGPR = index.gpr();
     3844        GPRReg resultPayloadGPR = resultPayload.gpr();
     3845        GPRReg resultTagGPR = resultTag.gpr();
     3846       
     3847        JITCompiler::JumpList slowPath;
     3848        slowPath.append(
     3849            m_jit.branch32(
     3850                JITCompiler::NotEqual,
     3851                JITCompiler::tagFor(m_jit.codeBlock()->argumentsRegister()),
     3852                TrustedImm32(JSValue::EmptyValueTag)));
     3853       
     3854        m_jit.add32(TrustedImm32(1), indexGPR, resultPayloadGPR);
     3855        slowPath.append(
     3856            m_jit.branch32(
     3857                JITCompiler::AboveOrEqual,
     3858                resultPayloadGPR,
     3859                JITCompiler::payloadFor(RegisterFile::ArgumentCount)));
     3860       
     3861        m_jit.neg32(resultPayloadGPR);
     3862       
     3863        m_jit.load32(
     3864            JITCompiler::BaseIndex(
     3865                GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
     3866                CallFrame::argumentOffsetIncludingThis(0) * sizeof(Register) +
     3867                OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)),
     3868            resultTagGPR);
     3869        m_jit.load32(
     3870            JITCompiler::BaseIndex(
     3871                GPRInfo::callFrameRegister, resultPayloadGPR, JITCompiler::TimesEight,
     3872                CallFrame::argumentOffsetIncludingThis(0) * sizeof(Register) +
     3873                OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)),
     3874            resultPayloadGPR);
     3875       
     3876        addSlowPathGenerator(
     3877            slowPathCall(
     3878                slowPath, this, operationGetArgumentByVal,
     3879                JSValueRegs(resultTagGPR, resultPayloadGPR), indexGPR));
     3880       
     3881        jsValueResult(resultTagGPR, resultPayloadGPR, m_compileIndex);
     3882        break;
     3883    }
     3884       
    38113885    case NewFunctionNoCheck:
    38123886        compileNewFunctionNoCheck(node);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r118102 r118112  
    38223822    }
    38233823       
     3824    case GetMyArgumentsLength: {
     3825        GPRTemporary result(this);
     3826        GPRReg resultGPR = result.gpr();
     3827       
     3828        JITCompiler::Jump created = m_jit.branchTestPtr(
     3829            JITCompiler::NonZero, JITCompiler::addressFor(m_jit.codeBlock()->argumentsRegister()));
     3830       
     3831        m_jit.load32(JITCompiler::payloadFor(RegisterFile::ArgumentCount), resultGPR);
     3832        m_jit.sub32(TrustedImm32(1), resultGPR);
     3833        m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);
     3834       
     3835        // FIXME: the slow path generator should perform a forward speculation that the
     3836        // result is an integer. For now we postpone the speculation by having this return
     3837        // a JSValue.
     3838       
     3839        addSlowPathGenerator(
     3840            slowPathCall(
     3841                created, this, operationGetArgumentsLength, resultGPR));
     3842       
     3843        jsValueResult(resultGPR, m_compileIndex);
     3844        break;
     3845    }
     3846       
     3847    case GetMyArgumentByVal: {
     3848        SpeculateStrictInt32Operand index(this, node.child1());
     3849        GPRTemporary result(this);
     3850        GPRReg indexGPR = index.gpr();
     3851        GPRReg resultGPR = result.gpr();
     3852       
     3853        JITCompiler::JumpList slowPath;
     3854        slowPath.append(
     3855            m_jit.branchTestPtr(
     3856                JITCompiler::NonZero,
     3857                JITCompiler::addressFor(m_jit.codeBlock()->argumentsRegister())));
     3858       
     3859        m_jit.add32(TrustedImm32(1), indexGPR, resultGPR);
     3860        slowPath.append(
     3861            m_jit.branch32(
     3862                JITCompiler::AboveOrEqual,
     3863                resultGPR,
     3864                JITCompiler::payloadFor(RegisterFile::ArgumentCount)));
     3865       
     3866        m_jit.neg32(resultGPR);
     3867        m_jit.signExtend32ToPtr(resultGPR, resultGPR);
     3868       
     3869        m_jit.loadPtr(
     3870            JITCompiler::BaseIndex(
     3871                GPRInfo::callFrameRegister, resultGPR, JITCompiler::TimesEight,
     3872                CallFrame::argumentOffsetIncludingThis(0) * sizeof(Register)),
     3873            resultGPR);
     3874       
     3875        addSlowPathGenerator(
     3876            slowPathCall(
     3877                slowPath, this, operationGetArgumentByVal, resultGPR, indexGPR));
     3878       
     3879        jsValueResult(resultGPR, m_compileIndex);
     3880        break;
     3881    }
     3882       
    38243883    case NewFunctionNoCheck:
    38253884        compileNewFunctionNoCheck(node);
  • trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp

    r116673 r118112  
    15271527    signExtend32ToPtr(regT1, regT1);
    15281528    loadPtr(BaseIndex(callFrameRegister, regT1, TimesEight, CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT0);
     1529    emitValueProfilingSite();
    15291530    emitPutVirtualRegister(dst, regT0);
    15301531}
  • trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp

    r116673 r118112  
    16371637    loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload) + CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT0);
    16381638    loadPtr(BaseIndex(callFrameRegister, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag) + CallFrame::thisArgumentOffset() * static_cast<int>(sizeof(Register))), regT1);
     1639    emitValueProfilingSite();
    16391640    emitStore(dst, regT1, regT0);
    16401641}
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm

    r116673 r118112  
    12151215    loadi ThisArgumentOffset + TagOffset[cfr, t2, 8], t0
    12161216    loadi ThisArgumentOffset + PayloadOffset[cfr, t2, 8], t1
     1217    loadi 16[PC], t2
    12171218    storei t0, TagOffset[cfr, t3, 8]
    12181219    storei t1, PayloadOffset[cfr, t3, 8]
     1220    valueProfile(t0, t1, t2)
    12191221    dispatch(5)
    12201222
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm

    r116673 r118112  
    10591059    sxi2p t2, t2
    10601060    loadis 8[PB, PC, 8], t3
     1061    loadp 32[PB, PC, 8], t1
    10611062    loadp ThisArgumentOffset[cfr, t2, 8], t0
    10621063    storep t0, [cfr, t3, 8]
     1064    valueProfile(t0, t1)
    10631065    dispatch(5)
    10641066
Note: See TracChangeset for help on using the changeset viewer.