Title: [171123] trunk/Source/_javascript_Core
Revision
171123
Author
benja...@webkit.org
Date
2014-07-15 16:59:14 -0700 (Tue, 15 Jul 2014)

Log Message

Reduce the overhead of updating the AssemblerBuffer
https://bugs.webkit.org/show_bug.cgi?id=134659

Reviewed by Gavin Barraclough.

In r164548, the linker was changed to allow the LinkBuffer to survive its MacroAssembler.
That feature is useful for JSC to get offsets inside a linked buffer in order to jump directly
there.

On ARM, we use branch compaction and we need to keep the "compaction offset" somewher to be able
to get the real address of a lable. That is done by reusing the memory of AssemblerData.

To share the memory between LinkBuffer and the Assembler, r164548 moved the AssemblerData into
a ref-counted object. Unfortunately, the extra complexity related to the new AssemblerData was enough
to make clang give up a bunch of optimizations.

This patch solve (some of) the problems by making AssemblerBuffer and AssemblerData super low overhead structures.
In particular, the grow() function becomes 8 Thumb instructions, which is easily inlined everywhere it is used.

Instead of sharing ownership between the Assembler and LinkBuffer, LinkBuffer now takes full ownership of
the AssemblerData. I feel this is also safer since LinkBuffer is reusing the AssemblerData is a very
specific way that would make it unusable for the Assembler.

-- Technical details --

>From LinkBuffer, we don't want to ever access the Assembler after releasing its buffer (or writting anything
into it really). This was obviously already the case, but that was hard to prove from LinkBuffer::copyCompactAndLinkCode().
To make this easier to work with, I changed all the assembler specific function to be static. This way we know
exactly what code access the Assembler instance. The code that does access the instance is then moved
at the beginning, before we modify anything.

The function recordLinkOffsets() that was on the MacroAssembler and copied in Assembler was moved directly
to LinkBuffer. This make the modification of AssemblerData completely explicit, and that code is specific
to LinkBuffer anyway (see LinkBuffer::executableOffsetFor()).

-- Perf impact --

This does not put us exactly at before r164548 due to the missing inline buffer. Still, it is very close.
On ARMv7, this reduces the time spent in Assembler by half. On the CSS JIT, this reduces the compilation
time by ~20%.

I could not measure any difference on x86_64.

* assembler/ARM64Assembler.h:
(JSC::ARM64Assembler::jumpSizeDelta):
(JSC::ARM64Assembler::canCompact):
(JSC::ARM64Assembler::computeJumpType):
(JSC::ARM64Assembler::link):
(JSC::ARM64Assembler::recordLinkOffsets): Deleted.
* assembler/ARMv7Assembler.h:
(JSC::ARMv7Assembler::ifThenElseConditionBit):
(JSC::ARMv7Assembler::ifThenElse):
(JSC::ARMv7Assembler::jumpSizeDelta):
(JSC::ARMv7Assembler::canCompact):
(JSC::ARMv7Assembler::computeJumpType):
(JSC::ARMv7Assembler::link):
(JSC::ARMv7Assembler::linkJumpT1):
(JSC::ARMv7Assembler::linkJumpT3):
(JSC::ARMv7Assembler::linkConditionalJumpT4):
(JSC::ARMv7Assembler::linkConditionalBX):
(JSC::ARMv7Assembler::recordLinkOffsets): Deleted.
* assembler/AssemblerBuffer.h:
(JSC::AssemblerData::AssemblerData):
(JSC::AssemblerData::operator=):
(JSC::AssemblerData::~AssemblerData):
(JSC::AssemblerData::buffer):
(JSC::AssemblerData::capacity):
(JSC::AssemblerData::grow):
(JSC::AssemblerBuffer::AssemblerBuffer):
(JSC::AssemblerBuffer::isAvailable):
(JSC::AssemblerBuffer::data):
(JSC::AssemblerBuffer::releaseAssemblerData):
(JSC::AssemblerBuffer::putIntegral):
(JSC::AssemblerBuffer::putIntegralUnchecked):
(JSC::AssemblerBuffer::append):
(JSC::AssemblerBuffer::grow):
(JSC::AssemblerBuffer::~AssemblerBuffer): Deleted.
(JSC::AssemblerBuffer::storage): Deleted.
* assembler/LinkBuffer.cpp:
(JSC::recordLinkOffsets):
(JSC::LinkBuffer::copyCompactAndLinkCode):
* assembler/LinkBuffer.h:
(JSC::LinkBuffer::LinkBuffer):
(JSC::LinkBuffer::executableOffsetFor):
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::canCompact):
(JSC::MacroAssemblerARM64::computeJumpType):
(JSC::MacroAssemblerARM64::jumpSizeDelta):
(JSC::MacroAssemblerARM64::link):
(JSC::MacroAssemblerARM64::recordLinkOffsets): Deleted.
* assembler/MacroAssemblerARMv7.h:
(JSC::MacroAssemblerARMv7::canCompact):
(JSC::MacroAssemblerARMv7::computeJumpType):
(JSC::MacroAssemblerARMv7::jumpSizeDelta):
(JSC::MacroAssemblerARMv7::link):
(JSC::MacroAssemblerARMv7::recordLinkOffsets): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (171122 => 171123)


