]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/AbstractMacroAssembler.h
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / assembler / AbstractMacroAssembler.h
index 198e8d10adffa84fc078811d7ebf177df68192ad..e7cc70fc5e2add38caa3eeb98b8ea65a1a2ef25b 100644 (file)
 #ifndef AbstractMacroAssembler_h
 #define AbstractMacroAssembler_h
 
-#include <wtf/Platform.h>
-
-#include <MacroAssemblerCodeRef.h>
-#include <CodeLocation.h>
+#include "AssemblerBuffer.h"
+#include "CodeLocation.h"
+#include "MacroAssemblerCodeRef.h"
+#include <wtf/CryptographicallyRandomNumber.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/UnusedParam.h>
 
 #if ENABLE(ASSEMBLER)
 
+
+#if PLATFORM(QT)
+#define ENABLE_JIT_CONSTANT_BLINDING 0
+#endif
+
+#ifndef ENABLE_JIT_CONSTANT_BLINDING
+#define ENABLE_JIT_CONSTANT_BLINDING 1
+#endif
+
 namespace JSC {
 
 class LinkBuffer;
 class RepatchBuffer;
+namespace DFG {
+class CorrectableJumpPoint;
+}
 
 template <class AssemblerType>
 class AbstractMacroAssembler {
 public:
+    friend class JITWriteBarrierBase;
     typedef AssemblerType AssemblerType_T;
 
     typedef MacroAssemblerCodePtr CodePtr;
@@ -51,10 +64,6 @@ public:
     class Jump;
 
     typedef typename AssemblerType::RegisterID RegisterID;
-    typedef typename AssemblerType::FPRegisterID FPRegisterID;
-    typedef typename AssemblerType::JmpSrc JmpSrc;
-    typedef typename AssemblerType::JmpDst JmpDst;
-
 
     // Section 1: MacroAssembler operand types
     //
@@ -83,6 +92,17 @@ public:
         int32_t offset;
     };
 
+    struct ExtendedAddress {
+        explicit ExtendedAddress(RegisterID base, intptr_t offset = 0)
+            : base(base)
+            , offset(offset)
+        {
+        }
+        
+        RegisterID base;
+        intptr_t offset;
+    };
+
     // ImplicitAddress:
     //
     // This class is used for explicit 'load' and 'store' operations
@@ -137,52 +157,80 @@ public:
     // Describes an memory operand given by a pointer.  For regular load & store
     // operations an unwrapped void* will be used, rather than using this.
     struct AbsoluteAddress {
-        explicit AbsoluteAddress(void* ptr)
+        explicit AbsoluteAddress(const void* ptr)
             : m_ptr(ptr)
         {
         }
 
-        void* m_ptr;
+        const void* m_ptr;
     };
 
-    // ImmPtr:
+    // TrustedImmPtr:
     //
     // A pointer sized immediate operand to an instruction - this is wrapped
     // in a class requiring explicit construction in order to differentiate
     // from pointers used as absolute addresses to memory operations
-    struct ImmPtr {
-        explicit ImmPtr(void* value)
+    struct TrustedImmPtr {
+        explicit TrustedImmPtr(const void* value)
             : m_value(value)
         {
         }
+        
+        // This is only here so that TrustedImmPtr(0) does not confuse the C++
+        // overload handling rules.
+        explicit TrustedImmPtr(int value)
+            : m_value(0)
+        {
+            ASSERT_UNUSED(value, !value);
+        }
+
+        explicit TrustedImmPtr(size_t value)
+            : m_value(reinterpret_cast<void*>(value))
+        {
+        }
 
         intptr_t asIntptr()
         {
             return reinterpret_cast<intptr_t>(m_value);
         }
 
-        void* m_value;
+        const void* m_value;
+    };
+
+    struct ImmPtr : 
+#if ENABLE(JIT_CONSTANT_BLINDING)
+        private TrustedImmPtr 
+#else
+        public TrustedImmPtr
+#endif
+    {
+        explicit ImmPtr(const void* value)
+            : TrustedImmPtr(value)
+        {
+        }
+
+        TrustedImmPtr asTrustedImmPtr() { return *this; }
     };
 
-    // Imm32:
+    // TrustedImm32:
     //
     // A 32bit immediate operand to an instruction - this is wrapped in a
     // class requiring explicit construction in order to prevent RegisterIDs
     // (which are implemented as an enum) from accidentally being passed as
     // immediate values.
-    struct Imm32 {
-        explicit Imm32(int32_t value)
+    struct TrustedImm32 {
+        explicit TrustedImm32(int32_t value)
             : m_value(value)
-#if CPU(ARM)
+#if CPU(ARM) || CPU(MIPS)
             , m_isPointer(false)
 #endif
         {
         }
 
 #if !CPU(X86_64)
-        explicit Imm32(ImmPtr ptr)
+        explicit TrustedImm32(TrustedImmPtr ptr)
             : m_value(ptr.asIntptr())
-#if CPU(ARM)
+#if CPU(ARM) || CPU(MIPS)
             , m_isPointer(true)
 #endif
         {
@@ -190,18 +238,40 @@ public:
 #endif
 
         int32_t m_value;
-#if CPU(ARM)
+#if CPU(ARM) || CPU(MIPS)
         // We rely on being able to regenerate code to recover exception handling
         // information.  Since ARMv7 supports 16-bit immediates there is a danger
         // that if pointer values change the layout of the generated code will change.
         // To avoid this problem, always generate pointers (and thus Imm32s constructed
         // from ImmPtrs) with a code sequence that is able  to represent  any pointer
         // value - don't use a more compact form in these cases.
+        // Same for MIPS.
         bool m_isPointer;
 #endif
     };
 
 
+    struct Imm32 : 
+#if ENABLE(JIT_CONSTANT_BLINDING)
+        private TrustedImm32 
+#else
+        public TrustedImm32
+#endif
+    {
+        explicit Imm32(int32_t value)
+            : TrustedImm32(value)
+        {
+        }
+#if !CPU(X86_64)
+        explicit Imm32(TrustedImmPtr ptr)
+            : TrustedImm32(ptr)
+        {
+        }
+#endif
+        const TrustedImm32& asTrustedImm32() const { return *this; }
+
+    };
+    
     // Section 2: MacroAssembler code buffer handles
     //
     // The following types are used to reference items in the code buffer
@@ -217,6 +287,7 @@ public:
     class Label {
         template<class TemplateAssemblerType>
         friend class AbstractMacroAssembler;
+        friend class DFG::CorrectableJumpPoint;
         friend class Jump;
         friend class MacroAssemblerCodeRef;
         friend class LinkBuffer;
@@ -231,10 +302,9 @@ public:
         {
         }
         
-        bool isUsed() const { return m_label.isUsed(); }
-        void used() { m_label.used(); }
+        bool isSet() const { return m_label.isSet(); }
     private:
-        JmpDst m_label;
+        AssemblerLabel m_label;
     };
 
     // DataLabelPtr:
@@ -255,8 +325,10 @@ public:
         {
         }
         
+        bool isSet() const { return m_label.isSet(); }
+        
     private:
-        JmpDst m_label;
+        AssemblerLabel m_label;
     };
 
     // DataLabel32:
@@ -277,8 +349,37 @@ public:
         {
         }
 
+        AssemblerLabel label() const { return m_label; }
+
+    private:
+        AssemblerLabel m_label;
+    };
+
+    // DataLabelCompact:
+    //
+    // A DataLabelCompact is used to refer to a location in the code containing a
+    // compact immediate to be patched after the code has been generated.
+    class DataLabelCompact {
+        template<class TemplateAssemblerType>
+        friend class AbstractMacroAssembler;
+        friend class LinkBuffer;
+    public:
+        DataLabelCompact()
+        {
+        }
+        
+        DataLabelCompact(AbstractMacroAssembler<AssemblerType>* masm)
+            : m_label(masm->m_assembler.label())
+        {
+        }
+    
+        DataLabelCompact(AssemblerLabel label)
+            : m_label(label)
+        {
+        }
+
     private:
-        JmpDst m_label;
+        AssemblerLabel m_label;
     };
 
     // Call:
@@ -304,8 +405,8 @@ public:
         {
         }
         
-        Call(JmpSrc jmp, Flags flags)
-            : m_jmp(jmp)
+        Call(AssemblerLabel jmp, Flags flags)
+            : m_label(jmp)
             , m_flags(flags)
         {
         }
@@ -317,10 +418,10 @@ public:
 
         static Call fromTailJump(Jump jump)
         {
-            return Call(jump.m_jmp, Linkable);
+            return Call(jump.m_label, Linkable);
         }
 
-        JmpSrc m_jmp;
+        AssemblerLabel m_label;
     private:
         Flags m_flags;
     };
@@ -335,29 +436,80 @@ public:
         template<class TemplateAssemblerType>
         friend class AbstractMacroAssembler;
         friend class Call;
+        friend class DFG::CorrectableJumpPoint;
         friend class LinkBuffer;
     public:
         Jump()
         {
         }
         
-        Jump(JmpSrc jmp)    
-            : m_jmp(jmp)
+#if CPU(ARM_THUMB2)
+        // Fixme: this information should be stored in the instruction stream, not in the Jump object.
+        Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid)
+            : m_label(jmp)
+            , m_type(type)
+            , m_condition(condition)
         {
         }
