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


Ignore:
Timestamp:
Nov 10, 2008, 9:09:46 PM (17 years ago)
Author:
[email protected]
Message:

2008-11-10 Gavin Barraclough <[email protected]>

Reviewed by Camron Zwarich.

Batch compile the set of static trampolines at the point Machine is constructed, using a single allocation.
Refactor out m_callFrame from CTI, since this is only needed to access the global data (instead store a
pointer to the global data directly, since this is available at the point the Machine is constructed).
Add a method to align the code buffer, to allow JIT generation for multiple trampolines in one block.

  • VM/CTI.cpp: (JSC::CTI::getConstant): (JSC::CTI::emitGetArg): (JSC::CTI::emitGetPutArg): (JSC::CTI::getConstantImmediateNumericArg): (JSC::CTI::printOpcodeOperandTypes): (JSC::CTI::CTI): (JSC::CTI::compileBinaryArithOp): (JSC::CTI::privateCompileMainPass): (JSC::CTI::privateCompileGetByIdProto): (JSC::CTI::privateCompileGetByIdChain): (JSC::CTI::privateCompileCTIMachineTrampolines): (JSC::CTI::freeCTIMachineTrampolines):
  • VM/CTI.h: (JSC::CTI::compile): (JSC::CTI::compileGetByIdSelf): (JSC::CTI::compileGetByIdProto): (JSC::CTI::compileGetByIdChain): (JSC::CTI::compilePutByIdReplace): (JSC::CTI::compilePutByIdTransition): (JSC::CTI::compileCTIMachineTrampolines): (JSC::CTI::compilePatchGetArrayLength):
  • VM/Machine.cpp: (JSC::Machine::initialize): (JSC::Machine::~Machine): (JSC::Machine::execute): (JSC::Machine::tryCTICachePutByID): (JSC::Machine::tryCTICacheGetByID): (JSC::Machine::cti_op_call_JSFunction): (JSC::Machine::cti_vm_lazyLinkCall):
  • VM/Machine.h:
  • masm/X86Assembler.h: (JSC::JITCodeBuffer::isAligned): (JSC::X86Assembler::): (JSC::X86Assembler::align):
  • runtime/JSGlobalData.cpp: (JSC::JSGlobalData::JSGlobalData):
File:
1 edited

