#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)
- {
- if (m_size > m_capacity - space)
- grow();
- }
+ bool isSet() const { return (m_offset != std::numeric_limits<uint32_t>::max()); }
- bool isAligned(int alignment) const
+ AssemblerLabel labelAtOffset(int offset) const
{
- return !(m_size & (alignment - 1));
+ return AssemblerLabel(m_offset + offset);
}
- void putByteUnchecked(int value)
+ uint32_t m_offset;
+ };
+
+ class AssemblerBuffer {
+ static const int inlineCapacity = 128;
+ public:
+ AssemblerBuffer()
+ : m_storage(inlineCapacity)
+ , m_buffer(m_storage.begin())
+ , m_capacity(inlineCapacity)
+ , m_index(0)
{
- ASSERT(!(m_size > m_capacity - 4));
- m_buffer[m_size] = value;
- m_size++;
}
- void putByte(int value)
+ ~AssemblerBuffer()
{
- if (m_size > m_capacity - 4)
- grow();
- putByteUnchecked(value);
}
- void putShortUnchecked(int value)
+ bool isAvailable(int space)
{
- ASSERT(!(m_size > m_capacity - 4));
- *reinterpret_cast<short*>(&m_buffer[m_size]) = value;
- m_size += 2;
+ return m_index + space <= m_capacity;
}
- void putShort(int value)
+ void ensureSpace(int space)
{
- if (m_size > m_capacity - 4)
+ if (!isAvailable(space))
grow();
- putShortUnchecked(value);
}
- void putIntUnchecked(int value)
+ bool isAligned(int alignment) const
{
- ASSERT(!(m_size > m_capacity - 4));
- *reinterpret_cast<int*>(&m_buffer[m_size]) = value;
- m_size += 4;
+ return !(m_index & (alignment - 1));
}
- void putInt64Unchecked(int64_t value)
+ template<typename IntegralType>
+ void putIntegral(IntegralType value)
{
- ASSERT(!(m_size > m_capacity - 8));
- *reinterpret_cast<int64_t*>(&m_buffer[m_size]) = value;
- m_size += 8;
+ ensureSpace(sizeof(IntegralType));
+ putIntegralUnchecked(value);
}
- void putInt(int value)
+ template<typename IntegralType>
+ void putIntegralUnchecked(IntegralType value)
{
- if (m_size > m_capacity - 4)
- grow();
- putIntUnchecked(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); }
+ 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;
}
- int size() const
+ size_t codeSize() const
{
- return m_size;
+ return m_index;
}
- void* executableCopy(ExecutablePool* allocator)
+ AssemblerLabel label() const
{
- if (!m_size)
+ return AssemblerLabel(m_index);
+ }
+
+ void* executableCopy(JSGlobalData& globalData, ExecutablePool* allocator)
+ {
+ if (!m_index)
return 0;
- void* result = allocator->alloc(m_size);
+ void* result = allocator->alloc(globalData, m_index);
if (!result)
return 0;
- ExecutableAllocator::makeWritable(result, m_size);
+ ExecutableAllocator::makeWritable(result, m_index);
- return memcpy(result, m_buffer, m_size);
+ return memcpy(result, m_buffer, m_index);
}
+ void rewindToLabel(AssemblerLabel label)
+ {
+ m_index = label.m_offset;
+ }
+
+#ifndef NDEBUG
+ unsigned debugOffset() { return m_index; }
+#endif
+
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_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(m_capacity);
+ m_buffer = m_storage.begin();
}
- char m_inlineBuffer[inlineCapacity];
+ private:
+ Vector<char, inlineCapacity> m_storage;
char* m_buffer;
int m_capacity;
- int m_size;
+ int m_index;
};
} // namespace JSC