-        
-        void link(AbstractMacroAssembler<AssemblerType>* masm)
+#elif CPU(SH4)
+        Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar)
+            : m_label(jmp)
+            , m_type(type)
         {
-            masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label());
+        }
+#else
+        Jump(AssemblerLabel jmp)    
+            : m_label(jmp)
+        {
+        }
+#endif
+
+        void link(AbstractMacroAssembler<AssemblerType>* masm) const
+        {
+#if CPU(ARM_THUMB2)
+            masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition);
+#elif CPU(SH4)
+            masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type);
+#else
+            masm->m_assembler.linkJump(m_label, masm->m_assembler.label());
+#endif
         }
         
-        void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm)
+        void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const
         {
-            masm->m_assembler.linkJump(m_jmp, label.m_label);
+#if CPU(ARM_THUMB2)
+            masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition);
+#else
+            masm->m_assembler.linkJump(m_label, label.m_label);
+#endif
         }
 
+        bool isSet() const { return m_label.isSet(); }
+
     private:
-        JmpSrc m_jmp;
+        AssemblerLabel m_label;
+#if CPU(ARM_THUMB2)
+        ARMv7Assembler::JumpType m_type;
+        ARMv7Assembler::Condition m_condition;
+#endif
+#if CPU(SH4)
+        SH4Assembler::JumpType m_type;
+#endif
+    };
+
+    struct PatchableJump {
+        PatchableJump()
+        {
+        }
+
+        explicit PatchableJump(Jump jump)
+            : m_jump(jump)
+        {
+        }
+
+        operator Jump&() { return m_jump; }
+
+        Jump m_jump;
     };
 
     // JumpList:
