Changeset 38330 in webkit for trunk/JavaScriptCore
- Timestamp:
- Nov 12, 2008, 1:34:22 AM (17 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r38322 r38330 1 2008-11-12 Cameron Zwarich <[email protected]> 2 3 Rubber-stamped by Mark Rowe. 4 5 Roll out r38322 due to test failures on the bots. 6 7 * VM/CTI.cpp: 8 (JSC::CTI::compileOpCallSetupArgs): 9 (JSC::CTI::compileOpCall): 10 (JSC::CTI::privateCompileMainPass): 11 (JSC::CTI::privateCompileSlowCases): 12 * VM/CTI.h: 13 * VM/CodeBlock.cpp: 14 (JSC::CodeBlock::dump): 15 * VM/Machine.cpp: 16 (JSC::Machine::callEval): 17 (JSC::Machine::dumpCallFrame): 18 (JSC::Machine::dumpRegisters): 19 (JSC::Machine::execute): 20 (JSC::Machine::privateExecute): 21 (JSC::Machine::throwStackOverflowPreviousFrame): 22 (JSC::Machine::cti_register_file_check): 23 (JSC::Machine::cti_op_call_arityCheck): 24 (JSC::Machine::cti_op_call_NotJSFunction): 25 (JSC::Machine::cti_op_construct_JSConstruct): 26 (JSC::Machine::cti_op_construct_NotJSConstruct): 27 (JSC::Machine::cti_op_call_eval): 28 (JSC::Machine::cti_vm_throw): 29 * VM/Machine.h: 30 * bytecompiler/CodeGenerator.cpp: 31 (JSC::CodeGenerator::emitCall): 32 (JSC::CodeGenerator::emitCallEval): 33 (JSC::CodeGenerator::emitConstruct): 34 * bytecompiler/CodeGenerator.h: 35 * parser/Nodes.cpp: 36 (JSC::EvalFunctionCallNode::emitCode): 37 (JSC::FunctionCallValueNode::emitCode): 38 (JSC::FunctionCallResolveNode::emitCode): 39 (JSC::FunctionCallBracketNode::emitCode): 40 (JSC::FunctionCallDotNode::emitCode): 41 * parser/Nodes.h: 42 (JSC::ScopeNode::neededConstants): 43 1 44 2008-11-11 Geoffrey Garen <[email protected]> 2 45 -
trunk/JavaScriptCore/VM/CTI.cpp
r38322 r38330 588 588 } 589 589 590 void CTI::compileOpCallSetupArgs(Instruction* instruction )591 { 592 int argCount = instruction[3].u.operand;593 int registerOffset = instruction[4].u.operand;594 595 // ecx holds func 590 void CTI::compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval) 591 { 592 int firstArg = instruction[4].u.operand; 593 int argCount = instruction[5].u.operand; 594 int registerOffset = instruction[6].u.operand; 595 596 596 emitPutArg(X86::ecx, 0); 597 597 emitPutArgConstant(registerOffset, 4); 598 598 emitPutArgConstant(argCount, 8); 599 599 emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12); 600 } 601 602 void CTI::compileOpCallEvalSetupArgs(Instruction* instruction) 603 { 604 int argCount = instruction[3].u.operand; 605 int registerOffset = instruction[4].u.operand; 606 607 // ecx holds func 608 emitPutArg(X86::ecx, 0); 609 emitPutArgConstant(registerOffset, 4); 610 emitPutArgConstant(argCount, 8); 611 emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 12); 612 } 613 614 void CTI::compileOpConstructSetupArgs(Instruction* instruction) 615 { 616 int argCount = instruction[3].u.operand; 617 int registerOffset = instruction[4].u.operand; 618 int proto = instruction[5].u.operand; 619 int thisRegister = instruction[6].u.operand; 620 621 // ecx holds func 622 emitPutArg(X86::ecx, 0); 623 emitPutArgConstant(registerOffset, 4); 624 emitPutArgConstant(argCount, 8); 625 emitGetPutArg(proto, 12, X86::eax); 626 emitPutArgConstant(thisRegister, 16); 627 emitPutArgConstant(reinterpret_cast<unsigned>(instruction), 20); 600 if (isConstruct) { 601 emitGetPutArg(instruction[3].u.operand, 16, X86::eax); 602 emitPutArgConstant(firstArg, 20); 603 } else if (isEval) 604 emitGetPutArg(instruction[3].u.operand, 16, X86::eax); 628 605 } 629 606 … … 632 609 int dst = instruction[1].u.operand; 633 610 int callee = instruction[2].u.operand; 634 int argCount = instruction[3].u.operand; 635 int registerOffset = instruction[4].u.operand; 611 int firstArg = instruction[4].u.operand; 612 int argCount = instruction[5].u.operand; 613 int registerOffset = instruction[6].u.operand; 614 615 // Setup this value as the first argument (does not apply to constructors) 616 if (opcodeID != op_construct) { 617 int thisVal = instruction[3].u.operand; 618 if (thisVal == missingThisObjectMarker()) 619 m_jit.movl_i32m(asInteger(jsNull()), firstArg * sizeof(Register), X86::edi); 620 else { 621 emitGetArg(thisVal, X86::eax); 622 emitPutResult(firstArg); 623 } 624 } 636 625 637 626 // Handle eval … … 639 628 if (opcodeID == op_call_eval) { 640 629 emitGetArg(callee, X86::ecx); 641 compileOpCall EvalSetupArgs(instruction);630 compileOpCallSetupArgs(instruction, false, true); 642 631 643 632 emitCTICall(instruction, i, Machine::cti_op_call_eval); … … 659 648 // In the case of OpConstruct, call out to a cti_ function to create the new object. 660 649 if (opcodeID == op_construct) { 661 int proto = instruction[5].u.operand;662 int thisRegister = instruction[6].u.operand;663 664 650 emitPutArg(X86::ecx, 0); 665 emitGetPutArg( proto, 12, X86::eax);651 emitGetPutArg(instruction[3].u.operand, 16, X86::eax); 666 652 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); 667 emitPutResult( thisRegister);653 emitPutResult(firstArg); 668 654 emitGetArg(callee, X86::ecx); 669 655 } … … 1300 1286 break; 1301 1287 } 1302 case op_call: 1303 case op_call_eval: 1304 case op_construct: { 1288 case op_call: { 1305 1289 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); 1306 i += (opcodeID == op_construct ? 7 : 5);1290 i += 7; 1307 1291 break; 1308 1292 } … … 1396 1380 emitPutResult(instruction[i + 1].u.operand); 1397 1381 i += 3; 1382 break; 1383 } 1384 case op_construct: { 1385 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); 1386 i += 7; 1398 1387 break; 1399 1388 } … … 1923 1912 emitPutResult(instruction[i + 1].u.operand); 1924 1913 i += 5; 1914 break; 1915 } 1916 case op_call_eval: { 1917 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); 1918 i += 7; 1925 1919 break; 1926 1920 } … … 2774 2768 int dst = instruction[i + 1].u.operand; 2775 2769 int callee = instruction[i + 2].u.operand; 2776 int argCount = instruction[i + 3].u.operand; 2777 int registerOffset = instruction[i + 4].u.operand; 2770 int firstArg = instruction[i + 4].u.operand; 2771 int argCount = instruction[i + 5].u.operand; 2772 int registerOffset = instruction[i + 6].u.operand; 2778 2773 2779 2774 m_jit.link(iter->from, m_jit.label()); 2780 2775 2781 2776 // The arguments have been set up on the hot path for op_call_eval 2782 if (opcodeID == op_call) 2783 compileOpCallSetupArgs(instruction + i); 2784 else if (opcodeID == op_construct) 2785 compileOpConstructSetupArgs(instruction + i); 2777 if (opcodeID != op_call_eval) 2778 compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false); 2786 2779 2787 2780 // Fast check for JS function. … … 2791 2784 X86Assembler::JmpSrc callLinkFailNotJSFunction = m_jit.emitUnlinkedJne(); 2792 2785 2793 // First, in the ca se of a construct, allocate the new object.2786 // First, in the cale of a construct, allocate the new object. 2794 2787 if (opcodeID == op_construct) { 2795 2788 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); 2796 emitPutResult( registerOffset - RegisterFile::CallFrameHeaderSize - argCount);2789 emitPutResult(firstArg); 2797 2790 emitGetArg(callee, X86::ecx); 2798 2791 } … … 2835 2828 2836 2829 // The arguments have been set up on the hot path for op_call_eval 2837 if (opcodeID == op_call) 2838 compileOpCallSetupArgs(instruction + i); 2839 else if (opcodeID == op_construct) 2840 compileOpConstructSetupArgs(instruction + i); 2830 if (opcodeID != op_call_eval) 2831 compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false); 2841 2832 2842 2833 // Check for JSFunctions. … … 2857 2848 m_jit.link(isJSFunction, m_jit.label()); 2858 2849 2859 // First, in the ca se of a construct, allocate the new object.2850 // First, in the cale of a construct, allocate the new object. 2860 2851 if (opcodeID == op_construct) { 2861 2852 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); 2862 emitPutResult( registerOffset - RegisterFile::CallFrameHeaderSize - argCount);2853 emitPutResult(firstArg); 2863 2854 emitGetArg(callee, X86::ecx); 2864 2855 } … … 2905 2896 ++callLinkInfoIndex; 2906 2897 2907 i += (opcodeID == op_construct ? 7 : 5);2898 i += 7; 2908 2899 break; 2909 2900 } -
trunk/JavaScriptCore/VM/CTI.h
r38322 r38330 366 366 void compileOpCall(OpcodeID, Instruction* instruction, unsigned i, unsigned callLinkInfoIndex); 367 367 void compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount); 368 void compileOpCallSetupArgs(Instruction*); 369 void compileOpCallEvalSetupArgs(Instruction*); 370 void compileOpConstructSetupArgs(Instruction*); 368 void compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval); 371 369 enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq }; 372 370 void compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type); -
trunk/JavaScriptCore/VM/CodeBlock.cpp
r38322 r38330 813 813 } 814 814 case op_call: { 815 int dst = (++it)->u.operand; 816 int func = (++it)->u.operand; 815 int r0 = (++it)->u.operand; 816 int r1 = (++it)->u.operand; 817 int r2 = (++it)->u.operand; 818 int tempCount = (++it)->u.operand; 817 819 int argCount = (++it)->u.operand; 818 820 int registerOffset = (++it)->u.operand; 819 printf("[%4d] call\t\t %s, %s, % d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);821 printf("[%4d] call\t\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset); 820 822 break; 821 823 } 822 824 case op_call_eval: { 823 int dst = (++it)->u.operand; 824 int func = (++it)->u.operand; 825 int r0 = (++it)->u.operand; 826 int r1 = (++it)->u.operand; 827 int r2 = (++it)->u.operand; 828 int tempCount = (++it)->u.operand; 825 829 int argCount = (++it)->u.operand; 826 830 int registerOffset = (++it)->u.operand; 827 printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset);831 printf("[%4d] call_eval\t\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset); 828 832 break; 829 833 } … … 843 847 } 844 848 case op_construct: { 845 int dst = (++it)->u.operand; 846 int func = (++it)->u.operand; 849 int r0 = (++it)->u.operand; 850 int r1 = (++it)->u.operand; 851 int r2 = (++it)->u.operand; 852 int tempCount = (++it)->u.operand; 847 853 int argCount = (++it)->u.operand; 848 854 int registerOffset = (++it)->u.operand; 849 int proto = (++it)->u.operand; 850 int thisRegister = (++it)->u.operand; 851 printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str()); 855 printf("[%4d] construct\t %s, %s, %s, %d, %d, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), tempCount, argCount, registerOffset); 852 856 break; 853 857 } -
trunk/JavaScriptCore/VM/Machine.cpp
r38322 r38330 581 581 } 582 582 583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue*& exceptionValue)583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, int argv, int argc, JSValue*& exceptionValue) 584 584 { 585 585 if (argc < 2) 586 586 return jsUndefined(); 587 587 588 JSValue* program = argv[1].jsValue(callFrame);588 JSValue* program = callFrame[argv + 1].jsValue(callFrame); 589 589 590 590 if (!program->isString()) … … 593 593 UString programSource = asString(program)->value(); 594 594 595 ScopeChainNode* scopeChain = callFrame->scopeChain();596 595 CodeBlock* codeBlock = callFrame->codeBlock(); 597 596 RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache.get(callFrame, programSource, scopeChain, exceptionValue); … … 599 598 JSValue* result = jsUndefined(); 600 599 if (evalNode) 601 result = callFrame->globalData().machine->execute(evalNode.get(), callFrame, callFrame->thisValue()->toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue);600 result = callFrame->globalData().machine->execute(evalNode.get(), callFrame, thisObj, callFrame->registers() - registerFile->start() + argv + 1 + RegisterFile::CallFrameHeaderSize, scopeChain, &exceptionValue); 602 601 603 602 return result; … … 657 656 #ifndef NDEBUG 658 657 659 void Machine::dumpCallFrame(CallFrame* callFrame) 660 { 661 callFrame->codeBlock()->dump(callFrame); 662 dumpRegisters(callFrame); 663 } 664 665 void Machine::dumpRegisters(CallFrame* callFrame) 658 void Machine::dumpCallFrame(const RegisterFile* registerFile, CallFrame* callFrame) 659 { 660 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); 661 662 CodeBlock* codeBlock = callFrame->codeBlock(); 663 codeBlock->dump(globalObject->globalExec()); 664 665 dumpRegisters(registerFile, callFrame); 666 } 667 668 void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFrame) 666 669 { 667 670 printf("Register frame: \n\n"); … … 671 674 672 675 CodeBlock* codeBlock = callFrame->codeBlock(); 673 RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->machine->registerFile();674 676 const Register* it; 675 677 const Register* end; … … 1022 1024 } 1023 1025 1024 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue** exception)1026 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception) 1025 1027 { 1026 1028 ASSERT(!scopeChain->globalData->exception); … … 1068 1070 1069 1071 Register* oldEnd = m_registerFile.end(); 1070 Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->numCalleeRegisters;1072 Register* newEnd = m_registerFile.start() + registerOffset + codeBlock->numCalleeRegisters; 1071 1073 if (!m_registerFile.grow(newEnd)) { 1072 1074 *exception = createStackOverflowError(callFrame); … … 1074 1076 } 1075 1077 1076 CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset);1078 CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + registerOffset); 1077 1079 1078 1080 // a 0 codeBlock indicates a built-in caller … … 3263 3265 } 3264 3266 BEGIN_OPCODE(op_call_eval) { 3265 /* call_eval dst(r) func(r) argCount(n) registerOffset(n)3267 /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n) 3266 3268 3267 3269 Call a function named "eval" with no explicit "this" value … … 3276 3278 int dst = vPC[1].u.operand; 3277 3279 int func = vPC[2].u.operand; 3278 int argCount = vPC[3].u.operand; 3279 int registerOffset = vPC[4].u.operand; 3280 int thisVal = vPC[3].u.operand; 3281 int firstArg = vPC[4].u.operand; 3282 int argCount = vPC[5].u.operand; 3280 3283 3281 3284 JSValue* funcVal = callFrame[func].jsValue(callFrame); 3282 3283 Register* newCallFrame = callFrame->registers() + registerOffset; 3284 Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; 3285 JSValue* thisValue = argv[0].jsValue(callFrame); 3286 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); 3287 3288 if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { 3289 JSValue* result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); 3285 JSValue* baseVal = callFrame[thisVal].jsValue(callFrame); 3286 3287 ScopeChainNode* scopeChain = callFrame->scopeChain(); 3288 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) { 3289 JSObject* thisObject = asObject(callFrame[callFrame->codeBlock()->thisRegister].jsValue(callFrame)); 3290 JSValue* result = callEval(callFrame, thisObject, scopeChain, registerFile, firstArg, argCount, exceptionValue); 3290 3291 if (exceptionValue) 3291 3292 goto vm_throw; 3293 3292 3294 callFrame[dst] = result; 3293 3295 3294 vPC += 5;3296 vPC += 7; 3295 3297 NEXT_OPCODE; 3296 3298 } 3297 3299 3298 // We didn't find the blessed version of eval, so process this 3299 // instruction as a normal function call. 3300 // We didn't find the blessed version of eval, so reset vPC and process 3301 // this instruction as a normal function call, supplying the proper 'this' 3302 // value. 3303 callFrame[thisVal] = baseVal->toThisObject(callFrame); 3300 3304 3301 3305 #if HAVE(COMPUTED_GOTO) … … 3308 3312 } 3309 3313 BEGIN_OPCODE(op_call) { 3310 /* call dst(r) func(r) argCount(n) registerOffset(n) 3311 3312 Perform a function call. 3313 3314 registerOffset is the distance the callFrame pointer should move 3315 before the VM initializes the new call frame's header. 3316 3317 dst is where op_ret should store its result. 3314 /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n) registerOffset(n) 3315 3316 Perform a function call. Specifically, call register func 3317 with a "this" value of register thisVal, and put the result 3318 in register dst. 3319 3320 The arguments start at register firstArg and go up to 3321 argCount, but the "this" value is considered an implicit 3322 first argument, so the argCount should be one greater than 3323 the number of explicit arguments passed, and the register 3324 after firstArg should contain the actual first 3325 argument. This opcode will copy from the thisVal register 3326 to the firstArg register, unless the register index of 3327 thisVal is the special missing this object marker, which is 3328 2^31-1; in that case, the global object will be used as the 3329 "this" value. 3330 3331 If func is a native code function, then this opcode calls 3332 it and returns the value immediately. 3333 3334 But if it is a JS function, then the current scope chain 3335 and code block is set to the function's, and we slide the 3336 register window so that the arguments would form the first 3337 few local registers of the called function's register 3338 window. In addition, a call frame header is written 3339 immediately before the arguments; see the call frame 3340 documentation for an explanation of how many registers a 3341 call frame takes and what they contain. That many registers 3342 before the firstArg register will be overwritten by the 3343 call. In addition, any registers higher than firstArg + 3344 argCount may be overwritten. Once this setup is complete, 3345 execution continues from the called function's first 3346 argument, and does not return until a "ret" opcode is 3347 encountered. 3318 3348 */ 3319 3349 3320 3350 int dst = vPC[1].u.operand; 3321 3351 int func = vPC[2].u.operand; 3322 int argCount = vPC[3].u.operand; 3323 int registerOffset = vPC[4].u.operand; 3352 int thisVal = vPC[3].u.operand; 3353 int firstArg = vPC[4].u.operand; 3354 int argCount = vPC[5].u.operand; 3355 int registerOffset = vPC[6].u.operand; 3324 3356 3325 3357 JSValue* v = callFrame[func].jsValue(callFrame); … … 3333 3365 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain); 3334 3366 3367 callFrame[firstArg] = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame); 3368 3335 3369 CallFrame* previousCallFrame = callFrame; 3336 3370 … … 3342 3376 } 3343 3377 3344 callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));3378 callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v)); 3345 3379 vPC = newCodeBlock->instructions.begin(); 3346 3380 … … 3353 3387 3354 3388 if (callType == CallTypeHost) { 3389 JSValue* thisValue = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame); 3390 ArgList args(callFrame->registers() + firstArg + 1, argCount - 1); 3391 3355 3392 ScopeChainNode* scopeChain = callFrame->scopeChain(); 3356 3393 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); 3357 newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0); 3358 3359 Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; 3360 ArgList args(thisRegister + 1, argCount - 1); 3361 3362 // FIXME: All host methods should be calling toThisObject, but this is not presently the case. 3363 JSValue* thisValue = thisRegister->jsValue(callFrame); 3364 if (thisValue == jsNull()) 3365 thisValue = callFrame->globalThisValue(); 3394 newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0); 3366 3395 3367 3396 JSValue* returnValue; … … 3374 3403 callFrame[dst] = returnValue; 3375 3404 3376 vPC += 5;3405 vPC += 7; 3377 3406 NEXT_OPCODE; 3378 3407 } … … 3544 3573 } 3545 3574 BEGIN_OPCODE(op_construct) { 3546 /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r)3547 3548 Invoke register " func" as a constructor. For JS3575 /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n) registerOffset(n) 3576 3577 Invoke register "constr" as a constructor. For JS 3549 3578 functions, the calling convention is exactly as for the 3550 3579 "call" opcode, except that the "this" value is a newly 3551 created Object. For native constructors, no"this"3552 value is passed. In either case, the argCount and registerOffset3580 created Object. For native constructors, a null "this" 3581 value is passed. In either case, the firstArg and argCount 3553 3582 registers are interpreted as for the "call" opcode. 3554 3583 3555 Register proto must contain the prototype property of3556 register func. This is to enable polymorphic inline3584 Register constrProto must contain the prototype property of 3585 register constsr. This is to enable polymorphic inline 3557 3586 caching of this lookup. 3558 3587 */ 3559 3588 3560 3589 int dst = vPC[1].u.operand; 3561 int func= vPC[2].u.operand;3562 int argCount= vPC[3].u.operand;3563 int registerOffset= vPC[4].u.operand;3564 int proto= vPC[5].u.operand;3565 int thisRegister= vPC[6].u.operand;3566 3567 JSValue* v = callFrame[ func].jsValue(callFrame);3590 int constr = vPC[2].u.operand; 3591 int constrProto = vPC[3].u.operand; 3592 int firstArg = vPC[4].u.operand; 3593 int argCount = vPC[5].u.operand; 3594 int registerOffset = vPC[6].u.operand; 3595 3596 JSValue* v = callFrame[constr].jsValue(callFrame); 3568 3597 3569 3598 ConstructData constructData; … … 3576 3605 3577 3606 StructureID* structure; 3578 JSValue* prototype = callFrame[ proto].jsValue(callFrame);3607 JSValue* prototype = callFrame[constrProto].jsValue(callFrame); 3579 3608 if (prototype->isObject()) 3580 3609 structure = asObject(prototype)->inheritorID(); … … 3583 3612 JSObject* newObject = new (globalData) JSObject(structure); 3584 3613 3585 callFrame[ thisRegister] = newObject; // "this" value3614 callFrame[firstArg] = newObject; // "this" value 3586 3615 3587 3616 CallFrame* previousCallFrame = callFrame; … … 3605 3634 3606 3635 if (constructType == ConstructTypeHost) { 3607 ArgList args(callFrame->registers() + thisRegister+ 1, argCount - 1);3636 ArgList args(callFrame->registers() + firstArg + 1, argCount - 1); 3608 3637 3609 3638 ScopeChainNode* scopeChain = callFrame->scopeChain(); … … 4336 4365 } while (0) 4337 4366 4338 // This macro rewinds to the previous call frame because CTI functions that4339 // throw stack overflow exceptions execute after the call frame has4340 // optimistically moved forward.4341 #define CTI_THROW_STACK_OVERFLOW() do { \4342 CallFrame* oldCallFrame = ARG_callFrame->callerFrame(); \4343 JSGlobalData* globalData = ARG_globalData; \4344 globalData->exception = createStackOverflowError(oldCallFrame); \4345 globalData->throwReturnAddress = CTI_RETURN_ADDRESS; \4346 ARG_setCallFrame(oldCallFrame); \4347 CTI_SET_RETURN_ADDRESS(reinterpret_cast<void*>(ctiVMThrowTrampoline)); \4348 } while (0);4349 4350 4367 JSObject* Machine::cti_op_convert_this(CTI_ARGS) 4351 4368 { … … 4436 4453 } 4437 4454 4455 NEVER_INLINE void Machine::throwStackOverflowPreviousFrame(CallFrame* callFrame, JSGlobalData* globalData, void*& returnAddress) 4456 { 4457 globalData->exception = createStackOverflowError(callFrame->callerFrame()); 4458 globalData->throwReturnAddress = callFrame->returnPC(); 4459 ctiSetReturnAddress(&returnAddress, reinterpret_cast<void*>(ctiVMThrowTrampoline)); 4460 } 4461 4438 4462 void Machine::cti_register_file_check(CTI_ARGS) 4439 4463 { … … 4443 4467 return; 4444 4468 4445 CTI_THROW_STACK_OVERFLOW(); 4469 ARG_setCallFrame(ARG_callFrame->callerFrame()); 4470 throwStackOverflowPreviousFrame(ARG_callFrame, ARG_globalData, CTI_RETURN_ADDRESS); 4446 4471 } 4447 4472 … … 4720 4745 Register* newEnd = r + newCodeBlock->numCalleeRegisters; 4721 4746 if (!ARG_registerFile->grow(newEnd)) { 4722 CTI_THROW_STACK_OVERFLOW(); 4723 VoidPtrPairValue pair = {{ 0, 0 }}; 4724 return pair.i; 4747 ARG_globalData->exception = createStackOverflowError(oldCallFrame); 4748 VM_THROW_EXCEPTION_2(); 4725 4749 } 4726 4750 … … 4787 4811 SamplingTool::HostCallRecord callRecord(CTI_SAMPLER); 4788 4812 4789 // FIXME:All host methods should be calling toThisObject, but this is not presently the case.4813 // All host methods should be calling toThisObject, but this is not presently the case. 4790 4814 JSValue* thisValue = argv[0].jsValue(callFrame); 4791 4815 if (thisValue == jsNull()) … … 4911 4935 4912 4936 StructureID* structure; 4913 if (ARG_src 4->isObject())4914 structure = asObject(ARG_src 4)->inheritorID();4937 if (ARG_src5->isObject()) 4938 structure = asObject(ARG_src5)->inheritorID(); 4915 4939 else 4916 4940 structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure(); … … 4926 4950 JSValue* constrVal = ARG_src1; 4927 4951 int argCount = ARG_int3; 4928 int thisRegister = ARG_int5;4952 int firstArg = ARG_int6; 4929 4953 4930 4954 ConstructData constructData; … … 4932 4956 4933 4957 if (constructType == ConstructTypeHost) { 4934 ArgList argList(callFrame->registers() + thisRegister+ 1, argCount - 1);4958 ArgList argList(callFrame->registers() + firstArg + 1, argCount - 1); 4935 4959 4936 4960 JSValue* returnValue; … … 4946 4970 ASSERT(constructType == ConstructTypeNone); 4947 4971 4948 ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr 6, callFrame->codeBlock());4972 ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr4, callFrame->codeBlock()); 4949 4973 VM_THROW_EXCEPTION(); 4950 4974 } … … 5545 5569 CallFrame* callFrame = ARG_callFrame; 5546 5570 RegisterFile* registerFile = ARG_registerFile; 5571 CodeBlock* codeBlock = callFrame->codeBlock(); 5572 ScopeChainNode* scopeChain = callFrame->scopeChain(); 5547 5573 5548 5574 Machine* machine = ARG_globalData->machine; … … 5551 5577 int registerOffset = ARG_int2; 5552 5578 int argCount = ARG_int3; 5553 5554 Register* newCallFrame = callFrame->registers() + registerOffset; 5555 Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; 5556 JSValue* thisValue = argv[0].jsValue(callFrame); 5557 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); 5558 5559 if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { 5579 JSValue* baseVal = ARG_src5; 5580 5581 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) { 5582 JSObject* thisObject = callFrame[codeBlock->thisRegister].jsValue(callFrame)->toThisObject(callFrame); 5560 5583 JSValue* exceptionValue = noValue(); 5561 JSValue* result = machine->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue);5584 JSValue* result = machine->callEval(callFrame, thisObject, scopeChain, registerFile, registerOffset - RegisterFile::CallFrameHeaderSize - argCount, argCount, exceptionValue); 5562 5585 if (UNLIKELY(exceptionValue != noValue())) { 5563 5586 ARG_globalData->exception = exceptionValue; … … 5922 5945 CallFrame* callFrame = ARG_callFrame; 5923 5946 CodeBlock* codeBlock = callFrame->codeBlock(); 5924 JSGlobalData* globalData = ARG_globalData; 5925 5926 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(globalData->throwReturnAddress)); 5927 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(globalData->throwReturnAddress); 5928 5929 JSValue* exceptionValue = globalData->exception; 5947 5948 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(ARG_globalData->throwReturnAddress)); 5949 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(ARG_globalData->throwReturnAddress); 5950 5951 JSValue* exceptionValue = ARG_globalData->exception; 5930 5952 ASSERT(exceptionValue); 5931 globalData->exception = noValue();5932 5933 Instruction* handlerVPC = globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false);5953 ARG_globalData->exception = noValue(); 5954 5955 Instruction* handlerVPC = ARG_globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false); 5934 5956 5935 5957 if (!handlerVPC) { -
trunk/JavaScriptCore/VM/Machine.h
r38322 r38330 285 285 enum ExecutionFlag { Normal, InitializeAndReturn }; 286 286 287 NEVER_INLINE JSValue* callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue*& exceptionValue);288 JSValue* execute(EvalNode*, CallFrame*, JSObject* thisObject, int globalRegisterOffset, ScopeChainNode*, JSValue** exception);287 NEVER_INLINE JSValue* callEval(CallFrame*, JSObject* thisObject, ScopeChainNode*, RegisterFile*, int argv, int argc, JSValue*& exceptionValue); 288 JSValue* execute(EvalNode*, CallFrame*, JSObject* thisObject, int registerOffset, ScopeChainNode*, JSValue** exception); 289 289 290 290 NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine); … … 307 307 JSValue* privateExecute(ExecutionFlag, RegisterFile*, CallFrame*, JSValue** exception); 308 308 309 void dumpCallFrame( CallFrame*);310 void dumpRegisters( CallFrame*);309 void dumpCallFrame(const RegisterFile*, CallFrame*); 310 void dumpRegisters(const RegisterFile*, CallFrame*); 311 311 312 312 JSValue* checkTimeout(JSGlobalObject*); … … 321 321 322 322 #if ENABLE(CTI) 323 static void throwStackOverflowPreviousFrame(CallFrame* *, JSGlobalData*, void*& returnAddress);323 static void throwStackOverflowPreviousFrame(CallFrame*, JSGlobalData*, void*& returnAddress); 324 324 325 325 void tryCTICacheGetByID(CallFrame*, CodeBlock*, void* returnAddress, JSValue* baseValue, const Identifier& propertyName, const PropertySlot&); -
trunk/JavaScriptCore/bytecompiler/CodeGenerator.cpp
r38322 r38330 1220 1220 } 1221 1221 1222 RegisterID* CodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)1223 { 1224 return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);1225 } 1226 1227 RegisterID* CodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)1228 { 1229 return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);1230 } 1231 1232 RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)1222 RegisterID* CodeGenerator::emitCall(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) 1223 { 1224 return emitCall(op_call, dst, func, base, argumentsNode, divot, startOffset, endOffset); 1225 } 1226 1227 RegisterID* CodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) 1228 { 1229 return emitCall(op_call_eval, dst, func, base, argumentsNode, divot, startOffset, endOffset); 1230 } 1231 1232 RegisterID* CodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset) 1233 1233 { 1234 1234 ASSERT(opcodeID == op_call || opcodeID == op_call_eval); 1235 1235 ASSERT(func->refCount()); 1236 ASSERT(!base || base->refCount()); 1236 1237 1237 1238 // Generate code for arguments. 1238 1239 Vector<RefPtr<RegisterID>, 16> argv; 1239 argv.append( thisRegister);1240 argv.append(newTemporary()); // reserve space for "this" 1240 1241 for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) { 1241 1242 argv.append(newTemporary()); … … 1255 1256 emitExpressionInfo(divot, startOffset, endOffset); 1256 1257 m_codeBlock->callLinkInfos.append(CallLinkInfo()); 1257 1258 // Emit call.1259 1258 emitOpcode(opcodeID); 1260 instructions().append(dst->index()); // dst 1261 instructions().append(func->index()); // func 1262 instructions().append(argv.size()); // argCount 1259 instructions().append(dst->index()); 1260 instructions().append(func->index()); 1261 instructions().append(base ? base->index() : missingThisObjectMarker()); // We encode the "this" value in the instruction stream, to avoid an explicit instruction for copying or loading it. 1262 instructions().append(argv[0]->index()); // argv 1263 instructions().append(argv.size()); // argc 1263 1264 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset 1264 1265 … … 1319 1320 emitExpressionInfo(divot, startOffset, endOffset); 1320 1321 m_codeBlock->callLinkInfos.append(CallLinkInfo()); 1321 1322 1322 emitOpcode(op_construct); 1323 instructions().append(dst->index()); // dst 1324 instructions().append(func->index()); // func 1325 instructions().append(argv.size()); // argCount 1323 instructions().append(dst->index()); 1324 instructions().append(func->index()); 1325 instructions().append(funcProto->index()); 1326 instructions().append(argv[0]->index()); // argv 1327 instructions().append(argv.size()); // argc 1326 1328 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset 1327 instructions().append(funcProto->index()); // proto1328 instructions().append(argv[0]->index()); // thisRegister1329 1329 1330 1330 emitOpcode(op_construct_verify); -
trunk/JavaScriptCore/bytecompiler/CodeGenerator.h
r38322 r38330 274 274 RegisterID* emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value); 275 275 276 RegisterID* emitCall(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);277 RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);276 RegisterID* emitCall(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); 277 RegisterID* emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* base, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); 278 278 279 279 RegisterID* emitReturn(RegisterID* src); … … 346 346 typedef HashMap<UString::Rep*, JSString*, IdentifierRepHash> IdentifierStringMap; 347 347 348 RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);348 RegisterID* emitCall(OpcodeID, RegisterID*, RegisterID*, RegisterID*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); 349 349 350 350 RegisterID* newRegister(); -
trunk/JavaScriptCore/parser/Nodes.cpp
r38322 r38330 586 586 RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst) 587 587 { 588 RefPtr<RegisterID> func= generator.tempDestination(dst);589 RefPtr<RegisterID> thisRegister= generator.newTemporary();590 generator.emitResolveWithBase( thisRegister.get(), func.get(), generator.propertyNames().eval);591 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());588 RefPtr<RegisterID> base = generator.tempDestination(dst); 589 RefPtr<RegisterID> func = generator.newTemporary(); 590 generator.emitResolveWithBase(base.get(), func.get(), generator.propertyNames().eval); 591 return generator.emitCallEval(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), divot(), startOffset(), endOffset()); 592 592 } 593 593 … … 608 608 { 609 609 RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); 610 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); 611 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); 610 return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), divot(), startOffset(), endOffset()); 612 611 } 613 612 … … 626 625 RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) 627 626 { 628 if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { 629 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); 630 return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); 631 } 627 if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) 628 return generator.emitCall(generator.finalDestination(dst), local.get(), 0, m_args.get(), divot(), startOffset(), endOffset()); 632 629 633 630 int index = 0; … … 636 633 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { 637 634 RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); 638 RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); 639 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); 640 } 641 642 RefPtr<RegisterID> func = generator.tempDestination(dst); 643 RefPtr<RegisterID> thisRegister = generator.newTemporary(); 635 return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), divot(), startOffset(), endOffset()); 636 } 637 638 RefPtr<RegisterID> base = generator.tempDestination(dst); 639 RefPtr<RegisterID> func = generator.newTemporary(); 644 640 int identifierStart = divot() - startOffset(); 645 641 generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0); 646 generator.emitResolveFunction( thisRegister.get(), func.get(), m_ident);647 return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset());642 generator.emitResolveFunction(base.get(), func.get(), m_ident); 643 return generator.emitCall(generator.finalDestination(dst, base.get()), func.get(), base.get(), m_args.get(), divot(), startOffset(), endOffset()); 648 644 } 649 645 … … 667 663 RegisterID* property = generator.emitNode(m_subscript.get()); 668 664 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 669 RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); 670 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); 671 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); 665 RefPtr<RegisterID> function = generator.emitGetByVal(generator.newTemporary(), base.get(), property); 666 return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), divot(), startOffset(), endOffset()); 672 667 } 673 668 … … 689 684 RefPtr<RegisterID> base = generator.emitNode(m_base.get()); 690 685 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 691 RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); 692 RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); 693 return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args.get(), divot(), startOffset(), endOffset()); 686 RefPtr<RegisterID> function = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); 687 return generator.emitCall(generator.finalDestination(dst, base.get()), function.get(), base.get(), m_args.get(), divot(), startOffset(), endOffset()); 694 688 } 695 689 -
trunk/JavaScriptCore/parser/Nodes.h
r38322 r38330 2079 2079 int neededConstants() 2080 2080 { 2081 // We may need 2 more constantsthan the count given by the parser,2082 // because of the various uses of jsUndefined() and jsNull().2083 return m_numConstants + 2;2081 // We may need 1 more constant than the count given by the parser, 2082 // because of the various uses of jsUndefined(). 2083 return m_numConstants + 1; 2084 2084 } 2085 2085
Note:
See TracChangeset
for help on using the changeset viewer.