Changeset 38209 in webkit
- Timestamp:
- Nov 6, 2008 5:30:03 PM (15 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r38205 r38209 1 2008-11-06 Gavin Barraclough barraclough@apple.com 2 3 Reviewed by Oliver Hunt. 4 5 Do not make a cti_* call to perform an op_call unless either: 6 (1) The codeblock for the function body has not been generated. 7 (2) The number of arguments passed does not match the callee arity. 8 9 ~1% progression on sunspider --v8 10 11 * VM/CTI.cpp: 12 (JSC::CTI::compileOpCallInitializeCallFrame): 13 (JSC::CTI::compileOpCall): 14 (JSC::CTI::privateCompileSlowCases): 15 * VM/CTI.h: 16 * VM/Machine.cpp: 17 (JSC::Machine::cti_op_call_JSFunction): 18 (JSC::Machine::cti_op_call_arityCheck): 19 (JSC::Machine::cti_op_construct_JSConstruct): 20 * VM/Machine.h: 21 * kjs/nodes.h: 22 1 23 2008-11-06 Cameron Zwarich <zwarich@apple.com> 2 24 -
trunk/JavaScriptCore/VM/CTI.cpp
r38148 r38209 588 588 } 589 589 590 void CTI::compileOpCallInitializeCallFrame(unsigned callee, unsigned argCount) 591 { 592 emitGetArg(callee, X86::ecx); // Load callee JSFunction into ecx 593 m_jit.movl_rm(X86::eax, RegisterFile::CodeBlock * static_cast<int>(sizeof(Register)), X86::edx); // callee CodeBlock was returned in eax 594 m_jit.movl_i32m(asInteger(noValue()), RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register)), X86::edx); 595 m_jit.movl_rm(X86::ecx, RegisterFile::Callee * static_cast<int>(sizeof(Register)), X86::edx); 596 590 void CTI::compileOpCallInitializeCallFrame(unsigned, unsigned argCount) 591 { 597 592 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_scopeChain) + OBJECT_OFFSET(ScopeChain, m_node), X86::ecx, X86::ebx); // newScopeChain 598 m_jit.movl_i32m(argCount, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)), X86::edx); 599 m_jit.movl_rm(X86::edi, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register)), X86::edx); 600 m_jit.movl_rm(X86::ebx, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)), X86::edx); 593 594 m_jit.movl_i32m(asInteger(noValue()), RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register)), X86::edi); 595 m_jit.movl_rm(X86::ecx, RegisterFile::Callee * static_cast<int>(sizeof(Register)), X86::edi); 596 m_jit.movl_i32m(argCount, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)), X86::edi); 597 m_jit.movl_rm(X86::ebx, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)), X86::edi); 601 598 } 602 599 … … 659 656 // The following is the fast case, only used whan a callee can be linked. 660 657 661 // In the case of OpConstruct, call o out to a cti_ function to create the new object.658 // In the case of OpConstruct, call out to a cti_ function to create the new object. 662 659 if (opcodeID == op_construct) { 663 660 emitPutArg(X86::ecx, 0); 664 emitGetPutArg(instruction[3].u.operand, 4, X86::eax);665 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct Fast);666 emitPutResult( instruction[4].u.operand);661 emitGetPutArg(instruction[3].u.operand, 16, X86::eax); 662 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); 663 emitPutResult(firstArg); 667 664 emitGetArg(callee, X86::ecx); 668 665 } … … 2778 2775 int dst = instruction[i + 1].u.operand; 2779 2776 int callee = instruction[i + 2].u.operand; 2777 int firstArg = instruction[i + 4].u.operand; 2780 2778 int argCount = instruction[i + 5].u.operand; 2779 int registerOffset = instruction[i + 6].u.operand; 2781 2780 2782 2781 m_jit.link(iter->from, m_jit.label()); … … 2792 2791 X86Assembler::JmpSrc callLinkFailNotJSFunction = m_jit.emitUnlinkedJne(); 2793 2792 2794 // This handles JSFunctions 2795 emitCTICall(instruction + i, i, (opcodeID == op_construct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction); 2796 // initialize the new call frame (pointed to by edx, after the last call), then set edi to point to it. 2793 // First, in the cale of a construct, allocate the new object. 2794 if (opcodeID == op_construct) { 2795 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); 2796 emitPutResult(firstArg); 2797 emitGetArg(callee, X86::ecx); 2798 } 2799 2800 // Load the callee CodeBlock* into eax 2801 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_body), X86::ecx, X86::eax); 2802 m_jit.movl_mr(OBJECT_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax); 2803 m_jit.testl_rr(X86::eax, X86::eax); 2804 X86Assembler::JmpSrc hasCodeBlockForLink = m_jit.emitUnlinkedJne(); 2805 emitCTICall(instruction + i, i, Machine::cti_op_call_JSFunction); 2806 emitGetArg(callee, X86::ecx); 2807 m_jit.link(hasCodeBlockForLink, m_jit.label()); 2808 2809 // Speculatively roll the callframe, assuming argCount will match the arity. 2810 m_jit.movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi); 2811 m_jit.addl_i32r(registerOffset * static_cast<int>(sizeof(Register)), X86::edi); 2812 2813 // Check argCount matches callee arity. 2814 m_jit.cmpl_i32m(argCount, OBJECT_OFFSET(CodeBlock, numParameters), X86::eax); 2815 X86Assembler::JmpSrc arityCheckOkayForLink = m_jit.emitUnlinkedJe(); 2816 emitPutArg(X86::eax, 12); 2817 emitCTICall(instruction + i, i, Machine::cti_op_call_arityCheck); 2818 emitGetArg(callee - registerOffset, X86::ecx); 2819 m_jit.movl_rr(X86::edx, X86::edi); 2820 m_jit.link(arityCheckOkayForLink, m_jit.label()); 2821 2822 // initialize the new call frame (pointed to by edx, after the last call). 2797 2823 compileOpCallInitializeCallFrame(callee, argCount); 2798 m_jit.movl_rr(X86::edx, X86::edi);2799 2824 2800 2825 // Try to link & repatch this call. … … 2829 2854 // Next, handle JSFunctions... 2830 2855 m_jit.link(isJSFunction, m_jit.label()); 2831 emitCTICall(instruction + i, i, (opcodeID == op_construct) ? Machine::cti_op_construct_JSConstruct : Machine::cti_op_call_JSFunction); 2856 2857 // First, in the cale of a construct, allocate the new object. 2858 if (opcodeID == op_construct) { 2859 emitCTICall(instruction, i, Machine::cti_op_construct_JSConstruct); 2860 emitPutResult(firstArg); 2861 emitGetArg(callee, X86::ecx); 2862 } 2863 2864 // Load the callee CodeBlock* into eax 2865 m_jit.movl_mr(OBJECT_OFFSET(JSFunction, m_body), X86::ecx, X86::eax); 2866 m_jit.movl_mr(OBJECT_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax); 2867 m_jit.testl_rr(X86::eax, X86::eax); 2868 X86Assembler::JmpSrc hasCodeBlock = m_jit.emitUnlinkedJne(); 2869 emitCTICall(instruction + i, i, Machine::cti_op_call_JSFunction); 2870 emitGetArg(callee, X86::ecx); 2871 m_jit.link(hasCodeBlock, m_jit.label()); 2872 2873 // Speculatively roll the callframe, assuming argCount will match the arity. 2874 m_jit.movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi); 2875 m_jit.addl_i32r(registerOffset * static_cast<int>(sizeof(Register)), X86::edi); 2876 2877 // Check argCount matches callee arity. 2878 m_jit.cmpl_i32m(argCount, OBJECT_OFFSET(CodeBlock, numParameters), X86::eax); 2879 X86Assembler::JmpSrc arityCheckOkay = m_jit.emitUnlinkedJe(); 2880 emitPutArg(X86::eax, 12); 2881 emitCTICall(instruction + i, i, Machine::cti_op_call_arityCheck); 2882 emitGetArg(callee - registerOffset, X86::ecx); 2883 m_jit.movl_rr(X86::edx, X86::edi); 2884 m_jit.link(arityCheckOkay, m_jit.label()); 2885 2832 2886 // initialize the new call frame (pointed to by edx, after the last call). 2833 2887 compileOpCallInitializeCallFrame(callee, argCount); 2834 m_jit.movl_rr(X86::edx, X86::edi);2835 2888 2836 2889 // load ctiCode from the new codeBlock. 2837 2890 m_jit.movl_mr(OBJECT_OFFSET(CodeBlock, ctiCode), X86::eax, X86::eax); 2838 2839 // Move the new callframe into edi.2840 m_jit.movl_rr(X86::edx, X86::edi);2841 2842 // Check the ctiCode has been generated (if not compile it now), and make the call.2843 m_jit.testl_rr(X86::eax, X86::eax);2844 X86Assembler::JmpSrc hasCode = m_jit.emitUnlinkedJne();2845 emitCTICall(instruction + i, i, Machine::cti_vm_compile);2846 m_jit.link(hasCode, m_jit.label());2847 2891 2848 2892 emitNakedCall(i, X86::eax); -
trunk/JavaScriptCore/VM/CTI.h
r37991 r38209 81 81 #define ARG_instr6 static_cast<Instruction*>(ARGS[6]) 82 82 #define ARG_linkInfo2 static_cast<CallLinkInfo*>(ARGS[2]) 83 #define ARG_codeBlock4 static_cast<CodeBlock*>(ARGS[4]) 83 84 84 85 #define CTI_RETURN_ADDRESS_SLOT (ARGS[-1]) -
trunk/JavaScriptCore/VM/Machine.cpp
r38148 r38209 4709 4709 } 4710 4710 4711 VoidPtrPairMachine::cti_op_call_JSFunction(CTI_ARGS)4711 void* Machine::cti_op_call_JSFunction(CTI_ARGS) 4712 4712 { 4713 4713 CTI_STACK_HACK(); … … 4720 4720 ScopeChainNode* callDataScopeChain = asFunction(ARG_src1)->m_scopeChain.node(); 4721 4721 CodeBlock* newCodeBlock = &asFunction(ARG_src1)->m_body->byteCode(callDataScopeChain); 4722 CallFrame* callFrame = ARG_callFrame; 4723 size_t registerOffset = ARG_int2; 4722 4723 if (!newCodeBlock->ctiCode) 4724 CTI::compile(ARG_globalData->machine, ARG_callFrame, newCodeBlock); 4725 4726 return newCodeBlock; 4727 } 4728 4729 VoidPtrPair Machine::cti_op_call_arityCheck(CTI_ARGS) 4730 { 4731 CTI_STACK_HACK(); 4732 4733 CallFrame* callFrame = ARG_callFrame; 4734 CodeBlock* newCodeBlock = ARG_codeBlock4; 4724 4735 int argCount = ARG_int3; 4725 4736 4726 if (LIKELY(argCount == newCodeBlock->numParameters)) { 4727 VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(callFrame->registers() + registerOffset) }}; 4728 return pair.i; 4729 } 4737 ASSERT(argCount != newCodeBlock->numParameters); 4738 4739 CallFrame* oldCallFrame = callFrame->callerFrame(); 4730 4740 4731 4741 if (argCount > newCodeBlock->numParameters) { 4732 4742 size_t numParameters = newCodeBlock->numParameters; 4733 Register* r = callFrame->registers() + registerOffset +numParameters;4743 Register* r = callFrame->registers() + numParameters; 4734 4744 4735 4745 Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount; … … 4737 4747 argv[i + argCount] = argv[i]; 4738 4748 4739 VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(r) }}; 4740 return pair.i; 4741 } 4742 4743 size_t omittedArgCount = newCodeBlock->numParameters - argCount; 4744 Register* r = callFrame->registers() + registerOffset + omittedArgCount; 4745 Register* newEnd = r + newCodeBlock->numCalleeRegisters; 4746 if (!ARG_registerFile->grow(newEnd)) { 4747 ARG_globalData->exception = createStackOverflowError(callFrame); 4748 VM_THROW_EXCEPTION_2(); 4749 } 4750 4751 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount; 4752 for (size_t i = 0; i < omittedArgCount; ++i) 4753 argv[i] = jsUndefined(); 4754 4755 VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(r) }}; 4749 callFrame = CallFrame::create(r); 4750 callFrame->setCallerFrame(oldCallFrame); 4751 } else { 4752 size_t omittedArgCount = newCodeBlock->numParameters - argCount; 4753 Register* r = callFrame->registers() + omittedArgCount; 4754 Register* newEnd = r + newCodeBlock->numCalleeRegisters; 4755 if (!ARG_registerFile->grow(newEnd)) { 4756 ARG_globalData->exception = createStackOverflowError(oldCallFrame); 4757 VM_THROW_EXCEPTION_2(); 4758 } 4759 4760 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount; 4761 for (size_t i = 0; i < omittedArgCount; ++i) 4762 argv[i] = jsUndefined(); 4763 4764 callFrame = CallFrame::create(r); 4765 callFrame->setCallerFrame(oldCallFrame); 4766 } 4767 4768 VoidPtrPairValue pair = {{ newCodeBlock, callFrame }}; 4756 4769 return pair.i; 4757 4770 } … … 4771 4784 CTI::linkCall(callee, codeBlock, codeBlock->ctiCode, ARG_linkInfo2, ARG_int3); 4772 4785 4773 return codeBlock->ctiCode;4774 }4775 4776 void* Machine::cti_vm_compile(CTI_ARGS)4777 {4778 CTI_STACK_HACK();4779 4780 CodeBlock* codeBlock = ARG_callFrame->codeBlock();4781 if (!codeBlock->ctiCode)4782 CTI::compile(ARG_globalData->machine, ARG_callFrame, codeBlock);4783 4786 return codeBlock->ctiCode; 4784 4787 } … … 4934 4937 } 4935 4938 4936 JSObject* Machine::cti_op_construct_JSConstruct Fast(CTI_ARGS)4939 JSObject* Machine::cti_op_construct_JSConstruct(CTI_ARGS) 4937 4940 { 4938 4941 CTI_STACK_HACK(); … … 4944 4947 4945 4948 StructureID* structure; 4946 if (ARG_src 2->isObject())4947 structure = asObject(ARG_src 2)->inheritorID();4949 if (ARG_src5->isObject()) 4950 structure = asObject(ARG_src5)->inheritorID(); 4948 4951 else 4949 4952 structure = asFunction(ARG_src1)->m_scopeChain.node()->globalObject()->emptyObjectStructure(); 4950 4953 return new (ARG_globalData) JSObject(structure); 4951 }4952 4953 VoidPtrPair Machine::cti_op_construct_JSConstruct(CTI_ARGS)4954 {4955 CTI_STACK_HACK();4956 4957 CallFrame* callFrame = ARG_callFrame;4958 4959 JSFunction* constructor = asFunction(ARG_src1);4960 int registerOffset = ARG_int2;4961 int argCount = ARG_int3;4962 JSValue* constrProtoVal = ARG_src5;4963 int firstArg = ARG_int6;4964 4965 #ifndef NDEBUG4966 ConstructData constructData;4967 ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS);4968 #endif4969 4970 ScopeChainNode* callDataScopeChain = constructor->m_scopeChain.node();4971 FunctionBodyNode* functionBodyNode = constructor->m_body.get();4972 CodeBlock* newCodeBlock = &functionBodyNode->byteCode(callDataScopeChain);4973 4974 StructureID* structure;4975 if (constrProtoVal->isObject())4976 structure = asObject(constrProtoVal)->inheritorID();4977 else4978 structure = callDataScopeChain->globalObject()->emptyObjectStructure();4979 JSObject* newObject = new (ARG_globalData) JSObject(structure);4980 callFrame[firstArg] = newObject; // "this" value4981 4982 if (LIKELY(argCount == newCodeBlock->numParameters)) {4983 VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(callFrame->registers() + registerOffset) }};4984 return pair.i;4985 }4986 4987 if (argCount > newCodeBlock->numParameters) {4988 size_t numParameters = newCodeBlock->numParameters;4989 Register* r = callFrame->registers() + registerOffset + numParameters;4990 4991 Register* argv = r - RegisterFile::CallFrameHeaderSize - numParameters - argCount;4992 for (size_t i = 0; i < numParameters; ++i)4993 argv[i + argCount] = argv[i];4994 4995 VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(r) }};4996 return pair.i;4997 }4998 4999 size_t omittedArgCount = newCodeBlock->numParameters - argCount;5000 Register* r = callFrame->registers() + registerOffset + omittedArgCount;5001 Register* newEnd = r + newCodeBlock->numCalleeRegisters;5002 if (!ARG_registerFile->grow(newEnd)) {5003 ARG_globalData->exception = createStackOverflowError(callFrame);5004 VM_THROW_EXCEPTION_2();5005 }5006 5007 Register* argv = r - RegisterFile::CallFrameHeaderSize - omittedArgCount;5008 for (size_t i = 0; i < omittedArgCount; ++i)5009 argv[i] = jsUndefined();5010 5011 VoidPtrPairValue pair = {{ newCodeBlock, CallFrame::create(r) }};5012 return pair.i;5013 4954 } 5014 4955 -
trunk/JavaScriptCore/VM/Machine.h
r37998 r38209 191 191 static JSValue* SFX_CALL cti_op_mul(CTI_ARGS); 192 192 static JSObject* SFX_CALL cti_op_new_func(CTI_ARGS); 193 static VoidPtrPair SFX_CALL cti_op_call_JSFunction(CTI_ARGS); 193 static void* SFX_CALL cti_op_call_JSFunction(CTI_ARGS); 194 static VoidPtrPair SFX_CALL cti_op_call_arityCheck(CTI_ARGS); 194 195 static JSValue* SFX_CALL cti_op_call_NotJSFunction(CTI_ARGS); 195 196 static void SFX_CALL cti_op_create_arguments(CTI_ARGS); … … 203 204 static JSValue* SFX_CALL cti_op_resolve(CTI_ARGS); 204 205 static JSValue* SFX_CALL cti_op_resolve_global(CTI_ARGS); 205 static JSObject* SFX_CALL cti_op_construct_JSConstructFast(CTI_ARGS); 206 static VoidPtrPair SFX_CALL cti_op_construct_JSConstruct(CTI_ARGS); 206 static JSObject* SFX_CALL cti_op_construct_JSConstruct(CTI_ARGS); 207 207 static JSValue* SFX_CALL cti_op_construct_NotJSConstruct(CTI_ARGS); 208 208 static JSValue* SFX_CALL cti_op_get_by_val(CTI_ARGS); … … 269 269 270 270 static JSValue* SFX_CALL cti_vm_throw(CTI_ARGS); 271 static void* SFX_CALL cti_vm_compile(CTI_ARGS);272 271 static void* SFX_CALL cti_vm_lazyLinkCall(CTI_ARGS); 273 272 static JSObject* SFX_CALL cti_op_push_activation(CTI_ARGS); -
trunk/JavaScriptCore/parser/Nodes.h
r38205 r38209 2246 2246 2247 2247 class FunctionBodyNode : public ScopeNode { 2248 friend class CTI; 2248 2249 public: 2249 2250 static FunctionBodyNode* create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants) JSC_FAST_CALL;
Note: See TracChangeset
for help on using the changeset viewer.