Extend the IC protection introduced by bug 614323. [Bug 615875] [r=cdleary]
authorJacob Bramley <Jacob.Bramley@arm.com>
Mon, 06 Dec 2010 11:07:37 +0000
changeset 58724 16a2d28ad4b4099306f0e262bf06cb6602b13f5b
parent 58723 0b53fd11e37410d971e75c149ba67523a315e480
child 58725 0d6d19884ccd0ba5214856f41d026c70f843143f
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewerscdleary
bugs614323, 615875
milestone2.0b8pre
Extend the IC protection introduced by bug 614323. [Bug 615875] [r=cdleary]
js/src/assembler/assembler/ARMAssembler.h
js/src/assembler/assembler/AssemblerBufferWithConstantPool.h
js/src/assembler/assembler/MacroAssemblerARM.h
js/src/methodjit/BaseCompiler.h
--- a/js/src/assembler/assembler/ARMAssembler.h
+++ b/js/src/assembler/assembler/ARMAssembler.h
@@ -927,16 +927,23 @@ namespace JSC {
             m_buffer.ensureSpace(space);
         }
 
         int sizeOfConstantPool()
         {
             return m_buffer.sizeOfConstantPool();
         }
 
+#ifdef DEBUG
+        void allowPoolFlush(bool allowFlush)
+        {
+            m_buffer.allowPoolFlush(allowFlush);
+        }
+#endif
+
         JmpDst label()
         {
             JmpDst label(m_buffer.size());
             js::JaegerSpew(js::JSpew_Insns, IPFX "#label     ((%d))\n", MAYBE_PAD, label.m_offset);
             return label;
         }
 
         JmpDst align(int alignment)
--- a/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h
+++ b/js/src/assembler/assembler/AssemblerBufferWithConstantPool.h
@@ -32,16 +32,17 @@
 #define AssemblerBufferWithConstantPool_h
 
 #include "assembler/wtf/Platform.h"
 
 #if ENABLE_ASSEMBLER
 
 #include "AssemblerBuffer.h"
 #include "assembler/wtf/SegmentedVector.h"
