Changeset 38322 in webkit for trunk/JavaScriptCore/VM/Machine.cpp
- Timestamp:
- Nov 11, 2008, 4:32:38 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/VM/Machine.cpp
r38311 r38322 581 581 } 582 582 583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, int argv, int argc, JSValue*& exceptionValue)583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue*& exceptionValue) 584 584 { 585 585 if (argc < 2) 586 586 return jsUndefined(); 587 587 588 JSValue* program = callFrame[argv +1].jsValue(callFrame);588 JSValue* program = argv[1].jsValue(callFrame); 589 589 590 590 if (!program->isString()) … … 593 593 UString programSource = asString(program)->value(); 594 594 595 ScopeChainNode* scopeChain = callFrame->scopeChain(); 595 596 CodeBlock* codeBlock = callFrame->codeBlock(); 596 597 RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache.get(callFrame, programSource, scopeChain, exceptionValue); … … 598 599 JSValue* result = jsUndefined(); 599 600 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); 601 602 602 603 return result; … … 656 657 #ifndef NDEBUG 657 658 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) 659 void Machine::dumpCallFrame(CallFrame* callFrame) 660 { 661 callFrame->codeBlock()->dump(callFrame); 662 dumpRegisters(callFrame); 663 } 664 665 void Machine::dumpRegisters(CallFrame* callFrame) 669 666 { 670 667 printf("Register frame: \n\n"); … … 674 671 675 672 CodeBlock* codeBlock = callFrame->codeBlock(); 673 RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->machine->registerFile(); 676 674 const Register* it; 677 675 const Register* end; … … 1024 1022 } 1025 1023 1026 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)1024 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue** exception) 1027 1025 { 1028 1026 ASSERT(!scopeChain->globalData->exception); … … 1070 1068 1071 1069 Register* oldEnd = m_registerFile.end(); 1072 Register* newEnd = m_registerFile.start() + registerOffset + codeBlock->numCalleeRegisters;1070 Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->numCalleeRegisters; 1073 1071 if (!m_registerFile.grow(newEnd)) { 1074 1072 *exception = createStackOverflowError(callFrame); … … 1076 1074 } 1077 1075 1078 CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + registerOffset);1076 CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset); 1079 1077 1080 1078 // a 0 codeBlock indicates a built-in caller … … 3265 3263 } 3266 3264 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) 3268 3266 3269 3267 Call a function named "eval" with no explicit "this" value … … 3278 3276 int dst = vPC[1].u.operand; 3279 3277 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; 3283 3280 3284 3281 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); 3291 3290 if (exceptionValue) 3292 3291 goto vm_throw; 3293 3294 3292 callFrame[dst] = result; 3295 3293 3296 vPC += 7;3294 vPC += 5; 3297 3295 NEXT_OPCODE; 3298 3296 } 3299 3297 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. 3304 3300 3305 3301 #if HAVE(COMPUTED_GOTO) … … 3312 3308 } 3313 3309 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. 3348 3318 */ 3349 3319 3350 3320 int dst = vPC[1].u.operand; 3351 3321 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; 3356 3324 3357 3325 JSValue* v = callFrame[func].jsValue(callFrame); … … 3365 3333 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain); 3366 3334 3367 callFrame[firstArg] = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame);3368 3369 3335 CallFrame* previousCallFrame = callFrame; 3370 3336 … … 3376 3342 } 3377 3343 3378 callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));3344 callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v)); 3379 3345 vPC = newCodeBlock->instructions.begin(); 3380 3346 … … 3387 3353 3388 3354 if (callType == CallTypeHost) { 3389 JSValue* thisValue = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame);3390 ArgList args(callFrame->registers() + firstArg + 1, argCount - 1);3391 3392 3355 ScopeChainNode* scopeChain = callFrame->scopeChain(); 3393 3356 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(); 3395 3366 3396 3367 JSValue* returnValue; … … 3403 3374 callFrame[dst] = returnValue; 3404 3375 3405 vPC += 7;3376 vPC += 5; 3406 3377 NEXT_OPCODE; 3407 3378 } … … 3573 3544 } 3574 3545 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 JS3546 /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r) 3547 3548 Invoke register "func" as a constructor. For JS 3578 3549 functions, the calling convention is exactly as for the 3579 3550 "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 argCount3551 created Object. For native constructors, no "this" 3552 value is passed. In either case, the argCount and registerOffset 3582 3553 registers are interpreted as for the "call" opcode. 3583 3554 3584 Register constrProto must contain the prototype property of3585 register constsr. This is to enable polymorphic inline3555 Register proto must contain the prototype property of 3556 register func. This is to enable polymorphic inline 3586 3557 caching of this lookup. 3587 3558 */ 3588 3559 3589 3560 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); 3597 3568 3598 3569 ConstructData constructData; … … 3605 3576 3606 3577 StructureID* structure; 3607 JSValue* prototype = callFrame[ constrProto].jsValue(callFrame);3578 JSValue* prototype = callFrame[proto].jsValue(callFrame); 3608 3579 if (prototype->isObject()) 3609 3580 structure = asObject(prototype)->inheritorID(); … … 3612 3583 JSObject* newObject = new (globalData) JSObject(structure); 3613 3584 3614 callFrame[ firstArg] = newObject; // "this" value3585 callFrame[thisRegister] = newObject; // "this" value 3615 3586 3616 3587 CallFrame* previousCallFrame = callFrame; … … 3634 3605 3635 3606 if (constructType == ConstructTypeHost) { 3636 ArgList args(callFrame->registers() + firstArg+ 1, argCount - 1);3607 ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1); 3637 3608 3638 3609 ScopeChainNode* scopeChain = callFrame->scopeChain(); … … 4365 4336 } while (0) 4366 4337 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 4367 4350 JSObject* Machine::cti_op_convert_this(CTI_ARGS) 4368 4351 { … … 4453 4436 } 4454 4437 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 4462 4438 void Machine::cti_register_file_check(CTI_ARGS) 4463 4439 { … … 4467 4443 return; 4468 4444 4469 ARG_setCallFrame(ARG_callFrame->callerFrame()); 4470 throwStackOverflowPreviousFrame(ARG_callFrame, ARG_globalData, CTI_RETURN_ADDRESS); 4445 CTI_THROW_STACK_OVERFLOW(); 4471 4446 } 4472 4447 … … 4745 4720 Register* newEnd = r + newCodeBlock->numCalleeRegisters; 4746 4721 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; 4749 4725 } 4750 4726 … … 4811 4787 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); 4812 4788 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. 4814 4790 JSValue* thisValue = argv[0].jsValue(callFrame); 4815 4791 if (thisValue == jsNull()) … … 4935 4911 4936 4912 StructureID* structure; 4937 if (ARG_src 5->isObject())4938 structure = asObject(ARG_src 5)->inheritorID();4913 if (ARG_src4->isObject()) 4914 structure = asObject(ARG_src4)->inheritorID(); 4939 4915 else 4940 4916 structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure(); … … 4950 4926 JSValue* constrVal = ARG_src1; 4951 4927 int argCount = ARG_int3; 4952 int firstArg = ARG_int6;4928 int thisRegister = ARG_int5; 4953 4929 4954 4930 ConstructData constructData; … … 4956 4932 4957 4933 if (constructType == ConstructTypeHost) { 4958 ArgList argList(callFrame->registers() + firstArg+ 1, argCount - 1);4934 ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1); 4959 4935 4960 4936 JSValue* returnValue; … … 4970 4946 ASSERT(constructType == ConstructTypeNone); 4971 4947 4972 ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr 4, callFrame->codeBlock());4948 ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr6, callFrame->codeBlock()); 4973 4949 VM_THROW_EXCEPTION(); 4974 4950 } … … 5569 5545 CallFrame* callFrame = ARG_callFrame; 5570 5546 RegisterFile* registerFile = ARG_registerFile; 5571 CodeBlock* codeBlock = callFrame->codeBlock();5572 ScopeChainNode* scopeChain = callFrame->scopeChain();5573 5547 5574 5548 Machine* machine = ARG_globalData->machine; … … 5577 5551 int registerOffset = ARG_int2; 5578 5552 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()) { 5583 5560 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); 5585 5562 if (UNLIKELY(exceptionValue != noValue())) { 5586 5563 ARG_globalData->exception = exceptionValue; … … 5945 5922 CallFrame* callFrame = ARG_callFrame; 5946 5923 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; 5952 5930 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); 5956 5934 5957 5935 if (!handlerVPC) {
Note:
See TracChangeset
for help on using the changeset viewer.