2009-05-08 Geoffrey Garen <ggaren@apple.com>
Reviewed by Gavin Barraclough.
More abstraction for JITStub calls from JITed code.
Added a JITStubCall class that automatically handles things like assigning
arguments to different stack slots and storing return values. Deployed
the class in about a billion places. A bunch more places remain to be
fixed up, but this is a good stopping point for now.
* jit/JIT.cpp:
(JSC::JIT::emitTimeoutCheck):
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
(JSC::JIT::privateCompile):
* jit/JIT.h:
(JSC::JIT::JSRInfo::JSRInfo):
(JSC::JITStubCall::JITStubCall):
(JSC::JITStubCall::addArgument):
(JSC::JITStubCall::call):
(JSC::JITStubCall::):
(JSC::CallEvalJITStub::CallEvalJITStub):
* jit/JITArithmetic.cpp:
(JSC::JIT::compileFastArithSlow_op_lshift):
(JSC::JIT::compileFastArithSlow_op_rshift):
(JSC::JIT::compileFastArithSlow_op_jnless):
(JSC::JIT::compileFastArithSlow_op_bitand):
(JSC::JIT::compileFastArithSlow_op_mod):
(JSC::JIT::compileFastArith_op_mod):
(JSC::JIT::compileFastArithSlow_op_post_inc):
(JSC::JIT::compileFastArithSlow_op_post_dec):
(JSC::JIT::compileFastArithSlow_op_pre_inc):
(JSC::JIT::compileFastArithSlow_op_pre_dec):
(JSC::JIT::compileFastArith_op_add):
(JSC::JIT::compileFastArith_op_mul):
(JSC::JIT::compileFastArith_op_sub):
(JSC::JIT::compileBinaryArithOpSlowCase):
(JSC::JIT::compileFastArithSlow_op_add):
(JSC::JIT::compileFastArithSlow_op_mul):
* jit/JITCall.cpp:
(JSC::JIT::compileOpCall):
(JSC::):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::compileGetByIdHotPath):
(JSC::JIT::compilePutByIdHotPath):
(JSC::JIT::compileGetByIdSlowCase):
(JSC::JIT::compilePutByIdSlowCase):
* jit/JITStubs.cpp:
(JSC::JITStubs::cti_op_resolve_func):
(JSC::JITStubs::cti_op_resolve_with_base):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@43409 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h
index 1bf2411..b25d150 100644
--- a/JavaScriptCore/jit/JIT.h
+++ b/JavaScriptCore/jit/JIT.h
@@ -32,6 +32,7 @@
#define WTF_USE_CTI_REPATCH_PIC 1
+#include "CodeBlock.h"
#include "Interpreter.h"
#include "JITCode.h"
#include "JITStubs.h"
@@ -46,6 +47,7 @@
namespace JSC {
class CodeBlock;
+ class JIT;
class JSPropertyNameIterator;
class Interpreter;
class Register;
@@ -61,13 +63,6 @@
struct PolymorphicAccessStructureList;
struct StructureStubInfo;
- typedef JSObject* (JIT_STUB *CTIHelper_o)(STUB_ARGS_DECLARATION);
- typedef JSPropertyNameIterator* (JIT_STUB *CTIHelper_p)(STUB_ARGS_DECLARATION);
- typedef void (JIT_STUB *CTIHelper_v)(STUB_ARGS_DECLARATION);
- typedef void* (JIT_STUB *CTIHelper_s)(STUB_ARGS_DECLARATION);
- typedef int (JIT_STUB *CTIHelper_b)(STUB_ARGS_DECLARATION);
- typedef VoidPtrPair (JIT_STUB *CTIHelper_2)(STUB_ARGS_DECLARATION);
-
struct CallRecord {
MacroAssembler::Call from;
unsigned bytecodeIndex;
@@ -159,6 +154,9 @@
void ctiPatchNearCallByReturnAddress(MacroAssembler::ProcessorReturnAddress returnAddress, void* newCalleeFunction);
class JIT : private MacroAssembler {
+ friend class JITStubCall;
+ friend class CallEvalJITStub;
+
using MacroAssembler::Jump;
using MacroAssembler::JumpList;
using MacroAssembler::Label;
@@ -332,6 +330,17 @@
static void unlinkCall(CallLinkInfo*);
private:
+ struct JSRInfo {
+ DataLabelPtr storeLocation;
+ Label target;
+
+ JSRInfo(DataLabelPtr storeLocation, Label targetLocation)
+ : storeLocation(storeLocation)
+ , target(targetLocation)
+ {
+ }
+ };
+
JIT(JSGlobalData*, CodeBlock* = 0);
void privateCompileMainPass();
@@ -365,7 +374,6 @@
void compileOpCallInitializeCallFrame();
void compileOpCallSetupArgs(Instruction*);
void compileOpCallVarargsSetupArgs(Instruction*);
- void compileOpCallEvalSetupArgs(Instruction*);
void compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter, unsigned callLinkInfoIndex, OpcodeID opcodeID);
void compileOpCallVarargsSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter);
void compileOpConstructSetupArgs(Instruction*);
@@ -482,13 +490,6 @@
void restoreArgumentReferenceForTrampoline();
Call emitNakedCall(void* function);
- Call emitCTICall_internal(void*);
- Call emitCTICall(CTIHelper_o helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
- Call emitCTICall(CTIHelper_p helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
- Call emitCTICall(CTIHelper_v helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
- Call emitCTICall(CTIHelper_s helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
- Call emitCTICall(CTIHelper_b helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
- Call emitCTICall(CTIHelper_2 helper) { return emitCTICall_internal(reinterpret_cast<void*>(helper)); }
void emitGetVariableObjectRegister(RegisterID variableObject, int index, RegisterID dst);
void emitPutVariableObjectRegister(RegisterID src, RegisterID variableObject, int index);
@@ -538,17 +539,6 @@
Vector<StructureStubCompilationInfo> m_callStructureStubCompilationInfo;
Vector<JumpTable> m_jmpTable;
- struct JSRInfo {
- DataLabelPtr storeLocation;
- Label target;
-
- JSRInfo(DataLabelPtr storeLocation, Label targetLocation)
- : storeLocation(storeLocation)
- , target(targetLocation)
- {
- }
- };
-
unsigned m_bytecodeIndex;
Vector<JSRInfo> m_jsrSites;
Vector<SlowCaseEntry> m_slowCases;
@@ -557,6 +547,141 @@
int m_lastResultBytecodeRegister;
unsigned m_jumpTargetsPosition;
};
+
+ class JITStubCall {
+ public:
+ JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Default)
+ , m_argumentIndex(1) // Index 0 is reserved for restoreArgumentReference();
+ {
+ }
+
+ JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Default)
+ , m_argumentIndex(1) // Index 0 is reserved for restoreArgumentReference();
+ {
+ }
+
+ JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Default)
+ , m_argumentIndex(1) // Index 0 is reserved for restoreArgumentReference();
+ {
+ }
+
+ JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Default)
+ , m_argumentIndex(1) // Index 0 is reserved for restoreArgumentReference();
+ {
+ }
+
+ JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Void)
+ , m_argumentIndex(1) // Index 0 is reserved for restoreArgumentReference();
+ {
+ }
+
+ JITStubCall(JIT* jit, VoidPtrPair (JIT_STUB *stub)(STUB_ARGS_DECLARATION))
+ : m_jit(jit)
+ , m_stub(reinterpret_cast<void*>(stub))
+ , m_returnType(Pair)
+ , m_argumentIndex(1) // Index 0 is reserved for restoreArgumentReference();
+ {
+ }
+
+ // Arguments are added first to last.
+
+ template <typename T> void addArgument(T argument)
+ {
+ m_jit->poke(argument, m_argumentIndex);
+ ++m_argumentIndex;
+ }
+
+ void addArgument(unsigned src, JIT::RegisterID scratchRegister) // src is a virtual register.
+ {
+ if (m_jit->m_codeBlock->isConstantRegisterIndex(src))
+ addArgument(JIT::ImmPtr(JSValue::encode(m_jit->m_codeBlock->getConstant(src))));
+ else {
+ m_jit->loadPtr(JIT::Address(JIT::callFrameRegister, src * sizeof(Register)), scratchRegister);
+ addArgument(scratchRegister);
+ }
+ m_jit->killLastResultRegister();
+ }
+
+ JIT::Call call()
+ {
+ ASSERT(m_jit->m_bytecodeIndex != (unsigned)-1); // This method should only be called during hot/cold path generation, so that m_bytecodeIndex is set.
+
+#if ENABLE(OPCODE_SAMPLING)
+ m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, true);
+#endif
+
+ m_jit->restoreArgumentReference();
+ JIT::Call call = m_jit->call();
+ m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeIndex, m_stub));
+
+#if ENABLE(OPCODE_SAMPLING)
+ m_jit->sampleInstruction(m_jit->m_codeBlock->instructions().begin() + m_jit->m_bytecodeIndex, false);
+#endif
+
+ m_jit->killLastResultRegister();
+ return call;
+ }
+
+ JIT::Call call(unsigned dst) // dst is a virtual register.
+ {
+ JIT::Call call = this->call();
+ m_jit->emitPutVirtualRegister(dst);
+ return call;
+ }
+
+ // Used for stubs that return two values encoded as a VoidPtrPair.
+ JIT::Call call(unsigned dst1, unsigned dst2) // dst1 and dst1 are virtual registers.
+ {
+ JIT::Call call = this->call();
+ m_jit->emitPutVirtualRegister(dst1);
+ m_jit->emitPutVirtualRegister(dst2, JIT::regT1);
+ return call;
+ }
+
+ JIT::Call call(JIT::RegisterID dst)
+ {
+ JIT::Call call = this->call();
+ if (dst != JIT::returnValueRegister)
+ m_jit->move(JIT::returnValueRegister, dst);
+ return call;
+ }
+
+ private:
+ JIT* m_jit;
+ void* m_stub;
+ enum { Default, Void, Pair } m_returnType;
+ size_t m_argumentIndex;
+ };
+
+ class CallEvalJITStub : public JITStubCall {
+ public:
+ CallEvalJITStub(JIT* jit, Instruction* instruction)
+ : JITStubCall(jit, JITStubs::cti_op_call_eval)
+ {
+ int callee = instruction[2].u.operand;
+ int argCount = instruction[3].u.operand;
+ int registerOffset = instruction[4].u.operand;
+
+ addArgument(callee, JIT::regT2);
+ addArgument(JIT::Imm32(registerOffset));
+ addArgument(JIT::Imm32(argCount));
+ }
+ };
}
#endif // ENABLE(JIT)