2011-04-11 Thouraya ANDOLSI <thouraya.andolsi@st.com>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Apr 2011 17:11:38 +0000 (17:11 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Apr 2011 17:11:38 +0000 (17:11 +0000)
        Reviewed by Oliver Hunt.

        SH4 JIT SUPPORT.
        https://bugs.webkit.org/show_bug.cgi?id=44329

        Add JIT remaining part for SH4 platforms.

        * assembler/MacroAssemblerSH4.h:
        * jit/JIT.h:
        * jit/JITInlineMethods.h:
        * jit/JITOpcodes32_64.cpp:
        * jit/JITPropertyAccess32_64.cpp:
        * jit/JITStubs.cpp:
        * jit/JITStubs.h:
        * jit/JSInterfaceJIT.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@83447 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/assembler/MacroAssemblerSH4.h
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITInlineMethods.h
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
Source/JavaScriptCore/jit/JITStubs.cpp
Source/JavaScriptCore/jit/JITStubs.h
Source/JavaScriptCore/jit/JSInterfaceJIT.h

index 569c9d2..6d7b1f4 100644 (file)
@@ -1,3 +1,21 @@
+2011-04-11  Thouraya ANDOLSI  <thouraya.andolsi@st.com>
+
+        Reviewed by Oliver Hunt.
+
+        SH4 JIT SUPPORT.
+        https://bugs.webkit.org/show_bug.cgi?id=44329
+
+        Add JIT remaining part for SH4 platforms.
+
+        * assembler/MacroAssemblerSH4.h:
+        * jit/JIT.h:
+        * jit/JITInlineMethods.h:
+        * jit/JITOpcodes32_64.cpp:
+        * jit/JITPropertyAccess32_64.cpp:
+        * jit/JITStubs.cpp:
+        * jit/JITStubs.h:
+        * jit/JSInterfaceJIT.h:
+
 2011-04-10  Geoffrey Garen  <ggaren@apple.com>
 
         Rubber-stamped by Beth Dakin.
index 04b0602..7e15e6c 100644 (file)
@@ -1651,6 +1651,14 @@ public:
         return Call(m_assembler.call(target), Call::None);
     }
 