--- trunk/Source/_javascript_Core/ChangeLog	2014-07-15 23:12:00 UTC (rev 171122)
+++ trunk/Source/_javascript_Core/ChangeLog	2014-07-15 23:59:14 UTC (rev 171123)
@@ -1,3 +1,102 @@
+2014-07-15  Benjamin Poulain  <benja...@webkit.org>
+
+        Reduce the overhead of updating the AssemblerBuffer
+        https://bugs.webkit.org/show_bug.cgi?id=134659
+
+        Reviewed by Gavin Barraclough.
+
+        In r164548, the linker was changed to allow the LinkBuffer to survive its MacroAssembler.
+        That feature is useful for JSC to get offsets inside a linked buffer in order to jump directly
+        there.
+
+        On ARM, we use branch compaction and we need to keep the "compaction offset" somewher to be able
+        to get the real address of a lable. That is done by reusing the memory of AssemblerData.
+
+        To share the memory between LinkBuffer and the Assembler, r164548 moved the AssemblerData into
+        a ref-counted object. Unfortunately, the extra complexity related to the new AssemblerData was enough
+        to make clang give up a bunch of optimizations.
+
+        This patch solve (some of) the problems by making AssemblerBuffer and AssemblerData super low overhead structures.
+        In particular, the grow() function becomes 8 Thumb instructions, which is easily inlined everywhere it is used.
+
+        Instead of sharing ownership between the Assembler and LinkBuffer, LinkBuffer now takes full ownership of
+        the AssemblerData. I feel this is also safer since LinkBuffer is reusing the AssemblerData is a very
+        specific way that would make it unusable for the Assembler.
+
+        -- Technical details --
+
+        From LinkBuffer, we don't want to ever access the Assembler after releasing its buffer (or writting anything
+        into it really). This was obviously already the case, but that was hard to prove from LinkBuffer::copyCompactAndLinkCode().
+        To make this easier to work with, I changed all the assembler specific function to be static. This way we know
+        exactly what code access the Assembler instance. The code that does access the instance is then moved
+        at the beginning, before we modify anything.
+
+        The function recordLinkOffsets() that was on the MacroAssembler and copied in Assembler was moved directly
+        to LinkBuffer. This make the modification of AssemblerData completely explicit, and that code is specific
+        to LinkBuffer anyway (see LinkBuffer::executableOffsetFor()).
+
+        -- Perf impact --
+
+        This does not put us exactly at before r164548 due to the missing inline buffer. Still, it is very close.
+        On ARMv7, this reduces the time spent in Assembler by half. On the CSS JIT, this reduces the compilation
+        time by ~20%.
+
+        I could not measure any difference on x86_64.
+
+        * assembler/ARM64Assembler.h:
+        (JSC::ARM64Assembler::jumpSizeDelta):
+        (JSC::ARM64Assembler::canCompact):
+        (JSC::ARM64Assembler::computeJumpType):
+        (JSC::ARM64Assembler::link):
+        (JSC::ARM64Assembler::recordLinkOffsets): Deleted.
+        * assembler/ARMv7Assembler.h:
+        (JSC::ARMv7Assembler::ifThenElseConditionBit):
+        (JSC::ARMv7Assembler::ifThenElse):
+        (JSC::ARMv7Assembler::jumpSizeDelta):
+        (JSC::ARMv7Assembler::canCompact):
+        (JSC::ARMv7Assembler::computeJumpType):
+        (JSC::ARMv7Assembler::link):
+        (JSC::ARMv7Assembler::linkJumpT1):
+        (JSC::ARMv7Assembler::linkJumpT3):
+        (JSC::ARMv7Assembler::linkConditionalJumpT4):
+        (JSC::ARMv7Assembler::linkConditionalBX):
+        (JSC::ARMv7Assembler::recordLinkOffsets): Deleted.
+        * assembler/AssemblerBuffer.h:
+        (JSC::AssemblerData::AssemblerData):
+        (JSC::AssemblerData::operator=):
+        (JSC::AssemblerData::~AssemblerData):
+        (JSC::AssemblerData::buffer):
+        (JSC::AssemblerData::capacity):
+        (JSC::AssemblerData::grow):
+        (JSC::AssemblerBuffer::AssemblerBuffer):
+        (JSC::AssemblerBuffer::isAvailable):
+        (JSC::AssemblerBuffer::data):
+        (JSC::AssemblerBuffer::releaseAssemblerData):
+        (JSC::AssemblerBuffer::putIntegral):
+        (JSC::AssemblerBuffer::putIntegralUnchecked):
+        (JSC::AssemblerBuffer::append):
+        (JSC::AssemblerBuffer::grow):
+        (JSC::AssemblerBuffer::~AssemblerBuffer): Deleted.
+        (JSC::AssemblerBuffer::storage): Deleted.
+        * assembler/LinkBuffer.cpp:
+        (JSC::recordLinkOffsets):
+        (JSC::LinkBuffer::copyCompactAndLinkCode):
+        * assembler/LinkBuffer.h:
+        (JSC::LinkBuffer::LinkBuffer):
+        (JSC::LinkBuffer::executableOffsetFor):
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::canCompact):
+        (JSC::MacroAssemblerARM64::computeJumpType):
+        (JSC::MacroAssemblerARM64::jumpSizeDelta):
+        (JSC::MacroAssemblerARM64::link):
+        (JSC::MacroAssemblerARM64::recordLinkOffsets): Deleted.
+        * assembler/MacroAssemblerARMv7.h:
+        (JSC::MacroAssemblerARMv7::canCompact):
+        (JSC::MacroAssemblerARMv7::computeJumpType):
+        (JSC::MacroAssemblerARMv7::jumpSizeDelta):
+        (JSC::MacroAssemblerARMv7::link):
+        (JSC::MacroAssemblerARMv7::recordLinkOffsets): Deleted.
+
 2014-07-15  Mark Hahnenberg  <mhahnenb...@apple.com>
 
         Stores to PropertyTable use the Structure as the owner

