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