Changeset 37570 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Oct 13, 2008, 5:20:49 PM (17 years ago)
Author:
[email protected]
Message:

2008-10-13 Cameron Zwarich <[email protected]>

Reviewed by Geoff Garen.

Bug 21541: Move RegisterFile growth check to callee
<https://bugs.webkit.org/show_bug.cgi?id=21541>

Move the RegisterFile growth check to the callee in the common case,
where some of the information is known statically at JIT time. There is
still a check in the caller in the case where the caller provides too
few arguments.

This is a 2.1% speedup on the V8 benchmark, including a 5.1% speedup on
the Richards benchmark, a 4.1% speedup on the DeltaBlue benchmark, and a
1.4% speedup on the Earley-Boyer benchmark. It is also a 0.5% speedup on
SunSpider.

  • VM/CTI.cpp: (JSC::CTI::privateCompile):
  • VM/Machine.cpp: (JSC::Machine::cti_register_file_check): (JSC::Machine::cti_op_call_JSFunction): (JSC::Machine::cti_op_construct_JSConstruct):
  • VM/Machine.h:
  • VM/RegisterFile.h:
  • masm/X86Assembler.h: (JSC::X86Assembler::): (JSC::X86Assembler::cmpl_mr): (JSC::X86Assembler::emitUnlinkedJg):