@@ -401,6 +553,11 @@ public:
             return !m_jumps.size();
         }
         
+        void clear()
+        {
+            m_jumps.clear();
+        }
+        
         const JumpVector& jumps() { return m_jumps; }
 
     private:
@@ -409,17 +566,6 @@ public:
 
 
     // Section 3: Misc admin methods
-
-    static CodePtr trampolineAt(CodeRef ref, Label label)
-    {
-        return CodePtr(AssemblerType::getRelocatedAddress(ref.m_code.dataLocation(), label.m_label));
-    }
-
-    size_t size()
-    {
-        return m_assembler.size();
-    }
-
     Label label()
     {
         return Label(this);
@@ -431,75 +577,65 @@ public:
         return Label(this);
     }
 
-    ptrdiff_t differenceBetween(Label from, Jump to)
-    {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
-    }
-
-    ptrdiff_t differenceBetween(Label from, Call to)
-    {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
-    }
-
-    ptrdiff_t differenceBetween(Label from, Label to)
+    template<typename T, typename U>
+    static ptrdiff_t differenceBetween(T from, U to)
     {
         return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
     }
 
-    ptrdiff_t differenceBetween(Label from, DataLabelPtr to)
+    static ptrdiff_t differenceBetweenCodePtr(const MacroAssemblerCodePtr& a, const MacroAssemblerCodePtr& b)
     {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
+        return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress());
     }
 
