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)