Changeset 38330 in webkit for trunk/JavaScriptCore/VM/Machine.cpp


Ignore:
Timestamp:
Nov 12, 2008, 1:34:22 AM (17 years ago)
Author:
[email protected]
Message:

2008-11-12 Cameron Zwarich <[email protected]>

Rubber-stamped by Mark Rowe.

Roll out r38322 due to test failures on the bots.

JavaScriptCore:

  • VM/CTI.cpp: (JSC::CTI::compileOpCallSetupArgs): (JSC::CTI::compileOpCall): (JSC::CTI::privateCompileMainPass): (JSC::CTI::privateCompileSlowCases):
  • VM/CTI.h:
  • VM/CodeBlock.cpp: (JSC::CodeBlock::dump):
  • VM/Machine.cpp: (JSC::Machine::callEval): (JSC::Machine::dumpCallFrame): (JSC::Machine::dumpRegisters): (JSC::Machine::execute): (JSC::Machine::privateExecute): (JSC::Machine::throwStackOverflowPreviousFrame): (JSC::Machine::cti_register_file_check): (JSC::Machine::cti_op_call_arityCheck): (JSC::Machine::cti_op_call_NotJSFunction): (JSC::Machine::cti_op_construct_JSConstruct): (JSC::Machine::cti_op_construct_NotJSConstruct): (JSC::Machine::cti_op_call_eval): (JSC::Machine::cti_vm_throw):
  • VM/Machine.h:
  • bytecompiler/CodeGenerator.cpp: (JSC::CodeGenerator::emitCall): (JSC::CodeGenerator::emitCallEval): (JSC::CodeGenerator::emitConstruct):
  • bytecompiler/CodeGenerator.h:
  • parser/Nodes.cpp: (JSC::EvalFunctionCallNode::emitCode): (JSC::FunctionCallValueNode::emitCode): (JSC::FunctionCallResolveNode::emitCode): (JSC::FunctionCallBracketNode::emitCode): (JSC::FunctionCallDotNode::emitCode):
  • parser/Nodes.h: (JSC::ScopeNode::neededConstants):

LayoutTests:

  • fast/js/global-recursion-on-full-stack-expected.txt:
File:
1 edited