Modified: trunk/Source/_javascript_Core/assembler/ARM64Assembler.h (171122 => 171123)


--- trunk/Source/_javascript_Core/assembler/ARM64Assembler.h	2014-07-15 23:12:00 UTC (rev 171122)
+++ trunk/Source/_javascript_Core/assembler/ARM64Assembler.h	2014-07-15 23:59:14 UTC (rev 171123)
@@ -2877,20 +2877,20 @@
 
     // Assembler admin methods:
 
-    int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JUMP_ENUM_SIZE(jumpType) - JUMP_ENUM_SIZE(jumpLinkType); }
+    static int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JUMP_ENUM_SIZE(jumpType) - JUMP_ENUM_SIZE(jumpLinkType); }
 
     static ALWAYS_INLINE bool linkRecordSourceComparator(const LinkRecord& a, const LinkRecord& b)
     {
         return a.from() < b.from();
     }
 
-    bool canCompact(JumpType jumpType)
+    static bool canCompact(JumpType jumpType)
     {
         // Fixed jumps cannot be compacted
         return (jumpType == JumpNoCondition) || (jumpType == JumpCondition) || (jumpType == JumpCompareAndBranch) || (jumpType == JumpTestBit);
     }
 
-    JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
+    static JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
     {
         switch (jumpType) {
         case JumpFixed:
@@ -2942,29 +2942,20 @@
         return LinkJumpNoCondition;
     }
 
-    JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
+    static JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
     {
         JumpLinkType linkType = computeJumpType(record.type(), from, to);
         record.setLinkType(linkType);
         return linkType;
     }
 
-    void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset)
-    {
-        int32_t ptr = regionStart / sizeof(int32_t);
-        const int32_t end = regionEnd / sizeof(int32_t);
-        int32_t* offsets = static_cast<int32_t*>(m_buffer.data());
-        while (ptr < end)
-            offsets[ptr++] = offset;
-    }
-
     Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink()
     {
         std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
         return m_jumpsToLink;
     }
 