-    ptrdiff_t differenceBetween(Label from, DataLabel32 to)
-    {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
-    }
+    unsigned debugOffset() { return m_assembler.debugOffset(); }
 
-    ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)
+    ALWAYS_INLINE static void cacheFlush(void* code, size_t size)
     {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+        AssemblerType::cacheFlush(code, size);
     }
-
-    ptrdiff_t differenceBetween(DataLabelPtr from, DataLabelPtr to)
+protected:
+    AbstractMacroAssembler()
+        : m_randomSource(cryptographicallyRandomNumber())
     {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);
     }
 
-    ptrdiff_t differenceBetween(DataLabelPtr from, Call to)
+    AssemblerType m_assembler;
+    
+    uint32_t random()
     {
-        return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);
+        return m_randomSource.getUint32();
     }
 
-protected:
-    AssemblerType m_assembler;
+    WeakRandom m_randomSource;
+
+#if ENABLE(JIT_CONSTANT_BLINDING)
+    static bool scratchRegisterForBlinding() { return false; }
+    static bool shouldBlindForSpecificArch(uint32_t) { return true; }
+    static bool shouldBlindForSpecificArch(uint64_t) { return true; }
+#endif
 
     friend class LinkBuffer;
     friend class RepatchBuffer;
 
     static void linkJump(void* code, Jump jump, CodeLocationLabel target)
     {
-        AssemblerType::linkJump(code, jump.m_jmp, target.dataLocation());
+        AssemblerType::linkJump(code, jump.m_label, target.dataLocation());
     }
 
-    static void linkPointer(void* code, typename AssemblerType::JmpDst label, void* value)
+    static void linkPointer(void* code, AssemblerLabel label, void* value)
     {
         AssemblerType::linkPointer(code, label, value);
     }
 
-    static void* getLinkerAddress(void* code, typename AssemblerType::JmpSrc label)
-    {
-        return AssemblerType::getRelocatedAddress(code, label);
-    }
-
-    static void* getLinkerAddress(void* code, typename AssemblerType::JmpDst label)
+    static void* getLinkerAddress(void* code, AssemblerLabel label)
     {
         return AssemblerType::getRelocatedAddress(code, label);
     }
 
     static unsigned getLinkerCallReturnOffset(Call call)
     {
-        return AssemblerType::getCallReturnOffset(call.m_jmp);
+        return AssemblerType::getCallReturnOffset(call.m_label);
     }
 
     static void repatchJump(CodeLocationJump jump, CodeLocationLabel destination)
@@ -512,6 +648,11 @@ protected:
         AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress());
     }
 
+    static void repatchCompact(CodeLocationDataLabelCompact dataLabelCompact, int32_t value)
+    {
+        AssemblerType::repatchCompact(dataLabelCompact.dataLocation(), value);
+    }
+    
     static void repatchInt32(CodeLocationDataLabel32 dataLabel32, int32_t value)
     {
         AssemblerType::repatchInt32(dataLabel32.dataLocation(), value);
@@ -521,10 +662,22 @@ protected:
     {
         AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value);
     }
-
-    static void repatchLoadPtrToLEA(CodeLocationInstruction instruction)
+    
+    static void* readPointer(CodeLocationDataLabelPtr dataLabelPtr)
     {
-        AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation());
+        return AssemblerType::readPointer(dataLabelPtr.dataLocation());
+    }
+    
+    static void unreachableForPlatform()
+    {
+#if COMPILER(CLANG)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wmissing-noreturn"
+        ASSERT_NOT_REACHED();
+#pragma clang diagnostic pop
+#else
+        ASSERT_NOT_REACHED();
+#endif
     }
 };