]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/AssemblerBufferWithConstantPool.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / assembler / AssemblerBufferWithConstantPool.h
index b1c537e1e3e0d2748e3175adf810ffd16101dbfe..053884b01fb7c3cd6971b558ec82348ec552e20a 100644 (file)
@@ -83,9 +83,16 @@ namespace JSC {
 */
 
 template <int maxPoolSize, int barrierSize, int maxInstructionSize, class AssemblerType>
-class AssemblerBufferWithConstantPool: public AssemblerBuffer {
+class AssemblerBufferWithConstantPool : public AssemblerBuffer {
     typedef SegmentedVector<uint32_t, 512> LoadOffsets;
+    using AssemblerBuffer::putIntegral;
+    using AssemblerBuffer::putIntegralUnchecked;
 public:
+    typedef struct {
+        short high;
+        short low;
+    } TwoShorts;
+
     enum {
         UniqueConst,
         ReusableConst,
@@ -120,6 +127,11 @@ public:
         AssemblerBuffer::ensureSpace(insnSpace);
     }
 
+    void ensureSpaceForAnyInstruction(int amount = 1)
+    {
+        flushIfNoSpaceFor(amount * maxInstructionSize, amount * sizeof(uint64_t));
+    }
+
     bool isAligned(int alignment)
     {
         flushIfNoSpaceFor(alignment);
@@ -171,51 +183,33 @@ public:
         correctDeltas(8);
     }
 
-    int size()
+    void putIntegral(TwoShorts value)
     {
-        flushIfNoSpaceFor(maxInstructionSize, sizeof(uint64_t));
-        return AssemblerBuffer::size();
+        putIntegral(value.high);
+        putIntegral(value.low);
     }
 
-    int uncheckedSize()
+    void putIntegralUnchecked(TwoShorts value)
     {
-        return AssemblerBuffer::size();
+        putIntegralUnchecked(value.high);
+        putIntegralUnchecked(value.low);
     }
 
-    void* executableCopy(ExecutablePool* allocator)
+    void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false)
     {
-        flushConstantPool(false);
-        return AssemblerBuffer::executableCopy(allocator);
+        putIntegralWithConstantInt(insn, constant, isReusable);
     }
 
     void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false)
     {
-        flushIfNoSpaceFor(4, 4);
-
-        m_loadOffsets.append(AssemblerBuffer::size());
-        if (isReusable)
-            for (int i = 0; i < m_numConsts; ++i) {
-                if (m_mask[i] == ReusableConst && m_pool[i] == constant) {
-                    AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, i));
-                    correctDeltas(4);
-                    return;
-                }
-            }
-
-        m_pool[m_numConsts] = constant;
-        m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst);
-
-        AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts));
-        ++m_numConsts;
-
-        correctDeltas(4, 4);
+        putIntegralWithConstantInt(insn, constant, isReusable);
     }
 
     // This flushing mechanism can be called after any unconditional jumps.
     void flushWithoutBarrier(bool isForced = false)
     {
         // Flush if constant pool is more than 60% full to avoid overuse of this function.
-        if (isForced || 5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t))
+        if (isForced || 5 * static_cast<uint32_t>(m_numConsts) > 3 * maxPoolSize / sizeof(uint32_t))
             flushConstantPool(false);
     }
 
@@ -229,35 +223,18 @@ public:
         return m_numConsts;
     }
 
-private:
-    void correctDeltas(int insnSize)
-    {
-        m_maxDistance -= insnSize;
-        m_lastConstDelta -= insnSize;
-        if (m_lastConstDelta < 0)
-            m_lastConstDelta = 0;
-    }
-
-    void correctDeltas(int insnSize, int constSize)
-    {
-        correctDeltas(insnSize);
-
-        m_maxDistance -= m_lastConstDelta;
-        m_lastConstDelta = constSize;
-    }
-
     void flushConstantPool(bool useBarrier = true)
     {
-        if (m_numConsts == 0)
+        if (!m_numConsts)
             return;
-        int alignPool = (AssemblerBuffer::size() + (useBarrier ? barrierSize : 0)) & (sizeof(uint64_t) - 1);
+        int alignPool = (codeSize() + (useBarrier ? barrierSize : 0)) & (sizeof(uint64_t) - 1);
 
         if (alignPool)
             alignPool = sizeof(uint64_t) - alignPool;
 
         // Callback to protect the constant pool from execution
         if (useBarrier)
-            AssemblerBuffer::putInt(AssemblerType::placeConstantPoolBarrier(m_numConsts * sizeof(uint32_t) + alignPool));
+            putIntegral(AssemblerType::placeConstantPoolBarrier(m_numConsts * sizeof(uint32_t) + alignPool));
 
         if (alignPool) {
             if (alignPool & 1)
@@ -268,18 +245,61 @@ private:
                 AssemblerBuffer::putInt(AssemblerType::padForAlign32);
         }
 
-        int constPoolOffset = AssemblerBuffer::size();
+        int constPoolOffset = codeSize();
         append(reinterpret_cast<char*>(m_pool), m_numConsts * sizeof(uint32_t));
 
         // Patch each PC relative load
         for (LoadOffsets::Iterator iter = m_loadOffsets.begin(); iter != m_loadOffsets.end(); ++iter) {
-            void* loadAddr = reinterpret_cast<void*>(m_buffer + *iter);
-            AssemblerType::patchConstantPoolLoad(loadAddr, reinterpret_cast<void*>(m_buffer + constPoolOffset));
+            void* loadAddr = reinterpret_cast<char*>(data()) + *iter;
+            AssemblerType::patchConstantPoolLoad(loadAddr, reinterpret_cast<char*>(data()) + constPoolOffset);
         }
 
         m_loadOffsets.clear();
         m_numConsts = 0;
-        m_maxDistance = maxPoolSize;
+    }
+
+private:
+    void correctDeltas(int insnSize)
+    {
+        m_maxDistance -= insnSize;
+        m_lastConstDelta -= insnSize;
+        if (m_lastConstDelta < 0)
+            m_lastConstDelta = 0;
+    }
+
+    void correctDeltas(int insnSize, int constSize)
+    {
+        correctDeltas(insnSize);
+
+        m_maxDistance -= m_lastConstDelta;
+        m_lastConstDelta = constSize;
+    }
+
+    template<typename IntegralType>
+    void putIntegralWithConstantInt(IntegralType insn, uint32_t constant, bool isReusable)
+    {
+        if (!m_numConsts)
+            m_maxDistance = maxPoolSize;
+        flushIfNoSpaceFor(sizeof(IntegralType), 4);
+
+        m_loadOffsets.append(codeSize());
+        if (isReusable) {
+            for (int i = 0; i < m_numConsts; ++i) {
+                if (m_mask[i] == ReusableConst && m_pool[i] == constant) {
+                    putIntegral(static_cast<IntegralType>(AssemblerType::patchConstantPoolLoad(insn, i)));
+                    correctDeltas(sizeof(IntegralType));
+                    return;
+                }
+            }
+        }
+
+        m_pool[m_numConsts] = constant;
+        m_mask[m_numConsts] = static_cast<char>(isReusable ? ReusableConst : UniqueConst);
+
+        putIntegral(static_cast<IntegralType>(AssemblerType::patchConstantPoolLoad(insn, m_numConsts)));
+        ++m_numConsts;
+
+        correctDeltas(sizeof(IntegralType), 4);
     }
 
     void flushIfNoSpaceFor(int nextInsnSize)