Changeset 38349 in webkit


Ignore:
Timestamp:
Nov 12, 2008 4:48:23 PM (15 years ago)
Author:
ggaren@apple.com
Message:

2008-11-12 Geoffrey Garen <ggaren@apple.com>

Reviewed by Sam Weinig.


Fixed https://bugs.webkit.org/show_bug.cgi?id=22192
+37 failures in fast/profiler


along with Darin's review comments in
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

  • VM/Machine.cpp: (JSC::returnToThrowTrampoline): (JSC::throwStackOverflowError): (JSC::Machine::cti_register_file_check): (JSC::Machine::cti_op_call_arityCheck): (JSC::Machine::cti_vm_throw): Moved the throw logic into a function, since functions are better than macros.
  • bytecompiler/CodeGenerator.cpp: (JSC::CodeGenerator::emitCall): (JSC::CodeGenerator::emitConstruct): Ensure that the function register is preserved if profiling is enabled, since the profiler uses that register.
  • runtime/JSGlobalData.h: Renamed throwReturnAddress to exceptionLocation, because I had a hard time understanding what "throwReturnAddress" meant.
Location:
trunk/JavaScriptCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r38334 r38349  
     12008-11-12  Geoffrey Garen  <ggaren@apple.com>
     2
     3        Reviewed by Sam Weinig.
     4       
     5        Fixed https://bugs.webkit.org/show_bug.cgi?id=22192
     6        +37 failures in fast/profiler
     7       
     8        along with Darin's review comments in
     9        https://bugs.webkit.org/show_bug.cgi?id=22174
     10        Simplified op_call by nixing its responsibility for moving the value of
     11        "this" into the first argument slot
     12
     13        * VM/Machine.cpp:
     14        (JSC::returnToThrowTrampoline):
     15        (JSC::throwStackOverflowError):
     16        (JSC::Machine::cti_register_file_check):
     17        (JSC::Machine::cti_op_call_arityCheck):
     18        (JSC::Machine::cti_vm_throw): Moved the throw logic into a function, since
     19        functions are better than macros.
     20
     21        * bytecompiler/CodeGenerator.cpp:
     22        (JSC::CodeGenerator::emitCall):
     23        (JSC::CodeGenerator::emitConstruct): Ensure that the function register
     24        is preserved if profiling is enabled, since the profiler uses that
     25        register.
     26
     27        * runtime/JSGlobalData.h: Renamed throwReturnAddress to exceptionLocation,
     28        because I had a hard time understanding what "throwReturnAddress" meant.
     29
     302008-11-12  Geoffrey Garen  <ggaren@apple.com>
     31
     32        Reviewed by Sam Weinig.
     33
     34        Roll in r38322, now that test failures have been fixed.
     35
     36        * VM/CTI.cpp:
     37        (JSC::CTI::compileOpCallSetupArgs):
     38        (JSC::CTI::compileOpCallEvalSetupArgs):
     39        (JSC::CTI::compileOpConstructSetupArgs):
     40        (JSC::CTI::compileOpCall):
     41        (JSC::CTI::privateCompileMainPass):
     42        (JSC::CTI::privateCompileSlowCases):
     43        * VM/CTI.h:
     44        * VM/CodeBlock.cpp:
     45        (JSC::CodeBlock::dump):
     46        * VM/Machine.cpp:
     47        (JSC::Machine::callEval):
     48        (JSC::Machine::dumpCallFrame):
     49        (JSC::Machine::dumpRegisters):
     50        (JSC::Machine::execute):
     51        (JSC::Machine::privateExecute):
     52        (JSC::Machine::cti_register_file_check):
     53        (JSC::Machine::cti_op_call_arityCheck):
     54        (JSC::Machine::cti_op_call_NotJSFunction):
     55        (JSC::Machine::cti_op_construct_JSConstruct):
     56        (JSC::Machine::cti_op_construct_NotJSConstruct):
     57        (JSC::Machine::cti_op_call_eval):
     58        (JSC::Machine::cti_vm_throw):
     59        * VM/Machine.h:
     60        * bytecompiler/CodeGenerator.cpp:
     61        (JSC::CodeGenerator::emitCall):
     62        (JSC::CodeGenerator::emitCallEval):
     63        (JSC::CodeGenerator::emitConstruct):
     64        * bytecompiler/CodeGenerator.h:
     65        * parser/Nodes.cpp:
     66        (JSC::EvalFunctionCallNode::emitCode):
     67        (JSC::FunctionCallValueNode::emitCode):
     68        (JSC::FunctionCallResolveNode::emitCode):
     69        (JSC::FunctionCallBracketNode::emitCode):
     70        (JSC::FunctionCallDotNode::emitCode):
     71        * parser/Nodes.h:
     72        (JSC::ScopeNode::neededConstants):
     73
    1742008-11-12  Gavin Barraclough  <barraclough@apple.com>
    275
  • trunk/JavaScriptCore/VM/CTI.cpp

    r38334 r38349  
    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

    r38330 r38349  
    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

    r38330 r38349  
    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

    r38330 r38349  
    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();
     
    43264297// good to keep the code size down by leaving as much of the exception
    43274298// handling code out of line as possible.
    4328 static NEVER_INLINE void setUpThrowTrampolineReturnAddress(JSGlobalData* globalData, void*& returnAddress)
     4299static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot)
    43294300{
    43304301    ASSERT(globalData->exception);
    4331     globalData->throwReturnAddress = returnAddress;
    4332     ctiSetReturnAddress(&returnAddress, reinterpret_cast<void*>(ctiVMThrowTrampoline));
     4302    globalData->exceptionLocation = exceptionLocation;
     4303    ctiSetReturnAddress(&returnAddressSlot, reinterpret_cast<void*>(ctiVMThrowTrampoline));
     4304}
     4305
     4306static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot)
     4307{
     4308    globalData->exception = createStackOverflowError(callFrame);
     4309    returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot);
    43334310}
    43344311
     
    43454322    } while (0)
    43464323#define VM_THROW_EXCEPTION_AT_END() \
    4347     setUpThrowTrampolineReturnAddress(ARG_globalData, CTI_RETURN_ADDRESS)
     4324    returnToThrowTrampoline(ARG_globalData, CTI_RETURN_ADDRESS, CTI_RETURN_ADDRESS)
    43484325
    43494326#define VM_CHECK_EXCEPTION() \
     
    44534430}
    44544431
    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 
    44624432void Machine::cti_register_file_check(CTI_ARGS)
    44634433{
     
    44674437        return;
    44684438
    4469     ARG_setCallFrame(ARG_callFrame->callerFrame());
    4470     throwStackOverflowPreviousFrame(ARG_callFrame, ARG_globalData, CTI_RETURN_ADDRESS);
     4439    // Rewind to the previous call frame because op_call already optimistically
     4440    // moved the call frame forward.
     4441    CallFrame* oldCallFrame = ARG_callFrame->callerFrame();
     4442    ARG_setCallFrame(oldCallFrame);
     4443    throwStackOverflowError(oldCallFrame, ARG_globalData, oldCallFrame->returnPC(), CTI_RETURN_ADDRESS);
    44714444}
    44724445
     
    47454718        Register* newEnd = r + newCodeBlock->numCalleeRegisters;
    47464719        if (!ARG_registerFile->grow(newEnd)) {
    4747             ARG_globalData->exception = createStackOverflowError(oldCallFrame);
    4748             VM_THROW_EXCEPTION_2();
     4720            // Rewind to the previous call frame because op_call already optimistically
     4721            // moved the call frame forward.
     4722            ARG_setCallFrame(oldCallFrame);
     4723            throwStackOverflowError(oldCallFrame, ARG_globalData, CTI_RETURN_ADDRESS, CTI_RETURN_ADDRESS);
     4724            VoidPtrPairValue pair = {{ 0, 0 }};
     4725            return pair.i;
    47494726        }
    47504727
     
    48114788            SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
    48124789
    4813             // All host methods should be calling toThisObject, but this is not presently the case.
     4790            // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
    48144791            JSValue* thisValue = argv[0].jsValue(callFrame);
    48154792            if (thisValue == jsNull())
     
    49354912
    49364913    StructureID* structure;
    4937     if (ARG_src5->isObject())
    4938         structure = asObject(ARG_src5)->inheritorID();
     4914    if (ARG_src4->isObject())
     4915        structure = asObject(ARG_src4)->inheritorID();
    49394916    else
    49404917        structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure();
     
    49504927    JSValue* constrVal = ARG_src1;
    49514928    int argCount = ARG_int3;
    4952     int firstArg = ARG_int6;
     4929    int thisRegister = ARG_int5;
    49534930
    49544931    ConstructData constructData;
     
    49564933
    49574934    if (constructType == ConstructTypeHost) {
    4958         ArgList argList(callFrame->registers() + firstArg + 1, argCount - 1);
     4935        ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1);
    49594936
    49604937        JSValue* returnValue;
     
    49704947    ASSERT(constructType == ConstructTypeNone);
    49714948
    4972     ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr4, callFrame->codeBlock());
     4949    ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr6, callFrame->codeBlock());
    49734950    VM_THROW_EXCEPTION();
    49744951}
     
    55695546    CallFrame* callFrame = ARG_callFrame;
    55705547    RegisterFile* registerFile = ARG_registerFile;
    5571     CodeBlock* codeBlock = callFrame->codeBlock();
    5572     ScopeChainNode* scopeChain = callFrame->scopeChain();
    55735548
    55745549    Machine* machine = ARG_globalData->machine;
     
    55775552    int registerOffset = ARG_int2;
    55785553    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);
     5554
     5555    Register* newCallFrame = callFrame->registers() + registerOffset;
     5556    Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount;
     5557    JSValue* thisValue = argv[0].jsValue(callFrame);
     5558    JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject();
     5559
     5560    if (thisValue == globalObject && funcVal == globalObject->evalFunction()) {
    55835561        JSValue* exceptionValue = noValue();
    5584         JSValue* result = machine->callEval(callFrame, thisObject, scopeChain, registerFile, registerOffset - RegisterFile::CallFrameHeaderSize - argCount, argCount, exceptionValue);
     5562        JSValue* result = machine->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
    55855563        if (UNLIKELY(exceptionValue != noValue())) {
    55865564            ARG_globalData->exception = exceptionValue;
     
    59455923    CallFrame* callFrame = ARG_callFrame;
    59465924    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;
     5925    JSGlobalData* globalData = ARG_globalData;
     5926
     5927    ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(globalData->exceptionLocation));
     5928    unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(globalData->exceptionLocation);
     5929
     5930    JSValue* exceptionValue = globalData->exception;
    59525931    ASSERT(exceptionValue);
    5953     ARG_globalData->exception = noValue();
    5954 
    5955     Instruction* handlerVPC = ARG_globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false);
     5932    globalData->exception = noValue();
     5933
     5934    Instruction* handlerVPC = globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false);
    59565935
    59575936    if (!handlerVPC) {
  • trunk/JavaScriptCore/VM/Machine.h

    r38330 r38349  
    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

    r38330 r38349  
    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());
    1237    
     1236
     1237    if (m_shouldEmitProfileHooks) {
     1238        // If codegen decided to recycle func as this call's destination register,
     1239        // we need to undo that optimization here so that func will still be around
     1240        // for the sake of op_profile_did_call.
     1241        if (dst == func) {
     1242            RefPtr<RegisterID> protect = thisRegister;
     1243            RefPtr<RegisterID> movedThisRegister = emitMove(newTemporary(), thisRegister);
     1244            RefPtr<RegisterID> movedFunc = emitMove(thisRegister, func);
     1245           
     1246            thisRegister = movedThisRegister.release().releaseRef();
     1247            func = movedFunc.release().releaseRef();
     1248        }
     1249    }
     1250
    12381251    // Generate code for arguments.
    12391252    Vector<RefPtr<RegisterID>, 16> argv;
    1240     argv.append(newTemporary()); // reserve space for "this"
     1253    argv.append(thisRegister);
    12411254    for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) {
    12421255        argv.append(newTemporary());
     
    12561269    emitExpressionInfo(divot, startOffset, endOffset);
    12571270    m_codeBlock->callLinkInfos.append(CallLinkInfo());
     1271
     1272    // Emit call.
    12581273    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
     1274    instructions().append(dst->index()); // dst
     1275    instructions().append(func->index()); // func
     1276    instructions().append(argv.size()); // argCount
    12641277    instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
    12651278
     
    12671280        emitOpcode(op_profile_did_call);
    12681281        instructions().append(func->index());
     1282
     1283        if (dst == func) {
     1284            thisRegister->deref();
     1285            func->deref();
     1286        }
    12691287    }
    12701288
     
    12931311{
    12941312    ASSERT(func->refCount());
     1313
     1314    if (m_shouldEmitProfileHooks) {
     1315        // If codegen decided to recycle func as this call's destination register,
     1316        // we need to undo that optimization here so that func will still be around
     1317        // for the sake of op_profile_did_call.
     1318        if (dst == func) {
     1319            RefPtr<RegisterID> movedFunc = emitMove(newTemporary(), func);
     1320            func = movedFunc.release().releaseRef();
     1321        }
     1322    }
    12951323
    12961324    RefPtr<RegisterID> funcProto = newTemporary();
     
    13201348    emitExpressionInfo(divot, startOffset, endOffset);
    13211349    m_codeBlock->callLinkInfos.append(CallLinkInfo());
     1350
    13221351    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
     1352    instructions().append(dst->index()); // dst
     1353    instructions().append(func->index()); // func
     1354    instructions().append(argv.size()); // argCount
    13281355    instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset
     1356    instructions().append(funcProto->index()); // proto
     1357    instructions().append(argv[0]->index()); // thisRegister
    13291358
    13301359    emitOpcode(op_construct_verify);
     
    13351364        emitOpcode(op_profile_did_call);
    13361365        instructions().append(func->index());
     1366       
     1367        if (dst == func)
     1368            func->deref();
    13371369    }
    13381370
  • trunk/JavaScriptCore/bytecompiler/CodeGenerator.h

    r38330 r38349  
    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

    r38330 r38349  
    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

    r38330 r38349  
    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
  • trunk/JavaScriptCore/runtime/JSGlobalData.h

    r38137 r38349  
    6868        JSValue* exception;
    6969#if ENABLE(CTI)
    70         void* throwReturnAddress;
     70        void* exceptionLocation;
    7171#endif
    7272
Note: See TracChangeset for help on using the changeset viewer.