Location:
trunk/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r37563 r37570  
     12008-10-13  Cameron Zwarich  <[email protected]>
     2
     3        Reviewed by Geoff Garen.
     4
     5        Bug 21541: Move RegisterFile growth check to callee
     6        <https://bugs.webkit.org/show_bug.cgi?id=21541>
     7
     8        Move the RegisterFile growth check to the callee in the common case,
     9        where some of the information is known statically at JIT time. There is
     10        still a check in the caller in the case where the caller provides too
     11        few arguments.
     12
     13        This is a 2.1% speedup on the V8 benchmark, including a 5.1% speedup on
     14        the Richards benchmark, a 4.1% speedup on the DeltaBlue benchmark, and a
     15        1.4% speedup on the Earley-Boyer benchmark. It is also a 0.5% speedup on
     16        SunSpider.
     17
     18        * VM/CTI.cpp:
     19        (JSC::CTI::privateCompile):
     20        * VM/Machine.cpp:
     21        (JSC::Machine::cti_register_file_check):
     22        (JSC::Machine::cti_op_call_JSFunction):
     23        (JSC::Machine::cti_op_construct_JSConstruct):
     24        * VM/Machine.h:
     25        * VM/RegisterFile.h:
     26        * masm/X86Assembler.h:
     27        (JSC::X86Assembler::):
     28        (JSC::X86Assembler::cmpl_mr):
     29        (JSC::X86Assembler::emitUnlinkedJg):
     30
    1312008-10-13  Sam Weinig  <[email protected]>
    232
  • trunk/JavaScriptCore/VM/CTI.cpp

    r37500 r37570  
    26162616    emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC);
    26172617
     2618    X86Assembler::JmpSrc slowRegisterFileCheck;
     2619    X86Assembler::JmpDst afterRegisterFileCheck;
     2620    if (m_codeBlock->codeType == FunctionCode) {
     2621        emitGetCTIParam(CTI_ARGS_registerFile, X86::eax);
     2622        m_jit.leal_mr(m_codeBlock->numCalleeRegisters * sizeof(Register), X86::edi, X86::edx);
     2623        m_jit.cmpl_mr(OBJECT_OFFSET(RegisterFile, m_end), X86::eax, X86::edx);
     2624        slowRegisterFileCheck = m_jit.emitUnlinkedJg();
     2625        afterRegisterFileCheck = m_jit.label();
     2626    }
     2627
    26182628    privateCompileMainPass();
    26192629    privateCompileLinkPass();
    26202630    privateCompileSlowCases();
     2631
     2632    if (m_codeBlock->codeType == FunctionCode) {
     2633        m_jit.link(slowRegisterFileCheck, m_jit.label());
     2634        emitCall(0, Machine::cti_register_file_check);
     2635        X86Assembler::JmpSrc backToBody = m_jit.emitUnlinkedJmp();
     2636        m_jit.link(backToBody, afterRegisterFileCheck);
     2637    }
    26212638
    26222639    ASSERT(m_jmpTable.isEmpty());
  • trunk/JavaScriptCore/VM/Machine.cpp

    r37457 r37570  
    43374337}
    43384338
     4339void Machine::cti_register_file_check(CTI_ARGS)
     4340{
     4341    CallFrame* callFrame = ARG_callFrame;
     4342    CodeBlock* codeBlock = callFrame->codeBlock();
     4343    RegisterFile* registerFile = ARG_registerFile;
     4344
     4345    if (!registerFile->grow(callFrame + codeBlock->numCalleeRegisters)) {
     4346        CallFrame* callerFrame = callFrame->callerFrame();
     4347        ARG_setCallFrame(callerFrame);
     4348        ARG_globalData->exception = createStackOverflowError(callerFrame);
     4349        ASSERT(ARG_globalData->exception);
     4350        ARG_globalData->throwReturnAddress = callFrame->returnPC();
     4351        doSetReturnAddressVMThrowTrampoline(&CTI_RETURN_ADDRESS);
     4352    }
     4353}
     4354
    43394355int Machine::cti_op_loop_if_less(CTI_ARGS)
    43404356{
     
    45514567    ScopeChainNode* callDataScopeChain = static_cast<JSFunction*>(ARG_src1)->m_scopeChain.node();
    45524568    CodeBlock* newCodeBlock = &static_cast<JSFunction*>(ARG_src1)->m_body->byteCode(callDataScopeChain);
    4553 
    4554     CallFrame* callFrame = slideRegisterWindowForCall(newCodeBlock, ARG_registerFile, ARG_callFrame, ARG_int2, ARG_int3);
    4555     if (UNLIKELY(!callFrame)) {
    4556         ARG_globalData->exception = createStackOverflowError(ARG_callFrame);
     4569    CallFrame* callFrame = ARG_callFrame;
     4570    size_t registerOffset = ARG_int2;
     4571    int argCount = ARG_int3;
     4572
     4573    if (LIKELY(argCount == newCodeBlock->numParameters)) {
     4574        VoidPtrPair pair = { newCodeBlock, CallFrame::create(callFrame->registers() + registerOffset) };
     4575        return pair;
     4576    }
     4577
     4578    if (argCount > newCodeBlock->numParameters) {
     4579        size_t numParameters = newCodeBlock->numParameters;
     4580        Register* r = callFrame->registers() + registerOffset + numParameters;
     4581
     4582        Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
     4583        for (size_t i = 0; i < numParameters; ++i)
     4584            argv[i + argCount] = argv[i];
     4585
     4586        VoidPtrPair pair = { newCodeBlock, CallFrame::create(r) };
     4587        return pair;
     4588    }
     4589
     4590    size_t omittedArgCount = newCodeBlock->numParameters - argCount;
     4591    Register* r = callFrame->registers() + registerOffset + omittedArgCount;
     4592    Register* newEnd = r + newCodeBlock->numCalleeRegisters;
     4593    if (!ARG_registerFile->grow(newEnd)) {
     4594        ARG_globalData->exception = createStackOverflowError(callFrame);
    45574595        VM_THROW_EXCEPTION_2();
    45584596    }
    45594597
    4560     VoidPtrPair pair = { newCodeBlock, callFrame };
     4598    Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
     4599    for (size_t i = 0; i < omittedArgCount; ++i)
     4600        argv[i] = jsUndefined();
     4601
     4602    VoidPtrPair pair = { newCodeBlock, CallFrame::create(r) };
    45614603    return pair;
    45624604}
     
    46864728VoidPtrPair Machine::cti_op_construct_JSConstruct(CTI_ARGS)
    46874729{
    4688     RegisterFile* registerFile = ARG_registerFile;
    46894730    CallFrame* callFrame = ARG_callFrame;
    46904731
     
    47134754        structure = callDataScopeChain->globalObject()->emptyObjectStructure();
    47144755    JSObject* newObject = new (ARG_globalData) JSObject(structure);
    4715 
    47164756    callFrame[firstArg] = newObject; // "this" value
    47174757
    4718     callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, callFrame, registerOffset, argCount);
    4719     if (UNLIKELY(!callFrame)) {
    4720         ARG_globalData->exception = createStackOverflowError(ARG_callFrame);
     4758    if (LIKELY(argCount == newCodeBlock->numParameters)) {
     4759        VoidPtrPair pair = { newCodeBlock, CallFrame::create(callFrame->registers() + registerOffset) };
     4760        return pair;
     4761    }
     4762
     4763    if (argCount > newCodeBlock->numParameters) {
     4764        size_t numParameters = newCodeBlock->numParameters;
     4765        Register* r = callFrame->registers() + registerOffset + numParameters;
     4766
     4767        Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;
     4768        for (size_t i = 0; i < numParameters; ++i)
     4769            argv[i + argCount] = argv[i];
     4770
     4771        VoidPtrPair pair = { newCodeBlock, CallFrame::create(r) };
     4772        return pair;
     4773    }
     4774
     4775    size_t omittedArgCount = newCodeBlock->numParameters - argCount;
     4776    Register* r = callFrame->registers() + registerOffset + omittedArgCount;
     4777    Register* newEnd = r + newCodeBlock->numCalleeRegisters;
     4778    if (!ARG_registerFile->grow(newEnd)) {
     4779        ARG_globalData->exception = createStackOverflowError(callFrame);
    47214780        VM_THROW_EXCEPTION_2();
    47224781    }
    47234782
    4724     VoidPtrPair pair = { newCodeBlock, callFrame };
     4783    Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;
     4784    for (size_t i = 0; i < omittedArgCount; ++i)
     4785        argv[i] = jsUndefined();
     4786
     4787    VoidPtrPair pair = { newCodeBlock, CallFrame::create(r) };
    47254788    return pair;
    47264789}
  • trunk/JavaScriptCore/VM/Machine.h

    r37500 r37570  
    163163
    164164        static void SFX_CALL cti_timeout_check(CTI_ARGS);
     165        static void SFX_CALL cti_register_file_check(CTI_ARGS);
    165166
    166167        static JSValue* SFX_CALL cti_op_convert_this(CTI_ARGS);
  • trunk/JavaScriptCore/VM/RegisterFile.h

    r37433 r37570  
    8989
    9090    class RegisterFile : Noncopyable {
     91        friend class CTI;
    9192    public:
    9293        enum CallFrameHeaderEntry {
  • trunk/JavaScriptCore/masm/X86Assembler.h

    r37457 r37570  
    192192        OP_XOR_EvGv                     = 0x31,
    193193        OP_CMP_EvGv                     = 0x39,
     194        OP_CMP_GvEv                     = 0x3B,
    194195        OP_PUSH_EAX                     = 0x50,
    195196        OP_POP_EAX                      = 0x58,
     
    241242        OP2_JGE_rel32       = 0x8D,
    242243        OP2_JLE_rel32       = 0x8E,
     244        OP2_JG_rel32       = 0x8F,
    243245        OP2_IMUL_GvEv       = 0xAF,
    244246        OP2_MOVZX_GvEb      = 0xB6,
     
    372374        m_buffer->putByte(OP_CMP_EvGv);
    373375        emitModRm_rm(src, base, offset);
     376    }
     377
     378    void cmpl_mr(int offset, RegisterID base, RegisterID dst)
     379    {
     380        m_buffer->putByte(OP_CMP_GvEv);
     381        emitModRm_rm(dst, base, offset);
    374382    }
    375383
     
    946954        return JmpSrc(m_buffer->getOffset());
    947955    }
    948    
     956
     957    JmpSrc emitUnlinkedJg()
     958    {
     959        m_buffer->putByte(OP_2BYTE_ESCAPE);
     960        m_buffer->putByte(OP2_JG_rel32);
     961        m_buffer->putInt(0);
     962        return JmpSrc(m_buffer->getOffset());
     963    }
     964
    949965    JmpSrc emitUnlinkedJa()
    950966    {
Note: See TracChangeset for help on using the changeset viewer.