]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/AssemblerBufferWithConstantPool.h
JavaScriptCore-7600.1.4.9.tar.gz
[apple/javascriptcore.git] / assembler / AssemblerBufferWithConstantPool.h
index f15b7f33498065c84b64b93c914c1658ad85ac24..053884b01fb7c3cd6971b558ec82348ec552e20a 100644 (file)
 #ifndef AssemblerBufferWithConstantPool_h
 #define AssemblerBufferWithConstantPool_h
 
-#include <wtf/Platform.h>
-
 #if ENABLE(ASSEMBLER)
 
 #include "AssemblerBuffer.h"
 #include <wtf/SegmentedVector.h>
 
+#define ASSEMBLER_HAS_CONSTANT_POOL 1
+
 namespace JSC {
 
 /*
@@ -83,9 +83,16 @@ namespace JSC {
 */
 
 template <int maxPoolSize, int barrierSize, int maxInstructionSize, class AssemblerType>
-class AssemblerBufferWithConstantPool: public AssemblerBuffer {
-    typedef WTF::SegmentedVector<uint32_t, 512> LoadOffsets;
+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,46 +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);
     }
 
-    void* executableCopy(ExecutablePool* allocator)
+    void putIntegralUnchecked(TwoShorts value)
     {
-        flushConstantPool(false);
-        return AssemblerBuffer::executableCopy(allocator);
+        putIntegralUnchecked(value.high);
+        putIntegralUnchecked(value.low);
     }
 
-    void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false)
+    void putShortWithConstantInt(uint16_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;
+        putIntegralWithConstantInt(insn, constant, isReusable);
+    }
 
-        correctDeltas(4, 4);
+    void putIntWithConstantInt(uint32_t insn, uint32_t constant, bool isReusable = false)
+    {
+        putIntegralWithConstantInt(insn, constant, isReusable);
     }
 
     // This flushing mechanism can be called after any unconditional jumps.
-    void flushWithoutBarrier()
+    void flushWithoutBarrier(bool isForced = false)
     {
         // Flush if constant pool is more than 60% full to avoid overuse of this function.
-        if (5 * m_numConsts > 3 * maxPoolSize / sizeof(uint32_t))
+        if (isForced || 5 * static_cast<uint32_t>(m_numConsts) > 3 * maxPoolSize / sizeof(uint32_t))
             flushConstantPool(false);
     }
 
@@ -219,35 +218,23 @@ public:
         return m_pool;
     }
 
-private:
-    void correctDeltas(int insnSize)
+    int sizeOfConstantPool()
     {
-        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;
+        return m_numConsts;
     }
 
     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)
@@ -258,25 +245,69 @@ 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)
     {
         if (m_numConsts == 0)
             return;
-        if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t)))
+        int lastConstDelta = m_lastConstDelta > nextInsnSize ? m_lastConstDelta - nextInsnSize : 0;
+        if ((m_maxDistance < nextInsnSize + lastConstDelta + barrierSize + (int)sizeof(uint32_t)))
             flushConstantPool();
     }
 
@@ -284,8 +315,8 @@ private:
     {
         if (m_numConsts == 0)
             return;
-        if ((m_maxDistance < nextInsnSize + m_lastConstDelta + barrierSize + (int)sizeof(uint32_t)) ||
-            (m_numConsts + nextConstSize / sizeof(uint32_t) >= maxPoolSize))
+        if ((m_maxDistance < nextInsnSize + m_lastConstDelta + nextConstSize + barrierSize + (int)sizeof(uint32_t)) ||
+            (m_numConsts * sizeof(uint32_t) + nextConstSize >= maxPoolSize))
             flushConstantPool();
     }