Changeset 38322 in webkit for trunk/JavaScriptCore


Ignore:
Timestamp:
Nov 11, 2008, 4:32:38 PM (17 years ago)
Author:
[email protected]
Message:

2008-11-11 Geoffrey Garen <[email protected]>

Reviewed by Darin Adler.


Fixed https://bugs.webkit.org/show_bug.cgi?id=22174
Simplified op_call by nixing its responsibility for moving the value of
"this" into the first argument slot.

Instead, the caller emits an explicit load or mov instruction, or relies
on implicit knowledge that "this" is already in the first argument slot.
As a result, two operands to op_call are gone: firstArg and thisVal.


SunSpider and v8 tests show no change in bytecode or CTI.

  • VM/CTI.cpp: (JSC::CTI::compileOpCallSetupArgs): (JSC::CTI::compileOpCallEvalSetupArgs): (JSC::CTI::compileOpConstructSetupArgs): Split apart these three versions of setting up arguments to op_call, because they're more different than they are the same -- even more so with this patch.

(JSC::CTI::compileOpCall): Updated for the fact that op_construct doesn't
match op_call anymore.

(JSC::CTI::privateCompileMainPass):
(JSC::CTI::privateCompileSlowCases): Merged a few call cases. Updated
for changes mentioned above.

  • VM/CTI.h:
  • VM/CodeBlock.cpp: (JSC::CodeBlock::dump): Updated for new bytecode format of call / construct.
  • VM/Machine.cpp: (JSC::Machine::callEval): Updated for new bytecode format of call / construct.

(JSC::Machine::dumpCallFrame):
(JSC::Machine::dumpRegisters): Simplified these debugging functions,
taking advantage of the new call frame layout.

(JSC::Machine::execute): Fixed up the eval version of execute to be
friendlier to calls in the new format.

(JSC::Machine::privateExecute): Implemented the new call format in
bytecode.

(JSC::Machine::cti_op_call_NotJSFunction):
(JSC::Machine::cti_op_construct_JSConstruct):
(JSC::Machine::cti_op_construct_NotJSConstruct):
(JSC::Machine::cti_op_call_eval): Updated CTI helpers to match the new
call format.


Fixed a latent bug in stack overflow checking that is now hit because
the register layout has changed a bit -- namely: when throwing a stack
overflow exception inside an op_call helper, we need to account for the
fact that the current call frame is only half-constructed, and use the
parent call frame instead.

  • VM/Machine.h:
  • bytecompiler/CodeGenerator.cpp: (JSC::CodeGenerator::emitCall): (JSC::CodeGenerator::emitCallEval): (JSC::CodeGenerator::emitConstruct):
  • bytecompiler/CodeGenerator.h: Updated codegen to match the new call format.
  • parser/Nodes.cpp: (JSC::EvalFunctionCallNode::emitCode): (JSC::FunctionCallValueNode::emitCode): (JSC::FunctionCallResolveNode::emitCode): (JSC::FunctionCallBracketNode::emitCode): (JSC::FunctionCallDotNode::emitCode):
  • parser/Nodes.h: (JSC::ScopeNode::neededConstants): ditto

2008-11-10 Geoffrey Garen <[email protected]>

Reviewed by Darin Adler.


Updated a test after fixing https://bugs.webkit.org/show_bug.cgi?id=22174
Simplified op_call by nixing its responsibility for moving the value of
"this" into the first argument slot.

  • fast/js/global-recursion-on-full-stack-expected.txt: This test passes a little differently now, because the register layout has changed. Specifically, the stack overflow now happens in the call to f() instead of the initiation of the <script> tag, so it is caught, and it does not log an exception to the console.
