Commit c8151c4c authored by mark.lam@apple.com's avatar mark.lam@apple.com

Adjust CallFrameHeader's ReturnPC and CallFrame locations to match the native ABI .

https://bugs.webkit.org/show_bug.cgi?id=123444.

Reviewed by Geoffrey Garen.

- Introduced an explicit CallerFrameAndPC struct.
- A CallFrame is expected to start with a CallerFrameAndPC struct. 
- The Register class no longer supports CallFrame* and Instruction*.

  These hides the differences between JSVALUE32_64 and JSVALUE64 in
  terms of managing the callerFrame() and returnPC() values.

- Convert all uses of JSStack::CallerFrame and JSStack::ReturnPC to
  go through CallFrame to access the appropriate values and offsets.
  CallFrame, in turn, will access the callerFrame and returnPC via
  the CallerFrameAndPC struct.

- InlineCallFrame will provide offsets for its callerFrame and
  returnPC. It will make use of CallFrame::callerFrameOffset() and
  CallerFrame::returnPCOffset() to compute these.

* bytecode/CodeOrigin.h:
(JSC::InlineCallFrame::callerFrameOffset):
(JSC::InlineCallFrame::returnPCOffset):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::compileEntry):
(JSC::DFG::JITCompiler::compileExceptionHandlers):
* dfg/DFGOSRExitCompilerCommon.cpp:
(JSC::DFG::reifyInlinedCallFrames):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::calleeFrameSlot):
(JSC::DFG::SpeculativeJIT::calleeArgumentSlot):
(JSC::DFG::SpeculativeJIT::calleeFrameTagSlot):
(JSC::DFG::SpeculativeJIT::calleeFramePayloadSlot):
(JSC::DFG::SpeculativeJIT::calleeArgumentTagSlot):
(JSC::DFG::SpeculativeJIT::calleeArgumentPayloadSlot):
- Prefixed all the above with callee since they apply to the callee frame.
(JSC::DFG::SpeculativeJIT::calleeFrameCallerFrame):
- Added to set the callerFrame pointer in the callee frame.

* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLink.cpp:
(JSC::FTL::compileEntry):
(JSC::FTL::link):
* interpreter/CallFrame.h:
(JSC::ExecState::callerFrame):
(JSC::ExecState::callerFrameOffset):
(JSC::ExecState::returnPC):
(JSC::ExecState::hasReturnPC):
(JSC::ExecState::clearReturnPC):
(JSC::ExecState::returnPCOffset):
(JSC::ExecState::setCallerFrame):
(JSC::ExecState::setReturnPC):
(JSC::ExecState::callerFrameAndPC):
* interpreter/JSStack.h:
* interpreter/Register.h:
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitPutToCallFrameHeader):
- Convert to using storePtr() here and simplify the code.
(JSC::AssemblyHelpers::emitGetCallerFrameFromCallFrameHeaderPtr):
(JSC::AssemblyHelpers::emitPutCallerFrameToCallFrameHeader):
(JSC::AssemblyHelpers::emitGetReturnPCFromCallFrameHeaderPtr):
(JSC::AssemblyHelpers::emitPutReturnPCToCallFrameHeader):
- Helpers to emit gets/puts of the callerFrame and returnPC.
(JSC::AssemblyHelpers::addressForByteOffset):
* jit/JIT.cpp:
(JSC::JIT::JIT):
(JSC::JIT::privateCompile):
(JSC::JIT::privateCompileExceptionHandlers):
* jit/JITCall.cpp:
(JSC::JIT::compileCallEval):
(JSC::JIT::compileOpCall):
* jit/JITCall32_64.cpp:
(JSC::JIT::emit_op_ret):
(JSC::JIT::emit_op_ret_object_or_this):
(JSC::JIT::compileCallEval):
(JSC::JIT::compileOpCall):
* jit/JITInlines.h:
(JSC::JIT::unmap):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_end):
(JSC::JIT::emit_op_ret):
(JSC::JIT::emit_op_ret_object_or_this):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::privateCompileCTINativeCall):
(JSC::JIT::emit_op_end):
* jit/JITOperations.cpp:
* jit/SpecializedThunkJIT.h:
(JSC::SpecializedThunkJIT::returnJSValue):
(JSC::SpecializedThunkJIT::returnDouble):
(JSC::SpecializedThunkJIT::returnInt32):
(JSC::SpecializedThunkJIT::returnJSCell):
* jit/ThunkGenerators.cpp:
(JSC::throwExceptionFromCallSlowPathGenerator):
(JSC::slowPathFor):
(JSC::nativeForGenerator):

* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
* llint/LowLevelInterpreter.asm:
- Updated offsets and asserts to match the new CallFrame layout.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@158315 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 69780866
2013-10-30 Mark Lam <mark.lam@apple.com>
Adjust CallFrameHeader's ReturnPC and CallFrame locations to match the native ABI .
https://bugs.webkit.org/show_bug.cgi?id=123444.
Reviewed by Geoffrey Garen.
- Introduced an explicit CallerFrameAndPC struct.
- A CallFrame is expected to start with a CallerFrameAndPC struct.
- The Register class no longer supports CallFrame* and Instruction*.
These hides the differences between JSVALUE32_64 and JSVALUE64 in
terms of managing the callerFrame() and returnPC() values.
- Convert all uses of JSStack::CallerFrame and JSStack::ReturnPC to
go through CallFrame to access the appropriate values and offsets.
CallFrame, in turn, will access the callerFrame and returnPC via
the CallerFrameAndPC struct.
- InlineCallFrame will provide offsets for its callerFrame and
returnPC. It will make use of CallFrame::callerFrameOffset() and
CallerFrame::returnPCOffset() to compute these.
* bytecode/CodeOrigin.h:
(JSC::InlineCallFrame::callerFrameOffset):
(JSC::InlineCallFrame::returnPCOffset):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::compileEntry):
(JSC::DFG::JITCompiler::compileExceptionHandlers):
* dfg/DFGOSRExitCompilerCommon.cpp:
(JSC::DFG::reifyInlinedCallFrames):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::calleeFrameSlot):
(JSC::DFG::SpeculativeJIT::calleeArgumentSlot):
(JSC::DFG::SpeculativeJIT::calleeFrameTagSlot):
(JSC::DFG::SpeculativeJIT::calleeFramePayloadSlot):
(JSC::DFG::SpeculativeJIT::calleeArgumentTagSlot):
(JSC::DFG::SpeculativeJIT::calleeArgumentPayloadSlot):
- Prefixed all the above with callee since they apply to the callee frame.
(JSC::DFG::SpeculativeJIT::calleeFrameCallerFrame):
- Added to set the callerFrame pointer in the callee frame.
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLink.cpp:
(JSC::FTL::compileEntry):
(JSC::FTL::link):
* interpreter/CallFrame.h:
(JSC::ExecState::callerFrame):
(JSC::ExecState::callerFrameOffset):
(JSC::ExecState::returnPC):
(JSC::ExecState::hasReturnPC):
(JSC::ExecState::clearReturnPC):
(JSC::ExecState::returnPCOffset):
(JSC::ExecState::setCallerFrame):
(JSC::ExecState::setReturnPC):
(JSC::ExecState::callerFrameAndPC):
* interpreter/JSStack.h:
* interpreter/Register.h:
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::emitPutToCallFrameHeader):
- Convert to using storePtr() here and simplify the code.
(JSC::AssemblyHelpers::emitGetCallerFrameFromCallFrameHeaderPtr):
(JSC::AssemblyHelpers::emitPutCallerFrameToCallFrameHeader):
(JSC::AssemblyHelpers::emitGetReturnPCFromCallFrameHeaderPtr):
(JSC::AssemblyHelpers::emitPutReturnPCToCallFrameHeader):
- Helpers to emit gets/puts of the callerFrame and returnPC.
(JSC::AssemblyHelpers::addressForByteOffset):
* jit/JIT.cpp:
(JSC::JIT::JIT):
(JSC::JIT::privateCompile):
(JSC::JIT::privateCompileExceptionHandlers):
* jit/JITCall.cpp:
(JSC::JIT::compileCallEval):
(JSC::JIT::compileOpCall):
* jit/JITCall32_64.cpp:
(JSC::JIT::emit_op_ret):
(JSC::JIT::emit_op_ret_object_or_this):
(JSC::JIT::compileCallEval):
(JSC::JIT::compileOpCall):
* jit/JITInlines.h:
(JSC::JIT::unmap):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_end):
(JSC::JIT::emit_op_ret):
(JSC::JIT::emit_op_ret_object_or_this):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::privateCompileCTINativeCall):
(JSC::JIT::emit_op_end):
* jit/JITOperations.cpp:
* jit/SpecializedThunkJIT.h:
(JSC::SpecializedThunkJIT::returnJSValue):
(JSC::SpecializedThunkJIT::returnDouble):
(JSC::SpecializedThunkJIT::returnInt32):
(JSC::SpecializedThunkJIT::returnJSCell):
* jit/ThunkGenerators.cpp:
(JSC::throwExceptionFromCallSlowPathGenerator):
(JSC::slowPathFor):
(JSC::nativeForGenerator):
* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
* llint/LowLevelInterpreter.asm:
- Updated offsets and asserts to match the new CallFrame layout.
2013-10-30 Filip Pizlo <fpizlo@apple.com>
Unreviewed, fix Mac.
......
......@@ -142,6 +142,9 @@ struct InlineCallFrame {
CodeBlock* baselineCodeBlock() const;
ptrdiff_t callerFrameOffset() const { return stackOffset * sizeof(Register) + CallFrame::callerFrameOffset(); }
ptrdiff_t returnPCOffset() const { return stackOffset * sizeof(Register) + CallFrame::returnPCOffset(); }
void dumpBriefFunctionInformation(PrintStream&) const;
void dump(PrintStream&) const;
void dumpInContext(PrintStream&, DumpContext*) const;
......
......@@ -99,7 +99,7 @@ void JITCompiler::compileEntry()
// check) which will be dependent on stack layout. (We'd need to account for this in
// both normal return code and when jumping to an exception handler).
preserveReturnAddressAfterCall(GPRInfo::regT2);
emitPutToCallFrameHeader(GPRInfo::regT2, JSStack::ReturnPC);
emitPutReturnPCToCallFrameHeader(GPRInfo::regT2);
emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
}
......@@ -127,7 +127,7 @@ void JITCompiler::compileExceptionHandlers()
if (!m_exceptionChecksWithCallFrameRollback.empty()) {
// Remove hostCallFrameFlag from caller.
m_exceptionChecksWithCallFrameRollback.link(this);
emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::argumentGPR0);
emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR0);
andPtr(TrustedImm32(safeCast<int32_t>(~CallFrame::hostCallFrameFlag())), GPRInfo::argumentGPR0);
doLookup = jump();
}
......
......@@ -111,8 +111,8 @@ void reifyInlinedCallFrames(CCallHelpers& jit, const OSRExitBase& exit)
jit.storePtr(AssemblyHelpers::TrustedImmPtr(baselineCodeBlock), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CodeBlock)));
if (!inlineCallFrame->isClosureCall)
jit.store64(AssemblyHelpers::TrustedImm64(JSValue::encode(JSValue(inlineCallFrame->calleeConstant()->scope()))), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ScopeChain)));
jit.store64(callerFrameGPR, AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CallerFrame)));
jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ReturnPC)));
jit.store64(callerFrameGPR, AssemblyHelpers::addressForByteOffset(inlineCallFrame->callerFrameOffset()));
jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset()));
uint32_t locationBits = CallFrame::Location::encodeAsBytecodeOffset(codeOrigin.bytecodeIndex);
jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ArgumentCount)));
jit.store32(AssemblyHelpers::TrustedImm32(inlineCallFrame->arguments.size()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ArgumentCount)));
......@@ -127,9 +127,8 @@ void reifyInlinedCallFrames(CCallHelpers& jit, const OSRExitBase& exit)
jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ScopeChain)));
if (!inlineCallFrame->isClosureCall)
jit.storePtr(AssemblyHelpers::TrustedImmPtr(inlineCallFrame->calleeConstant()->scope()), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ScopeChain)));
jit.store32(AssemblyHelpers::TrustedImm32(JSValue::CellTag), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CallerFrame)));
jit.storePtr(callerFrameGPR, AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::CallerFrame)));
jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::payloadFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ReturnPC)));
jit.storePtr(callerFrameGPR, AssemblyHelpers::addressForByteOffset(inlineCallFrame->callerFrameOffset()));
jit.storePtr(AssemblyHelpers::TrustedImmPtr(jumpTarget), AssemblyHelpers::addressForByteOffset(inlineCallFrame->returnPCOffset()));
Instruction* instruction = baselineCodeBlock->instructions().begin() + codeOrigin.bytecodeIndex;
uint32_t locationBits = CallFrame::Location::encodeAsBytecodeInstruction(instruction);
jit.store32(AssemblyHelpers::TrustedImm32(locationBits), AssemblyHelpers::tagFor((VirtualRegister)(inlineCallFrame->stackOffset + JSStack::ArgumentCount)));
......
......@@ -731,35 +731,40 @@ public:
}
// Access to our fixed callee CallFrame.
MacroAssembler::Address callFrameSlot(int numArgs, int slot)
MacroAssembler::Address calleeFrameSlot(int numArgs, int slot)
{
return MacroAssembler::Address(GPRInfo::callFrameRegister, calleeFrameOffset(numArgs) + sizeof(Register) * slot);
}
// Access to our fixed callee CallFrame.
MacroAssembler::Address argumentSlot(int numArgs, int argument)
MacroAssembler::Address calleeArgumentSlot(int numArgs, int argument)
{
return callFrameSlot(numArgs, virtualRegisterForArgument(argument).offset());
return calleeFrameSlot(numArgs, virtualRegisterForArgument(argument).offset());
}
MacroAssembler::Address callFrameTagSlot(int numArgs, int slot)
MacroAssembler::Address calleeFrameTagSlot(int numArgs, int slot)
{
return callFrameSlot(numArgs, slot).withOffset(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
return calleeFrameSlot(numArgs, slot).withOffset(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
}
MacroAssembler::Address callFramePayloadSlot(int numArgs, int slot)
MacroAssembler::Address calleeFramePayloadSlot(int numArgs, int slot)
{
return callFrameSlot(numArgs, slot).withOffset(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
return calleeFrameSlot(numArgs, slot).withOffset(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
}
MacroAssembler::Address argumentTagSlot(int numArgs, int argument)
MacroAssembler::Address calleeArgumentTagSlot(int numArgs, int argument)
{
return argumentSlot(numArgs, argument).withOffset(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
return calleeArgumentSlot(numArgs, argument).withOffset(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag));
}
MacroAssembler::Address argumentPayloadSlot(int numArgs, int argument)
MacroAssembler::Address calleeArgumentPayloadSlot(int numArgs, int argument)
{
return argumentSlot(numArgs, argument).withOffset(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
return calleeArgumentSlot(numArgs, argument).withOffset(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload));
}
MacroAssembler::Address calleeFrameCallerFrame(int numArgs)
{
return calleeFrameSlot(numArgs, 0).withOffset(CallFrame::callerFrameOffset());
}
void emitCall(Node*);
......
......@@ -659,10 +659,10 @@ void SpeculativeJIT::emitCall(Node* node)
int numArgs = numPassedArgs + dummyThisArgument;
m_jit.store32(MacroAssembler::TrustedImm32(numArgs), callFramePayloadSlot(numArgs, JSStack::ArgumentCount));
m_jit.storePtr(GPRInfo::callFrameRegister, callFramePayloadSlot(numArgs, JSStack::CallerFrame));
m_jit.store32(calleePayloadGPR, callFramePayloadSlot(numArgs, JSStack::Callee));
m_jit.store32(calleeTagGPR, callFrameTagSlot(numArgs, JSStack::Callee));
m_jit.store32(MacroAssembler::TrustedImm32(numArgs), calleeFramePayloadSlot(numArgs, JSStack::ArgumentCount));
m_jit.storePtr(GPRInfo::callFrameRegister, calleeFrameCallerFrame(numArgs));
m_jit.store32(calleePayloadGPR, calleeFramePayloadSlot(numArgs, JSStack::Callee));
m_jit.store32(calleeTagGPR, calleeFrameTagSlot(numArgs, JSStack::Callee));
for (int i = 0; i < numPassedArgs; i++) {
Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
......@@ -671,8 +671,8 @@ void SpeculativeJIT::emitCall(Node* node)
GPRReg argPayloadGPR = arg.payloadGPR();
use(argEdge);
m_jit.store32(argTagGPR, argumentTagSlot(numArgs, i + dummyThisArgument));
m_jit.store32(argPayloadGPR, argumentPayloadSlot(numArgs, i + dummyThisArgument));
m_jit.store32(argTagGPR, calleeArgumentTagSlot(numArgs, i + dummyThisArgument));
m_jit.store32(argPayloadGPR, calleeArgumentPayloadSlot(numArgs, i + dummyThisArgument));
}
flushRegisters();
......@@ -3093,9 +3093,9 @@ void SpeculativeJIT::compile(Node* node)
}
// Grab the return address.
m_jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT2);
m_jit.emitGetReturnPCFromCallFrameHeaderPtr(GPRInfo::regT2);
// Restore our caller's "r".
m_jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
m_jit.emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::callFrameRegister);
// Return.
m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT2);
m_jit.ret();
......
......@@ -683,9 +683,9 @@ void SpeculativeJIT::emitCall(Node* node)
int numArgs = numPassedArgs + dummyThisArgument;
m_jit.store32(MacroAssembler::TrustedImm32(numArgs), callFramePayloadSlot(numArgs, JSStack::ArgumentCount));
m_jit.store64(GPRInfo::callFrameRegister, callFrameSlot(numArgs, JSStack::CallerFrame));
m_jit.store64(calleeGPR, callFrameSlot(numArgs, JSStack::Callee));
m_jit.store32(MacroAssembler::TrustedImm32(numArgs), calleeFramePayloadSlot(numArgs, JSStack::ArgumentCount));
m_jit.store64(GPRInfo::callFrameRegister, calleeFrameCallerFrame(numArgs));
m_jit.store64(calleeGPR, calleeFrameSlot(numArgs, JSStack::Callee));
for (int i = 0; i < numPassedArgs; i++) {
Edge argEdge = m_jit.graph().m_varArgChildren[node->firstChild() + 1 + i];
......@@ -693,7 +693,7 @@ void SpeculativeJIT::emitCall(Node* node)
GPRReg argGPR = arg.gpr();
use(argEdge);
m_jit.store64(argGPR, argumentSlot(numArgs, i + dummyThisArgument));
m_jit.store64(argGPR, calleeArgumentSlot(numArgs, i + dummyThisArgument));
}
flushRegisters();
......@@ -3413,9 +3413,9 @@ void SpeculativeJIT::compile(Node* node)
m_jit.move(op1.gpr(), GPRInfo::returnValueGPR);
// Grab the return address.
m_jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
m_jit.emitGetReturnPCFromCallFrameHeaderPtr(GPRInfo::regT1);
// Restore our caller's "r".
m_jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
m_jit.emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::callFrameRegister);
// Return.
m_jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
m_jit.ret();
......
......@@ -46,7 +46,7 @@ using namespace DFG;
static void compileEntry(CCallHelpers& jit)
{
jit.preserveReturnAddressAfterCall(GPRInfo::regT2);
jit.emitPutToCallFrameHeader(GPRInfo::regT2, JSStack::ReturnPC);
jit.emitPutReturnPCToCallFrameHeader(GPRInfo::regT2);
jit.emitPutImmediateToCallFrameHeader(jit.codeBlock(), JSStack::CodeBlock);
}
......@@ -93,8 +93,8 @@ void link(State& state)
CCallHelpers::TrustedImmPtr(reinterpret_cast<void*>(state.generatedFunction)),
GPRInfo::nonArgGPR0);
jit.call(GPRInfo::nonArgGPR0);
jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
jit.emitGetReturnPCFromCallFrameHeaderPtr(GPRInfo::regT1);
jit.emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::callFrameRegister);
jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
jit.ret();
......@@ -162,8 +162,8 @@ void link(State& state)
CCallHelpers::TrustedImmPtr(reinterpret_cast<void*>(state.generatedFunction)),
GPRInfo::nonArgGPR0);
jit.call(GPRInfo::nonArgGPR0);
jit.emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, GPRInfo::regT1);
jit.emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::callFrameRegister);
jit.emitGetReturnPCFromCallFrameHeaderPtr(GPRInfo::regT1);
jit.emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::callFrameRegister);
jit.restoreReturnAddressBeforeReturn(GPRInfo::regT1);
jit.ret();
......
......@@ -112,12 +112,13 @@ namespace JSC {
CallFrame& operator=(const Register& r) { *static_cast<Register*>(this) = r; return *this; }
CallFrame* callerFrame() const { return this[JSStack::CallerFrame].callFrame(); }
#if ENABLE(JIT) || ENABLE(LLINT)
ReturnAddressPtr returnPC() const { return ReturnAddressPtr(this[JSStack::ReturnPC].vPC()); }
bool hasReturnPC() const { return !!this[JSStack::ReturnPC].vPC(); }
void clearReturnPC() { registers()[JSStack::ReturnPC] = static_cast<Instruction*>(0); }
#endif
CallFrame* callerFrame() const { return callerFrameAndPC().callerFrame; }
static ptrdiff_t callerFrameOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, callerFrame); }
ReturnAddressPtr returnPC() const { return ReturnAddressPtr(callerFrameAndPC().pc); }
bool hasReturnPC() const { return !!callerFrameAndPC().pc; }
void clearReturnPC() { callerFrameAndPC().pc = 0; }
static ptrdiff_t returnPCOffset() { return OBJECT_OFFSETOF(CallerFrameAndPC, pc); }
AbstractPC abstractReturnPC(VM& vm) { return AbstractPC(vm, this); }
class Location {
......@@ -199,7 +200,7 @@ namespace JSC {
void setCurrentVPC(Instruction* vpc);
#endif
void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[JSStack::CallerFrame] = callerFrame; }
void setCallerFrame(CallFrame* frame) { callerFrameAndPC().callerFrame = frame; }
void setScope(JSScope* scope) { static_cast<Register*>(this)[JSStack::ScopeChain] = scope; }
ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, JSScope* scope,
......@@ -274,8 +275,8 @@ namespace JSC {
void setArgumentCountIncludingThis(int count) { static_cast<Register*>(this)[JSStack::ArgumentCount].payload() = count; }
void setCallee(JSObject* callee) { static_cast<Register*>(this)[JSStack::Callee] = Register::withCallee(callee); }
void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[JSStack::CodeBlock] = codeBlock; }
void setReturnPC(void* value) { static_cast<Register*>(this)[JSStack::ReturnPC] = (Instruction*)value; }
void setReturnPC(void* value) { callerFrameAndPC().pc = reinterpret_cast<Instruction*>(value); }
CallFrame* callerFrameNoFlags() { return callerFrame()->removeHostCallFrameFlag(); }
// CallFrame::iterate() expects a Functor that implements the following method:
......@@ -324,6 +325,9 @@ namespace JSC {
return this[argumentOffset(argIndex)].jsValue();
}
CallerFrameAndPC& callerFrameAndPC() { return *reinterpret_cast<CallerFrameAndPC*>(this); }
const CallerFrameAndPC& callerFrameAndPC() const { return *reinterpret_cast<const CallerFrameAndPC*>(this); }
friend class JSStack;
friend class VMInspector;
};
......
......@@ -48,19 +48,27 @@ namespace JSC {
class VM;
class LLIntOffsetsExtractor;
struct Instruction;
typedef ExecState CallFrame;
struct CallerFrameAndPC {
CallFrame* callerFrame;
Instruction* pc;
};
class JSStack {
WTF_MAKE_NONCOPYABLE(JSStack);
public:
enum CallFrameHeaderEntry {
CallFrameHeaderSize = 6,
FirstArgument = 7,
ThisArgument = 6,
ArgumentCount = 5,
CallerFrame = 4,
Callee = 3,
ScopeChain = 2,
ReturnPC = 1, // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*.
CodeBlock = 0,
CodeBlock = sizeof(CallerFrameAndPC) / sizeof(Register),
ScopeChain,
Callee,
ArgumentCount,
CallFrameHeaderSize,
// The following entries are not part of the CallFrameHeader but are provided here as a convenience:
ThisArgument = CallFrameHeaderSize,
FirstArgument,
};
static const size_t defaultCapacity = 512 * 1024;
......
......@@ -42,8 +42,6 @@ namespace JSC {
class JSPropertyNameIterator;
class JSScope;
struct Instruction;
typedef ExecState CallFrame;
class Register {
......@@ -56,19 +54,15 @@ namespace JSC {
JSValue jsValue() const;
EncodedJSValue encodedJSValue() const;
Register& operator=(CallFrame*);
Register& operator=(CodeBlock*);
Register& operator=(JSScope*);
Register& operator=(Instruction*);
int32_t i() const;
JSActivation* activation() const;
CallFrame* callFrame() const;
CodeBlock* codeBlock() const;
JSObject* function() const;
JSPropertyNameIterator* propertyNameIterator() const;
JSScope* scope() const;
Instruction* vPC() const;
int32_t unboxedInt32() const;
int64_t unboxedInt52() const;
int64_t unboxedStrictInt52() const;
......@@ -91,9 +85,7 @@ namespace JSC {
private:
union {
EncodedJSValue value;
CallFrame* callFrame;
CodeBlock* codeBlock;
Instruction* vPC;
EncodedValueDescriptor encodedValue;
double number;
int64_t integer;
......@@ -130,44 +122,22 @@ namespace JSC {
// Interpreter functions
ALWAYS_INLINE Register& Register::operator=(CallFrame* callFrame)
{
u.callFrame = callFrame;
return *this;
}
ALWAYS_INLINE Register& Register::operator=(CodeBlock* codeBlock)
{
u.codeBlock = codeBlock;
return *this;
}
ALWAYS_INLINE Register& Register::operator=(Instruction* vPC)
{
u.vPC = vPC;
return *this;
}
ALWAYS_INLINE int32_t Register::i() const
{
return jsValue().asInt32();
}
ALWAYS_INLINE CallFrame* Register::callFrame() const
{
return u.callFrame;
}
ALWAYS_INLINE CodeBlock* Register::codeBlock() const
{
return u.codeBlock;
}
ALWAYS_INLINE Instruction* Register::vPC() const
{
return u.vPC;
}
ALWAYS_INLINE int32_t Register::unboxedInt32() const
{
return payload();
......
......@@ -133,11 +133,7 @@ public:
}
void emitPutToCallFrameHeader(GPRReg from, JSStack::CallFrameHeaderEntry entry)
{
#if USE(JSVALUE64)
store64(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
#else
store32(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
#endif
storePtr(from, Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
}
void emitPutImmediateToCallFrameHeader(void* value, JSStack::CallFrameHeaderEntry entry)
......@@ -145,6 +141,28 @@ public:
storePtr(TrustedImmPtr(value), Address(GPRInfo::callFrameRegister, entry * sizeof(Register)));
}
void emitGetCallerFrameFromCallFrameHeaderPtr(RegisterID to)
{
loadPtr(Address(GPRInfo::callFrameRegister, CallFrame::callerFrameOffset()), to);
}
void emitPutCallerFrameToCallFrameHeader(RegisterID from)
{
storePtr(from, Address(GPRInfo::callFrameRegister, CallFrame::callerFrameOffset()));
}
void emitGetReturnPCFromCallFrameHeaderPtr(RegisterID to)
{
loadPtr(Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()), to);
}
void emitPutReturnPCToCallFrameHeader(RegisterID from)
{
storePtr(from, Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()));
}
void emitPutReturnPCToCallFrameHeader(TrustedImmPtr from)
{
storePtr(from, Address(GPRInfo::callFrameRegister, CallFrame::returnPCOffset()));
}
Jump branchIfNotCell(GPRReg reg)
{
#if USE(JSVALUE64)
......@@ -154,6 +172,10 @@ public:
#endif
}
static Address addressForByteOffset(ptrdiff_t byteOffset)
{
return Address(GPRInfo::callFrameRegister, byteOffset);
}
static Address addressFor(VirtualRegister virtualRegister)
{
ASSERT(virtualRegister.isValid());
......
......@@ -83,7 +83,7 @@ JIT::JIT(VM* vm, CodeBlock* codeBlock)
#if USE(JSVALUE32_64)
, m_jumpTargetIndex(0)
, m_mappedBytecodeOffset((unsigned)-1)
, m_mappedVirtualRegisterIndex(JSStack::ReturnPC)
, m_mappedVirtualRegisterIndex(UINT_MAX)
, m_mappedTag((RegisterID)-1)
, m_mappedPayload((RegisterID)-1)
#else
......@@ -547,7 +547,7 @@ CompilationResult JIT::privateCompile(JITCompilationEffort effort)
nop();
preserveReturnAddressAfterCall(regT2);
emitPutToCallFrameHeader(regT2, JSStack::ReturnPC);
emitPutReturnPCToCallFrameHeader(regT2);
emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
Label beginLabel(this);
......@@ -612,7 +612,7 @@ CompilationResult JIT::privateCompile(JITCompilationEffort effort)
arityCheck = label();
store8(TrustedImm32(0), &m_codeBlock->m_shouldAlwaysBeInlined);
preserveReturnAddressAfterCall(regT2);
emitPutToCallFrameHeader(regT2, JSStack::ReturnPC);
emitPutReturnPCToCallFrameHeader(regT2);
emitPutImmediateToCallFrameHeader(m_codeBlock, JSStack::CodeBlock);
load32(payloadFor(JSStack::ArgumentCount), regT1);
......@@ -802,7 +802,7 @@ void JIT::privateCompileExceptionHandlers()
if (!m_exceptionChecksWithCallFrameRollback.empty()) {
// Remove hostCallFlag from caller
m_exceptionChecksWithCallFrameRollback.link(this);
emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, GPRInfo::argumentGPR0);
emitGetCallerFrameFromCallFrameHeaderPtr(GPRInfo::argumentGPR0);
andPtr(TrustedImm32(safeCast<int32_t>(~CallFrame::hostCallFrameFlag())), GPRInfo::argumentGPR0);
doLookup = jump();
}
......
......@@ -131,7 +131,7 @@ void JIT::compileCallEval(Instruction* instruction)
{
callOperationWithCallFrameRollbackOnException(operationCallEval);
addSlowCase(branch64(Equal, regT0, TrustedImm64(JSValue::encode(JSValue()))));
emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister);
emitGetCallerFrameFromCallFrameHeaderPtr(callFrameRegister);
sampleCodeBlock(m_codeBlock);
......@@ -191,7 +191,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
store32(TrustedImm32(locationBits), Address(callFrameRegister, JSStack::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
emitGetVirtualRegister(callee, regT0); // regT0 holds callee.
store64(callFrameRegister, Address(regT1, JSStack::CallerFrame * static_cast<int>(sizeof(Register))));
store64(callFrameRegister, Address(regT1, CallFrame::callerFrameOffset()));
store64(regT0, Address(regT1, JSStack::Callee * static_cast<int>(sizeof(Register))));
move(regT1, callFrameRegister);
......
......@@ -61,8 +61,8 @@ void JIT::emit_op_ret(Instruction* currentInstruction)
unsigned dst = currentInstruction[1].u.operand;
emitLoad(dst, regT1, regT0);
emitGetFromCallFrameHeaderPtr(JSStack::ReturnPC, regT2);
emitGetFromCallFrameHeaderPtr(JSStack::CallerFrame, callFrameRegister);
emitGetReturnPCFromCallFrameHe