Legend:

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

    r38284 r38286  
    169169#endif
    170170
    171 ALWAYS_INLINE JSValue* CTI::getConstant(CallFrame* callFrame, int src)
    172 {
    173     return m_codeBlock->constantRegisters[src - m_codeBlock->numVars].jsValue(callFrame);
     171ALWAYS_INLINE JSValue* CTI::getConstant(int src)
     172{
     173    return m_codeBlock->constantRegisters[src - m_codeBlock->numVars].getJSValue();
    174174}
    175175
     
    184184    // TODO: we want to reuse values that are already in registers if we can - add a register allocator!
    185185    if (m_codeBlock->isConstant(src)) {
    186         JSValue* js = getConstant(m_callFrame, src);
     186        JSValue* js = getConstant(src);
    187187        m_jit.movl_i32r(asInteger(js), dst);
    188188    } else
     
    194194{
    195195    if (m_codeBlock->isConstant(src)) {
    196         JSValue* js = getConstant(m_callFrame, src);
     196        JSValue* js = getConstant(src);
    197197        m_jit.movl_i32m(asInteger(js), offset + sizeof(void*), X86::esp);
    198198    } else {
     
    216216{
    217217    if (m_codeBlock->isConstant(src)) {
    218         JSValue* js = getConstant(m_callFrame, src);
     218        JSValue* js = getConstant(src);
    219219        return JSImmediate::isNumber(js) ? js : noValue();
    220220    }
     
    275275    char which1 = '*';
    276276    if (m_codeBlock->isConstant(src1)) {
    277         JSValue* js = getConstant(m_callFrame, src1);
     277        JSValue* js = getConstant(src1);
    278278        which1 =
    279279            JSImmediate::isImmediate(js) ?
     
    289289    char which2 = '*';
    290290    if (m_codeBlock->isConstant(src2)) {
    291         JSValue* js = getConstant(m_callFrame, src2);
     291        JSValue* js = getConstant(src2);
    292292        which2 =
    293293            JSImmediate::isImmediate(js) ?
     
    547547}
    548548
    549 CTI::CTI(Machine* machine, CallFrame* callFrame, CodeBlock* codeBlock)
    550     : m_jit(machine->jitCodeBuffer())
    551     , m_machine(machine)
    552     , m_callFrame(callFrame)
     549CTI::CTI(JSGlobalData* globalData, CodeBlock* codeBlock)
     550    : m_jit(globalData->machine->jitCodeBuffer())
     551    , m_machine(globalData->machine)
     552    , m_globalData(globalData)
    553553    , m_codeBlock(codeBlock)
    554554    , m_labels(codeBlock ? codeBlock->instructions.size() : 0)
     
    792792void CTI::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes types, unsigned i)
    793793{
    794     StructureID* numberStructureID = m_callFrame->globalData().numberStructureID.get();
     794    StructureID* numberStructureID = m_globalData->numberStructureID.get();
    795795    X86Assembler::JmpSrc wasJSNumberCell1;
    796796    X86Assembler::JmpSrc wasJSNumberCell1b;
     
    10061006            unsigned src = instruction[i + 2].u.operand;
    10071007            if (m_codeBlock->isConstant(src))
    1008                 m_jit.movl_i32r(asInteger(getConstant(m_callFrame, src)), X86::eax);
     1008                m_jit.movl_i32r(asInteger(getConstant(src)), X86::eax);
    10091009            else
    10101010                emitGetArg(src, X86::eax);
     
    15311531                if (!resultType.definitelyIsNumber()) {
    15321532                    emitJumpSlowCaseIfNotJSCell(X86::eax, i);
    1533                     StructureID* numberStructureID = m_callFrame->globalData().numberStructureID.get();
     1533                    StructureID* numberStructureID = m_globalData->numberStructureID.get();
    15341534                    m_jit.cmpl_i32m(reinterpret_cast<unsigned>(numberStructureID), OBJECT_OFFSET(JSCell, m_structureID), X86::eax);
    15351535                    m_slowCases.append(SlowCaseEntry(m_jit.emitUnlinkedJne(), i));
     
    15411541                X86Assembler::JmpSrc wasCell;
    15421542                if (!resultType.isReusableNumber())
    1543                     emitAllocateNumber(&m_callFrame->globalData(), i);
     1543                    emitAllocateNumber(m_globalData, i);
    15441544
    15451545                putDoubleResultToJSNumberCellOrJSImmediate(X86::xmm0, X86::eax, instruction[i + 1].u.operand, &wasCell,
     
    30513051}
    30523052
    3053 void CTI::privateCompileGetByIdProto(StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress)
     3053void CTI::privateCompileGetByIdProto(StructureID* structureID, StructureID* prototypeStructureID, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
    30543054{
    30553055#if USE(CTI_REPATCH_PIC)
     
    30613061    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a StructureID that is
    30623062    // referencing the prototype object - let's speculatively load it's table nice and early!)
    3063     JSObject* protoObject = asObject(structureID->prototypeForLookup(m_callFrame));
     3063    JSObject* protoObject = asObject(structureID->prototypeForLookup(callFrame));
    30643064    PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
    30653065    m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
     
    31043104    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a StructureID that is
    31053105    // referencing the prototype object - let's speculatively load it's table nice and early!)
    3106     JSObject* protoObject = asObject(structureID->prototypeForLookup(m_callFrame));
     3106    JSObject* protoObject = asObject(structureID->prototypeForLookup(callFrame));
    31073107    PropertyStorage* protoPropertyStorage = &protoObject->m_propertyStorage;
    31083108    m_jit.movl_mr(static_cast<void*>(protoPropertyStorage), X86::edx);
     
    31373137}
    31383138
    3139 void CTI::privateCompileGetByIdChain(StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset, void* returnAddress)
     3139void CTI::privateCompileGetByIdChain(StructureID* structureID, StructureIDChain* chain, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame)
    31403140{
    31413141    ASSERT(count);
     
    31533153    JSObject* protoObject = 0;
    31543154    for (unsigned i = 0; i<count; ++i) {
    3155         protoObject = asObject(currStructureID->prototypeForLookup(m_callFrame));
     3155        protoObject = asObject(currStructureID->prototypeForLookup(callFrame));
    31563156        currStructureID = chainEntries[i].get();
    31573157
     
    33293329}
    33303330
    3331 void* CTI::privateCompileArrayLengthTrampoline()
    3332 {
     3331void CTI::privateCompileCTIMachineTrampolines()
     3332{
     3333    // (1) The first function provides fast property access for array length
     3334   
    33333335    // Check eax is an array
    33343336    m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
    3335     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
     3337    X86Assembler::JmpSrc array_failureCases1 = m_jit.emitUnlinkedJne();
    33363338    m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsArrayVptr), X86::eax);
    3337     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
     3339    X86Assembler::JmpSrc array_failureCases2 = m_jit.emitUnlinkedJne();
    33383340
    33393341    // Checks out okay! - get the length from the storage
     
    33423344
    33433345    m_jit.addl_rr(X86::eax, X86::eax);
    3344     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
     3346    X86Assembler::JmpSrc array_failureCases3 = m_jit.emitUnlinkedJo();
    33453347    m_jit.addl_i8r(1, X86::eax);
    33463348   
    33473349    m_jit.ret();
    33483350
    3349     void* code = m_jit.copy();
    3350     ASSERT(code);
    3351 
    3352     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
    3353     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
    3354     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
     3351    // (2) The second function provides fast property access for string length
    33553352   
    3356     return code;
    3357 }
    3358 
    3359 void* CTI::privateCompileStringLengthTrampoline()
    3360 {
     3353    X86Assembler::JmpDst stringLengthBegin = m_jit.align(16);
     3354
    33613355    // Check eax is a string
    33623356    m_jit.testl_i32r(JSImmediate::TagMask, X86::eax);
    3363     X86Assembler::JmpSrc failureCases1 = m_jit.emitUnlinkedJne();
     3357    X86Assembler::JmpSrc string_failureCases1 = m_jit.emitUnlinkedJne();
    33643358    m_jit.cmpl_i32m(reinterpret_cast<unsigned>(m_machine->m_jsStringVptr), X86::eax);
    3365     X86Assembler::JmpSrc failureCases2 = m_jit.emitUnlinkedJne();
     3359    X86Assembler::JmpSrc string_failureCases2 = m_jit.emitUnlinkedJne();
    33663360
    33673361    // Checks out okay! - get the length from the Ustring.
     
    33703364
    33713365    m_jit.addl_rr(X86::eax, X86::eax);
    3372     X86Assembler::JmpSrc failureCases3 = m_jit.emitUnlinkedJo();
     3366    X86Assembler::JmpSrc string_failureCases3 = m_jit.emitUnlinkedJo();
    33733367    m_jit.addl_i8r(1, X86::eax);
    33743368   
    33753369    m_jit.ret();
    33763370
     3371    // All trampolines constructed! copy the code, link up calls, and set the pointers on the Machine object.
     3372
    33773373    void* code = m_jit.copy();
    33783374    ASSERT(code);
    33793375
    3380     X86Assembler::link(code, failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
    3381     X86Assembler::link(code, failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
    3382     X86Assembler::link(code, failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
    3383 
    3384     return code;
     3376    X86Assembler::link(code, array_failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
     3377    X86Assembler::link(code, array_failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
     3378    X86Assembler::link(code, array_failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
     3379    X86Assembler::link(code, string_failureCases1, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
     3380    X86Assembler::link(code, string_failureCases2, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
     3381    X86Assembler::link(code, string_failureCases3, reinterpret_cast<void*>(Machine::cti_op_get_by_id_fail));
     3382
     3383    m_machine->m_ctiArrayLengthTrampoline = code;
     3384    m_machine->m_ctiStringLengthTrampoline = X86Assembler::getRelocatedAddress(code, stringLengthBegin);
     3385}
     3386
     3387void CTI::freeCTIMachineTrampolines(Machine* machine)
     3388{
     3389    WTF::fastFreeExecutable(machine->m_ctiArrayLengthTrampoline);
    33853390}
    33863391
Note: See TracChangeset for help on using the changeset viewer.