-    void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, uint8_t* to)
+    static void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, uint8_t* to)
     {
         switch (record.linkType()) {
         case LinkJumpNoCondition:

Modified: trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h (171122 => 171123)


--- trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h	2014-07-15 23:12:00 UTC (rev 171122)
+++ trunk/Source/_javascript_Core/assembler/ARMv7Assembler.h	2014-07-15 23:59:14 UTC (rev 171123)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009, 2010, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2010, 2012, 2013, 2014 Apple Inc. All rights reserved.
  * Copyright (C) 2010 University of Szeged
  *
  * Redistribution and use in source and binary forms, with or without
@@ -805,11 +805,11 @@
     class ARMInstructionFormatter;
 
     // false means else!
-    bool ifThenElseConditionBit(Condition condition, bool isIf)
+    static bool ifThenElseConditionBit(Condition condition, bool isIf)
     {
         return isIf ? (condition & 1) : !(condition & 1);
     }
-    uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
+    static uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if, bool inst4if)
     {
         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
             | (ifThenElseConditionBit(condition, inst3if) << 2)
@@ -818,7 +818,7 @@
         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
         return (condition << 4) | mask;
     }
-    uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
+    static uint8_t ifThenElse(Condition condition, bool inst2if, bool inst3if)
     {
         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
             | (ifThenElseConditionBit(condition, inst3if) << 2)
@@ -826,7 +826,7 @@
         ASSERT((condition != ConditionAL) || !(mask & (mask - 1)));
         return (condition << 4) | mask;
     }
-    uint8_t ifThenElse(Condition condition, bool inst2if)
+    static uint8_t ifThenElse(Condition condition, bool inst2if)
     {
         int mask = (ifThenElseConditionBit(condition, inst2if) << 3)
             | 4;
@@ -834,7 +834,7 @@
         return (condition << 4) | mask;
     }
 
-    uint8_t ifThenElse(Condition condition)
+    static uint8_t ifThenElse(Condition condition)
     {
         int mask = 8;
         return (condition << 4) | mask;
@@ -2087,7 +2087,7 @@
         return b.m_offset - a.m_offset;
     }
 
-    int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JUMP_ENUM_SIZE(jumpType) - JUMP_ENUM_SIZE(jumpLinkType); }
+    static int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return JUMP_ENUM_SIZE(jumpType) - JUMP_ENUM_SIZE(jumpLinkType); }
     
     // Assembler admin methods:
 
@@ -2096,7 +2096,7 @@
         return a.from() < b.from();
     }
 
-    bool canCompact(JumpType jumpType)
+    static bool canCompact(JumpType jumpType)
     {
         // The following cannot be compacted:
         //   JumpFixed: represents custom jump sequence
@@ -2105,7 +2105,7 @@
         return (jumpType == JumpNoCondition) || (jumpType == JumpCondition);
     }
     
-    JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
+    static JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to)
     {
         if (jumpType == JumpFixed)
             return LinkInvalid;
@@ -2149,29 +2149,20 @@
         return LinkConditionalBX;
     }
     
