Changeset 36514 in webkit for trunk/JavaScriptCore/VM/CTI.cpp


Ignore:
Timestamp:
Sep 16, 2008, 10:40:01 AM (17 years ago)
Author:
[email protected]
Message:

2008-09-16 Gavin Barraclough <[email protected]>

Reviewed by Geoff Garen.

CTI code generation for op_ret. The majority of the work
(updating variables on the stack & on exec) can be performed
directly in generated code.

We still need to check, & to call out to C-code to handle
activation records, profiling, and full scope chains.

+1.5% Sunspider, +5/6% v8 tests.

  • VM/CTI.cpp: (JSC::CTI::emitPutCTIParam): (JSC::CTI::compileOpCall): (JSC::CTI::privateCompileMainPass):
  • VM/CTI.h:
  • VM/Machine.cpp: (JSC::Machine::cti_op_ret_activation): (JSC::Machine::cti_op_ret_profiler): (JSC::Machine::cti_op_ret_scopeChain):
  • VM/Machine.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/VM/CTI.cpp

    r36480 r36514  
    148148    }
    149149    return 0;
     150}
     151
     152ALWAYS_INLINE void CTI::emitPutCTIParam(void* value, unsigned name)
     153{
     154    m_jit.movl_i32m(reinterpret_cast<intptr_t>(value), name * sizeof(void*), X86::esp);
    150155}
    151156
     
    465470    emitCall(i, ((type == OpConstruct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction));
    466471    m_jit.call_r(X86::eax);
    467     emitGetCTIParam(CTI_ARGS_r, X86::edi); // edi := r
     472   
     473    // In the interpreter the following actions are performed by op_ret:
     474   
     475    // Store the scope chain - returned by op_ret in %edx (see below) - to ExecState::m_scopeChain and CTI_ARGS_scopeChain on the stack.
     476    emitGetCTIParam(CTI_ARGS_exec, X86::ecx);
     477    emitPutCTIParam(X86::edx, CTI_ARGS_scopeChain);
     478    m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_scopeChain), X86::ecx);
     479    // Restore ExecState::m_callFrame.
     480    m_jit.leal_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) * sizeof(Register), X86::edi, X86::edx);
     481    m_jit.movl_rm(X86::edx, OBJECT_OFFSET(ExecState, m_callFrame), X86::ecx);
     482    // Restore CTI_ARGS_codeBlock.
     483    emitPutCTIParam(m_codeBlock, CTI_ARGS_codeBlock);
    468484
    469485    X86Assembler::JmpDst end = m_jit.label();
     
    799815        }
    800816        case op_ret: {
    801             emitGetPutArg(instruction[i + 1].u.operand, 0, X86::ecx);
    802             emitCall(i, Machine::cti_op_ret);
    803 
    804             m_jit.pushl_m(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize) - RegisterFile::CTIReturnEIP) * sizeof(Register), X86::edi);
     817            // Check for an activation - if there is one, jump to the hook below.
     818            m_jit.cmpl_i32m(0, -((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::OptionalCalleeActivation) * sizeof(Register)), X86::edi);
     819            X86Assembler::JmpSrc activation = m_jit.emitUnlinkedJne();
     820            X86Assembler::JmpDst activated = m_jit.label();
     821
     822            // Check for a profiler - if there is one, jump to the hook below.
     823            emitGetCTIParam(CTI_ARGS_profilerReference, X86::eax);
     824            m_jit.cmpl_i32m(0, X86::eax);
     825            X86Assembler::JmpSrc profile = m_jit.emitUnlinkedJne();
     826            X86Assembler::JmpDst profiled = m_jit.label();
     827
     828            // We could JIT generate the deref, only calling out to C when the refcount hits zero.
     829            if (m_codeBlock->needsFullScopeChain)
     830                emitCall(i, Machine::cti_op_ret_scopeChain);
     831
     832            // Return the result in %eax, and the caller scope chain in %edx (this is read from the callee call frame,
     833            // but is only assigned to ExecState::m_scopeChain if returning to a JSFunction).
     834            emitGetArg(instruction[i + 1].u.operand, X86::eax);
     835            m_jit.movl_mr(-((m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::CallerScopeChain) * sizeof(Register)), X86::edi, X86::edx);
     836            // Restore the machine return addess from the callframe, roll the callframe back to the caller callframe,
     837            // and preserve a copy of r on the stack at CTI_ARGS_r.
     838            m_jit.movl_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::CTIReturnEIP) * sizeof(Register), X86::edi, X86::ecx);
     839            m_jit.movl_mr(-(m_codeBlock->numLocals + RegisterFile::CallFrameHeaderSize - RegisterFile::CallerRegisters) * sizeof(Register), X86::edi, X86::edi);
     840            emitPutCTIParam(X86::edi, CTI_ARGS_r);
     841
     842            m_jit.pushl_r(X86::ecx);
    805843            m_jit.ret();
     844
     845            // Activation hook
     846            m_jit.link(activation, m_jit.label());
     847            emitCall(i, Machine::cti_op_ret_activation);
     848            m_jit.link(m_jit.emitUnlinkedJmp(), activated);
     849
     850            // Profiling hook
     851            m_jit.link(profile, m_jit.label());
     852            emitCall(i, Machine::cti_op_ret_profiler);
     853            m_jit.link(m_jit.emitUnlinkedJmp(), profiled);
     854
    806855            i += 2;
    807856            break;
Note: See TracChangeset for help on using the changeset viewer.