Changeset 38349 in webkit
- Timestamp:
- Nov 12, 2008 4:48:23 PM (15 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r38334 r38349 1 2008-11-12 Geoffrey Garen <ggaren@apple.com> 2 3 Reviewed by Sam Weinig. 4 5 Fixed https://bugs.webkit.org/show_bug.cgi?id=22192 6 +37 failures in fast/profiler 7 8 along with Darin's review comments in 9 https://bugs.webkit.org/show_bug.cgi?id=22174 10 Simplified op_call by nixing its responsibility for moving the value of 11 "this" into the first argument slot 12 13 * VM/Machine.cpp: 14 (JSC::returnToThrowTrampoline): 15 (JSC::throwStackOverflowError): 16 (JSC::Machine::cti_register_file_check): 17 (JSC::Machine::cti_op_call_arityCheck): 18 (JSC::Machine::cti_vm_throw): Moved the throw logic into a function, since 19 functions are better than macros. 20 21 * bytecompiler/CodeGenerator.cpp: 22 (JSC::CodeGenerator::emitCall): 23 (JSC::CodeGenerator::emitConstruct): Ensure that the function register 24 is preserved if profiling is enabled, since the profiler uses that 25 register. 26 27 * runtime/JSGlobalData.h: Renamed throwReturnAddress to exceptionLocation, 28 because I had a hard time understanding what "throwReturnAddress" meant. 29 30 2008-11-12 Geoffrey Garen <ggaren@apple.com> 31 32 Reviewed by Sam Weinig. 33 34 Roll in r38322, now that test failures have been fixed. 35 36 * VM/CTI.cpp: 37 (JSC::CTI::compileOpCallSetupArgs): 38 (JSC::CTI::compileOpCallEvalSetupArgs): 39 (JSC::CTI::compileOpConstructSetupArgs): 40 (JSC::CTI::compileOpCall): 41 (JSC::CTI::privateCompileMainPass): 42 (JSC::CTI::privateCompileSlowCases): 43 * VM/CTI.h: 44 * VM/CodeBlock.cpp: 45 (JSC::CodeBlock::dump): 46 * VM/Machine.cpp: 47 (JSC::Machine::callEval): 48 (JSC::Machine::dumpCallFrame): 49 (JSC::Machine::dumpRegisters): 50 (JSC::Machine::execute): 51 (JSC::Machine::privateExecute): 52 (JSC::Machine::cti_register_file_check): 53 (JSC::Machine::cti_op_call_arityCheck): 54 (JSC::Machine::cti_op_call_NotJSFunction): 55 (JSC::Machine::cti_op_construct_JSConstruct): 56 (JSC::Machine::cti_op_construct_NotJSConstruct): 57 (JSC::Machine::cti_op_call_eval): 58 (JSC::Machine::cti_vm_throw): 59 * VM/Machine.h: 60 * bytecompiler/CodeGenerator.cpp: 61 (JSC::CodeGenerator::emitCall): 62 (JSC::CodeGenerator::emitCallEval): 63 (JSC::CodeGenerator::emitConstruct): 64 * bytecompiler/CodeGenerator.h: 65 * parser/Nodes.cpp: 66 (JSC::EvalFunctionCallNode::emitCode): 67 (JSC::FunctionCallValueNode::emitCode): 68 (JSC::FunctionCallResolveNode::emitCode): 69 (JSC::FunctionCallBracketNode::emitCode): 70 (JSC::FunctionCallDotNode::emitCode): 71 * parser/Nodes.h: 72 (JSC::ScopeNode::neededConstants): 73 1 74 2008-11-12 Gavin Barraclough <barraclough@apple.com> 2 75 -
trunk/JavaScriptCore/VM/CTI.cpp
r38334 r38349 588 588 } 589 589 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 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 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 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); 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); 605 628 } 606 629 … … 609 632 int dst = instruction[1].u.operand; 610 633 int callee = instruction[2].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 } 634 int argCount = instruction[3].u.operand; 635 int registerOffset = instruction[4].u.operand; 625 636 626 637 // Handle eval … … 628 639 if (opcodeID == op_call_eval) { 629 640 emitGetArg(callee, X86::ecx); 630 compileOpCall SetupArgs(instruction, false, true);641 compileOpCallEvalSetupArgs(instruction); 631 642 632 643 emitCTICall(instruction, i, Machine::cti_op_call_eval); … … 648 659 // In the case of OpConstruct, call out to a cti_ function to create the new object. 649 660 if (opcodeID == op_construct) { 661 int proto = instruction[5].u.operand; 662 int thisRegister = instruction[6].u.operand; 663 650 664 emitPutArg(X86::ecx, 0); 651 emitGetPutArg( instruction[3].u.operand, 16, X86::eax);665 emitGetPutArg(proto, 12, X86::eax); 652 666 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); 653 emitPutResult( firstArg);667 emitPutResult(thisRegister); 654 668 emitGetArg(callee, X86::ecx); 655 669 } … … 1286 1300 break; 1287 1301 } 1288 case op_call: { 1302 case op_call: 1303 case op_call_eval: 1304 case op_construct: { 1289 1305 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++); 1290 i += 7;1306 i += (opcodeID == op_construct ? 7 : 5); 1291 1307 break; 1292 1308 } … … 1380 1396 emitPutResult(instruction[i + 1].u.operand); 1381 1397 i += 3; 1382 break;1383 }1384 case op_construct: {1385 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++);1386 i += 7;1387 1398 break; 1388 1399 } … … 1912 1923 emitPutResult(instruction[i + 1].u.operand); 1913 1924 i += 5; 1914 break;1915 }1916 case op_call_eval: {1917 compileOpCall(opcodeID, instruction + i, i, callLinkInfoIndex++);1918 i += 7;1919 1925 break; 1920 1926 } … … 2768 2774 int dst = instruction[i + 1].u.operand; 2769 2775 int callee = instruction[i + 2].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; 2776 int argCount = instruction[i + 3].u.operand; 2777 int registerOffset = instruction[i + 4].u.operand; 2773 2778 2774 2779 m_jit.link(iter->from, m_jit.label()); 2775 2780 2776 2781 // The arguments have been set up on the hot path for op_call_eval 2777 if (opcodeID != op_call_eval) 2778 compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false); 2782 if (opcodeID == op_call) 2783 compileOpCallSetupArgs(instruction + i); 2784 else if (opcodeID == op_construct) 2785 compileOpConstructSetupArgs(instruction + i); 2779 2786 2780 2787 // Fast check for JS function. … … 2784 2791 X86Assembler::JmpSrc callLinkFailNotJSFunction = m_jit.emitUnlinkedJne(); 2785 2792 2786 // First, in the ca le of a construct, allocate the new object.2793 // First, in the case of a construct, allocate the new object. 2787 2794 if (opcodeID == op_construct) { 2788 2795 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); 2789 emitPutResult( firstArg);2796 emitPutResult(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); 2790 2797 emitGetArg(callee, X86::ecx); 2791 2798 } … … 2828 2835 2829 2836 // The arguments have been set up on the hot path for op_call_eval 2830 if (opcodeID != op_call_eval) 2831 compileOpCallSetupArgs(instruction + i, (opcodeID == op_construct), false); 2837 if (opcodeID == op_call) 2838 compileOpCallSetupArgs(instruction + i); 2839 else if (opcodeID == op_construct) 2840 compileOpConstructSetupArgs(instruction + i); 2832 2841 2833 2842 // Check for JSFunctions. … … 2848 2857 m_jit.link(isJSFunction, m_jit.label()); 2849 2858 2850 // First, in the ca le of a construct, allocate the new object.2859 // First, in the case of a construct, allocate the new object. 2851 2860 if (opcodeID == op_construct) { 2852 2861 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); 2853 emitPutResult( firstArg);2862 emitPutResult(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); 2854 2863 emitGetArg(callee, X86::ecx); 2855 2864 } … … 2896 2905 ++callLinkInfoIndex; 2897 2906 2898 i += 7;2907 i += (opcodeID == op_construct ? 7 : 5); 2899 2908 break; 2900 2909 } -
trunk/JavaScriptCore/VM/CTI.h
r38330 r38349 366 366 void compileOpCall(OpcodeID, Instruction* instruction, unsigned i, unsigned callLinkInfoIndex); 367 367 void compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount); 368 void compileOpCallSetupArgs(Instruction* instruction, bool isConstruct, bool isEval); 368 void compileOpCallSetupArgs(Instruction*); 369 void compileOpCallEvalSetupArgs(Instruction*); 370 void compileOpConstructSetupArgs(Instruction*); 369 371 enum CompileOpStrictEqType { OpStrictEq, OpNStrictEq }; 370 372 void compileOpStrictEq(Instruction* instruction, unsigned i, CompileOpStrictEqType type); -
trunk/JavaScriptCore/VM/CodeBlock.cpp
r38330 r38349 813 813 } 814 814 case op_call: { 815 int r0 = (++it)->u.operand; 816 int r1 = (++it)->u.operand; 817 int r2 = (++it)->u.operand; 818 int tempCount = (++it)->u.operand; 815 int dst = (++it)->u.operand; 816 int func = (++it)->u.operand; 819 817 int argCount = (++it)->u.operand; 820 818 int registerOffset = (++it)->u.operand; 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);819 printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset); 822 820 break; 823 821 } 824 822 case op_call_eval: { 825 int r0 = (++it)->u.operand; 826 int r1 = (++it)->u.operand; 827 int r2 = (++it)->u.operand; 828 int tempCount = (++it)->u.operand; 823 int dst = (++it)->u.operand; 824 int func = (++it)->u.operand; 829 825 int argCount = (++it)->u.operand; 830 826 int registerOffset = (++it)->u.operand; 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);827 printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset); 832 828 break; 833 829 } … … 847 843 } 848 844 case op_construct: { 849 int r0 = (++it)->u.operand; 850 int r1 = (++it)->u.operand; 851 int r2 = (++it)->u.operand; 852 int tempCount = (++it)->u.operand; 845 int dst = (++it)->u.operand; 846 int func = (++it)->u.operand; 853 847 int argCount = (++it)->u.operand; 854 848 int registerOffset = (++it)->u.operand; 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); 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()); 856 852 break; 857 853 } -
trunk/JavaScriptCore/VM/Machine.cpp
r38330 r38349 581 581 } 582 582 583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, JSObject* thisObj, ScopeChainNode* scopeChain, RegisterFile* registerFile, int argv, int argc, JSValue*& exceptionValue)583 NEVER_INLINE JSValue* Machine::callEval(CallFrame* callFrame, RegisterFile* registerFile, Register* argv, int argc, int registerOffset, JSValue*& exceptionValue) 584 584 { 585 585 if (argc < 2) 586 586 return jsUndefined(); 587 587 588 JSValue* program = callFrame[argv +1].jsValue(callFrame);588 JSValue* program = argv[1].jsValue(callFrame); 589 589 590 590 if (!program->isString()) … … 593 593 UString programSource = asString(program)->value(); 594 594 595 ScopeChainNode* scopeChain = callFrame->scopeChain(); 595 596 CodeBlock* codeBlock = callFrame->codeBlock(); 596 597 RefPtr<EvalNode> evalNode = codeBlock->evalCodeCache.get(callFrame, programSource, scopeChain, exceptionValue); … … 598 599 JSValue* result = jsUndefined(); 599 600 if (evalNode) 600 result = callFrame->globalData().machine->execute(evalNode.get(), callFrame, thisObj, callFrame->registers() - registerFile->start() + argv + 1 + RegisterFile::CallFrameHeaderSize, scopeChain, &exceptionValue);601 result = callFrame->globalData().machine->execute(evalNode.get(), callFrame, callFrame->thisValue()->toThisObject(callFrame), callFrame->registers() - registerFile->start() + registerOffset, scopeChain, &exceptionValue); 601 602 602 603 return result; … … 656 657 #ifndef NDEBUG 657 658 658 void Machine::dumpCallFrame(const RegisterFile* registerFile, CallFrame* callFrame) 659 { 660 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); 661 662 CodeBlock* codeBlock = callFrame->codeBlock(); 663 codeBlock->dump(globalObject->globalExec()); 664 665 dumpRegisters(registerFile, callFrame); 666 } 667 668 void Machine::dumpRegisters(const RegisterFile* registerFile, CallFrame* callFrame) 659 void Machine::dumpCallFrame(CallFrame* callFrame) 660 { 661 callFrame->codeBlock()->dump(callFrame); 662 dumpRegisters(callFrame); 663 } 664 665 void Machine::dumpRegisters(CallFrame* callFrame) 669 666 { 670 667 printf("Register frame: \n\n"); … … 674 671 675 672 CodeBlock* codeBlock = callFrame->codeBlock(); 673 RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->machine->registerFile(); 676 674 const Register* it; 677 675 const Register* end; … … 1024 1022 } 1025 1023 1026 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int registerOffset, ScopeChainNode* scopeChain, JSValue** exception)1024 JSValue* Machine::execute(EvalNode* evalNode, CallFrame* callFrame, JSObject* thisObj, int globalRegisterOffset, ScopeChainNode* scopeChain, JSValue** exception) 1027 1025 { 1028 1026 ASSERT(!scopeChain->globalData->exception); … … 1070 1068 1071 1069 Register* oldEnd = m_registerFile.end(); 1072 Register* newEnd = m_registerFile.start() + registerOffset + codeBlock->numCalleeRegisters;1070 Register* newEnd = m_registerFile.start() + globalRegisterOffset + codeBlock->numCalleeRegisters; 1073 1071 if (!m_registerFile.grow(newEnd)) { 1074 1072 *exception = createStackOverflowError(callFrame); … … 1076 1074 } 1077 1075 1078 CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + registerOffset);1076 CallFrame* newCallFrame = CallFrame::create(m_registerFile.start() + globalRegisterOffset); 1079 1077 1080 1078 // a 0 codeBlock indicates a built-in caller … … 3265 3263 } 3266 3264 BEGIN_OPCODE(op_call_eval) { 3267 /* call_eval dst(r) func(r) thisVal(r) firstArg(r) argCount(n)3265 /* call_eval dst(r) func(r) argCount(n) registerOffset(n) 3268 3266 3269 3267 Call a function named "eval" with no explicit "this" value … … 3278 3276 int dst = vPC[1].u.operand; 3279 3277 int func = vPC[2].u.operand; 3280 int thisVal = vPC[3].u.operand; 3281 int firstArg = vPC[4].u.operand; 3282 int argCount = vPC[5].u.operand; 3278 int argCount = vPC[3].u.operand; 3279 int registerOffset = vPC[4].u.operand; 3283 3280 3284 3281 JSValue* funcVal = callFrame[func].jsValue(callFrame); 3285 JSValue* baseVal = callFrame[thisVal].jsValue(callFrame); 3286 3287 ScopeChainNode* scopeChain = callFrame->scopeChain(); 3288 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) { 3289 JSObject* thisObject = asObject(callFrame[callFrame->codeBlock()->thisRegister].jsValue(callFrame)); 3290 JSValue* result = callEval(callFrame, thisObject, scopeChain, registerFile, firstArg, argCount, exceptionValue); 3282 3283 Register* newCallFrame = callFrame->registers() + registerOffset; 3284 Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; 3285 JSValue* thisValue = argv[0].jsValue(callFrame); 3286 JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); 3287 3288 if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { 3289 JSValue* result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); 3291 3290 if (exceptionValue) 3292 3291 goto vm_throw; 3293 3294 3292 callFrame[dst] = result; 3295 3293 3296 vPC += 7;3294 vPC += 5; 3297 3295 NEXT_OPCODE; 3298 3296 } 3299 3297 3300 // We didn't find the blessed version of eval, so reset vPC and process 3301 // this instruction as a normal function call, supplying the proper 'this' 3302 // value. 3303 callFrame[thisVal] = baseVal->toThisObject(callFrame); 3298 // We didn't find the blessed version of eval, so process this 3299 // instruction as a normal function call. 3304 3300 3305 3301 #if HAVE(COMPUTED_GOTO) … … 3312 3308 } 3313 3309 BEGIN_OPCODE(op_call) { 3314 /* call dst(r) func(r) thisVal(r) firstArg(r) argCount(n) registerOffset(n) 3315 3316 Perform a function call. Specifically, call register func 3317 with a "this" value of register thisVal, and put the result 3318 in register dst. 3319 3320 The arguments start at register firstArg and go up to 3321 argCount, but the "this" value is considered an implicit 3322 first argument, so the argCount should be one greater than 3323 the number of explicit arguments passed, and the register 3324 after firstArg should contain the actual first 3325 argument. This opcode will copy from the thisVal register 3326 to the firstArg register, unless the register index of 3327 thisVal is the special missing this object marker, which is 3328 2^31-1; in that case, the global object will be used as the 3329 "this" value. 3330 3331 If func is a native code function, then this opcode calls 3332 it and returns the value immediately. 3333 3334 But if it is a JS function, then the current scope chain 3335 and code block is set to the function's, and we slide the 3336 register window so that the arguments would form the first 3337 few local registers of the called function's register 3338 window. In addition, a call frame header is written 3339 immediately before the arguments; see the call frame 3340 documentation for an explanation of how many registers a 3341 call frame takes and what they contain. That many registers 3342 before the firstArg register will be overwritten by the 3343 call. In addition, any registers higher than firstArg + 3344 argCount may be overwritten. Once this setup is complete, 3345 execution continues from the called function's first 3346 argument, and does not return until a "ret" opcode is 3347 encountered. 3310 /* call dst(r) func(r) argCount(n) registerOffset(n) 3311 3312 Perform a function call. 3313 3314 registerOffset is the distance the callFrame pointer should move 3315 before the VM initializes the new call frame's header. 3316 3317 dst is where op_ret should store its result. 3348 3318 */ 3349 3319 3350 3320 int dst = vPC[1].u.operand; 3351 3321 int func = vPC[2].u.operand; 3352 int thisVal = vPC[3].u.operand; 3353 int firstArg = vPC[4].u.operand; 3354 int argCount = vPC[5].u.operand; 3355 int registerOffset = vPC[6].u.operand; 3322 int argCount = vPC[3].u.operand; 3323 int registerOffset = vPC[4].u.operand; 3356 3324 3357 3325 JSValue* v = callFrame[func].jsValue(callFrame); … … 3365 3333 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain); 3366 3334 3367 callFrame[firstArg] = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame);3368 3369 3335 CallFrame* previousCallFrame = callFrame; 3370 3336 … … 3376 3342 } 3377 3343 3378 callFrame->init(newCodeBlock, vPC + 7, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v));3344 callFrame->init(newCodeBlock, vPC + 5, callDataScopeChain, previousCallFrame, dst, argCount, asFunction(v)); 3379 3345 vPC = newCodeBlock->instructions.begin(); 3380 3346 … … 3387 3353 3388 3354 if (callType == CallTypeHost) { 3389 JSValue* thisValue = thisVal == missingThisObjectMarker() ? callFrame->globalThisValue() : callFrame[thisVal].jsValue(callFrame);3390 ArgList args(callFrame->registers() + firstArg + 1, argCount - 1);3391 3392 3355 ScopeChainNode* scopeChain = callFrame->scopeChain(); 3393 3356 CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); 3394 newCallFrame->init(0, vPC + 7, scopeChain, callFrame, dst, argCount, 0); 3357 newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, 0); 3358 3359 Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; 3360 ArgList args(thisRegister + 1, argCount - 1); 3361 3362 // FIXME: All host methods should be calling toThisObject, but this is not presently the case. 3363 JSValue* thisValue = thisRegister->jsValue(callFrame); 3364 if (thisValue == jsNull()) 3365 thisValue = callFrame->globalThisValue(); 3395 3366 3396 3367 JSValue* returnValue; … … 3403 3374 callFrame[dst] = returnValue; 3404 3375 3405 vPC += 7;3376 vPC += 5; 3406 3377 NEXT_OPCODE; 3407 3378 } … … 3573 3544 } 3574 3545 BEGIN_OPCODE(op_construct) { 3575 /* construct dst(r) constr(r) constrProto(r) firstArg(r) argCount(n) registerOffset(n)3576 3577 Invoke register " constr" as a constructor. For JS3546 /* construct dst(r) func(r) argCount(n) registerOffset(n) proto(r) thisRegister(r) 3547 3548 Invoke register "func" as a constructor. For JS 3578 3549 functions, the calling convention is exactly as for the 3579 3550 "call" opcode, except that the "this" value is a newly 3580 created Object. For native constructors, a null"this"3581 value is passed. In either case, the firstArg and argCount3551 created Object. For native constructors, no "this" 3552 value is passed. In either case, the argCount and registerOffset 3582 3553 registers are interpreted as for the "call" opcode. 3583 3554 3584 Register constrProto must contain the prototype property of3585 register constsr. This is to enable polymorphic inline3555 Register proto must contain the prototype property of 3556 register func. This is to enable polymorphic inline 3586 3557 caching of this lookup. 3587 3558 */ 3588 3559 3589 3560 int dst = vPC[1].u.operand; 3590 int constr= vPC[2].u.operand;3591 int constrProto= vPC[3].u.operand;3592 int firstArg= vPC[4].u.operand;3593 int argCount= vPC[5].u.operand;3594 int registerOffset= vPC[6].u.operand;3595 3596 JSValue* v = callFrame[ constr].jsValue(callFrame);3561 int func = vPC[2].u.operand; 3562 int argCount = vPC[3].u.operand; 3563 int registerOffset = vPC[4].u.operand; 3564 int proto = vPC[5].u.operand; 3565 int thisRegister = vPC[6].u.operand; 3566 3567 JSValue* v = callFrame[func].jsValue(callFrame); 3597 3568 3598 3569 ConstructData constructData; … … 3605 3576 3606 3577 StructureID* structure; 3607 JSValue* prototype = callFrame[ constrProto].jsValue(callFrame);3578 JSValue* prototype = callFrame[proto].jsValue(callFrame); 3608 3579 if (prototype->isObject()) 3609 3580 structure = asObject(prototype)->inheritorID(); … … 3612 3583 JSObject* newObject = new (globalData) JSObject(structure); 3613 3584 3614 callFrame[ firstArg] = newObject; // "this" value3585 callFrame[thisRegister] = newObject; // "this" value 3615 3586 3616 3587 CallFrame* previousCallFrame = callFrame; … … 3634 3605 3635 3606 if (constructType == ConstructTypeHost) { 3636 ArgList args(callFrame->registers() + firstArg+ 1, argCount - 1);3607 ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1); 3637 3608 3638 3609 ScopeChainNode* scopeChain = callFrame->scopeChain(); … … 4326 4297 // good to keep the code size down by leaving as much of the exception 4327 4298 // handling code out of line as possible. 4328 static NEVER_INLINE void setUpThrowTrampolineReturnAddress(JSGlobalData* globalData, void*& returnAddress)4299 static NEVER_INLINE void returnToThrowTrampoline(JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot) 4329 4300 { 4330 4301 ASSERT(globalData->exception); 4331 globalData->throwReturnAddress = returnAddress; 4332 ctiSetReturnAddress(&returnAddress, reinterpret_cast<void*>(ctiVMThrowTrampoline)); 4302 globalData->exceptionLocation = exceptionLocation; 4303 ctiSetReturnAddress(&returnAddressSlot, reinterpret_cast<void*>(ctiVMThrowTrampoline)); 4304 } 4305 4306 static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalData* globalData, void* exceptionLocation, void*& returnAddressSlot) 4307 { 4308 globalData->exception = createStackOverflowError(callFrame); 4309 returnToThrowTrampoline(globalData, exceptionLocation, returnAddressSlot); 4333 4310 } 4334 4311 … … 4345 4322 } while (0) 4346 4323 #define VM_THROW_EXCEPTION_AT_END() \ 4347 setUpThrowTrampolineReturnAddress(ARG_globalData, CTI_RETURN_ADDRESS)4324 returnToThrowTrampoline(ARG_globalData, CTI_RETURN_ADDRESS, CTI_RETURN_ADDRESS) 4348 4325 4349 4326 #define VM_CHECK_EXCEPTION() \ … … 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*>(ctiVMThrowTrampoline));4460 }4461 4462 4432 void Machine::cti_register_file_check(CTI_ARGS) 4463 4433 { … … 4467 4437 return; 4468 4438 4469 ARG_setCallFrame(ARG_callFrame->callerFrame()); 4470 throwStackOverflowPreviousFrame(ARG_callFrame, ARG_globalData, CTI_RETURN_ADDRESS); 4439 // Rewind to the previous call frame because op_call already optimistically 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 … … 4745 4718 Register* newEnd = r + newCodeBlock->numCalleeRegisters; 4746 4719 if (!ARG_registerFile->grow(newEnd)) { 4747 ARG_globalData->exception = createStackOverflowError(oldCallFrame); 4748 VM_THROW_EXCEPTION_2(); 4720 // Rewind to the previous call frame because op_call already optimistically 4721 // moved the call frame forward. 4722 ARG_setCallFrame(oldCallFrame); 4723 throwStackOverflowError(oldCallFrame, ARG_globalData, CTI_RETURN_ADDRESS, CTI_RETURN_ADDRESS); 4724 VoidPtrPairValue pair = {{ 0, 0 }}; 4725 return pair.i; 4749 4726 } 4750 4727 … … 4811 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 4791 JSValue* thisValue = argv[0].jsValue(callFrame); 4815 4792 if (thisValue == jsNull()) … … 4935 4912 4936 4913 StructureID* structure; 4937 if (ARG_src 5->isObject())4938 structure = asObject(ARG_src 5)->inheritorID();4914 if (ARG_src4->isObject()) 4915 structure = asObject(ARG_src4)->inheritorID(); 4939 4916 else 4940 4917 structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure(); … … 4950 4927 JSValue* constrVal = ARG_src1; 4951 4928 int argCount = ARG_int3; 4952 int firstArg = ARG_int6;4929 int thisRegister = ARG_int5; 4953 4930 4954 4931 ConstructData constructData; … … 4956 4933 4957 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 4937 JSValue* returnValue; … … 4970 4947 ASSERT(constructType == ConstructTypeNone); 4971 4948 4972 ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr 4, callFrame->codeBlock());4949 ARG_globalData->exception = createNotAConstructorError(callFrame, constrVal, ARG_instr6, callFrame->codeBlock()); 4973 4950 VM_THROW_EXCEPTION(); 4974 4951 } … … 5569 5546 CallFrame* callFrame = ARG_callFrame; 5570 5547 RegisterFile* registerFile = ARG_registerFile; 5571 CodeBlock* codeBlock = callFrame->codeBlock();5572 ScopeChainNode* scopeChain = callFrame->scopeChain();5573 5548 5574 5549 Machine* machine = ARG_globalData->machine; … … 5577 5552 int registerOffset = ARG_int2; 5578 5553 int argCount = ARG_int3; 5579 JSValue* baseVal = ARG_src5; 5580 5581 if (baseVal == scopeChain->globalObject() && funcVal == scopeChain->globalObject()->evalFunction()) { 5582 JSObject* thisObject = callFrame[codeBlock->thisRegister].jsValue(callFrame)->toThisObject(callFrame); 5554 5555 Register* newCallFrame = callFrame->registers() + registerOffset; 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 5561 JSValue* exceptionValue = noValue(); 5584 JSValue* result = machine->callEval(callFrame, thisObject, scopeChain, registerFile, registerOffset - RegisterFile::CallFrameHeaderSize - argCount, argCount, exceptionValue);5562 JSValue* result = machine->callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); 5585 5563 if (UNLIKELY(exceptionValue != noValue())) { 5586 5564 ARG_globalData->exception = exceptionValue; … … 5945 5923 CallFrame* callFrame = ARG_callFrame; 5946 5924 CodeBlock* codeBlock = callFrame->codeBlock(); 5947 5948 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(ARG_globalData->throwReturnAddress)); 5949 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(ARG_globalData->throwReturnAddress); 5950 5951 JSValue* exceptionValue = ARG_globalData->exception; 5925 JSGlobalData* globalData = ARG_globalData; 5926 5927 ASSERT(codeBlock->ctiReturnAddressVPCMap.contains(globalData->exceptionLocation)); 5928 unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(globalData->exceptionLocation); 5929 5930 JSValue* exceptionValue = globalData->exception; 5952 5931 ASSERT(exceptionValue); 5953 ARG_globalData->exception = noValue();5954 5955 Instruction* handlerVPC = ARG_globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false);5932 globalData->exception = noValue(); 5933 5934 Instruction* handlerVPC = globalData->machine->throwException(callFrame, exceptionValue, codeBlock->instructions.begin() + vPCIndex, false); 5956 5935 5957 5936 if (!handlerVPC) { -
trunk/JavaScriptCore/VM/Machine.h
r38330 r38349 285 285 enum ExecutionFlag { Normal, InitializeAndReturn }; 286 286 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);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); 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( const RegisterFile*,CallFrame*);310 void dumpRegisters( const RegisterFile*,CallFrame*);309 void dumpCallFrame(CallFrame*); 310 void dumpRegisters(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
r38330 r38349 1220 1220 } 1221 1221 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)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) 1233 1233 { 1234 1234 ASSERT(opcodeID == op_call || opcodeID == op_call_eval); 1235 1235 ASSERT(func->refCount()); 1236 ASSERT(!base || base->refCount()); 1237 1236 1237 if (m_shouldEmitProfileHooks) { 1238 // If codegen decided to recycle func as this call's destination register, 1239 // we need to undo that optimization here so that func will still be around 1240 // for the sake of op_profile_did_call. 1241 if (dst == func) { 1242 RefPtr<RegisterID> protect = thisRegister; 1243 RefPtr<RegisterID> movedThisRegister = emitMove(newTemporary(), thisRegister); 1244 RefPtr<RegisterID> movedFunc = emitMove(thisRegister, func); 1245 1246 thisRegister = movedThisRegister.release().releaseRef(); 1247 func = movedFunc.release().releaseRef(); 1248 } 1249 } 1250 1238 1251 // Generate code for arguments. 1239 1252 Vector<RefPtr<RegisterID>, 16> argv; 1240 argv.append( newTemporary()); // reserve space for "this"1253 argv.append(thisRegister); 1241 1254 for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) { 1242 1255 argv.append(newTemporary()); … … 1256 1269 emitExpressionInfo(divot, startOffset, endOffset); 1257 1270 m_codeBlock->callLinkInfos.append(CallLinkInfo()); 1271 1272 // Emit call. 1258 1273 emitOpcode(opcodeID); 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 1274 instructions().append(dst->index()); // dst 1275 instructions().append(func->index()); // func 1276 instructions().append(argv.size()); // argCount 1264 1277 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset 1265 1278 … … 1267 1280 emitOpcode(op_profile_did_call); 1268 1281 instructions().append(func->index()); 1282 1283 if (dst == func) { 1284 thisRegister->deref(); 1285 func->deref(); 1286 } 1269 1287 } 1270 1288 … … 1293 1311 { 1294 1312 ASSERT(func->refCount()); 1313 1314 if (m_shouldEmitProfileHooks) { 1315 // If codegen decided to recycle func as this call's destination register, 1316 // we need to undo that optimization here so that func will still be around 1317 // for the sake of op_profile_did_call. 1318 if (dst == func) { 1319 RefPtr<RegisterID> movedFunc = emitMove(newTemporary(), func); 1320 func = movedFunc.release().releaseRef(); 1321 } 1322 } 1295 1323 1296 1324 RefPtr<RegisterID> funcProto = newTemporary(); … … 1320 1348 emitExpressionInfo(divot, startOffset, endOffset); 1321 1349 m_codeBlock->callLinkInfos.append(CallLinkInfo()); 1350 1322 1351 emitOpcode(op_construct); 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 1352 instructions().append(dst->index()); // dst 1353 instructions().append(func->index()); // func 1354 instructions().append(argv.size()); // argCount 1328 1355 instructions().append(argv[0]->index() + argv.size() + RegisterFile::CallFrameHeaderSize); // registerOffset 1356 instructions().append(funcProto->index()); // proto 1357 instructions().append(argv[0]->index()); // thisRegister 1329 1358 1330 1359 emitOpcode(op_construct_verify); … … 1335 1364 emitOpcode(op_profile_did_call); 1336 1365 instructions().append(func->index()); 1366 1367 if (dst == func) 1368 func->deref(); 1337 1369 } 1338 1370 -
trunk/JavaScriptCore/bytecompiler/CodeGenerator.h
r38330 r38349 274 274 RegisterID* emitPutSetter(RegisterID* base, const Identifier& property, RegisterID* value); 275 275 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);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); 278 278 279 279 RegisterID* emitReturn(RegisterID* src); … … 346 346 typedef HashMap<UString::Rep*, JSString*, IdentifierRepHash> IdentifierStringMap; 347 347 348 RegisterID* emitCall(OpcodeID, RegisterID* , RegisterID*, RegisterID*, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset);348 RegisterID* emitCall(OpcodeID, RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode*, unsigned divot, unsigned startOffset, unsigned endOffset); 349 349 350 350 RegisterID* newRegister(); -
trunk/JavaScriptCore/parser/Nodes.cpp
r38330 r38349 586 586 RegisterID* EvalFunctionCallNode::emitCode(CodeGenerator& generator, RegisterID* dst) 587 587 { 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());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()); 592 592 } 593 593 … … 608 608 { 609 609 RefPtr<RegisterID> func = generator.emitNode(m_expr.get()); 610 return generator.emitCall(generator.finalDestination(dst), func.get(), 0, m_args.get(), divot(), startOffset(), endOffset()); 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()); 611 612 } 612 613 … … 625 626 RegisterID* FunctionCallResolveNode::emitCode(CodeGenerator& generator, RegisterID* dst) 626 627 { 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()); 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 } 629 632 630 633 int index = 0; … … 633 636 if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { 634 637 RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); 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(); 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(); 640 644 int identifierStart = divot() - startOffset(); 641 645 generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0); 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());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()); 644 648 } 645 649 … … 663 667 RegisterID* property = generator.emitNode(m_subscript.get()); 664 668 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 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()); 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()); 667 672 } 668 673 … … 684 689 RefPtr<RegisterID> base = generator.emitNode(m_base.get()); 685 690 generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); 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()); 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()); 688 694 } 689 695 -
trunk/JavaScriptCore/parser/Nodes.h
r38330 r38349 2079 2079 int neededConstants() 2080 2080 { 2081 // We may need 1 more constantthan the count given by the parser,2082 // because of the various uses of jsUndefined() .2083 return m_numConstants + 1;2081 // We may need 2 more constants than the count given by the parser, 2082 // because of the various uses of jsUndefined() and jsNull(). 2083 return m_numConstants + 2; 2084 2084 } 2085 2085 -
trunk/JavaScriptCore/runtime/JSGlobalData.h
r38137 r38349 68 68 JSValue* exception; 69 69 #if ENABLE(CTI) 70 void* throwReturnAddress;70 void* exceptionLocation; 71 71 #endif 72 72
Note: See TracChangeset
for help on using the changeset viewer.