-    JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
+    static JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to)
     {
         JumpLinkType linkType = computeJumpType(record.type(), from, to);
         record.setLinkType(linkType);
         return linkType;
     }
     
-    void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset)
-    {
-        int32_t ptr = regionStart / sizeof(int32_t);
-        const int32_t end = regionEnd / sizeof(int32_t);
-        int32_t* offsets = static_cast<int32_t*>(m_formatter.data());
-        while (ptr < end)
-            offsets[ptr++] = offset;
-    }
-    
     Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink()
     {
         std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator);
         return m_jumpsToLink;
     }
 
-    void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, uint8_t* to)
+    static void ALWAYS_INLINE link(LinkRecord& record, uint8_t* from, uint8_t* to)
     {
         switch (record.linkType()) {
         case LinkJumpT1:
@@ -2622,7 +2613,7 @@
         return ((relative << 7) >> 7) == relative;
     }
     
-    void linkJumpT1(Condition cond, uint16_t* instruction, void* target)
+    static void linkJumpT1(Condition cond, uint16_t* instruction, void* target)
     {
         // FIMXE: this should be up in the MacroAssembler layer. :-(        
         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
@@ -2658,7 +2649,7 @@
         instruction[-1] = OP_B_T2 | ((relative & 0xffe) >> 1);
     }
     
-    void linkJumpT3(Condition cond, uint16_t* instruction, void* target)
+    static void linkJumpT3(Condition cond, uint16_t* instruction, void* target)
     {
         // FIMXE: this should be up in the MacroAssembler layer. :-(
         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
@@ -2691,7 +2682,7 @@
         instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1);
     }
     
-    void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target)
+    static void linkConditionalJumpT4(Condition cond, uint16_t* instruction, void* target)
     {
         // FIMXE: this should be up in the MacroAssembler layer. :-(        
         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));
@@ -2717,7 +2708,7 @@
         instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3);
     }
     
-    void linkConditionalBX(Condition cond, uint16_t* instruction, void* target)
+    static void linkConditionalBX(Condition cond, uint16_t* instruction, void* target)
     {
         // FIMXE: this should be up in the MacroAssembler layer. :-(        
         ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1));

Modified: trunk/Source/_javascript_Core/assembler/AssemblerBuffer.h (171122 => 171123)


--- trunk/Source/_javascript_Core/assembler/AssemblerBuffer.h	2014-07-15 23:12:00 UTC (rev 171122)
+++ trunk/Source/_javascript_Core/assembler/AssemblerBuffer.h	2014-07-15 23:59:14 UTC (rev 171123)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2012, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -59,32 +59,69 @@
         uint32_t m_offset;
     };
 
-    struct AssemblerData : public RefCounted<AssemblerData> {
-        static const int inlineCapacity = 128;
+    class AssemblerData {
+    public:
+        AssemblerData()
+            : m_buffer(nullptr)
+            , m_capacity(0)
+        {
+        }
 
-        AssemblerData() : m_data(inlineCapacity) { }
-        
-        typedef Vector<char, inlineCapacity, UnsafeVectorOverflow> DataVector;
-        DataVector m_data;
+        AssemblerData(unsigned initialCapacity)
+        {
+            m_capacity = fastMallocGoodSize(initialCapacity);
+            m_buffer = static_cast<char*>(fastMalloc(m_capacity));
+        }
+
+        AssemblerData(AssemblerData&& other)
+        {
+            m_buffer = other.m_buffer;
+            other.m_buffer = nullptr;
+            m_capacity = other.m_capacity;
+            other.m_capacity = 0;
+        }
+
+        AssemblerData& operator=(AssemblerData&& other)
+        {
+            m_buffer = other.m_buffer;
+            other.m_buffer = nullptr;
+            m_capacity = other.m_capacity;
+            other.m_capacity = 0;
+            return *this;
+        }
+
+        ~AssemblerData()
+        {
+            fastFree(m_buffer);
+        }
+
+        char* buffer() const { return m_buffer; }
+
+        unsigned capacity() const { return m_capacity; }
+
+        void grow(unsigned extraCapacity = 0)
+        {
+            m_capacity = fastMallocGoodSize(m_capacity + m_capacity / 2 + extraCapacity);
+            m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_capacity));
+        }
+
+    private:
+        char* m_buffer;
+        unsigned m_capacity;
     };
 
     class AssemblerBuffer {
+        static const int initialCapacity = 128;
     public:
         AssemblerBuffer()
-            : m_storage(adoptRef(new AssemblerData()))
-            , m_buffer(m_storage->m_data.begin())
-            , m_capacity(AssemblerData::inlineCapacity)
+            : m_storage(initialCapacity)
             , m_index(0)
         {
         }
 
-        ~AssemblerBuffer()
-        {
-        }
-
         bool isAvailable(int space)
         {
-            return m_index + space <= m_capacity;
+            return m_index + space <= m_storage.capacity();
         }
 
         void ensureSpace(int space)
@@ -98,21 +135,6 @@
             return !(m_index & (alignment - 1));
         }
 