+    void call(Address address, RegisterID target)
+    {
+        load32(address.base, address.offset, target);
+        m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2);
+        m_assembler.branch(JSR_OPCODE, target);
+        m_assembler.nop();
+    }
+
     void breakpoint()
     {
         m_assembler.bkpt();
index 99c8cd4..3d87e51 100644 (file)
@@ -473,6 +473,48 @@ namespace JSC {
         static const int patchOffsetMethodCheckProtoStruct = 52;
         static const int patchOffsetMethodCheckPutFunction = 84;
 #endif
+#elif CPU(SH4)
+       // These architecture specific value are used to enable patching - see comment on op_put_by_id.
+        static const int patchOffsetGetByIdStructure = 6;
+        static const int patchOffsetPutByIdPropertyMapOffset = 24;
+        static const int patchOffsetPutByIdStructure = 6;
+        // These architecture specific value are used to enable patching - see comment on op_get_by_id.
+        static const int patchOffsetGetByIdBranchToSlowCase = 10;
+        static const int patchOffsetGetByIdPropertyMapOffset = 24;
+        static const int patchOffsetGetByIdPutResult = 32;
+
+        // sequenceOpCall
+        static const int sequenceOpCallInstructionSpace = 12;
+        static const int sequenceOpCallConstantSpace = 2;
+        // sequenceMethodCheck
+        static const int sequenceMethodCheckInstructionSpace = 40;
+        static const int sequenceMethodCheckConstantSpace = 6;
+        // sequenceGetByIdHotPath
+        static const int sequenceGetByIdHotPathInstructionSpace = 36;
+        static const int sequenceGetByIdHotPathConstantSpace = 5;
+        // sequenceGetByIdSlowCase
+        static const int sequenceGetByIdSlowCaseInstructionSpace = 26;
+        static const int sequenceGetByIdSlowCaseConstantSpace = 2;
+        // sequencePutById
+        static const int sequencePutByIdInstructionSpace = 36;
+        static const int sequencePutByIdConstantSpace = 5;
+
+        static const int patchOffsetGetByIdPropertyMapOffset1 = 20;
+        static const int patchOffsetGetByIdPropertyMapOffset2 = 26;
+
+        static const int patchOffsetPutByIdPropertyMapOffset1 = 20;
+        static const int patchOffsetPutByIdPropertyMapOffset2 = 26;
+
+#if ENABLE(OPCODE_SAMPLING)
+        static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE
+#else
+        static const int patchOffsetGetByIdSlowCaseCall = 22;
+#endif
+        static const int patchOffsetOpCallCompareToJump = 4;
+
+        static const int patchOffsetMethodCheckProtoObj = 12;
+        static const int patchOffsetMethodCheckProtoStruct = 20;
+        static const int patchOffsetMethodCheckPutFunction = 32;
 #else
 #error "JSVALUE32_64 not supported on this platform."
 #endif
@@ -665,14 +707,16 @@ namespace JSC {
 
 #if (defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL)
 #define BEGIN_UNINTERRUPTED_SEQUENCE(name) do { beginUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace); } while (false)
-#define END_UNINTERRUPTED_SEQUENCE(name) do { endUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace); } while (false)
+#define END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, dst) do { endUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace, dst); } while (false)
+#define END_UNINTERRUPTED_SEQUENCE(name) END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, 0)
 
         void beginUninterruptedSequence(int, int);
-        void endUninterruptedSequence(int, int);
+        void endUninterruptedSequence(int, int, int);
 
 #else
 #define BEGIN_UNINTERRUPTED_SEQUENCE(name)  do { beginUninterruptedSequence(); } while (false)
 #define END_UNINTERRUPTED_SEQUENCE(name)  do { endUninterruptedSequence(); } while (false)
+#define END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, dst) do { endUninterruptedSequence(); } while (false)
 #endif
 
         void emit_op_add(Instruction*);
index 9afaf1a..3dfa105 100644 (file)
@@ -123,6 +123,13 @@ ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace
 
     ensureSpace(insnSpace, constSpace);
 
+#elif CPU(SH4)
+#ifndef NDEBUG
+    insnSpace += sizeof(SH4Word);
+    constSpace += sizeof(uint64_t);
+#endif
+
+    m_assembler.ensureSpace(insnSpace + m_assembler.maxInstructionSize + 2, constSpace + 8);
 #endif
 
 #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
@@ -133,8 +140,9 @@ ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace
 #endif
 }
 
-ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace)
+ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace, int dst)
 {
+    UNUSED_PARAM(dst);
 #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL
     /* There are several cases when the uninterrupted sequence is larger than
      * maximum required offset for pathing the same sequence. Eg.: if in a
@@ -143,6 +151,15 @@ ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace)
      * calculation of length of uninterrupted sequence. So, the insnSpace and
      * constSpace should be upper limit instead of hard limit.
      */
+#if CPU(SH4)
+    if ((dst > 15) || (dst < -16)) {
+        insnSpace += 8;
+        constSpace += 2;
+    }
+
+    if (((dst >= -16) && (dst < 0)) || ((dst > 7) && (dst <= 15)))
+        insnSpace += 8;
+#endif
     ASSERT(differenceBetween(m_uninterruptedInstructionSequenceBegin, label()) <= insnSpace);
     ASSERT(sizeOfConstantPool() - m_uninterruptedConstantSequenceBegin <= constSpace);
 #endif
@@ -167,6 +184,22 @@ ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
 {
     loadPtr(address, linkRegister);
 }
+#elif CPU(SH4)
+
+ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg)
+{
+    m_assembler.stspr(reg);
+}
+
+ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg)
+{
+    m_assembler.ldspr(reg);
+}
+
+ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address)
+{
+    loadPtrLinkReg(address);
+}
 
 #elif CPU(MIPS)
 
@@ -217,6 +250,8 @@ ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline()
     addPtr(TrustedImm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister);
 #elif CPU(ARM)
     move(stackPointerRegister, firstArgumentRegister);
+#elif CPU(SH4)
+    move(stackPointerRegister, firstArgumentRegister);
 #endif
     // In the trampoline on x86-64, the first argument register is not overwritten.
 }
index e2d8548..edce21c 100644 (file)
@@ -245,7 +245,26 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon
     call(Address(regT2, executableOffsetToFunction));
 
     restoreReturnAddressBeforeReturn(regT3);
+#elif CPU(SH4)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+    emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
 
+    // Calling convention: f(r0 == regT4, r1 == regT5, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, regT4);
+
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT5);
+    move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    loadPtr(Address(regT5, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+
+    call(Address(regT2, executableOffsetToFunction), regT0);
+    restoreReturnAddressBeforeReturn(regT3);
 #elif CPU(MIPS)
     // Load caller frame's scope chain into this callframe so that whatever we call can
     // get to its global data.
@@ -394,7 +413,28 @@ JIT::CodePtr JIT::privateCompileCTINativeCall(PassRefPtr<ExecutablePool> executa
     addPtr(TrustedImm32(16), stackPointerRegister);
 
     restoreReturnAddressBeforeReturn(regT3);
+#elif CPU(SH4)
+    // Load caller frame's scope chain into this callframe so that whatever we call can
+    // get to its global data.
+    emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, regT2);
+    emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT2);
+    emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain);
+
+    preserveReturnAddressAfterCall(regT3); // Callee preserved
+    emitPutToCallFrameHeader(regT3, RegisterFile::ReturnPC);
+
+    // Calling convention: f(r0 == regT4, r1 == regT5, ...);
+    // Host function signature: f(ExecState*);
+    move(callFrameRegister, regT4);
 
