]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/AssemblerBuffer.h
JavaScriptCore-7600.1.4.13.1.tar.gz
[apple/javascriptcore.git] / assembler / AssemblerBuffer.h
index e2fb8a1cc68d019c0ed4305e9e5c0b3611bafd69..1c33fe1ac26fa017eb73e9da923d09567a6e4dd5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 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
 
 #if ENABLE(ASSEMBLER)
 
+#include "ExecutableAllocator.h"
+#include "JITCompilationEffort.h"
 #include "stdint.h"
 #include <string.h>
-#include <jit/ExecutableAllocator.h>
 #include <wtf/Assertions.h>
 #include <wtf/FastMalloc.h>
+#include <wtf/StdLibExtras.h>
 
 namespace JSC {
 
-    class AssemblerBuffer {
-        static const int inlineCapacity = 256;
-    public:
-        AssemblerBuffer()
-            : m_buffer(m_inlineBuffer)
-            , m_capacity(inlineCapacity)
-            , m_size(0)
+    struct AssemblerLabel {
+        AssemblerLabel()
+            : m_offset(std::numeric_limits<uint32_t>::max())
         {
         }
 
-        ~AssemblerBuffer()
+        explicit AssemblerLabel(uint32_t offset)
+            : m_offset(offset)
         {
-            if (m_buffer != m_inlineBuffer)
-                fastFree(m_buffer);
         }
 
-        void ensureSpace(int space)
+        bool isSet() const { return (m_offset != std::numeric_limits<uint32_t>::max()); }
+
+        AssemblerLabel labelAtOffset(int offset) const
         {
-            if (m_size > m_capacity - space)
-                grow();
+            return AssemblerLabel(m_offset + offset);
         }
 
-        bool isAligned(int alignment) const
+        uint32_t m_offset;
+    };
+
+    class AssemblerData {
+    public:
+        AssemblerData()
+            : m_buffer(nullptr)
+            , m_capacity(0)
         {
-            return !(m_size & (alignment - 1));
         }
 
-        void putByteUnchecked(int value)
+        AssemblerData(unsigned initialCapacity)
         {
-            ASSERT(!(m_size > m_capacity - 4));
-            m_buffer[m_size] = value;
-            m_size++;
+            m_capacity = fastMallocGoodSize(initialCapacity);
+            m_buffer = static_cast<char*>(fastMalloc(m_capacity));
         }
 
-        void putByte(int value)
+        AssemblerData(AssemblerData&& other)
         {
-            if (m_size > m_capacity - 4)
-                grow();
-            putByteUnchecked(value);
+            m_buffer = other.m_buffer;
+            other.m_buffer = nullptr;
+            m_capacity = other.m_capacity;
+            other.m_capacity = 0;
         }
 
-        void putShortUnchecked(int value)
+        AssemblerData& operator=(AssemblerData&& other)
         {
-            ASSERT(!(m_size > m_capacity - 4));
-            *reinterpret_cast<short*>(&m_buffer[m_size]) = value;
-            m_size += 2;
+            m_buffer = other.m_buffer;
+            other.m_buffer = nullptr;
+            m_capacity = other.m_capacity;
+            other.m_capacity = 0;
+            return *this;
         }
 
-        void putShort(int value)
+        ~AssemblerData()
         {
-            if (m_size > m_capacity - 4)
-                grow();
-            putShortUnchecked(value);
+            fastFree(m_buffer);
         }
 
-        void putIntUnchecked(int value)
+        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(initialCapacity)
+            , m_index(0)
         {
-            ASSERT(!(m_size > m_capacity - 4));
-            *reinterpret_cast<int*>(&m_buffer[m_size]) = value;
-            m_size += 4;
         }
 
-        void putInt64Unchecked(int64_t value)
+        bool isAvailable(int space)
         {
-            ASSERT(!(m_size > m_capacity - 8));
-            *reinterpret_cast<int64_t*>(&m_buffer[m_size]) = value;
-            m_size += 8;
+            return m_index + space <= m_storage.capacity();
         }
 
-        void putInt(int value)
+        void ensureSpace(int space)
         {
-            if (m_size > m_capacity - 4)
+            if (!isAvailable(space))
                 grow();
-            putIntUnchecked(value);
         }
 
+        bool isAligned(int alignment) const
+        {
+            return !(m_index & (alignment - 1));
+        }
+
+        void putByteUnchecked(int8_t value) { putIntegralUnchecked(value); }
+        void putByte(int8_t value) { putIntegral(value); }
+        void putShortUnchecked(int16_t value) { putIntegralUnchecked(value); }
+        void putShort(int16_t value) { putIntegral(value); }
+        void putIntUnchecked(int32_t value) { putIntegralUnchecked(value); }
+        void putInt(int32_t value) { putIntegral(value); }
+        void putInt64Unchecked(int64_t value) { putIntegralUnchecked(value); }
+        void putInt64(int64_t value) { putIntegral(value); }
+
         void* data() const
         {
-            return m_buffer;
+            return m_storage.buffer();
         }
 
-        int size() const
+        size_t codeSize() const
         {
-            return m_size;
+            return m_index;
         }
 
-        void* executableCopy(ExecutablePool* allocator)
+        AssemblerLabel label() const
         {
-            if (!m_size)
-                return 0;
+            return AssemblerLabel(m_index);
+        }
 
-            void* result = allocator->alloc(m_size);
+        unsigned debugOffset() { return m_index; }
 
-            if (!result)
-                return 0;
+        AssemblerData releaseAssemblerData() { return WTF::move(m_storage); }
 
-            ExecutableAllocator::makeWritable(result, m_size);
+    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;
+        }
 
-            return memcpy(result, m_buffer, m_size);
+        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);
         }
 
-    protected:
         void append(const char* data, int size)
         {
-            if (m_size > m_capacity - size)
+            if (!isAvailable(size))
                 grow(size);
 
-            memcpy(m_buffer + m_size, data, size);
-            m_size += size;
+            memcpy(m_storage.buffer() + m_index, data, size);
+            m_index += size;
         }
 
         void grow(int extraCapacity = 0)
         {
-            m_capacity += m_capacity / 2 + extraCapacity;
-
-            if (m_buffer == m_inlineBuffer) {
-                char* newBuffer = static_cast<char*>(fastMalloc(m_capacity));
-                m_buffer = static_cast<char*>(memcpy(newBuffer, m_buffer, m_size));
-            } else
-                m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_capacity));
+            m_storage.grow(extraCapacity);
         }
 
-        char m_inlineBuffer[inlineCapacity];
-        char* m_buffer;
-        int m_capacity;
-        int m_size;
+    private:
+        AssemblerData m_storage;
+        unsigned m_index;
     };
 
 } // namespace JSC