diff options
author | Feng Qian <> | 2009-04-10 18:11:29 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-04-10 18:11:29 -0700 |
commit | 8f72e70a9fd78eec56623b3a62e68f16b7b27e28 (patch) | |
tree | 181bf9a400c30a1bf34ea6d72560e8d00111d549 /JavaScriptCore/jit/JITCall.cpp | |
parent | 7ed56f225e0ade046e1c2178977f72b2d896f196 (diff) | |
download | external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.zip external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.gz external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.bz2 |
AI 145796: Land the WebKit merge @r42026.
Automated import of CL 145796
Diffstat (limited to 'JavaScriptCore/jit/JITCall.cpp')
-rw-r--r-- | JavaScriptCore/jit/JITCall.cpp | 108 |
1 files changed, 51 insertions, 57 deletions
diff --git a/JavaScriptCore/jit/JITCall.cpp b/JavaScriptCore/jit/JITCall.cpp index af26712..62c7149 100644 --- a/JavaScriptCore/jit/JITCall.cpp +++ b/JavaScriptCore/jit/JITCall.cpp @@ -49,10 +49,11 @@ void JIT::unlinkCall(CallLinkInfo* callLinkInfo) // When the JSFunction is deleted the pointer embedded in the instruction stream will no longer be valid // (and, if a new JSFunction happened to be constructed at the same location, we could get a false positive // match). Reset the check so it no longer matches. - DataLabelPtr::patch(callLinkInfo->hotPathBegin, JSValuePtr::encode(jsImpossibleValue())); + callLinkInfo->hotPathBegin.repatch(JSValuePtr::encode(jsImpossibleValue())); } -void JIT::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount) +//void JIT::linkCall(JSFunction* , CodeBlock* , JITCode , CallLinkInfo* callLinkInfo, int ) +void JIT::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, JITCode ctiCode, CallLinkInfo* callLinkInfo, int callerArgCount) { // Currently we only link calls with the exact number of arguments. if (callerArgCount == calleeCodeBlock->m_numParameters) { @@ -60,24 +61,23 @@ void JIT::linkCall(JSFunction* callee, CodeBlock* calleeCodeBlock, void* ctiCode calleeCodeBlock->addCaller(callLinkInfo); - DataLabelPtr::patch(callLinkInfo->hotPathBegin, callee); - Jump::patch(callLinkInfo->hotPathOther, ctiCode); + callLinkInfo->hotPathBegin.repatch(callee); + callLinkInfo->hotPathOther.relink(ctiCode.addressForCall()); } // patch the instruction that jumps out to the cold path, so that we only try to link once. - void* patchCheck = reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(callLinkInfo->hotPathBegin) + patchOffsetOpCallCompareToJump); - Jump::patch(patchCheck, callLinkInfo->coldPathOther); + callLinkInfo->hotPathBegin.jumpAtOffset(patchOffsetOpCallCompareToJump).relink(callLinkInfo->coldPathOther); } void JIT::compileOpCallInitializeCallFrame() { - store32(X86::edx, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)))); + store32(regT1, Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)))); - loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node)), X86::edx); // newScopeChain + loadPtr(Address(regT2, FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node)), regT1); // newScopeChain storePtr(ImmPtr(JSValuePtr::encode(noValue())), Address(callFrameRegister, RegisterFile::OptionalCalleeArguments * static_cast<int>(sizeof(Register)))); - storePtr(X86::ecx, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register)))); - storePtr(X86::edx, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)))); + storePtr(regT2, Address(callFrameRegister, RegisterFile::Callee * static_cast<int>(sizeof(Register)))); + storePtr(regT1, Address(callFrameRegister, RegisterFile::ScopeChain * static_cast<int>(sizeof(Register)))); } void JIT::compileOpCallSetupArgs(Instruction* instruction) @@ -86,7 +86,7 @@ void JIT::compileOpCallSetupArgs(Instruction* instruction) int registerOffset = instruction[4].u.operand; // ecx holds func - emitPutJITStubArg(X86::ecx, 1); + emitPutJITStubArg(regT2, 1); emitPutJITStubArgConstant(registerOffset, 2); emitPutJITStubArgConstant(argCount, 3); } @@ -97,7 +97,7 @@ void JIT::compileOpCallEvalSetupArgs(Instruction* instruction) int registerOffset = instruction[4].u.operand; // ecx holds func - emitPutJITStubArg(X86::ecx, 1); + emitPutJITStubArg(regT2, 1); emitPutJITStubArgConstant(registerOffset, 2); emitPutJITStubArgConstant(argCount, 3); } @@ -110,10 +110,10 @@ void JIT::compileOpConstructSetupArgs(Instruction* instruction) int thisRegister = instruction[6].u.operand; // ecx holds func - emitPutJITStubArg(X86::ecx, 1); + emitPutJITStubArg(regT2, 1); emitPutJITStubArgConstant(registerOffset, 2); emitPutJITStubArgConstant(argCount, 3); - emitPutJITStubArgFromVirtualRegister(proto, 4, X86::eax); + emitPutJITStubArgFromVirtualRegister(proto, 4, regT0); emitPutJITStubArgConstant(thisRegister, 5); } @@ -129,14 +129,14 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) // Handle eval Jump wasEval; if (opcodeID == op_call_eval) { - emitGetVirtualRegister(callee, X86::ecx); + emitGetVirtualRegister(callee, regT2); compileOpCallEvalSetupArgs(instruction); - emitCTICall(Interpreter::cti_op_call_eval); - wasEval = jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsImpossibleValue()))); + emitCTICall(JITStubs::cti_op_call_eval); + wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValuePtr::encode(jsImpossibleValue()))); } - emitGetVirtualRegister(callee, X86::ecx); + emitGetVirtualRegister(callee, regT2); // The arguments have been set up on the hot path for op_call_eval if (opcodeID == op_call) compileOpCallSetupArgs(instruction); @@ -144,22 +144,22 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) compileOpConstructSetupArgs(instruction); // Check for JSFunctions. - emitJumpSlowCaseIfNotJSCell(X86::ecx); - addSlowCase(jnePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr))); + emitJumpSlowCaseIfNotJSCell(regT2); + addSlowCase(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr))); // First, in the case of a construct, allocate the new object. if (opcodeID == op_construct) { - emitCTICall(Interpreter::cti_op_construct_JSConstruct); + emitCTICall(JITStubs::cti_op_construct_JSConstruct); emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); - emitGetVirtualRegister(callee, X86::ecx); + emitGetVirtualRegister(callee, regT2); } // Speculatively roll the callframe, assuming argCount will match the arity. storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); - move(Imm32(argCount), X86::edx); + move(Imm32(argCount), regT1); - emitNakedCall(m_interpreter->m_ctiVirtualCall); + emitNakedCall(m_globalData->jitStubs.ctiVirtualCall()); if (opcodeID == op_call_eval) wasEval.link(this); @@ -178,7 +178,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: linkSlowCase(iter); // This handles host functions - emitCTICall(((opcodeID == op_construct) ? Interpreter::cti_op_construct_NotJSConstruct : Interpreter::cti_op_call_NotJSFunction)); + emitCTICall(((opcodeID == op_construct) ? JITStubs::cti_op_construct_NotJSConstruct : JITStubs::cti_op_call_NotJSFunction)); // Put the return value in dst. In the interpreter, op_ret does this. emitPutVirtualRegister(dst); @@ -187,12 +187,6 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: #else -static NO_RETURN void unreachable() -{ - ASSERT_NOT_REACHED(); - exit(1); -} - void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex) { int dst = instruction[1].u.operand; @@ -203,18 +197,18 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca // Handle eval Jump wasEval; if (opcodeID == op_call_eval) { - emitGetVirtualRegister(callee, X86::ecx); + emitGetVirtualRegister(callee, regT2); compileOpCallEvalSetupArgs(instruction); - emitCTICall(Interpreter::cti_op_call_eval); - wasEval = jnePtr(X86::eax, ImmPtr(JSValuePtr::encode(jsImpossibleValue()))); + emitCTICall(JITStubs::cti_op_call_eval); + wasEval = branchPtr(NotEqual, regT0, ImmPtr(JSValuePtr::encode(jsImpossibleValue()))); } // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee. // This deliberately leaves the callee in ecx, used when setting up the stack frame below - emitGetVirtualRegister(callee, X86::ecx); + emitGetVirtualRegister(callee, regT2); DataLabelPtr addressOfLinkedFunctionCheck; - Jump jumpToSlow = jnePtrWithPatch(X86::ecx, addressOfLinkedFunctionCheck, ImmPtr(JSValuePtr::encode(jsImpossibleValue()))); + Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT2, addressOfLinkedFunctionCheck, ImmPtr(JSValuePtr::encode(jsImpossibleValue()))); addSlowCase(jumpToSlow); ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump); m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck; @@ -226,25 +220,25 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca int proto = instruction[5].u.operand; int thisRegister = instruction[6].u.operand; - emitPutJITStubArg(X86::ecx, 1); - emitPutJITStubArgFromVirtualRegister(proto, 4, X86::eax); - emitCTICall(Interpreter::cti_op_construct_JSConstruct); + emitPutJITStubArg(regT2, 1); + emitPutJITStubArgFromVirtualRegister(proto, 4, regT0); + emitCTICall(JITStubs::cti_op_construct_JSConstruct); emitPutVirtualRegister(thisRegister); - emitGetVirtualRegister(callee, X86::ecx); + emitGetVirtualRegister(callee, regT2); } // Fast version of stack frame initialization, directly relative to edi. // Note that this omits to set up RegisterFile::CodeBlock, which is set in the callee storePtr(ImmPtr(JSValuePtr::encode(noValue())), Address(callFrameRegister, (registerOffset + RegisterFile::OptionalCalleeArguments) * static_cast<int>(sizeof(Register)))); - storePtr(X86::ecx, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register)))); - loadPtr(Address(X86::ecx, FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node)), X86::edx); // newScopeChain + storePtr(regT2, Address(callFrameRegister, (registerOffset + RegisterFile::Callee) * static_cast<int>(sizeof(Register)))); + loadPtr(Address(regT2, FIELD_OFFSET(JSFunction, m_scopeChain) + FIELD_OFFSET(ScopeChain, m_node)), regT1); // newScopeChain store32(Imm32(argCount), Address(callFrameRegister, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register)))); storePtr(callFrameRegister, Address(callFrameRegister, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register)))); - storePtr(X86::edx, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register)))); + storePtr(regT1, Address(callFrameRegister, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register)))); addPtr(Imm32(registerOffset * sizeof(Register)), callFrameRegister); // Call to the callee - m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(reinterpret_cast<void*>(unreachable)); + m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(reinterpret_cast<void*>(0)); if (opcodeID == op_call_eval) wasEval.link(this); @@ -271,24 +265,24 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: compileOpConstructSetupArgs(instruction); // Fast check for JS function. - Jump callLinkFailNotObject = emitJumpIfNotJSCell(X86::ecx); - Jump callLinkFailNotJSFunction = jnePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr)); + Jump callLinkFailNotObject = emitJumpIfNotJSCell(regT2); + Jump callLinkFailNotJSFunction = branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr)); // First, in the case of a construct, allocate the new object. if (opcodeID == op_construct) { - emitCTICall(Interpreter::cti_op_construct_JSConstruct); + emitCTICall(JITStubs::cti_op_construct_JSConstruct); emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); - emitGetVirtualRegister(callee, X86::ecx); + emitGetVirtualRegister(callee, regT2); } - move(Imm32(argCount), X86::edx); + move(Imm32(argCount), regT1); // Speculatively roll the callframe, assuming argCount will match the arity. storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation = - emitNakedCall(m_interpreter->m_ctiVirtualCallPreLink); + emitNakedCall(m_globalData->jitStubs.ctiVirtualCallPreLink()); Jump storeResultForFirstRun = jump(); @@ -303,14 +297,14 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: compileOpConstructSetupArgs(instruction); // Check for JSFunctions. - Jump isNotObject = emitJumpIfNotJSCell(X86::ecx); - Jump isJSFunction = jePtr(Address(X86::ecx), ImmPtr(m_interpreter->m_jsFunctionVptr)); + Jump isNotObject = emitJumpIfNotJSCell(regT2); + Jump isJSFunction = branchPtr(Equal, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr)); // This handles host functions isNotObject.link(this); callLinkFailNotObject.link(this); callLinkFailNotJSFunction.link(this); - emitCTICall(((opcodeID == op_construct) ? Interpreter::cti_op_construct_NotJSConstruct : Interpreter::cti_op_call_NotJSFunction)); + emitCTICall(((opcodeID == op_construct) ? JITStubs::cti_op_construct_NotJSConstruct : JITStubs::cti_op_call_NotJSFunction)); Jump wasNotJSFunction = jump(); // Next, handle JSFunctions... @@ -318,17 +312,17 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>: // First, in the case of a construct, allocate the new object. if (opcodeID == op_construct) { - emitCTICall(Interpreter::cti_op_construct_JSConstruct); + emitCTICall(JITStubs::cti_op_construct_JSConstruct); emitPutVirtualRegister(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); - emitGetVirtualRegister(callee, X86::ecx); + emitGetVirtualRegister(callee, regT2); } // Speculatively roll the callframe, assuming argCount will match the arity. storePtr(callFrameRegister, Address(callFrameRegister, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)))); addPtr(Imm32(registerOffset * static_cast<int>(sizeof(Register))), callFrameRegister); - move(Imm32(argCount), X86::edx); + move(Imm32(argCount), regT1); - emitNakedCall(m_interpreter->m_ctiVirtualCall); + emitNakedCall(m_globalData->jitStubs.ctiVirtualCall()); // Put the return value in dst. In the interpreter, op_ret does this. wasNotJSFunction.link(this); |