+#include "assembler/wtf/Assertions.h"
 
 #define ASSEMBLER_HAS_CONSTANT_POOL 1
 
 namespace JSC {
 
 /*
     On a constant pool 4 or 8 bytes data can be stored. The values can be
     constants or addresses. The addresses should be 32 or 64 bits. The constants
@@ -98,16 +99,19 @@ public:
         UnusedEntry
     };
 
     AssemblerBufferWithConstantPool()
         : AssemblerBuffer()
         , m_numConsts(0)
         , m_maxDistance(maxPoolSize)
         , m_lastConstDelta(0)
+#ifdef DEBUG
+        , m_allowFlush(true)
+#endif
     {
         m_pool = static_cast<uint32_t*>(malloc(maxPoolSize));
         m_mask = static_cast<char*>(malloc(maxPoolSize / sizeof(uint32_t)));
     }
 
     ~AssemblerBufferWithConstantPool()
     {
         free(m_mask);
@@ -230,16 +234,25 @@ public:
         return m_pool;
     }
 
     int sizeOfConstantPool()
     {
         return m_numConsts;
     }
 
+#ifdef DEBUG
+    // Guard constant pool flushes to ensure that they don't occur during
+    // regions where offsets into the code have to be maintained (such as PICs).
+    void allowPoolFlush(bool allowFlush)
+    {
+        m_allowFlush = allowFlush;
+    }
+#endif
+
 private:
     void correctDeltas(int insnSize)
     {
         m_maxDistance -= insnSize;
         m_lastConstDelta -= insnSize;
         if (m_lastConstDelta < 0)
             m_lastConstDelta = 0;
     }
@@ -249,16 +262,17 @@ private:
         correctDeltas(insnSize);
 
         m_maxDistance -= m_lastConstDelta;
         m_lastConstDelta = constSize;
     }
 
     void flushConstantPool(bool useBarrier = true)
     {
+        ASSERT(m_allowFlush);
         if (m_numConsts == 0)
             return;
         int alignPool = (AssemblerBuffer::size() + (useBarrier ? barrierSize : 0)) & (sizeof(uint64_t) - 1);
 
         if (alignPool)
             alignPool = sizeof(uint64_t) - alignPool;
 
         // Callback to protect the constant pool from execution
@@ -308,15 +322,19 @@ private:
 
     uint32_t* m_pool;
     char* m_mask;
     LoadOffsets m_loadOffsets;
 
     int m_numConsts;
     int m_maxDistance;
     int m_lastConstDelta;
+
+#ifdef DEBUG
+    bool    m_allowFlush;
+#endif
 };
 
 } // namespace JSC
 
 #endif // ENABLE(ASSEMBLER)
 
 #endif // AssemblerBufferWithConstantPool_h
--- a/js/src/assembler/assembler/MacroAssemblerARM.h
+++ b/js/src/assembler/assembler/MacroAssemblerARM.h
@@ -1073,16 +1073,23 @@ public:
         m_assembler.ensureSpace(space);
     }
 
     void forceFlushConstantPool()
     {
         m_assembler.forceFlushConstantPool();
     }
 
+#ifdef DEBUG
+    void allowPoolFlush(bool allowFlush)
+    {
+        m_assembler.allowPoolFlush(allowFlush);
+    }
+#endif
+
 protected:
     ARMAssembler::Condition ARMCondition(Condition cond)
     {
         return static_cast<ARMAssembler::Condition>(cond);
     }
 
     void ensureSpace(int insnSpace, int constSpace)
     {
--- a/js/src/methodjit/BaseCompiler.h
+++ b/js/src/methodjit/BaseCompiler.h
@@ -202,37 +202,52 @@ class Repatcher : public JSC::RepatchBuf
  * live. Dumping a huge constant pool into the middle of an IC's inline path
  * makes the distance between emitted instructions potentially variable and/or
  * large, which makes the IC offsets invalid. We must reserve contiguous space
  * up front to prevent this from happening.
  */
 #ifdef JS_CPU_ARM
 class AutoReserveICSpace {
     typedef Assembler::Label Label;
-    static const size_t reservedSpace = 64;
+    static const size_t reservedSpace = 68;
 
     Assembler           &masm;
 #ifdef DEBUG
     Label               startLabel;
 #endif
 
   public:
     AutoReserveICSpace(Assembler &masm) : masm(masm) {
         masm.ensureSpace(reservedSpace);
 #ifdef DEBUG
         startLabel = masm.label();
+
+        /* Assert that the constant pool is not flushed until we reach a safe point. */
+        masm.allowPoolFlush(false);
+
+        JaegerSpew(JSpew_Insns, " -- BEGIN CONSTANT-POOL-FREE REGION -- \n");
 #endif
     }
 
     ~AutoReserveICSpace() {
 #ifdef DEBUG
         Label endLabel = masm.label();
         int spaceUsed = masm.differenceBetween(startLabel, endLabel);
+
+        /* Spew the space used, to help tuning of reservedSpace. */
+        JaegerSpew(JSpew_Insns,
+                   " -- END CONSTANT-POOL-FREE REGION: %u bytes used of %u reserved. -- \n",
+                   spaceUsed, reservedSpace);
+
+        /* Assert that we didn't emit more code than we protected. */
         JS_ASSERT(spaceUsed >= 0);
         JS_ASSERT(size_t(spaceUsed) <= reservedSpace);
+
+        /* Allow the pool to be flushed. */
+        masm.allowPoolFlush(true);
 #endif
     }
 };
 # define RESERVE_IC_SPACE(__masm) AutoReserveICSpace arics(__masm)
 #else
 # define RESERVE_IC_SPACE(__masm) /* Nothing. */
 #endif