Location:
trunk/JavaScriptCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r38320 r38322  
     12008-11-11  Geoffrey Garen  <[email protected]>
     2
     3        Reviewed by Darin Adler.
     4       
     5        Fixed https://bugs.webkit.org/show_bug.cgi?id=22174
     6        Simplified op_call by nixing its responsibility for moving the value of
     7        "this" into the first argument slot.
     8
     9        Instead, the caller emits an explicit load or mov instruction, or relies
     10        on implicit knowledge that "this" is already in the first argument slot.
     11        As a result, two operands to op_call are gone: firstArg and thisVal.
     12       
     13        SunSpider and v8 tests show no change in bytecode or CTI.
     14
     15        * VM/CTI.cpp:
     16        (JSC::CTI::compileOpCallSetupArgs):
     17        (JSC::CTI::compileOpCallEvalSetupArgs):
     18        (JSC::CTI::compileOpConstructSetupArgs): Split apart these three versions
     19        of setting up arguments to op_call, because they're more different than
     20        they are the same -- even more so with this patch.
     21
     22        (JSC::CTI::compileOpCall): Updated for the fact that op_construct doesn't
     23        match op_call anymore.
     24
     25        (JSC::CTI::privateCompileMainPass):
     26        (JSC::CTI::privateCompileSlowCases): Merged a few call cases. Updated
     27        for changes mentioned above.
     28
     29        * VM/CTI.h:
     30
     31        * VM/CodeBlock.cpp:
     32        (JSC::CodeBlock::dump): Updated for new bytecode format of call / construct.
     33
     34        * VM/Machine.cpp:
     35        (JSC::Machine::callEval): Updated for new bytecode format of call / construct.
     36
     37        (JSC::Machine::dumpCallFrame):
     38        (JSC::Machine::dumpRegisters): Simplified these debugging functions,
     39        taking advantage of the new call frame layout.
     40
     41        (JSC::Machine::execute): Fixed up the eval version of execute to be
     42        friendlier to calls in the new format.
     43
     44        (JSC::Machine::privateExecute): Implemented the new call format in
     45        bytecode.
     46
     47        (JSC::Machine::cti_op_call_NotJSFunction):
     48        (JSC::Machine::cti_op_construct_JSConstruct):
     49        (JSC::Machine::cti_op_construct_NotJSConstruct):
     50        (JSC::Machine::cti_op_call_eval): Updated CTI helpers to match the new
     51        call format.
     52       
     53        Fixed a latent bug in stack overflow checking that is now hit because
     54        the register layout has changed a bit -- namely: when throwing a stack
     55        overflow exception inside an op_call helper, we need to account for the
     56        fact that the current call frame is only half-constructed, and use the
     57        parent call frame instead.
     58
     59        * VM/Machine.h:
     60
     61        * bytecompiler/CodeGenerator.cpp:
     62        (JSC::CodeGenerator::emitCall):
     63        (JSC::CodeGenerator::emitCallEval):
     64        (JSC::CodeGenerator::emitConstruct):
     65        * bytecompiler/CodeGenerator.h: Updated codegen to match the new call
     66        format.
     67
     68        * parser/Nodes.cpp:
     69        (JSC::EvalFunctionCallNode::emitCode):
     70        (JSC::FunctionCallValueNode::emitCode):
     71        (JSC::FunctionCallResolveNode::emitCode):
     72        (JSC::FunctionCallBracketNode::emitCode):
     73        (JSC::FunctionCallDotNode::emitCode):
     74        * parser/Nodes.h:
     75        (JSC::ScopeNode::neededConstants): ditto
     76
    1772008-11-11  Cameron Zwarich  <[email protected]>
    278
  • trunk/JavaScriptCore/VM/CTI.cpp

    r38306 r38322  
    588588}
    589589
    590 void CTI::compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval)
    591 {
    592     int firstArg = instruction[4].u.operand;
    593     int argCount = instruction[5].u.operand;
    594     int registerOffset = instruction[6].u.operand;
    595 
     590void CTI::compileOpCallSetupArgs(Instruction* instruction)
     591{
     592    int argCount = instruction[3].u.operand;
     593    int registerOffset = instruction[4].u.operand;
     594
     595    // ecx holds func
    596596    emitPutArg(X86::ecx, 0);
    597597    emitPutArgConstant(registerOffset, 4);
    598598    emitPutArgConstant(argCount, 8);
    599599    emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12);
    600     if (isConstruct) {
    601         emitGetPutArg(instruction[3].u.operand, 16, X86::eax);
    602         emitPutArgConstant(firstArg, 20);
    603     } else if (isEval)
    604         emitGetPutArg(instruction[3].u.operand, 16, X86::eax);
     600}
     601
     602void CTI::compileOpCallEvalSetupArgs(Instruction* instruction)
     603{
     604    int argCount = instruction[3].u.operand;
     605    int registerOffset = instruction[4].u.operand;
     606
     607    // ecx holds func
     608    emitPutArg(X86::ecx, 0);
     609    emitPutArgConstant(registerOffset, 4);
     610    emitPutArgConstant(argCount, 8);
     611    emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12);
     612}
     613
     614void CTI::compileOpConstructSetupArgs(Instruction* instruction)
     615{
     616    int argCount = instruction[3].u.operand;
     617    int registerOffset = instruction[4].u.operand;
     618    int proto = instruction[5].u.operand;
     619    int thisRegister = instruction[6].u.operand;
     620
     621    // ecx holds func
     622    emitPutArg(X86::ecx, 0);
     623    emitPutArgConstant(registerOffset, 4);
     624    emitPutArgConstant(argCount, 8);
     625    emitGetPutArg(proto, 12, X86::eax);
     626    emitPutArgConstant(thisRegister, 16);
     627    emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 20);
    605628}
    606629
     
    609632    int dst = instruction[1].u.operand;
    610633    int callee = instruction[2].u.operand;
    611     int firstArg = instruction[4].u.operand;
    612     int argCount = instruction[5].u.operand;
    613     int registerOffset = instruction[6].u.operand;
    614 
    615     // Setup this value as the first argument (does not apply to constructors)
    616     if (opcodeID != op_construct) {
    617         int thisVal = instruction[3].u.operand;
    618         if (thisVal == missingThisObjectMarker())
    619             m_jit.movl_i32m(asInteger(jsNull()), firstArg * sizeof(Register), X86::edi);
    620         else {
    621             emitGetArg(thisVal, X86::eax);
    622             emitPutResult(firstArg);
    623         }
    624     }
     634    int argCount = instruction[3].u.operand;
     635    int registerOffset = instruction[4].u.operand;
    625636
    626637    // Handle eval
     
    628639    if (opcodeID == op_call_eval) {
    629640        emitGetArg(callee, X86::ecx);
    630         compileOpCallSetupArgs(instruction, false, true);
     641        compileOpCallEvalSetupArgs(instruction);
    631642
    632643        emitCTICall(instruction, i, Machine::cti_op_call_eval);
     
    648659    // In the case of OpConstruct, call out to a cti_ function to create the new object.
    649660    if (opcodeID == op_construct) {
     661        int proto = instruction[5].u.operand;
     662        int thisRegister = instruction[6].u.operand;
     663
    650664        emitPutArg(X86::ecx, 0);
    651         emitGetPutArg(instruction[3].u.operand, 16, X86::eax);
     665        emitGetPutArg(proto, 12, X86::eax);
    652666        emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct);
    653         emitPutResult(firstArg);
     667        emitPutResult(thisRegister);
    654668        emitGetArg(callee, X86::ecx);
    655669    }
     
    12861300            break;
    12871301        }
    1288         case op_call: {
     1302        case op_call:
     1303        case op_call_eval:
     1304        case op_construct: {
    12891305            compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++);
    1290             i += 7;
     1306            i += (opcodeID == op_construct ? 7 : 5);
    12911307            break;
    12921308        }
     
    13801396            emitPutResult(instruction[i + 1].u.operand);
    13811397            i += 3;
    1382             break;
    1383         }
    1384         case op_construct: {
    1385             compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++);
    1386             i += 7;
    13871398            break;
    13881399        }
     
    19121923            emitPutResult(instruction[i + 1].u.operand);
    19131924            i += 5;
    1914             break;
    1915         }
    1916         case op_call_eval: {
    1917             compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++);
    1918             i += 7;
    19191925            break;
    19201926        }
     
    27682774            int dst = instruction[i + 1].u.operand;
    27692775            int callee = instruction[i + 2].u.operand;
    2770             int firstArg = instruction[i + 4].u.operand;
    2771             int argCount = instruction[i + 5].u.operand;
    2772             int registerOffset = instruction[i + 6].u.operand;
     2776            int argCount = instruction[i + 3].u.operand;
     2777            int registerOffset = instruction[i + 4].u.operand;
    27732778
    27742779            m_jit.link(iter->from, m_jit.label());
    27752780
    27762781            // The arguments have been set up on the hot path for op_call_eval
    2777             if (opcodeID != op_call_eval)
    2778                 compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false);
     2782            if (opcodeID == op_call)
     2783                compileOpCallSetupArgs(instruction + i);
     2784            else if (opcodeID == op_construct)
     2785                compileOpConstructSetupArgs(instruction + i);
    27792786
    27802787            // Fast check for JS function.
     
    27842791            X86Assembler::JmpSrc callLinkFailNotJSFunction = m_jit.emitUnlinkedJne();
    27852792
    2786             // First, in the cale of a construct, allocate the new object.
     2793            // First, in the case of a construct, allocate the new object.
    27872794            if (opcodeID == op_construct) {
    27882795                emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct);
    2789                 emitPutResult(firstArg);
     2796                emitPutResult(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
    27902797                emitGetArg(callee, X86::ecx);
    27912798            }
     
    28282835
    28292836            // The arguments have been set up on the hot path for op_call_eval
    2830             if (opcodeID != op_call_eval)
    2831                 compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false);
     2837            if (opcodeID == op_call)
     2838                compileOpCallSetupArgs(instruction + i);
     2839            else if (opcodeID == op_construct)
     2840                compileOpConstructSetupArgs(instruction + i);
    28322841
    28332842            // Check for JSFunctions.
     
    28482857            m_jit.link(isJSFunction, m_jit.label());
    28492858
    2850             // First, in the cale of a construct, allocate the new object.
     2859            // First, in the case of a construct, allocate the new object.
    28512860            if (opcodeID == op_construct) {
    28522861                emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct);
    2853                 emitPutResult(firstArg);
     2862                emitPutResult(registerOffset - RegisterFile::CallFrameHeaderSize - argCount);
    28542863                emitGetArg(callee, X86::ecx);
    28552864            }
     
    28962905            ++callLinkInfoIndex;
    28972906
    2898             i += 7;
     2907            i += (opcodeID == op_construct ? 7 : 5);
    28992908            break;
    29002909        }
  • trunk/JavaScriptCore/VM/CTI.h

    r38306 r38322  
    366366        void compileOpCall(OpcodeID, Instruction* instruction, unsigned i, unsigned callLinkInfoIndex);
    367367        void compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount);
    368         void compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval);
     368        void compileOpCallSetupArgs(Instruction*);
     369        void compileOpCallEvalSetupArgs(Instruction*);
     370        void compileOpConstructSetupArgs(Instruction*);
    369371        enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq };
    370372        void compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type);
  • trunk/JavaScriptCore/VM/CodeBlock.cpp

    r38027 r38322  
    813813        }
    814814        case op_call: {
    815             int r0 = (++it)->u.operand;
    816             int r1 = (++it)->u.operand;
    817             int r2 = (++it)->u.operand;
    818             int tempCount = (++it)->u.operand;
     815            int dst = (++it)->u.operand;
     816            int func = (++it)->u.operand;
    819817            int argCount = (++it)->u.operand;
    820818            int registerOffset = (++it)->u.operand;
    821             printf("[%4d] call\t\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset);
     819            printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
    822820            break;
    823821        }
    824822        case op_call_eval: {
    825             int r0 = (++it)->u.operand;
    826             int r1 = (++it)->u.operand;
    827             int r2 = (++it)->u.operand;
    828             int tempCount = (++it)->u.operand;
     823            int dst = (++it)->u.operand;
     824            int func = (++it)->u.operand;
    829825            int argCount = (++it)->u.operand;
    830826            int registerOffset = (++it)->u.operand;
    831             printf("[%4d] call_eval\t\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset);
     827            printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);
    832828            break;
    833829        }
     
    847843        }
    848844        case op_construct: {
    849             int r0 = (++it)->u.operand;
    850             int r1 = (++it)->u.operand;
    851             int r2 = (++it)->u.operand;
    852             int tempCount = (++it)->u.operand;
     845            int dst = (++it)->u.operand;
     846            int func = (++it)->u.operand;
    853847            int argCount = (++it)->u.operand;
    854848            int registerOffset = (++it)->u.operand;
    855             printf("[%4d] construct\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset);
     849            int proto = (++it)->u.operand;
     850            int thisRegister = (++it)->u.operand;
     851            printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str());
    856852            break;
    857853        }
  • trunk/JavaScriptCore/VM/Machine.cpp

    r38311 r38322  
    581581}
    582582
    583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, int argv, int argc, JSValue*& exceptionValue)
     583NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue*& exceptionValue)
    584584{
    585585    if (argc < 2)
    586586        return jsUndefined();
    587587
    588     JSValue* program = callFrame[argv + 1].jsValue(callFrame);
     588    JSValue* program = argv[1].jsValue(callFrame);
    589589
    590590    if (!program->isString())
     
    593593    UString programSource = asString(program)->value();
    594594
     595    ScopeChainNode* scopeChain = callFrame->scopeChain();
    595596    CodeBlock* codeBlock = callFrame->codeBlock();
    596597    RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache.get(callFrame, programSource, scopeChain, exceptionValue);
     
    598599    JSValue* result = jsUndefined();
    599600    if (evalNode)
    600         result = callFrame->globalData().machine->execute(evalNode.get(), callFrame, thisObj, callFrame->registers() - registerFile->start() + argv + 1 + RegisterFile::CallFrameHeaderSize, scopeChain, &exceptionValue);
     601        result = callFrame->globalData().machine->execute(evalNode.get(), callFrame, callFrame->thisValue()->toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
    601602
    602603    return result;
     
    656657#ifndef NDEBUG
    657658
    658 void Machine::dumpCallFrame(const RegisterFile* registerFile, CallFrame* callFrame)
    659 {
    660     JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
    661 
    662     CodeBlock* codeBlock = callFrame->codeBlock();
    663     codeBlock->dump(globalObject->globalExec());
    664 
    665     dumpRegisters(registerFile, callFrame);
    666 }
    667 
    668 void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFrame)
     659void Machine::dumpCallFrame(CallFrame* callFrame)
     660{
     661    callFrame->codeBlock()->dump(callFrame);
     662    dumpRegisters(callFrame);
     663}
     664
     665void Machine::dumpRegisters(CallFrame* callFrame)
    669666{
    670667    printf("Register frame: \n\n");
     
    674671
    675672    CodeBlock* codeBlock = callFrame->codeBlock();
     673    RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->machine->registerFile();
    676674    const Register* it;
    677675    const Register* end;
     
    10241022}
    10251023
    1026 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
     1024JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue** exception)
    10271025{
    10281026    ASSERT(!scopeChain->globalData->exception);
     
    10701068
    10711069    Register* oldEnd = m_registerFile.end();
    1072     Register* newEnd = m_registerFile.start() + registerOffset + codeBlock->numCalleeRegisters;
     1070    Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->numCalleeRegisters;
    10731071    if (!m_registerFile.grow(newEnd)) {
    10741072        *exception = createStackOverflowError(callFrame);
     
    10761074    }
    10771075
    1078     CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + registerOffset);
     1076    CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
    10791077
    10801078    // a 0 codeBlock indicates a built-in caller
     
    32653263    }
    32663264    BEGIN_OPCODE(op_call_eval) {
    3267         /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
     3265        /* call_eval dst(r) func(r) argCount(n) registerOffset(n)
    32683266
    32693267           Call a function named "eval" with no explicit "this" value
     
    32783276        int dst = vPC[1].u.operand;
    32793277        int func = vPC[2].u.operand;
    3280         int thisVal = vPC[3].u.operand;
    3281         int firstArg = vPC[4].u.operand;
    3282         int argCount = vPC[5].u.operand;
     3278        int argCount = vPC[3].u.operand;
     3279        int registerOffset = vPC[4].u.operand;
    32833280
    32843281        JSValue* funcVal = callFrame[func].jsValue(callFrame);
    3285         JSValue* baseVal = callFrame[thisVal].jsValue(callFrame);
    3286 
    3287         ScopeChainNode* scopeChain = callFrame->scopeChain();
    3288         if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
    3289             JSObject* thisObject = asObject(callFrame[callFrame->codeBlock()->thisRegister].jsValue(callFrame));
    3290             JSValue* result = callEval(callFrame, thisObject, scopeChain, registerFile, firstArg, argCount, exceptionValue);
     3282
     3283        Register* newCallFrame = callFrame->registers() + registerOffset;
     3284        Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
     3285        JSValue* thisValue = argv[0].jsValue(callFrame);
     3286        JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
     3287
     3288        if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
     3289            JSValue* result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
    32913290            if (exceptionValue)
    32923291                goto vm_throw;
    3293 
    32943292            callFrame[dst] = result;
    32953293
    3296             vPC += 7;
     3294            vPC += 5;
    32973295            NEXT_OPCODE;
    32983296        }
    32993297
    3300         // We didn't find the blessed version of eval, so reset vPC and process
    3301         // this instruction as a normal function call, supplying the proper 'this'
    3302         // value.
    3303         callFrame[thisVal] = baseVal->toThisObject(callFrame);
     3298        // We didn't find the blessed version of eval, so process this
     3299        // instruction as a normal function call.
    33043300
    33053301#if HAVE(COMPUTED_GOTO)
     
    33123308    }
    33133309    BEGIN_OPCODE(op_call) {
    3314         /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n) registerOffset(n)
    3315 
    3316            Perform a function call. Specifically, call register func
    3317            with a "this" value of register thisVal, and put the result
    3318            in register dst.
    3319 
    3320            The arguments start at register firstArg and go up to
    3321            argCount, but the "this" value is considered an implicit
    3322            first argument, so the argCount should be one greater than
    3323            the number of explicit arguments passed, and the register
    3324            after firstArg should contain the actual first
    3325            argument. This opcode will copy from the thisVal register
    3326            to the firstArg register, unless the register index of
    3327            thisVal is the special missing this object marker, which is
    3328            2^31-1; in that case, the global object will be used as the
    3329            "this" value.
    3330 
    3331            If func is a native code function, then this opcode calls
    3332            it and returns the value immediately.
    3333 
    3334            But if it is a JS function, then the current scope chain
    3335            and code block is set to the function's, and we slide the
    3336            register window so that the arguments would form the first
    3337            few local registers of the called function's register
    3338            window. In addition, a call frame header is written
    3339            immediately before the arguments; see the call frame
    3340            documentation for an explanation of how many registers a
    3341            call frame takes and what they contain. That many registers
    3342            before the firstArg register will be overwritten by the
    3343            call. In addition, any registers higher than firstArg +
    3344            argCount may be overwritten. Once this setup is complete,
    3345            execution continues from the called function's first
    3346            argument, and does not return until a "ret" opcode is
    3347            encountered.
     3310        /* call dst(r) func(r) argCount(n) registerOffset(n)
     3311
     3312           Perform a function call.
     3313           
     3314           registerOffset is the distance the callFrame pointer should move
     3315           before the VM initializes the new call frame's header.
     3316           
     3317           dst is where op_ret should store its result.
    33483318         */
    33493319
    33503320        int dst = vPC[1].u.operand;
    33513321        int func = vPC[2].u.operand;
    3352         int thisVal = vPC[3].u.operand;
    3353         int firstArg = vPC[4].u.operand;
    3354         int argCount = vPC[5].u.operand;
    3355         int registerOffset = vPC[6].u.operand;
     3322        int argCount = vPC[3].u.operand;
     3323        int registerOffset = vPC[4].u.operand;
    33563324
    33573325        JSValue* v = callFrame[func].jsValue(callFrame);
     
    33653333            CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
    33663334
    3367             callFrame[firstArg] = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame);
    3368            
    33693335            CallFrame* previousCallFrame = callFrame;
    33703336
     
    33763342            }
    33773343
    3378             callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
     3344            callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
    33793345            vPC = newCodeBlock->instructions.begin();
    33803346
     
    33873353
    33883354        if (callType == CallTypeHost) {
    3389             JSValue* thisValue = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame);
    3390             ArgList args(callFrame->registers() + firstArg + 1, argCount - 1);
    3391 
    33923355            ScopeChainNode* scopeChain = callFrame->scopeChain();
    33933356            CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
    3394             newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0);
     3357            newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0);
     3358
     3359            Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount;
     3360            ArgList args(thisRegister + 1, argCount - 1);
     3361
     3362            // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
     3363            JSValue* thisValue = thisRegister->jsValue(callFrame);
     3364            if (thisValue == jsNull())
     3365                thisValue = callFrame->globalThisValue();
    33953366
    33963367            JSValue* returnValue;
     
    34033374            callFrame[dst] = returnValue;
    34043375
    3405             vPC += 7;
     3376            vPC += 5;
    34063377            NEXT_OPCODE;
    34073378        }
     
    35733544    }
    35743545    BEGIN_OPCODE(op_construct) {
    3575         /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n) registerOffset(n)
    3576 
    3577            Invoke register "constr" as a constructor. For JS
     3546        /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
     3547
     3548           Invoke register "func" as a constructor. For JS
    35783549           functions, the calling convention is exactly as for the
    35793550           "call" opcode, except that the "this" value is a newly
    3580            created Object. For native constructors, a null "this"
    3581            value is passed. In either case, the firstArg and argCount
     3551           created Object. For native constructors, no "this"
     3552           value is passed. In either case, the argCount and registerOffset
    35823553           registers are interpreted as for the "call" opcode.
    35833554
    3584            Register constrProto must contain the prototype property of
    3585            register constsr. This is to enable polymorphic inline
     3555           Register proto must contain the prototype property of
     3556           register func. This is to enable polymorphic inline
    35863557           caching of this lookup.
    35873558        */
    35883559
    35893560        int dst = vPC[1].u.operand;
    3590         int constr = vPC[2].u.operand;
    3591         int constrProto = vPC[3].u.operand;
    3592         int firstArg = vPC[4].u.operand;
    3593         int argCount = vPC[5].u.operand;
    3594         int registerOffset = vPC[6].u.operand;
    3595 
    3596         JSValue* v = callFrame[constr].jsValue(callFrame);
     3561        int func = vPC[2].u.operand;
     3562        int argCount = vPC[3].u.operand;
     3563        int registerOffset = vPC[4].u.operand;
     3564        int proto = vPC[5].u.operand;
     3565        int thisRegister = vPC[6].u.operand;
     3566
     3567        JSValue* v = callFrame[func].jsValue(callFrame);
    35973568
    35983569        ConstructData constructData;
     
    36053576
    36063577            StructureID* structure;
    3607             JSValue* prototype = callFrame[constrProto].jsValue(callFrame);
     3578            JSValue* prototype = callFrame[proto].jsValue(callFrame);
    36083579            if (prototype->isObject())
    36093580                structure = asObject(prototype)->inheritorID();
     
    36123583            JSObject* newObject = new (globalData) JSObject(structure);
    36133584
    3614             callFrame[firstArg] = newObject; // "this" value
     3585            callFrame[thisRegister] = newObject; // "this" value
    36153586
    36163587            CallFrame* previousCallFrame = callFrame;
     
    36343605
    36353606        if (constructType == ConstructTypeHost) {
    3636             ArgList args(callFrame->registers() + firstArg + 1, argCount - 1);
     3607            ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
    36373608
    36383609            ScopeChainNode* scopeChain = callFrame->scopeChain();
     
    43654336    } while (0)
    43664337
     4338// This macro rewinds to the previous call frame because CTI functions that
     4339// throw stack overflow exceptions execute after the call frame has
     4340// optimistically moved forward.
     4341#define CTI_THROW_STACK_OVERFLOW() do { \
     4342    CallFrame* oldCallFrame = ARG_callFrame->callerFrame(); \
     4343    JSGlobalData* globalData = ARG_globalData; \
     4344    globalData->exception = createStackOverflowError(oldCallFrame); \
     4345    globalData->throwReturnAddress = CTI_RETURN_ADDRESS; \
     4346    ARG_setCallFrame(oldCallFrame); \
     4347    CTI_SET_RETURN_ADDRESS(reinterpret_cast<void*>(ctiVMThrowTrampoline)); \
     4348} while (0);
     4349
    43674350JSObject* Machine::cti_op_convert_this(CTI_ARGS)
    43684351{
     
    44534436}
    44544437
    4455 NEVER_INLINE void Machine::throwStackOverflowPreviousFrame(CallFrame* callFrame, JSGlobalData* globalData, void*& returnAddress)
    4456 {
    4457     globalData->exception = createStackOverflowError(callFrame->callerFrame());
    4458     globalData->throwReturnAddress = callFrame->returnPC();
    4459     ctiSetReturnAddress(&returnAddress, reinterpret_cast<void*>(ctiVMThrowTrampoline));
    4460 }
    4461 
    44624438void Machine::cti_register_file_check(CTI_ARGS)
    44634439{
     
    44674443        return;
    44684444
    4469     ARG_setCallFrame(ARG_callFrame->callerFrame());
    4470     throwStackOverflowPreviousFrame(ARG_callFrame, ARG_globalData, CTI_RETURN_ADDRESS);
     4445    CTI_THROW_STACK_OVERFLOW();
    44714446}
    44724447
     
    47454720        Register* newEnd = r + newCodeBlock->numCalleeRegisters;
    47464721        if (!ARG_registerFile->grow(newEnd)) {
    4747             ARG_globalData->exception = createStackOverflowError(oldCallFrame);
    4748             VM_THROW_EXCEPTION_2();
     4722            CTI_THROW_STACK_OVERFLOW();
     4723            VoidPtrPairValue pair = {{ 0, 0 }};
     4724            return pair.i;
    47494725        }
    47504726
     
    48114787            SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
    48124788
    4813             // All host methods should be calling toThisObject, but this is not presently the case.
     4789            // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
    48144790            JSValue* thisValue = argv[0].jsValue(callFrame);
    48154791            if (thisValue == jsNull())
     
    49354911
    49364912    StructureID* structure;
    4937     if (ARG_src5->isObject())
    4938         structure = asObject(ARG_src5)->inheritorID();
     4913    if (ARG_src4->isObject())
     4914        structure = asObject(ARG_src4)->inheritorID();
    49394915    else
    49404916        structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure();
     
    49504926    JSValue* constrVal = ARG_src1;
    49514927    int argCount = ARG_int3;
    4952     int firstArg = ARG_int6;
     4928    int thisRegister = ARG_int5;
    49534929
    49544930    ConstructData constructData;
     
    49564932
    49574933    if (constructType == ConstructTypeHost) {
    4958         ArgList argList(callFrame->registers() + firstArg + 1, argCount - 1);
     4934        ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1);
    49594935
    49604936        JSValue* returnValue;
     
    49704946    ASSERT(constructType == ConstructTypeNone);
    49714947
    4972     ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr4, callFrame->codeBlock());
     4948    ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr6, callFrame->codeBlock());
    49734949    VM_THROW_EXCEPTION();
    49744950}
     
    55695545    CallFrame* callFrame = ARG_callFrame;
    55705546    RegisterFile* registerFile = ARG_registerFile;
    5571     CodeBlock* codeBlock = callFrame->codeBlock();
    5572     ScopeChainNode* scopeChain = callFrame->scopeChain();
    55735547
    55745548    Machine* machine = ARG_globalData->machine;
     
    55775551    int registerOffset = ARG_int2;
    55785552    int argCount = ARG_int3;
    5579     JSValue* baseVal = ARG_src5;
    5580 
    5581     if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) {
    5582         JSObject* thisObject = callFrame[codeBlock->thisRegister].jsValue(callFrame)->toThisObject(callFrame);
     5553
     5554    Register* newCallFrame = callFrame->registers() + registerOffset;
     5555    Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
     5556    JSValue* thisValue = argv[0].jsValue(callFrame);
     5557    JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
     5558
     5559    if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
    55835560        JSValue* exceptionValue = noValue();
    5584         JSValue* result = machine->callEval(callFrame, thisObject, scopeChain, registerFile, registerOffset - RegisterFile::CallFrameHeaderSize - argCount, argCount, exceptionValue);
     5561        JSValue* result = machine->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
    55855562        if (UNLIKELY(exceptionValue != noValue())) {
    55865563            ARG_globalData->exception = exceptionValue;
     
    59455922    CallFrame* callFrame = ARG_callFrame;
    59465923    CodeBlock* codeBlock = callFrame->codeBlock();
    5947 
    5948     ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(ARG_globalData->throwReturnAddress));
    5949     unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(ARG_globalData->throwReturnAddress);
    5950 
    5951     JSValue* exceptionValue = ARG_globalData->exception;
     5924    JSGlobalData* globalData = ARG_globalData;
     5925
     5926    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(globalData->throwReturnAddress));
     5927    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(globalData->throwReturnAddress);
     5928
     5929    JSValue* exceptionValue = globalData->exception;
    59525930    ASSERT(exceptionValue);
    5953     ARG_globalData->exception = noValue();
    5954 
    5955     Instruction* handlerVPC = ARG_globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false);
     5931    globalData->exception = noValue();
     5932
     5933    Instruction* handlerVPC = globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false);
    59565934
    59575935    if (!handlerVPC) {
  • trunk/JavaScriptCore/VM/Machine.h

    r38286 r38322  
    285285        enum ExecutionFlag { Normal, InitializeAndReturn };
    286286
    287         NEVER_INLINE JSValue* callEval(CallFrame*, JSObject* thisObject, ScopeChainNode*, RegisterFile*, int argv, int argc, JSValue*& exceptionValue);
    288         JSValue* execute(EvalNode*, CallFrame*, JSObject* thisObject, int registerOffset, ScopeChainNode*, JSValue** exception);
     287        NEVER_INLINE JSValue* callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue*& exceptionValue);
     288        JSValue* execute(EvalNode*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue** exception);
    289289
    290290        NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine);
     
    307307        JSValue* privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValue** exception);
    308308
    309         void dumpCallFrame(const RegisterFile*, CallFrame*);
    310         void dumpRegisters(const RegisterFile*, CallFrame*);
     309        void dumpCallFrame(CallFrame*);
     310        void dumpRegisters(CallFrame*);
    311311
    312312        JSValue* checkTimeout(JSGlobalObject*);
     
    321321
    322322#if ENABLE(CTI)
    323         static void throwStackOverflowPreviousFrame(CallFrame*, JSGlobalData*, void*& returnAddress);
     323        static void throwStackOverflowPreviousFrame(CallFrame**, JSGlobalData*, void*& returnAddress);
    324324
    325325        void tryCTICacheGetByID(CallFrame*, CodeBlock*, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot&);
  • trunk/JavaScriptCore/bytecompiler/CodeGenerator.cpp

    r38298 r38322  
    12201220}
    12211221
    1222 RegisterID* CodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
    1223 {
    1224     return emitCall(op_call, dst, func, base, argumentsNode, divot, startOffset, endOffset);
    1225 }
    1226 
    1227 RegisterID* CodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
    1228 {
    1229     return emitCall(op_call_eval, dst, func, base, argumentsNode, divot, startOffset, endOffset);
    1230 }
    1231 
    1232 RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
     1222RegisterID* CodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
     1223{
     1224    return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
     1225}
     1226
     1227RegisterID* CodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
     1228{
     1229    return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
     1230}
     1231
     1232RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
    12331233{
    12341234    ASSERT(opcodeID == op_call || opcodeID == op_call_eval);
    12351235    ASSERT(func->refCount());
    1236     ASSERT(!base || base->refCount());
    12371236   
    12381237    // Generate code for arguments.
    12391238    Vector<RefPtr<RegisterID>, 16> argv;
    1240     argv.append(newTemporary()); // reserve space for "this"
     1239    argv.append(thisRegister);
    12411240    for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) {
    12421241        argv.append(newTemporary());
     
    12561255    emitExpressionInfo(divot, startOffset, endOffset);
    12571256    m_codeBlock->callLinkInfos.append(CallLinkInfo());
     1257
     1258    // Emit call.
    12581259    emitOpcode(opcodeID);
    1259     instructions().append(dst->index());
    1260     instructions().append(func->index());
    1261     instructions().append(base ? base->index() : missingThisObjectMarker()); // We encode the "this" value in the instruction stream, to avoid an explicit instruction for copying or loading it.
    1262     instructions().append(argv[0]->index()); // argv
    1263     instructions().append(argv.size()); // argc
     1260    instructions().append(dst->index()); // dst
     1261    instructions().append(func->index()); // func
     1262    instructions().append(argv.size()); // argCount
    12641263    instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
    12651264
     
    13201319    emitExpressionInfo(divot, startOffset, endOffset);
    13211320    m_codeBlock->callLinkInfos.append(CallLinkInfo());
     1321
    13221322    emitOpcode(op_construct);
    1323     instructions().append(dst->index());
    1324     instructions().append(func->index());
    1325     instructions().append(funcProto->index());
    1326     instructions().append(argv[0]->index()); // argv
    1327     instructions().append(argv.size()); // argc
     1323    instructions().append(dst->index()); // dst
     1324    instructions().append(func->index()); // func
     1325    instructions().append(argv.size()); // argCount
    13281326    instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
     1327    instructions().append(funcProto->index()); // proto
     1328    instructions().append(argv[0]->index()); // thisRegister
    13291329
    13301330    emitOpcode(op_construct_verify);
  • trunk/JavaScriptCore/bytecompiler/CodeGenerator.h

    r38247 r38322  
    274274        RegisterID* emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value);
    275275
    276         RegisterID* emitCall(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
    277         RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
     276        RegisterID* emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
     277        RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
    278278
    279279        RegisterID* emitReturn(RegisterID* src);
     
    346346        typedef HashMap<UString::Rep*, JSString*, IdentifierRepHash> IdentifierStringMap;
    347347
    348         RegisterID* emitCall(OpcodeID, RegisterID*, RegisterID*, RegisterID*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
     348        RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);
    349349       
    350350        RegisterID* newRegister();
  • trunk/JavaScriptCore/parser/Nodes.cpp

    r38249 r38322  
    586586RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst)
    587587{
    588     RefPtr<RegisterID> base = generator.tempDestination(dst);
    589     RefPtr<RegisterID> func = generator.newTemporary();
    590     generator.emitResolveWithBase(base.get(), func.get(), generator.propertyNames().eval);
    591     return generator.emitCallEval(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), divot(), startOffset(), endOffset());
     588    RefPtr<RegisterID> func = generator.tempDestination(dst);
     589    RefPtr<RegisterID> thisRegister = generator.newTemporary();
     590    generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval);
     591    return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
    592592}
    593593
     
    608608{
    609609    RefPtr<RegisterID> func = generator.emitNode(m_expr.get());
    610     return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), divot(), startOffset(), endOffset());
     610    RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
     611    return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
    611612}
    612613
     
    625626RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst)
    626627{
    627     if (RefPtr<RegisterID> local = generator.registerFor(m_ident))
    628         return generator.emitCall(generator.finalDestination(dst), local.get(), 0, m_args.get(), divot(), startOffset(), endOffset());
     628    if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
     629        RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
     630        return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
     631    }
    629632
    630633    int index = 0;
     
    633636    if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) {
    634637        RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
    635         return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), divot(), startOffset(), endOffset());
    636     }
    637 
    638     RefPtr<RegisterID> base = generator.tempDestination(dst);
    639     RefPtr<RegisterID> func = generator.newTemporary();
     638        RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull());
     639        return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
     640    }
     641
     642    RefPtr<RegisterID> func = generator.tempDestination(dst);
     643    RefPtr<RegisterID> thisRegister = generator.newTemporary();
    640644    int identifierStart = divot() - startOffset();
    641645    generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0);
    642     generator.emitResolveFunction(base.get(), func.get(), m_ident);
    643     return generator.emitCall(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), divot(), startOffset(), endOffset());
     646    generator.emitResolveFunction(thisRegister.get(), func.get(), m_ident);
     647    return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
    644648}
    645649
     
    663667    RegisterID* property = generator.emitNode(m_subscript.get());
    664668    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    665     RefPtr<RegisterID> function = generator.emitGetByVal(generator.newTemporary(), base.get(), property);
    666     return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), divot(), startOffset(), endOffset());
     669    RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property);
     670    RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
     671    return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
    667672}
    668673
     
    684689    RefPtr<RegisterID> base = generator.emitNode(m_base.get());
    685690    generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset);
    686     RefPtr<RegisterID> function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident);
    687     return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), divot(), startOffset(), endOffset());
     691    RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident);
     692    RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get());
     693    return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());
    688694}
    689695
  • trunk/JavaScriptCore/parser/Nodes.h

    r38298 r38322  
    20792079        int neededConstants()
    20802080        {
    2081             // We may need 1 more constant than the count given by the parser,
    2082             // because of the various uses of jsUndefined().
    2083             return m_numConstants + 1;
     2081            // We may need 2 more constants than the count given by the parser,
     2082            // because of the various uses of jsUndefined() and jsNull().
     2083            return m_numConstants + 2;
    20842084        }
    20852085
Note: See TracChangeset for help on using the changeset viewer.