-        template<typename IntegralType>
-        void putIntegral(IntegralType value)
-        {
-            ensureSpace(sizeof(IntegralType));
-            putIntegralUnchecked(value);
-        }
-
-        template<typename IntegralType>
-        void putIntegralUnchecked(IntegralType value)
-        {
-            ASSERT(isAvailable(sizeof(IntegralType)));
-            *reinterpret_cast_ptr<IntegralType*>(m_buffer + m_index) = value;
-            m_index += sizeof(IntegralType);
-        }
-
         void putByteUnchecked(int8_t value) { putIntegralUnchecked(value); }
         void putByte(int8_t value) { putIntegral(value); }
         void putShortUnchecked(int16_t value) { putIntegralUnchecked(value); }
@@ -124,7 +146,7 @@
 
         void* data() const
         {
-            return m_buffer;
+            return m_storage.buffer();
         }
 
         size_t codeSize() const
@@ -138,32 +160,46 @@
         }
 
         unsigned debugOffset() { return m_index; }
-        
-        AssemblerData* storage() { return m_storage.get(); }
 
+        AssemblerData releaseAssemblerData() { return WTF::move(m_storage); }
+
     protected:
+        template<typename IntegralType>
+        void putIntegral(IntegralType value)
+        {
+            unsigned nextIndex = m_index + sizeof(IntegralType);
+            if (UNLIKELY(nextIndex > m_storage.capacity()))
+                grow();
+            ASSERT(isAvailable(sizeof(IntegralType)));
+            *reinterpret_cast_ptr<IntegralType*>(m_storage.buffer() + m_index) = value;
+            m_index = nextIndex;
+        }
+
+        template<typename IntegralType>
+        void putIntegralUnchecked(IntegralType value)
+        {
+            ASSERT(isAvailable(sizeof(IntegralType)));
+            *reinterpret_cast_ptr<IntegralType*>(m_storage.buffer() + m_index) = value;
+            m_index += sizeof(IntegralType);
+        }
+
         void append(const char* data, int size)
         {
             if (!isAvailable(size))
                 grow(size);
 
-            memcpy(m_buffer + m_index, data, size);
+            memcpy(m_storage.buffer() + m_index, data, size);
             m_index += size;
         }
 
         void grow(int extraCapacity = 0)
         {
-            m_capacity += m_capacity / 2 + extraCapacity;
-
-            m_storage->m_data.grow(m_capacity);
-            m_buffer = m_storage->m_data.begin();
+            m_storage.grow(extraCapacity);
         }
 
     private:
-        RefPtr<AssemblerData> m_storage;
-        char* m_buffer;
-        int m_capacity;
-        int m_index;
+        AssemblerData m_storage;
+        unsigned m_index;
     };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/assembler/LinkBuffer.cpp (171122 => 171123)


--- trunk/Source/_javascript_Core/assembler/LinkBuffer.cpp	2014-07-15 23:12:00 UTC (rev 171122)
+++ trunk/Source/_javascript_Core/assembler/LinkBuffer.cpp	2014-07-15 23:59:14 UTC (rev 171123)
@@ -77,6 +77,15 @@
 }
 
 #if ENABLE(BRANCH_COMPACTION)
