]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/AssemblerBufferWithConstantPool.h
JavaScriptCore-1218.tar.gz
[apple/javascriptcore.git] / assembler / AssemblerBufferWithConstantPool.h
index f15b7f33498065c84b64b93c914c1658ad85ac24..852f86df79835525c33b9a12e59116090733d79e 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,39 @@ 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)
+    PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort)
     {
-        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);
+        flushConstantPool(false);
+        return AssemblerBuffer::executableCopy(vm, ownerUID, effort);
+    }
 
-        AssemblerBuffer::putInt(AssemblerType::patchConstantPoolLoad(insn, m_numConsts));
-        ++m_numConsts;
+    void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false)
+    {
+        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,6 +224,11 @@ public:
         return m_pool;
     }
 
+    int sizeOfConstantPool()
+    {
+        return m_numConsts;
+    }
+
 private:
     void correctDeltas(int insnSize)
     {
@@ -236,18 +246,45 @@ private:
         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 flushConstantPool(bool useBarrier = true)
     {
         if (m_numConsts == 0)
             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 +295,25 @@ 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;
     }
 
     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 +321,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();
     }