+    emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT5);
+    move(regT2, callFrameRegister); // Eagerly restore caller frame register to avoid loading from stack.
+    loadPtr(Address(regT5, OBJECT_OFFSETOF(JSFunction, m_executable)), regT2);
+
+    // call the function
+    nativeCall = call();
+
+    restoreReturnAddressBeforeReturn(regT3);
 #elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL)
 #error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform."
 #else
index 2a47e5c..9379f7a 100644 (file)
@@ -475,7 +475,7 @@ void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<Sl
     stubCall.addArgument(TrustedImmPtr(ident));
     Call call = stubCall.call(dst);
     
-    END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase);
+    END_UNINTERRUPTED_SEQUENCE_FOR_PUT(sequenceGetByIdSlowCase, dst);
     
     ASSERT_JIT_OFFSET(differenceBetween(coldPathBegin, call), patchOffsetGetByIdSlowCaseCall);
     
@@ -624,7 +624,7 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     add32(TrustedImm32(1), AbsoluteAddress(newStructure->addressOfCount()));
     storePtr(TrustedImmPtr(newStructure), Address(regT0, JSCell::structureOffset()));
     
-#if CPU(MIPS)
+#if CPU(MIPS) || CPU(SH4)
     // For MIPS, we don't add sizeof(void*) to the stack offset.
     load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT3);
     load32(Address(stackPointerRegister, OBJECT_OFFSETOF(JITStackFrame, args[2]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT2);
index 44ca867..922bd59 100644 (file)
@@ -314,7 +314,79 @@ extern "C" {
 #define ENABLE_PROFILER_REFERENCE_OFFSET 96
 #define GLOBAL_DATA_OFFSET         100
 #define STACK_LENGTH               104
+#elif CPU(SH4)
+#define SYMBOL_STRING(name) #name
+/* code (r4), RegisterFile* (r5), CallFrame* (r6), JSValue* exception (r7), Profiler**(sp), JSGlobalData (sp)*/
 
+asm volatile (
+".text\n"
+".globl " SYMBOL_STRING(ctiTrampoline) "\n"
+HIDE_SYMBOL(ctiTrampoline) "\n"
+SYMBOL_STRING(ctiTrampoline) ":" "\n"
+    "mov.l r7, @-r15" "\n"
+    "mov.l r6, @-r15" "\n"
+    "mov.l r5, @-r15" "\n"
+    "mov.l r8, @-r15" "\n"
+    "mov #127, r8" "\n"
+    "mov.l r14, @-r15" "\n"
+    "sts.l pr, @-r15" "\n"
+    "mov.l r13, @-r15" "\n"
+    "mov.l r11, @-r15" "\n"
+    "mov.l r10, @-r15" "\n"
+    "add #-60, r15" "\n"
+    "mov r6, r14" "\n"
+    "jsr @r4" "\n"
+    "nop" "\n"
+    "add #60, r15" "\n"
+    "mov.l @r15+,r10" "\n"
+    "mov.l @r15+,r11" "\n"
+    "mov.l @r15+,r13" "\n"
+    "lds.l @r15+,pr" "\n"
+    "mov.l @r15+,r14" "\n"
+    "mov.l @r15+,r8" "\n"
+    "add #12, r15" "\n"
+    "rts" "\n"
+    "nop" "\n"
+);
+
+asm volatile (
+".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n"
+HIDE_SYMBOL(ctiVMThrowTrampoline) "\n"
+SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n"
+    "mov.l .L2"SYMBOL_STRING(cti_vm_throw)",r0" "\n"
+    "mov r15, r4" "\n"
+    "mov.l @(r0,r12),r11" "\n"
+    "jsr @r11" "\n"
+    "nop" "\n"
+    "add #60, r15" "\n"
+    "mov.l @r15+,r10" "\n"
+    "mov.l @r15+,r11" "\n"
+    "mov.l @r15+,r13" "\n"
+    "lds.l @r15+,pr" "\n"
+    "mov.l @r15+,r14" "\n"
+    "mov.l @r15+,r8" "\n"
+    "add #12, r15" "\n"
+    "rts" "\n"
+    "nop" "\n"
+    ".align 2" "\n"
+    ".L2"SYMBOL_STRING(cti_vm_throw)":.long " SYMBOL_STRING(cti_vm_throw)"@GOT \n"
+);
+
+asm volatile (
+".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n"
+HIDE_SYMBOL(ctiOpThrowNotCaught) "\n"
+SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n"
+    "add #60, r15" "\n"
+    "mov.l @r15+,r10" "\n"
+    "mov.l @r15+,r11" "\n"
+    "mov.l @r15+,r13" "\n"
+    "lds.l @r15+,pr" "\n"
+    "mov.l @r15+,r14" "\n"
+    "mov.l @r15+,r8" "\n"
+    "add #12, r15" "\n"
+    "rts" "\n"
+    "nop" "\n"
+);
 #else
     #error "JIT not supported on this platform."
 #endif
@@ -1156,6 +1228,29 @@ MSVC()
 MSVC_END(    END)
 */
 
+#elif CPU(SH4)
+#define DEFINE_STUB_FUNCTION(rtype, op) \
+    extern "C" { \
+        rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \
+    }; \
+    asm volatile( \
+    ".align 2" "\n" \
+    ".globl " SYMBOL_STRING(cti_##op) "\n" \
+    SYMBOL_STRING(cti_##op) ":" "\n" \
+    "sts pr, r11" "\n" \
+    "mov.l r11, @(0x38, r15)" "\n" \
+    "mov.l .L2"SYMBOL_STRING(JITStubThunked_##op)",r0" "\n" \
+    "mov.l @(r0,r12),r11" "\n" \
+    "jsr @r11" "\n" \
+    "nop" "\n" \
+    "mov.l @(0x38, r15), r11 " "\n" \
+    "lds r11, pr " "\n" \
+    "rts" "\n" \
+    "nop" "\n" \
+    ".align 2" "\n" \
+    ".L2"SYMBOL_STRING(JITStubThunked_##op)":.long " SYMBOL_STRING(JITStubThunked_##op)"@GOT \n" \
+    ); \
+    rtype JITStubThunked_##op(STUB_ARGS_DECLARATION)
 #else
 #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION)
 #endif
index 610ae3f..7c67f6e 100644 (file)
@@ -229,6 +229,27 @@ namespace JSC {
 
         ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
     };
+#elif CPU(SH4)
+    struct JITStackFrame {
+        JITStubArg padding; // Unused
+        JITStubArg args[6];
+
+        ReturnAddressPtr thunkReturnAddress;
+        void* savedR10;
+        void* savedR11;
+        void* savedR13;
+        void* savedRPR;
+        void* savedR14;
+        void* savedTimeoutReg;
+
+        RegisterFile* registerFile;
+        CallFrame* callFrame;
+        JSValue* exception;
+        Profiler** enabledProfilerReference;
+        JSGlobalData* globalData;
+
+        ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; }
+    };
 #else
 #error "JITStackFrame not defined for this platform."
 #endif
index 852e01a..07218c1 100644 (file)
@@ -154,6 +154,31 @@ namespace JSC {
         static const FPRegisterID fpRegT1 = MIPSRegisters::f6;
         static const FPRegisterID fpRegT2 = MIPSRegisters::f8;
         static const FPRegisterID fpRegT3 = MIPSRegisters::f10;
+#elif CPU(SH4)
+        static const RegisterID timeoutCheckRegister = SH4Registers::r8;
+        static const RegisterID callFrameRegister = SH4Registers::fp;
+
+        static const RegisterID regT0 = SH4Registers::r0;
+        static const RegisterID regT1 = SH4Registers::r1;
+        static const RegisterID regT2 = SH4Registers::r2;
+        static const RegisterID regT3 = SH4Registers::r10;
+        static const RegisterID regT4 = SH4Registers::r4;
+        static const RegisterID regT5 = SH4Registers::r5;
+        static const RegisterID regT6 = SH4Registers::r6;
+        static const RegisterID regT7 = SH4Registers::r7;
+        static const RegisterID firstArgumentRegister =regT4;
+
+        static const RegisterID returnValueRegister = SH4Registers::r0;
+        static const RegisterID cachedResultRegister = SH4Registers::r0;
+
+        static const FPRegisterID fpRegT0  = SH4Registers::fr0;
+        static const FPRegisterID fpRegT1  = SH4Registers::fr2;
+        static const FPRegisterID fpRegT2  = SH4Registers::fr4;
+        static const FPRegisterID fpRegT3  = SH4Registers::fr6;
+        static const FPRegisterID fpRegT4  = SH4Registers::fr8;
+        static const FPRegisterID fpRegT5  = SH4Registers::fr10;
+        static const FPRegisterID fpRegT6  = SH4Registers::fr12;
+        static const FPRegisterID fpRegT7  = SH4Registers::fr14;
 #else
 #error "JIT not supported on this platform."
 #endif