Legend:

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

    r38322 r38330  
    581581}
    582582
    583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue*& exceptionValue)
     583NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, int argv, int argc, JSValue*& exceptionValue)
    584584{
    585585    if (argc < 2)
    586586        return jsUndefined();
    587587
    588     JSValue* program = argv[1].jsValue(callFrame);
     588    JSValue* program = callFrame[argv + 1].jsValue(callFrame);
    589589
    590590    if (!program->isString())
     
    593593    UString programSource = asString(program)->value();
    594594
    595     ScopeChainNode* scopeChain = callFrame->scopeChain();
    596595    CodeBlock* codeBlock = callFrame->codeBlock();
    597596    RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache.get(callFrame, programSource, scopeChain, exceptionValue);
     
    599598    JSValue* result = jsUndefined();
    600599    if (evalNode)
    601         result = callFrame->globalData().machine->execute(evalNode.get(), callFrame, callFrame->thisValue()->toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);
     600        result = callFrame->globalData().machine->execute(evalNode.get(), callFrame, thisObj, callFrame->registers() - registerFile->start() + argv + 1 + RegisterFile::CallFrameHeaderSize, scopeChain, &exceptionValue);
    602601
    603602    return result;
     
    657656#ifndef NDEBUG
    658657
    659 void Machine::dumpCallFrame(CallFrame* callFrame)
    660 {
    661     callFrame->codeBlock()->dump(callFrame);
    662     dumpRegisters(callFrame);
    663 }
    664 
    665 void Machine::dumpRegisters(CallFrame* callFrame)
     658void 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
     668void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFrame)
    666669{
    667670    printf("Register frame: \n\n");
     
    671674
    672675    CodeBlock* codeBlock = callFrame->codeBlock();
    673     RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->machine->registerFile();
    674676    const Register* it;
    675677    const Register* end;
     
    10221024}
    10231025
    1024 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue** exception)
     1026JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)
    10251027{
    10261028    ASSERT(!scopeChain->globalData->exception);
     
    10681070
    10691071    Register* oldEnd = m_registerFile.end();
    1070     Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->numCalleeRegisters;
     1072    Register* newEnd = m_registerFile.start() + registerOffset + codeBlock->numCalleeRegisters;
    10711073    if (!m_registerFile.grow(newEnd)) {
    10721074        *exception = createStackOverflowError(callFrame);
     
    10741076    }
    10751077
    1076     CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);
     1078    CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + registerOffset);
    10771079
    10781080    // a 0 codeBlock indicates a built-in caller
     
    32633265    }
    32643266    BEGIN_OPCODE(op_call_eval) {
    3265         /* call_eval dst(r) func(r) argCount(n) registerOffset(n)
     3267        /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)
    32663268
    32673269           Call a function named "eval" with no explicit "this" value
     
    32763278        int dst = vPC[1].u.operand;
    32773279        int func = vPC[2].u.operand;
    3278         int argCount = vPC[3].u.operand;
    3279         int registerOffset = vPC[4].u.operand;
     3280        int thisVal = vPC[3].u.operand;
     3281        int firstArg = vPC[4].u.operand;
     3282        int argCount = vPC[5].u.operand;
    32803283
    32813284        JSValue* funcVal = callFrame[func].jsValue(callFrame);
    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);
     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);
    32903291            if (exceptionValue)
    32913292                goto vm_throw;
     3293
    32923294            callFrame[dst] = result;
    32933295
    3294             vPC += 5;
     3296            vPC += 7;
    32953297            NEXT_OPCODE;
    32963298        }
    32973299
    3298         // We didn't find the blessed version of eval, so process this
    3299         // instruction as a normal function call.
     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);
    33003304
    33013305#if HAVE(COMPUTED_GOTO)
     
    33083312    }
    33093313    BEGIN_OPCODE(op_call) {
    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.
     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.
    33183348         */
    33193349
    33203350        int dst = vPC[1].u.operand;
    33213351        int func = vPC[2].u.operand;
    3322         int argCount = vPC[3].u.operand;
    3323         int registerOffset = vPC[4].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;
    33243356
    33253357        JSValue* v = callFrame[func].jsValue(callFrame);
     
    33333365            CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);
    33343366
     3367            callFrame[firstArg] = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame);
     3368           
    33353369            CallFrame* previousCallFrame = callFrame;
    33363370
     
    33423376            }
    33433377
    3344             callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
     3378            callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));
    33453379            vPC = newCodeBlock->instructions.begin();
    33463380
     
    33533387
    33543388        if (callType == CallTypeHost) {
     3389            JSValue* thisValue = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame);
     3390            ArgList args(callFrame->registers() + firstArg + 1, argCount - 1);
     3391
    33553392            ScopeChainNode* scopeChain = callFrame->scopeChain();
    33563393            CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset);
    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();
     3394            newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0);
    33663395
    33673396            JSValue* returnValue;
     
    33743403            callFrame[dst] = returnValue;
    33753404
    3376             vPC += 5;
     3405            vPC += 7;
    33773406            NEXT_OPCODE;
    33783407        }
     
    35443573    }
    35453574    BEGIN_OPCODE(op_construct) {
    3546         /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)
    3547 
    3548            Invoke register "func" as a constructor. For JS
     3575        /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n) registerOffset(n)
     3576
     3577           Invoke register "constr" as a constructor. For JS
    35493578           functions, the calling convention is exactly as for the
    35503579           "call" opcode, except that the "this" value is a newly
    3551            created Object. For native constructors, no "this"
    3552            value is passed. In either case, the argCount and registerOffset
     3580           created Object. For native constructors, a null "this"
     3581           value is passed. In either case, the firstArg and argCount
    35533582           registers are interpreted as for the "call" opcode.
    35543583
    3555            Register proto must contain the prototype property of
    3556            register func. This is to enable polymorphic inline
     3584           Register constrProto must contain the prototype property of
     3585           register constsr. This is to enable polymorphic inline
    35573586           caching of this lookup.
    35583587        */
    35593588
    35603589        int dst = vPC[1].u.operand;
    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);
     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);
    35683597
    35693598        ConstructData constructData;
     
    35763605
    35773606            StructureID* structure;
    3578             JSValue* prototype = callFrame[proto].jsValue(callFrame);
     3607            JSValue* prototype = callFrame[constrProto].jsValue(callFrame);
    35793608            if (prototype->isObject())
    35803609                structure = asObject(prototype)->inheritorID();
     
    35833612            JSObject* newObject = new (globalData) JSObject(structure);
    35843613
    3585             callFrame[thisRegister] = newObject; // "this" value
     3614            callFrame[firstArg] = newObject; // "this" value
    35863615
    35873616            CallFrame* previousCallFrame = callFrame;
     
    36053634
    36063635        if (constructType == ConstructTypeHost) {
    3607             ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1);
     3636            ArgList args(callFrame->registers() + firstArg + 1, argCount - 1);
    36083637
    36093638            ScopeChainNode* scopeChain = callFrame->scopeChain();
     
    43364365    } while (0)
    43374366
    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 
    43504367JSObject* Machine::cti_op_convert_this(CTI_ARGS)
    43514368{
     
    44364453}
    44374454
     4455NEVER_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
    44384462void Machine::cti_register_file_check(CTI_ARGS)
    44394463{
     
    44434467        return;
    44444468
    4445     CTI_THROW_STACK_OVERFLOW();
     4469    ARG_setCallFrame(ARG_callFrame->callerFrame());
     4470    throwStackOverflowPreviousFrame(ARG_callFrame, ARG_globalData, CTI_RETURN_ADDRESS);
    44464471}
    44474472
     
    47204745        Register* newEnd = r + newCodeBlock->numCalleeRegisters;
    47214746        if (!ARG_registerFile->grow(newEnd)) {
    4722             CTI_THROW_STACK_OVERFLOW();
    4723             VoidPtrPairValue pair = {{ 0, 0 }};
    4724             return pair.i;
     4747            ARG_globalData->exception = createStackOverflowError(oldCallFrame);
     4748            VM_THROW_EXCEPTION_2();
    47254749        }
    47264750
     
    47874811            SamplingTool::HostCallRecord callRecord(CTI_SAMPLER);
    47884812
    4789             // FIXME: All host methods should be calling toThisObject, but this is not presently the case.
     4813            // All host methods should be calling toThisObject, but this is not presently the case.
    47904814            JSValue* thisValue = argv[0].jsValue(callFrame);
    47914815            if (thisValue == jsNull())
     
    49114935
    49124936    StructureID* structure;
    4913     if (ARG_src4->isObject())
    4914         structure = asObject(ARG_src4)->inheritorID();
     4937    if (ARG_src5->isObject())
     4938        structure = asObject(ARG_src5)->inheritorID();
    49154939    else
    49164940        structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure();
     
    49264950    JSValue* constrVal = ARG_src1;
    49274951    int argCount = ARG_int3;
    4928     int thisRegister = ARG_int5;
     4952    int firstArg = ARG_int6;
    49294953
    49304954    ConstructData constructData;
     
    49324956
    49334957    if (constructType == ConstructTypeHost) {
    4934         ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1);
     4958        ArgList argList(callFrame->registers() + firstArg + 1, argCount - 1);
    49354959
    49364960        JSValue* returnValue;
     
    49464970    ASSERT(constructType == ConstructTypeNone);
    49474971
    4948     ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr6, callFrame->codeBlock());
     4972    ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr4, callFrame->codeBlock());
    49494973    VM_THROW_EXCEPTION();
    49504974}
     
    55455569    CallFrame* callFrame = ARG_callFrame;
    55465570    RegisterFile* registerFile = ARG_registerFile;
     5571    CodeBlock* codeBlock = callFrame->codeBlock();
     5572    ScopeChainNode* scopeChain = callFrame->scopeChain();
    55475573
    55485574    Machine* machine = ARG_globalData->machine;
     
    55515577    int registerOffset = ARG_int2;
    55525578    int argCount = ARG_int3;
    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()) {
     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);
    55605583        JSValue* exceptionValue = noValue();
    5561         JSValue* result = machine->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);
     5584        JSValue* result = machine->callEval(callFrame, thisObject, scopeChain, registerFile, registerOffset - RegisterFile::CallFrameHeaderSize - argCount, argCount, exceptionValue);
    55625585        if (UNLIKELY(exceptionValue != noValue())) {
    55635586            ARG_globalData->exception = exceptionValue;
     
    59225945    CallFrame* callFrame = ARG_callFrame;
    59235946    CodeBlock* codeBlock = callFrame->codeBlock();
    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;
     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;
    59305952    ASSERT(exceptionValue);
    5931     globalData->exception = noValue();
    5932 
    5933     Instruction* handlerVPC = globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false);
     5953    ARG_globalData->exception = noValue();
     5954
     5955    Instruction* handlerVPC = ARG_globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false);
    59345956
    59355957    if (!handlerVPC) {
Note: See TracChangeset for help on using the changeset viewer.