OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple Inc. All rights reserved. |
3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> | 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * | 8 * |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 } | 573 } |
574 | 574 |
575 static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, C
odeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exception
Data) | 575 static NEVER_INLINE bool isNotObject(CallFrame* callFrame, bool forInstanceOf, C
odeBlock* codeBlock, const Instruction* vPC, JSValue* value, JSValue*& exception
Data) |
576 { | 576 { |
577 if (value->isObject()) | 577 if (value->isObject()) |
578 return false; | 578 return false; |
579 exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instance
of" : "in" , value, vPC, codeBlock); | 579 exceptionData = createInvalidParamError(callFrame, forInstanceOf ? "instance
of" : "in" , value, vPC, codeBlock); |
580 return true; | 580 return true; |
581 } | 581 } |
582 | 582 |
583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, JSObject* thisObj,
ScopeChainNode* scopeChain, RegisterFile* registerFile, int argv, int argc, JSV
alue*& exceptionValue) | 583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, RegisterFile* regi
sterFile, Register* argv, int argc, int registerOffset, JSValue*& exceptionValue
) |
584 { | 584 { |
585 if (argc < 2) | 585 if (argc < 2) |
586 return jsUndefined(); | 586 return jsUndefined(); |
587 | 587 |
588 JSValue* program = callFrame[argv + 1].jsValue(callFrame); | 588 JSValue* program = argv[1].jsValue(callFrame); |
589 | 589 |
590 if (!program->isString()) | 590 if (!program->isString()) |
591 return program; | 591 return program; |
592 | 592 |
593 UString programSource = asString(program)->value(); | 593 UString programSource = asString(program)->value(); |
594 | 594 |
| 595 ScopeChainNode* scopeChain = callFrame->scopeChain(); |
595 CodeBlock* codeBlock = callFrame->codeBlock(); | 596 CodeBlock* codeBlock = callFrame->codeBlock(); |
596 RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache.get(callFrame, programS
ource, scopeChain, exceptionValue); | 597 RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache.get(callFrame, programS
ource, scopeChain, exceptionValue); |
597 | 598 |
598 JSValue* result = jsUndefined(); | 599 JSValue* result = jsUndefined(); |
599 if (evalNode) | 600 if (evalNode) |
600 result = callFrame->globalData().machine->execute(evalNode.get(), callFr
ame, thisObj, callFrame->registers() - registerFile->start() + argv + 1 + Regist
erFile::CallFrameHeaderSize, scopeChain, &exceptionValue); | 601 result = callFrame->globalData().machine->execute(evalNode.get(), callFr
ame, callFrame->thisValue()->toThisObject(callFrame), callFrame->registers() - r
egisterFile->start() + registerOffset, scopeChain, &exceptionValue); |
601 | 602 |
602 return result; | 603 return result; |
603 } | 604 } |
604 | 605 |
605 Machine::Machine() | 606 Machine::Machine() |
606 : m_sampler(0) | 607 : m_sampler(0) |
607 #if ENABLE(CTI) | 608 #if ENABLE(CTI) |
608 , m_ctiArrayLengthTrampoline(0) | 609 , m_ctiArrayLengthTrampoline(0) |
609 , m_ctiStringLengthTrampoline(0) | 610 , m_ctiStringLengthTrampoline(0) |
610 , m_jitCodeBuffer(new JITCodeBuffer(1024 * 1024)) | 611 , m_jitCodeBuffer(new JITCodeBuffer(1024 * 1024)) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 | 649 |
649 Machine::~Machine() | 650 Machine::~Machine() |
650 { | 651 { |
651 #if ENABLE(CTI) | 652 #if ENABLE(CTI) |
652 CTI::freeCTIMachineTrampolines(this); | 653 CTI::freeCTIMachineTrampolines(this); |
653 #endif | 654 #endif |
654 } | 655 } |
655 | 656 |
656 #ifndef NDEBUG | 657 #ifndef NDEBUG |
657 | 658 |
658 void Machine::dumpCallFrame(const RegisterFile* registerFile, CallFrame* callFra
me) | 659 void Machine::dumpCallFrame(CallFrame* callFrame) |
659 { | 660 { |
660 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); | 661 callFrame->codeBlock()->dump(callFrame); |
661 | 662 dumpRegisters(callFrame); |
662 CodeBlock* codeBlock = callFrame->codeBlock(); | |
663 codeBlock->dump(globalObject->globalExec()); | |
664 | |
665 dumpRegisters(registerFile, callFrame); | |
666 } | 663 } |
667 | 664 |
668 void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFra
me) | 665 void Machine::dumpRegisters(CallFrame* callFrame) |
669 { | 666 { |
670 printf("Register frame: \n\n"); | 667 printf("Register frame: \n\n"); |
671 printf("----------------------------------------------------\n"); | 668 printf("----------------------------------------------------\n"); |
672 printf(" use | address | value \n"); | 669 printf(" use | address | value \n"); |
673 printf("----------------------------------------------------\n"); | 670 printf("----------------------------------------------------\n"); |
674 | 671 |
675 CodeBlock* codeBlock = callFrame->codeBlock(); | 672 CodeBlock* codeBlock = callFrame->codeBlock(); |
| 673 RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globa
lData()->machine->registerFile(); |
676 const Register* it; | 674 const Register* it; |
677 const Register* end; | 675 const Register* end; |
678 | 676 |
679 if (codeBlock->codeType == GlobalCode) { | 677 if (codeBlock->codeType == GlobalCode) { |
680 it = registerFile->lastGlobal(); | 678 it = registerFile->lastGlobal(); |
681 end = it + registerFile->numGlobals(); | 679 end = it + registerFile->numGlobals(); |
682 while (it != end) { | 680 while (it != end) { |
683 printf("[global var] | %10p | %10p \n", it, (*it).v())
; | 681 printf("[global var] | %10p | %10p \n", it, (*it).v())
; |
684 ++it; | 682 ++it; |
685 } | 683 } |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1016 | 1014 |
1017 m_registerFile.shrink(oldEnd); | 1015 m_registerFile.shrink(oldEnd); |
1018 return result; | 1016 return result; |
1019 } | 1017 } |
1020 | 1018 |
1021 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* th
isObj, ScopeChainNode* scopeChain, JSValue** exception) | 1019 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* th
isObj, ScopeChainNode* scopeChain, JSValue** exception) |
1022 { | 1020 { |
1023 return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNod
e->byteCode(scopeChain).numParameters + RegisterFile::CallFrameHeaderSize, scope
Chain, exception); | 1021 return execute(evalNode, callFrame, thisObj, m_registerFile.size() + evalNod
e->byteCode(scopeChain).numParameters + RegisterFile::CallFrameHeaderSize, scope
Chain, exception); |
1024 } | 1022 } |
1025 | 1023 |
1026 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* th
isObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception) | 1024 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* th
isObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue** exception
) |
1027 { | 1025 { |
1028 ASSERT(!scopeChain->globalData->exception); | 1026 ASSERT(!scopeChain->globalData->exception); |
1029 | 1027 |
1030 if (m_reentryDepth >= MaxReentryDepth) { | 1028 if (m_reentryDepth >= MaxReentryDepth) { |
1031 *exception = createStackOverflowError(callFrame); | 1029 *exception = createStackOverflowError(callFrame); |
1032 return jsNull(); | 1030 return jsNull(); |
1033 } | 1031 } |
1034 | 1032 |
1035 DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData(
).dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain
->globalObject()); | 1033 DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData(
).dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain
->globalObject()); |
1036 | 1034 |
(...skipping 25 matching lines...) Expand all Loading... |
1062 const DeclarationStacks::FunctionStack& functionStack = codeBlock->owner
Node->functionStack(); | 1060 const DeclarationStacks::FunctionStack& functionStack = codeBlock->owner
Node->functionStack(); |
1063 DeclarationStacks::FunctionStack::const_iterator functionStackEnd = func
tionStack.end(); | 1061 DeclarationStacks::FunctionStack::const_iterator functionStackEnd = func
tionStack.end(); |
1064 for (DeclarationStacks::FunctionStack::const_iterator it = functionStack
.begin(); it != functionStackEnd; ++it) { | 1062 for (DeclarationStacks::FunctionStack::const_iterator it = functionStack
.begin(); it != functionStackEnd; ++it) { |
1065 PutPropertySlot slot; | 1063 PutPropertySlot slot; |
1066 variableObject->put(callFrame, (*it)->m_ident, (*it)->makeFunction(c
allFrame, scopeChain), slot); | 1064 variableObject->put(callFrame, (*it)->m_ident, (*it)->makeFunction(c
allFrame, scopeChain), slot); |
1067 } | 1065 } |
1068 | 1066 |
1069 } | 1067 } |
1070 | 1068 |
1071 Register* oldEnd = m_registerFile.end(); | 1069 Register* oldEnd = m_registerFile.end(); |
1072 Register* newEnd = m_registerFile.start() + registerOffset + codeBlock->numC
alleeRegisters; | 1070 Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock
->numCalleeRegisters; |
1073 if (!m_registerFile.grow(newEnd)) { | 1071 if (!m_registerFile.grow(newEnd)) { |
1074 *exception = createStackOverflowError(callFrame); | 1072 *exception = createStackOverflowError(callFrame); |
1075 return jsNull(); | 1073 return jsNull(); |
1076 } | 1074 } |
1077 | 1075 |
1078 CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + registe
rOffset); | 1076 CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalR
egisterOffset); |
1079 | 1077 |
1080 // a 0 codeBlock indicates a built-in caller | 1078 // a 0 codeBlock indicates a built-in caller |
1081 newCallFrame[codeBlock->thisRegister] = thisObj; | 1079 newCallFrame[codeBlock->thisRegister] = thisObj; |
1082 newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag
(), 0, 0, 0); | 1080 newCallFrame->init(codeBlock, 0, scopeChain, callFrame->addHostCallFrameFlag
(), 0, 0, 0); |
1083 | 1081 |
1084 if (codeBlock->needsFullScopeChain) | 1082 if (codeBlock->needsFullScopeChain) |
1085 scopeChain->ref(); | 1083 scopeChain->ref(); |
1086 | 1084 |
1087 Profiler** profiler = Profiler::enabledProfilerReference(); | 1085 Profiler** profiler = Profiler::enabledProfilerReference(); |
1088 if (*profiler) | 1086 if (*profiler) |
(...skipping 2168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3257 */ | 3255 */ |
3258 int dst = (++vPC)->u.operand; | 3256 int dst = (++vPC)->u.operand; |
3259 int func = (++vPC)->u.operand; | 3257 int func = (++vPC)->u.operand; |
3260 | 3258 |
3261 callFrame[dst] = callFrame->codeBlock()->functionExpressions[func]->make
Function(callFrame, callFrame->scopeChain()); | 3259 callFrame[dst] = callFrame->codeBlock()->functionExpressions[func]->make
Function(callFrame, callFrame->scopeChain()); |
3262 | 3260 |
3263 ++vPC; | 3261 ++vPC; |
3264 NEXT_OPCODE; | 3262 NEXT_OPCODE; |
3265 } | 3263 } |
3266 BEGIN_OPCODE(op_call_eval) { | 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 Call a function named "eval" with no explicit "this" value | 3267 Call a function named "eval" with no explicit "this" value |
3270 (which may therefore be the eval operator). If register | 3268 (which may therefore be the eval operator). If register |
3271 thisVal is the global object, and register func contains | 3269 thisVal is the global object, and register func contains |
3272 that global object's original global eval function, then | 3270 that global object's original global eval function, then |
3273 perform the eval operator in local scope (interpreting | 3271 perform the eval operator in local scope (interpreting |
3274 the argument registers as for the "call" | 3272 the argument registers as for the "call" |
3275 opcode). Otherwise, act exactly as the "call" opcode would. | 3273 opcode). Otherwise, act exactly as the "call" opcode would. |
3276 */ | 3274 */ |
3277 | 3275 |
3278 int dst = vPC[1].u.operand; | 3276 int dst = vPC[1].u.operand; |
3279 int func = vPC[2].u.operand; | 3277 int func = vPC[2].u.operand; |
3280 int thisVal = vPC[3].u.operand; | 3278 int argCount = vPC[3].u.operand; |
3281 int firstArg = vPC[4].u.operand; | 3279 int registerOffset = vPC[4].u.operand; |
3282 int argCount = vPC[5].u.operand; | |
3283 | 3280 |
3284 JSValue* funcVal = callFrame[func].jsValue(callFrame); | 3281 JSValue* funcVal = callFrame[func].jsValue(callFrame); |
3285 JSValue* baseVal = callFrame[thisVal].jsValue(callFrame); | |
3286 | 3282 |
3287 ScopeChainNode* scopeChain = callFrame->scopeChain(); | 3283 Register* newCallFrame = callFrame->registers() + registerOffset; |
3288 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->glob
alObject()->evalFunction()) { | 3284 Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argC
ount; |
3289 JSObject* thisObject = asObject(callFrame[callFrame->codeBlock()->th
isRegister].jsValue(callFrame)); | 3285 JSValue* thisValue = argv[0].jsValue(callFrame); |
3290 JSValue* result = callEval(callFrame, thisObject, scopeChain, regist
erFile, firstArg, argCount, exceptionValue); | 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 if (exceptionValue) | 3290 if (exceptionValue) |
3292 goto vm_throw; | 3291 goto vm_throw; |
3293 | |
3294 callFrame[dst] = result; | 3292 callFrame[dst] = result; |
3295 | 3293 |
3296 vPC += 7; | 3294 vPC += 5; |
3297 NEXT_OPCODE; | 3295 NEXT_OPCODE; |
3298 } | 3296 } |
3299 | 3297 |
3300 // We didn't find the blessed version of eval, so reset vPC and process | 3298 // We didn't find the blessed version of eval, so process this |
3301 // this instruction as a normal function call, supplying the proper 'thi
s' | 3299 // instruction as a normal function call. |
3302 // value. | |
3303 callFrame[thisVal] = baseVal->toThisObject(callFrame); | |
3304 | 3300 |
3305 #if HAVE(COMPUTED_GOTO) | 3301 #if HAVE(COMPUTED_GOTO) |
3306 // Hack around gcc performance quirk by performing an indirect goto | 3302 // Hack around gcc performance quirk by performing an indirect goto |
3307 // in order to set the vPC -- attempting to do so directly results in a | 3303 // in order to set the vPC -- attempting to do so directly results in a |
3308 // significant regression. | 3304 // significant regression. |
3309 goto *op_call_indirect; // indirect goto -> op_call | 3305 goto *op_call_indirect; // indirect goto -> op_call |
3310 #endif | 3306 #endif |
3311 // fall through to op_call | 3307 // fall through to op_call |
3312 } | 3308 } |
3313 BEGIN_OPCODE(op_call) { | 3309 BEGIN_OPCODE(op_call) { |
3314 /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n) registerOffset
(n) | 3310 /* call dst(r) func(r) argCount(n) registerOffset(n) |
3315 | 3311 |
3316 Perform a function call. Specifically, call register func | 3312 Perform a function call. |
3317 with a "this" value of register thisVal, and put the result | 3313 |
3318 in register dst. | 3314 registerOffset is the distance the callFrame pointer should move |
3319 | 3315 before the VM initializes the new call frame's header. |
3320 The arguments start at register firstArg and go up to | 3316 |
3321 argCount, but the "this" value is considered an implicit | 3317 dst is where op_ret should store its result. |
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. | |
3348 */ | 3318 */ |
3349 | 3319 |
3350 int dst = vPC[1].u.operand; | 3320 int dst = vPC[1].u.operand; |
3351 int func = vPC[2].u.operand; | 3321 int func = vPC[2].u.operand; |
3352 int thisVal = vPC[3].u.operand; | 3322 int argCount = vPC[3].u.operand; |
3353 int firstArg = vPC[4].u.operand; | 3323 int registerOffset = vPC[4].u.operand; |
3354 int argCount = vPC[5].u.operand; | |
3355 int registerOffset = vPC[6].u.operand; | |
3356 | 3324 |
3357 JSValue* v = callFrame[func].jsValue(callFrame); | 3325 JSValue* v = callFrame[func].jsValue(callFrame); |
3358 | 3326 |
3359 CallData callData; | 3327 CallData callData; |
3360 CallType callType = v->getCallData(callData); | 3328 CallType callType = v->getCallData(callData); |
3361 | 3329 |
3362 if (callType == CallTypeJS) { | 3330 if (callType == CallTypeJS) { |
3363 ScopeChainNode* callDataScopeChain = callData.js.scopeChain; | 3331 ScopeChainNode* callDataScopeChain = callData.js.scopeChain; |
3364 FunctionBodyNode* functionBodyNode = callData.js.functionBody; | 3332 FunctionBodyNode* functionBodyNode = callData.js.functionBody; |
3365 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeC
hain); | 3333 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeC
hain); |
3366 | 3334 |
3367 callFrame[firstArg] = thisVal == missingThisObjectMarker() ? callFra
me->globalThisValue() : callFrame[thisVal].jsValue(callFrame); | |
3368 | |
3369 CallFrame* previousCallFrame = callFrame; | 3335 CallFrame* previousCallFrame = callFrame; |
3370 | 3336 |
3371 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, c
allFrame, registerOffset, argCount); | 3337 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, c
allFrame, registerOffset, argCount); |
3372 if (UNLIKELY(!callFrame)) { | 3338 if (UNLIKELY(!callFrame)) { |
3373 callFrame = previousCallFrame; | 3339 callFrame = previousCallFrame; |
3374 exceptionValue = createStackOverflowError(callFrame); | 3340 exceptionValue = createStackOverflowError(callFrame); |
3375 goto vm_throw; | 3341 goto vm_throw; |
3376 } | 3342 } |
3377 | 3343 |
3378 callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousC
allFrame, dst, argCount, asFunction(v)); | 3344 callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousC
allFrame, dst, argCount, asFunction(v)); |
3379 vPC = newCodeBlock->instructions.begin(); | 3345 vPC = newCodeBlock->instructions.begin(); |
3380 | 3346 |
3381 #if ENABLE(OPCODE_STATS) | 3347 #if ENABLE(OPCODE_STATS) |
3382 OpcodeStats::resetLastInstruction(); | 3348 OpcodeStats::resetLastInstruction(); |
3383 #endif | 3349 #endif |
3384 | 3350 |
3385 NEXT_OPCODE; | 3351 NEXT_OPCODE; |
3386 } | 3352 } |
3387 | 3353 |
3388 if (callType == CallTypeHost) { | 3354 if (callType == CallTypeHost) { |
3389 JSValue* thisValue = thisVal == missingThisObjectMarker() ? callFram
e->globalThisValue() : callFrame[thisVal].jsValue(callFrame); | |
3390 ArgList args(callFrame->registers() + firstArg + 1, argCount - 1); | |
3391 | |
3392 ScopeChainNode* scopeChain = callFrame->scopeChain(); | 3355 ScopeChainNode* scopeChain = callFrame->scopeChain(); |
3393 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() +
registerOffset); | 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::C
allFrameHeaderSize - 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 JSValue* returnValue; | 3367 JSValue* returnValue; |
3397 { | 3368 { |
3398 SamplingTool::HostCallRecord callRecord(m_sampler); | 3369 SamplingTool::HostCallRecord callRecord(m_sampler); |
3399 returnValue = callData.native.function(newCallFrame, asObject(v)
, thisValue, args); | 3370 returnValue = callData.native.function(newCallFrame, asObject(v)
, thisValue, args); |
3400 } | 3371 } |
3401 VM_CHECK_EXCEPTION(); | 3372 VM_CHECK_EXCEPTION(); |
3402 | 3373 |
3403 callFrame[dst] = returnValue; | 3374 callFrame[dst] = returnValue; |
3404 | 3375 |
3405 vPC += 7; | 3376 vPC += 5; |
3406 NEXT_OPCODE; | 3377 NEXT_OPCODE; |
3407 } | 3378 } |
3408 | 3379 |
3409 ASSERT(callType == CallTypeNone); | 3380 ASSERT(callType == CallTypeNone); |
3410 | 3381 |
3411 exceptionValue = createNotAFunctionError(callFrame, v, vPC, callFrame->c
odeBlock()); | 3382 exceptionValue = createNotAFunctionError(callFrame, v, vPC, callFrame->c
odeBlock()); |
3412 goto vm_throw; | 3383 goto vm_throw; |
3413 } | 3384 } |
3414 BEGIN_OPCODE(op_tear_off_activation) { | 3385 BEGIN_OPCODE(op_tear_off_activation) { |
3415 /* tear_off_activation activation(r) | 3386 /* tear_off_activation activation(r) |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3565 */ | 3536 */ |
3566 | 3537 |
3567 Arguments* arguments = new (globalData) Arguments(callFrame); | 3538 Arguments* arguments = new (globalData) Arguments(callFrame); |
3568 callFrame->setCalleeArguments(arguments); | 3539 callFrame->setCalleeArguments(arguments); |
3569 callFrame[RegisterFile::ArgumentsRegister] = arguments; | 3540 callFrame[RegisterFile::ArgumentsRegister] = arguments; |
3570 | 3541 |
3571 ++vPC; | 3542 ++vPC; |
3572 NEXT_OPCODE; | 3543 NEXT_OPCODE; |
3573 } | 3544 } |
3574 BEGIN_OPCODE(op_construct) { | 3545 BEGIN_OPCODE(op_construct) { |
3575 /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n) reg
isterOffset(n) | 3546 /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisR
egister(r) |
3576 | 3547 |
3577 Invoke register "constr" as a constructor. For JS | 3548 Invoke register "func" as a constructor. For JS |
3578 functions, the calling convention is exactly as for the | 3549 functions, the calling convention is exactly as for the |
3579 "call" opcode, except that the "this" value is a newly | 3550 "call" opcode, except that the "this" value is a newly |
3580 created Object. For native constructors, a null "this" | 3551 created Object. For native constructors, no "this" |
3581 value is passed. In either case, the firstArg and argCount | 3552 value is passed. In either case, the argCount and registerOffset |
3582 registers are interpreted as for the "call" opcode. | 3553 registers are interpreted as for the "call" opcode. |
3583 | 3554 |
3584 Register constrProto must contain the prototype property of | 3555 Register proto must contain the prototype property of |
3585 register constsr. This is to enable polymorphic inline | 3556 register func. This is to enable polymorphic inline |
3586 caching of this lookup. | 3557 caching of this lookup. |
3587 */ | 3558 */ |
3588 | 3559 |
3589 int dst = vPC[1].u.operand; | 3560 int dst = vPC[1].u.operand; |
3590 int constr = vPC[2].u.operand; | 3561 int func = vPC[2].u.operand; |
3591 int constrProto = vPC[3].u.operand; | 3562 int argCount = vPC[3].u.operand; |
3592 int firstArg = vPC[4].u.operand; | 3563 int registerOffset = vPC[4].u.operand; |
3593 int argCount = vPC[5].u.operand; | 3564 int proto = vPC[5].u.operand; |
3594 int registerOffset = vPC[6].u.operand; | 3565 int thisRegister = vPC[6].u.operand; |
3595 | 3566 |
3596 JSValue* v = callFrame[constr].jsValue(callFrame); | 3567 JSValue* v = callFrame[func].jsValue(callFrame); |
3597 | 3568 |
3598 ConstructData constructData; | 3569 ConstructData constructData; |
3599 ConstructType constructType = v->getConstructData(constructData); | 3570 ConstructType constructType = v->getConstructData(constructData); |
3600 | 3571 |
3601 if (constructType == ConstructTypeJS) { | 3572 if (constructType == ConstructTypeJS) { |
3602 ScopeChainNode* callDataScopeChain = constructData.js.scopeChain; | 3573 ScopeChainNode* callDataScopeChain = constructData.js.scopeChain; |
3603 FunctionBodyNode* functionBodyNode = constructData.js.functionBody; | 3574 FunctionBodyNode* functionBodyNode = constructData.js.functionBody; |
3604 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeC
hain); | 3575 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeC
hain); |
3605 | 3576 |
3606 StructureID* structure; | 3577 StructureID* structure; |
3607 JSValue* prototype = callFrame[constrProto].jsValue(callFrame); | 3578 JSValue* prototype = callFrame[proto].jsValue(callFrame); |
3608 if (prototype->isObject()) | 3579 if (prototype->isObject()) |
3609 structure = asObject(prototype)->inheritorID(); | 3580 structure = asObject(prototype)->inheritorID(); |
3610 else | 3581 else |
3611 structure = callDataScopeChain->globalObject()->emptyObjectStruc
ture(); | 3582 structure = callDataScopeChain->globalObject()->emptyObjectStruc
ture(); |
3612 JSObject* newObject = new (globalData) JSObject(structure); | 3583 JSObject* newObject = new (globalData) JSObject(structure); |
3613 | 3584 |
3614 callFrame[firstArg] = newObject; // "this" value | 3585 callFrame[thisRegister] = newObject; // "this" value |
3615 | 3586 |
3616 CallFrame* previousCallFrame = callFrame; | 3587 CallFrame* previousCallFrame = callFrame; |
3617 | 3588 |
3618 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, c
allFrame, registerOffset, argCount); | 3589 callFrame = slideRegisterWindowForCall(newCodeBlock, registerFile, c
allFrame, registerOffset, argCount); |
3619 if (UNLIKELY(!callFrame)) { | 3590 if (UNLIKELY(!callFrame)) { |
3620 callFrame = previousCallFrame; | 3591 callFrame = previousCallFrame; |
3621 exceptionValue = createStackOverflowError(callFrame); | 3592 exceptionValue = createStackOverflowError(callFrame); |
3622 goto vm_throw; | 3593 goto vm_throw; |
3623 } | 3594 } |
3624 | 3595 |
3625 callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousC
allFrame, dst, argCount, asFunction(v)); | 3596 callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousC
allFrame, dst, argCount, asFunction(v)); |
3626 vPC = newCodeBlock->instructions.begin(); | 3597 vPC = newCodeBlock->instructions.begin(); |
3627 | 3598 |
3628 #if ENABLE(OPCODE_STATS) | 3599 #if ENABLE(OPCODE_STATS) |
3629 OpcodeStats::resetLastInstruction(); | 3600 OpcodeStats::resetLastInstruction(); |
3630 #endif | 3601 #endif |
3631 | 3602 |
3632 NEXT_OPCODE; | 3603 NEXT_OPCODE; |
3633 } | 3604 } |
3634 | 3605 |
3635 if (constructType == ConstructTypeHost) { | 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 ScopeChainNode* scopeChain = callFrame->scopeChain(); | 3609 ScopeChainNode* scopeChain = callFrame->scopeChain(); |
3639 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() +
registerOffset); | 3610 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() +
registerOffset); |
3640 newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount,
0); | 3611 newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount,
0); |
3641 | 3612 |
3642 JSValue* returnValue; | 3613 JSValue* returnValue; |
3643 { | 3614 { |
3644 SamplingTool::HostCallRecord callRecord(m_sampler); | 3615 SamplingTool::HostCallRecord callRecord(m_sampler); |
3645 returnValue = constructData.native.function(newCallFrame, asObje
ct(v), args); | 3616 returnValue = constructData.native.function(newCallFrame, asObje
ct(v), args); |
3646 } | 3617 } |
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4318 #define CTI_STACK_HACK() (void)0 | 4289 #define CTI_STACK_HACK() (void)0 |
4319 #define CTI_SET_RETURN_ADDRESS(address) ctiSetReturnAddress(&CTI_RETURN_ADDRESS_
SLOT, address); | 4290 #define CTI_SET_RETURN_ADDRESS(address) ctiSetReturnAddress(&CTI_RETURN_ADDRESS_
SLOT, address); |
4320 #define CTI_RETURN_ADDRESS CTI_RETURN_ADDRESS_SLOT | 4291 #define CTI_RETURN_ADDRESS CTI_RETURN_ADDRESS_SLOT |
4321 | 4292 |
4322 #endif | 4293 #endif |
4323 | 4294 |
4324 // The reason this is not inlined is to avoid having to do a PIC branch | 4295 // The reason this is not inlined is to avoid having to do a PIC branch |
4325 // to get the address of the ctiVMThrowTrampoline function. It's also | 4296 // to get the address of the ctiVMThrowTrampoline function. It's also |
4326 // good to keep the code size down by leaving as much of the exception | 4297 // good to keep the code size down by leaving as much of the exception |
4327 // handling code out of line as possible. | 4298 // handling code out of line as possible. |
4328 static NEVER_INLINE void setUpThrowTrampolineReturnAddress(JSGlobalData* globalD
ata, void*& returnAddress) | 4299 static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, void*
exceptionLocation, void*& returnAddressSlot) |
4329 { | 4300 { |
4330 ASSERT(globalData->exception); | 4301 ASSERT(globalData->exception); |
4331 globalData->throwReturnAddress = returnAddress; | 4302 globalData->exceptionLocation = exceptionLocation; |
4332 ctiSetReturnAddress(&returnAddress, reinterpret_cast<void*>(ctiVMThrowTrampo
line)); | 4303 ctiSetReturnAddress(&returnAddressSlot, reinterpret_cast<void*>(ctiVMThrowTr
ampoline)); |
| 4304 } |
| 4305 |
| 4306 static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD
ata* globalData, void* exceptionLocation, void*& returnAddressSlot) |
| 4307 { |
| 4308 globalData->exception = createStackOverflowError(callFrame); |
| 4309 returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot); |
4333 } | 4310 } |
4334 | 4311 |
4335 #define VM_THROW_EXCEPTION() \ | 4312 #define VM_THROW_EXCEPTION() \ |
4336 do { \ | 4313 do { \ |
4337 VM_THROW_EXCEPTION_AT_END(); \ | 4314 VM_THROW_EXCEPTION_AT_END(); \ |
4338 return 0; \ | 4315 return 0; \ |
4339 } while (0) | 4316 } while (0) |
4340 #define VM_THROW_EXCEPTION_2() \ | 4317 #define VM_THROW_EXCEPTION_2() \ |
4341 do { \ | 4318 do { \ |
4342 VM_THROW_EXCEPTION_AT_END(); \ | 4319 VM_THROW_EXCEPTION_AT_END(); \ |
4343 VoidPtrPairValue pair = {{ 0, 0 }}; \ | 4320 VoidPtrPairValue pair = {{ 0, 0 }}; \ |
4344 return pair.i; \ | 4321 return pair.i; \ |
4345 } while (0) | 4322 } while (0) |
4346 #define VM_THROW_EXCEPTION_AT_END() \ | 4323 #define VM_THROW_EXCEPTION_AT_END() \ |
4347 setUpThrowTrampolineReturnAddress(ARG_globalData, CTI_RETURN_ADDRESS) | 4324 returnToThrowTrampoline(ARG_globalData, CTI_RETURN_ADDRESS, CTI_RETURN_ADDRE
SS) |
4348 | 4325 |
4349 #define VM_CHECK_EXCEPTION() \ | 4326 #define VM_CHECK_EXCEPTION() \ |
4350 do { \ | 4327 do { \ |
4351 if (UNLIKELY(ARG_globalData->exception != noValue())) \ | 4328 if (UNLIKELY(ARG_globalData->exception != noValue())) \ |
4352 VM_THROW_EXCEPTION(); \ | 4329 VM_THROW_EXCEPTION(); \ |
4353 } while (0) | 4330 } while (0) |
4354 #define VM_CHECK_EXCEPTION_AT_END() \ | 4331 #define VM_CHECK_EXCEPTION_AT_END() \ |
4355 do { \ | 4332 do { \ |
4356 if (UNLIKELY(ARG_globalData->exception != noValue())) \ | 4333 if (UNLIKELY(ARG_globalData->exception != noValue())) \ |
4357 VM_THROW_EXCEPTION_AT_END(); \ | 4334 VM_THROW_EXCEPTION_AT_END(); \ |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4445 void Machine::cti_timeout_check(CTI_ARGS) | 4422 void Machine::cti_timeout_check(CTI_ARGS) |
4446 { | 4423 { |
4447 CTI_STACK_HACK(); | 4424 CTI_STACK_HACK(); |
4448 | 4425 |
4449 if (ARG_globalData->machine->checkTimeout(ARG_callFrame->dynamicGlobalObject
())) { | 4426 if (ARG_globalData->machine->checkTimeout(ARG_callFrame->dynamicGlobalObject
())) { |
4450 ARG_globalData->exception = createInterruptedExecutionException(ARG_glob
alData); | 4427 ARG_globalData->exception = createInterruptedExecutionException(ARG_glob
alData); |
4451 VM_THROW_EXCEPTION_AT_END(); | 4428 VM_THROW_EXCEPTION_AT_END(); |
4452 } | 4429 } |
4453 } | 4430 } |
4454 | 4431 |
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*>(ctiVMThrowTrampo
line)); | |
4460 } | |
4461 | |
4462 void Machine::cti_register_file_check(CTI_ARGS) | 4432 void Machine::cti_register_file_check(CTI_ARGS) |
4463 { | 4433 { |
4464 CTI_STACK_HACK(); | 4434 CTI_STACK_HACK(); |
4465 | 4435 |
4466 if (LIKELY(ARG_registerFile->grow(ARG_callFrame + ARG_callFrame->codeBlock()
->numCalleeRegisters))) | 4436 if (LIKELY(ARG_registerFile->grow(ARG_callFrame + ARG_callFrame->codeBlock()
->numCalleeRegisters))) |
4467 return; | 4437 return; |
4468 | 4438 |
4469 ARG_setCallFrame(ARG_callFrame->callerFrame()); | 4439 // Rewind to the previous call frame because op_call already optimistically |
4470 throwStackOverflowPreviousFrame(ARG_callFrame, ARG_globalData, CTI_RETURN_AD
DRESS); | 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); |
4471 } | 4444 } |
4472 | 4445 |
4473 int Machine::cti_op_loop_if_less(CTI_ARGS) | 4446 int Machine::cti_op_loop_if_less(CTI_ARGS) |
4474 { | 4447 { |
4475 CTI_STACK_HACK(); | 4448 CTI_STACK_HACK(); |
4476 | 4449 |
4477 JSValue* src1 = ARG_src1; | 4450 JSValue* src1 = ARG_src1; |
4478 JSValue* src2 = ARG_src2; | 4451 JSValue* src2 = ARG_src2; |
4479 CallFrame* callFrame = ARG_callFrame; | 4452 CallFrame* callFrame = ARG_callFrame; |
4480 | 4453 |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4737 for (size_t i = 0; i < numParameters; ++i) | 4710 for (size_t i = 0; i < numParameters; ++i) |
4738 argv[i + argCount] = argv[i]; | 4711 argv[i + argCount] = argv[i]; |
4739 | 4712 |
4740 callFrame = CallFrame::create(r); | 4713 callFrame = CallFrame::create(r); |
4741 callFrame->setCallerFrame(oldCallFrame); | 4714 callFrame->setCallerFrame(oldCallFrame); |
4742 } else { | 4715 } else { |
4743 size_t omittedArgCount = newCodeBlock->numParameters - argCount; | 4716 size_t omittedArgCount = newCodeBlock->numParameters - argCount; |
4744 Register* r = callFrame->registers() + omittedArgCount; | 4717 Register* r = callFrame->registers() + omittedArgCount; |
4745 Register* newEnd = r + newCodeBlock->numCalleeRegisters; | 4718 Register* newEnd = r + newCodeBlock->numCalleeRegisters; |
4746 if (!ARG_registerFile->grow(newEnd)) { | 4719 if (!ARG_registerFile->grow(newEnd)) { |
4747 ARG_globalData->exception = createStackOverflowError(oldCallFrame); | 4720 // Rewind to the previous call frame because op_call already optimis
tically |
4748 VM_THROW_EXCEPTION_2(); | 4721 // moved the call frame forward. |
| 4722 ARG_setCallFrame(oldCallFrame); |
| 4723 throwStackOverflowError(oldCallFrame, ARG_globalData, CTI_RETURN_ADD
RESS, CTI_RETURN_ADDRESS); |
| 4724 VoidPtrPairValue pair = {{ 0, 0 }}; |
| 4725 return pair.i; |
4749 } | 4726 } |
4750 | 4727 |
4751 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount
; | 4728 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount
; |
4752 for (size_t i = 0; i < omittedArgCount; ++i) | 4729 for (size_t i = 0; i < omittedArgCount; ++i) |
4753 argv[i] = jsUndefined(); | 4730 argv[i] = jsUndefined(); |
4754 | 4731 |
4755 callFrame = CallFrame::create(r); | 4732 callFrame = CallFrame::create(r); |
4756 callFrame->setCallerFrame(oldCallFrame); | 4733 callFrame->setCallerFrame(oldCallFrame); |
4757 } | 4734 } |
4758 | 4735 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4803 callFrame->init(0, ARG_instr4 + 1, previousCallFrame->scopeChain(), prev
iousCallFrame, 0, argCount, 0); | 4780 callFrame->init(0, ARG_instr4 + 1, previousCallFrame->scopeChain(), prev
iousCallFrame, 0, argCount, 0); |
4804 ARG_setCallFrame(callFrame); | 4781 ARG_setCallFrame(callFrame); |
4805 | 4782 |
4806 Register* argv = ARG_callFrame->registers() - RegisterFile::CallFrameHea
derSize - argCount; | 4783 Register* argv = ARG_callFrame->registers() - RegisterFile::CallFrameHea
derSize - argCount; |
4807 ArgList argList(argv + 1, argCount - 1); | 4784 ArgList argList(argv + 1, argCount - 1); |
4808 | 4785 |
4809 JSValue* returnValue; | 4786 JSValue* returnValue; |
4810 { | 4787 { |
4811 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); | 4788 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); |
4812 | 4789 |
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. |
4814 JSValue* thisValue = argv[0].jsValue(callFrame); | 4791 JSValue* thisValue = argv[0].jsValue(callFrame); |
4815 if (thisValue == jsNull()) | 4792 if (thisValue == jsNull()) |
4816 thisValue = callFrame->globalThisValue(); | 4793 thisValue = callFrame->globalThisValue(); |
4817 | 4794 |
4818 returnValue = callData.native.function(callFrame, asObject(funcVal),
thisValue, argList); | 4795 returnValue = callData.native.function(callFrame, asObject(funcVal),
thisValue, argList); |
4819 } | 4796 } |
4820 ARG_setCallFrame(previousCallFrame); | 4797 ARG_setCallFrame(previousCallFrame); |
4821 VM_CHECK_EXCEPTION(); | 4798 VM_CHECK_EXCEPTION(); |
4822 | 4799 |
4823 return returnValue; | 4800 return returnValue; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4927 JSObject* Machine::cti_op_construct_JSConstruct(CTI_ARGS) | 4904 JSObject* Machine::cti_op_construct_JSConstruct(CTI_ARGS) |
4928 { | 4905 { |
4929 CTI_STACK_HACK(); | 4906 CTI_STACK_HACK(); |
4930 | 4907 |
4931 #ifndef NDEBUG | 4908 #ifndef NDEBUG |
4932 ConstructData constructData; | 4909 ConstructData constructData; |
4933 ASSERT(asFunction(ARG_src1)->getConstructData(constructData) == ConstructTyp
eJS); | 4910 ASSERT(asFunction(ARG_src1)->getConstructData(constructData) == ConstructTyp
eJS); |
4934 #endif | 4911 #endif |
4935 | 4912 |
4936 StructureID* structure; | 4913 StructureID* structure; |
4937 if (ARG_src5->isObject()) | 4914 if (ARG_src4->isObject()) |
4938 structure = asObject(ARG_src5)->inheritorID(); | 4915 structure = asObject(ARG_src4)->inheritorID(); |
4939 else | 4916 else |
4940 structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->e
mptyObjectStructure(); | 4917 structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->e
mptyObjectStructure(); |
4941 return new (ARG_globalData) JSObject(structure); | 4918 return new (ARG_globalData) JSObject(structure); |
4942 } | 4919 } |
4943 | 4920 |
4944 JSValue* Machine::cti_op_construct_NotJSConstruct(CTI_ARGS) | 4921 JSValue* Machine::cti_op_construct_NotJSConstruct(CTI_ARGS) |
4945 { | 4922 { |
4946 CTI_STACK_HACK(); | 4923 CTI_STACK_HACK(); |
4947 | 4924 |
4948 CallFrame* callFrame = ARG_callFrame; | 4925 CallFrame* callFrame = ARG_callFrame; |
4949 | 4926 |
4950 JSValue* constrVal = ARG_src1; | 4927 JSValue* constrVal = ARG_src1; |
4951 int argCount = ARG_int3; | 4928 int argCount = ARG_int3; |
4952 int firstArg = ARG_int6; | 4929 int thisRegister = ARG_int5; |
4953 | 4930 |
4954 ConstructData constructData; | 4931 ConstructData constructData; |
4955 ConstructType constructType = constrVal->getConstructData(constructData); | 4932 ConstructType constructType = constrVal->getConstructData(constructData); |
4956 | 4933 |
4957 if (constructType == ConstructTypeHost) { | 4934 if (constructType == ConstructTypeHost) { |
4958 ArgList argList(callFrame->registers() + firstArg + 1, argCount - 1); | 4935 ArgList argList(callFrame->registers() + thisRegister + 1, argCount - 1)
; |
4959 | 4936 |
4960 JSValue* returnValue; | 4937 JSValue* returnValue; |
4961 { | 4938 { |
4962 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); | 4939 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); |
4963 returnValue = constructData.native.function(callFrame, asObject(cons
trVal), argList); | 4940 returnValue = constructData.native.function(callFrame, asObject(cons
trVal), argList); |
4964 } | 4941 } |
4965 VM_CHECK_EXCEPTION(); | 4942 VM_CHECK_EXCEPTION(); |
4966 | 4943 |
4967 return returnValue; | 4944 return returnValue; |
4968 } | 4945 } |
4969 | 4946 |
4970 ASSERT(constructType == ConstructTypeNone); | 4947 ASSERT(constructType == ConstructTypeNone); |
4971 | 4948 |
4972 ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal,
ARG_instr4, callFrame->codeBlock()); | 4949 ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal,
ARG_instr6, callFrame->codeBlock()); |
4973 VM_THROW_EXCEPTION(); | 4950 VM_THROW_EXCEPTION(); |
4974 } | 4951 } |
4975 | 4952 |
4976 JSValue* Machine::cti_op_get_by_val(CTI_ARGS) | 4953 JSValue* Machine::cti_op_get_by_val(CTI_ARGS) |
4977 { | 4954 { |
4978 CTI_STACK_HACK(); | 4955 CTI_STACK_HACK(); |
4979 | 4956 |
4980 CallFrame* callFrame = ARG_callFrame; | 4957 CallFrame* callFrame = ARG_callFrame; |
4981 Machine* machine = ARG_globalData->machine; | 4958 Machine* machine = ARG_globalData->machine; |
4982 | 4959 |
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5561 VM_CHECK_EXCEPTION_AT_END(); | 5538 VM_CHECK_EXCEPTION_AT_END(); |
5562 return result; | 5539 return result; |
5563 } | 5540 } |
5564 | 5541 |
5565 JSValue* Machine::cti_op_call_eval(CTI_ARGS) | 5542 JSValue* Machine::cti_op_call_eval(CTI_ARGS) |
5566 { | 5543 { |
5567 CTI_STACK_HACK(); | 5544 CTI_STACK_HACK(); |
5568 | 5545 |
5569 CallFrame* callFrame = ARG_callFrame; | 5546 CallFrame* callFrame = ARG_callFrame; |
5570 RegisterFile* registerFile = ARG_registerFile; | 5547 RegisterFile* registerFile = ARG_registerFile; |
5571 CodeBlock* codeBlock = callFrame->codeBlock(); | |
5572 ScopeChainNode* scopeChain = callFrame->scopeChain(); | |
5573 | 5548 |
5574 Machine* machine = ARG_globalData->machine; | 5549 Machine* machine = ARG_globalData->machine; |
5575 | 5550 |
5576 JSValue* funcVal = ARG_src1; | 5551 JSValue* funcVal = ARG_src1; |
5577 int registerOffset = ARG_int2; | 5552 int registerOffset = ARG_int2; |
5578 int argCount = ARG_int3; | 5553 int argCount = ARG_int3; |
5579 JSValue* baseVal = ARG_src5; | |
5580 | 5554 |
5581 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalOb
ject()->evalFunction()) { | 5555 Register* newCallFrame = callFrame->registers() + registerOffset; |
5582 JSObject* thisObject = callFrame[codeBlock->thisRegister].jsValue(callFr
ame)->toThisObject(callFrame); | 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()) { |
5583 JSValue* exceptionValue = noValue(); | 5561 JSValue* exceptionValue = noValue(); |
5584 JSValue* result = machine->callEval(callFrame, thisObject, scopeChain, r
egisterFile, registerOffset - RegisterFile::CallFrameHeaderSize - argCount, argC
ount, exceptionValue); | 5562 JSValue* result = machine->callEval(callFrame, registerFile, argv, argCo
unt, registerOffset, exceptionValue); |
5585 if (UNLIKELY(exceptionValue != noValue())) { | 5563 if (UNLIKELY(exceptionValue != noValue())) { |
5586 ARG_globalData->exception = exceptionValue; | 5564 ARG_globalData->exception = exceptionValue; |
5587 VM_THROW_EXCEPTION_AT_END(); | 5565 VM_THROW_EXCEPTION_AT_END(); |
5588 } | 5566 } |
5589 return result; | 5567 return result; |
5590 } | 5568 } |
5591 | 5569 |
5592 return JSImmediate::impossibleValue(); | 5570 return JSImmediate::impossibleValue(); |
5593 } | 5571 } |
5594 | 5572 |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5937 | 5915 |
5938 ARG_globalData->machine->debug(callFrame, static_cast<DebugHookID>(debugHook
ID), firstLine, lastLine); | 5916 ARG_globalData->machine->debug(callFrame, static_cast<DebugHookID>(debugHook
ID), firstLine, lastLine); |
5939 } | 5917 } |
5940 | 5918 |
5941 JSValue* Machine::cti_vm_throw(CTI_ARGS) | 5919 JSValue* Machine::cti_vm_throw(CTI_ARGS) |
5942 { | 5920 { |
5943 CTI_STACK_HACK(); | 5921 CTI_STACK_HACK(); |
5944 | 5922 |
5945 CallFrame* callFrame = ARG_callFrame; | 5923 CallFrame* callFrame = ARG_callFrame; |
5946 CodeBlock* codeBlock = callFrame->codeBlock(); | 5924 CodeBlock* codeBlock = callFrame->codeBlock(); |
| 5925 JSGlobalData* globalData = ARG_globalData; |
5947 | 5926 |
5948 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(ARG_globalData->throwRetur
nAddress)); | 5927 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(globalData->exceptionLocat
ion)); |
5949 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(ARG_globalData->th
rowReturnAddress); | 5928 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(globalData->except
ionLocation); |
5950 | 5929 |
5951 JSValue* exceptionValue = ARG_globalData->exception; | 5930 JSValue* exceptionValue = globalData->exception; |
5952 ASSERT(exceptionValue); | 5931 ASSERT(exceptionValue); |
5953 ARG_globalData->exception = noValue(); | 5932 globalData->exception = noValue(); |
5954 | 5933 |
5955 Instruction* handlerVPC = ARG_globalData->machine->throwException(callFrame,
exceptionValue, codeBlock->instructions.begin() + vPCIndex, false); | 5934 Instruction* handlerVPC = globalData->machine->throwException(callFrame, exc
eptionValue, codeBlock->instructions.begin() + vPCIndex, false); |
5956 | 5935 |
5957 if (!handlerVPC) { | 5936 if (!handlerVPC) { |
5958 *ARG_exception = exceptionValue; | 5937 *ARG_exception = exceptionValue; |
5959 return JSImmediate::nullImmediate(); | 5938 return JSImmediate::nullImmediate(); |
5960 } | 5939 } |
5961 | 5940 |
5962 ARG_setCallFrame(callFrame); | 5941 ARG_setCallFrame(callFrame); |
5963 void* catchRoutine = callFrame->codeBlock()->nativeExceptionCodeForHandlerVP
C(handlerVPC); | 5942 void* catchRoutine = callFrame->codeBlock()->nativeExceptionCodeForHandlerVP
C(handlerVPC); |
5964 ASSERT(catchRoutine); | 5943 ASSERT(catchRoutine); |
5965 CTI_SET_RETURN_ADDRESS(catchRoutine); | 5944 CTI_SET_RETURN_ADDRESS(catchRoutine); |
5966 return exceptionValue; | 5945 return exceptionValue; |
5967 } | 5946 } |
5968 | 5947 |
5969 #undef CTI_RETURN_ADDRESS | 5948 #undef CTI_RETURN_ADDRESS |
5970 #undef CTI_SET_RETURN_ADDRESS | 5949 #undef CTI_SET_RETURN_ADDRESS |
5971 #undef CTI_STACK_HACK | 5950 #undef CTI_STACK_HACK |
5972 #undef VM_CHECK_EXCEPTION | 5951 #undef VM_CHECK_EXCEPTION |
5973 #undef VM_CHECK_EXCEPTION_AT_END | 5952 #undef VM_CHECK_EXCEPTION_AT_END |
5974 #undef VM_CHECK_EXCEPTION_VOID | 5953 #undef VM_CHECK_EXCEPTION_VOID |
5975 #undef VM_THROW_EXCEPTION | 5954 #undef VM_THROW_EXCEPTION |
5976 #undef VM_THROW_EXCEPTION_2 | 5955 #undef VM_THROW_EXCEPTION_2 |
5977 #undef VM_THROW_EXCEPTION_AT_END | 5956 #undef VM_THROW_EXCEPTION_AT_END |
5978 | 5957 |
5979 #endif // ENABLE(CTI) | 5958 #endif // ENABLE(CTI) |
5980 | 5959 |
5981 } // namespace JSC | 5960 } // namespace JSC |
OLD | NEW |