+static ALWAYS_INLINE void recordLinkOffsets(AssemblerData& assemblerData, int32_t regionStart, int32_t regionEnd, int32_t offset)
+{
+    int32_t ptr = regionStart / sizeof(int32_t);
+    const int32_t end = regionEnd / sizeof(int32_t);
+    int32_t* offsets = reinterpret_cast<int32_t*>(assemblerData.buffer());
+    while (ptr < end)
+        offsets[ptr++] = offset;
+}
+
 template <typename InstructionType>
 void LinkBuffer::copyCompactAndLinkCode(MacroAssembler& macroAssembler, void* ownerUID, JITCompilationEffort effort)
 {
@@ -84,11 +93,12 @@
     allocate(m_initialSize, ownerUID, effort);
     if (didFailToAllocate())
         return;
-    uint8_t* inData = (uint8_t*)macroAssembler.unlinkedCode();
+    Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink = macroAssembler.jumpsToLink();
+    m_assemblerStorage = macroAssembler.m_assembler.buffer().releaseAssemblerData();
+    uint8_t* inData = reinterpret_cast<uint8_t*>(m_assemblerStorage.buffer());
     uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
     int readPtr = 0;
     int writePtr = 0;
-    Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink = macroAssembler.jumpsToLink();
     unsigned jumpCount = jumpsToLink.size();
     for (unsigned i = 0; i < jumpCount; ++i) {
         int offset = readPtr - writePtr;
@@ -104,7 +114,7 @@
         ASSERT(!(writePtr % 2));
         while (copySource != copyEnd)
             *copyDst++ = *copySource++;
-        macroAssembler.recordLinkOffsets(readPtr, jumpsToLink[i].from(), offset);
+        recordLinkOffsets(m_assemblerStorage, readPtr, jumpsToLink[i].from(), offset);
         readPtr += regionSize;
         writePtr += regionSize;
             
@@ -116,26 +126,26 @@
         else
             target = outData + jumpsToLink[i].to() - executableOffsetFor(jumpsToLink[i].to());
             
-        JumpLinkType jumpLinkType = macroAssembler.computeJumpType(jumpsToLink[i], outData + writePtr, target);
+        JumpLinkType jumpLinkType = MacroAssembler::computeJumpType(jumpsToLink[i], outData + writePtr, target);
         // Compact branch if we can...
-        if (macroAssembler.canCompact(jumpsToLink[i].type())) {
+        if (MacroAssembler::canCompact(jumpsToLink[i].type())) {
             // Step back in the write stream
-            int32_t delta = macroAssembler.jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType);
+            int32_t delta = MacroAssembler::jumpSizeDelta(jumpsToLink[i].type(), jumpLinkType);
             if (delta) {
                 writePtr -= delta;
-                macroAssembler.recordLinkOffsets(jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
+                recordLinkOffsets(m_assemblerStorage, jumpsToLink[i].from() - delta, readPtr, readPtr - writePtr);
             }
         }
         jumpsToLink[i].setFrom(writePtr);
     }
     // Copy everything after the last jump
     memcpy(outData + writePtr, inData + readPtr, m_initialSize - readPtr);
-    macroAssembler.recordLinkOffsets(readPtr, m_initialSize, readPtr - writePtr);
+    recordLinkOffsets(m_assemblerStorage, readPtr, m_initialSize, readPtr - writePtr);
         
     for (unsigned i = 0; i < jumpCount; ++i) {
         uint8_t* location = outData + jumpsToLink[i].from();
         uint8_t* target = outData + jumpsToLink[i].to() - executableOffsetFor(jumpsToLink[i].to());
-        macroAssembler.link(jumpsToLink[i], location, target);
+        MacroAssembler::link(jumpsToLink[i], location, target);
     }
 
     jumpsToLink.clear();

Modified: trunk/Source/_javascript_Core/assembler/LinkBuffer.h (171122 => 171123)


--- trunk/Source/_javascript_Core/assembler/LinkBuffer.h	2014-07-15 23:12:00 UTC (rev 171122)
+++ trunk/Source/_javascript_Core/assembler/LinkBuffer.h	2014-07-15 23:59:14 UTC (rev 171123)
@@ -87,7 +87,6 @@
 #endif
         , m_didAllocate(false)
         , m_code(0)
-        , m_storage(macroAssembler.m_assembler.buffer().storage())
         , m_vm(&vm)
 #ifndef NDEBUG
         , m_completed(false)
@@ -103,7 +102,6 @@
 #endif
         , m_didAllocate(false)
         , m_code(code)
-        , m_storage(macroAssembler.m_assembler.buffer().storage())
         , m_vm(&vm)
 #ifndef NDEBUG
         , m_completed(false)
@@ -250,7 +248,8 @@
     {
         return m_code;
     }
-    
+
+    // FIXME: this does not account for the AssemblerData size!
     size_t size()
     {
         return m_size;
@@ -262,7 +261,7 @@
     {
         if (!location)
             return 0;
-        return bitwise_cast<int32_t*>(m_storage->m_data.begin())[location / sizeof(int32_t) - 1];
+        return bitwise_cast<int32_t*>(m_assemblerStorage.buffer())[location / sizeof(int32_t) - 1];
     }
 #endif
     
@@ -303,10 +302,10 @@
     size_t m_size;
 #if ENABLE(BRANCH_COMPACTION)
     size_t m_initialSize;
+    AssemblerData m_assemblerStorage;
 #endif
     bool m_didAllocate;
     void* m_code;
-    RefPtr<AssemblerData> m_storage;
     VM* m_vm;
 #ifndef NDEBUG
     bool m_completed;

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (171122 => 171123)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2014-07-15 23:12:00 UTC (rev 171122)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h	2014-07-15 23:59:14 UTC (rev 171123)
@@ -64,12 +64,11 @@
 
     Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink() { return m_assembler.jumpsToLink(); }
     void* unlinkedCode() { return m_assembler.unlinkedCode(); }
-    bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); }
-    JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(jumpType, from, to); }
-    JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(record, from, to); }
-    void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset) {return m_assembler.recordLinkOffsets(regionStart, regionEnd, offset); }
-    int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return m_assembler.jumpSizeDelta(jumpType, jumpLinkType); }
-    void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return m_assembler.link(record, from, to); }
+    static bool canCompact(JumpType jumpType) { return ARM64Assembler::canCompact(jumpType); }
+    static JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return ARM64Assembler::computeJumpType(jumpType, from, to); }
+    static JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return ARM64Assembler::computeJumpType(record, from, to); }
+    static int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return ARM64Assembler::jumpSizeDelta(jumpType, jumpLinkType); }
+    static void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return ARM64Assembler::link(record, from, to); }
 
     static const Scale ScalePtr = TimesEight;
 

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (171122 => 171123)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2014-07-15 23:12:00 UTC (rev 171122)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h	2014-07-15 23:59:14 UTC (rev 171123)
@@ -62,12 +62,11 @@
 
     Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink() { return m_assembler.jumpsToLink(); }
     void* unlinkedCode() { return m_assembler.unlinkedCode(); }
-    bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); }
-    JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(jumpType, from, to); }
-    JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(record, from, to); }
-    void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset) {return m_assembler.recordLinkOffsets(regionStart, regionEnd, offset); }
-    int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return m_assembler.jumpSizeDelta(jumpType, jumpLinkType); }
-    void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return m_assembler.link(record, from, to); }
+    static bool canCompact(JumpType jumpType) { return ARMv7Assembler::canCompact(jumpType); }
+    static JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return ARMv7Assembler::computeJumpType(jumpType, from, to); }
+    static JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return ARMv7Assembler::computeJumpType(record, from, to); }
+    static int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return ARMv7Assembler::jumpSizeDelta(jumpType, jumpLinkType); }
+    static void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return ARMv7Assembler::link(record, from, to); }
 
     struct ArmAddress {
         enum AddressType {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to