summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/assembler/AssemblerBuffer.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/assembler/AssemblerBuffer.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/assembler/AssemblerBuffer.h')
-rw-r--r--Source/JavaScriptCore/assembler/AssemblerBuffer.h217
1 files changed, 178 insertions, 39 deletions
diff --git a/Source/JavaScriptCore/assembler/AssemblerBuffer.h b/Source/JavaScriptCore/assembler/AssemblerBuffer.h
index 120868d63..7340952d5 100644
--- a/Source/JavaScriptCore/assembler/AssemblerBuffer.h
+++ b/Source/JavaScriptCore/assembler/AssemblerBuffer.h
@@ -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
@@ -23,8 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef AssemblerBuffer_h
-#define AssemblerBuffer_h
+#pragma once
#if ENABLE(ASSEMBLER)
@@ -56,53 +55,113 @@ namespace JSC {
return AssemblerLabel(m_offset + offset);
}
+ bool operator==(const AssemblerLabel& other) const { return m_offset == other.m_offset; }
+
uint32_t m_offset;
};
- class AssemblerBuffer {
- static const int inlineCapacity = 128;
+ class AssemblerData {
+ WTF_MAKE_NONCOPYABLE(AssemblerData);
+ static const size_t InlineCapacity = 128;
public:
- AssemblerBuffer()
- : m_storage(inlineCapacity)
- , m_buffer(m_storage.begin())
- , m_capacity(inlineCapacity)
- , m_index(0)
+ AssemblerData()
+ : m_buffer(m_inlineBuffer)
+ , m_capacity(InlineCapacity)
{
}
- ~AssemblerBuffer()
+ AssemblerData(size_t initialCapacity)
{
+ if (initialCapacity <= InlineCapacity) {
+ m_capacity = InlineCapacity;
+ m_buffer = m_inlineBuffer;
+ } else {
+ m_capacity = initialCapacity;
+ m_buffer = static_cast<char*>(fastMalloc(m_capacity));
+ }
}
- bool isAvailable(int space)
+ AssemblerData(AssemblerData&& other)
{
- return m_index + space <= m_capacity;
+ if (other.isInlineBuffer()) {
+ ASSERT(other.m_capacity == InlineCapacity);
+ memcpy(m_inlineBuffer, other.m_inlineBuffer, InlineCapacity);
+ m_buffer = m_inlineBuffer;
+ } else
+ m_buffer = other.m_buffer;
+ m_capacity = other.m_capacity;
+
+ other.m_buffer = nullptr;
+ other.m_capacity = 0;
}
- void ensureSpace(int space)
+ AssemblerData& operator=(AssemblerData&& other)
{
- if (!isAvailable(space))
- grow();
+ if (m_buffer && !isInlineBuffer())
+ fastFree(m_buffer);
+
+ if (other.isInlineBuffer()) {
+ ASSERT(other.m_capacity == InlineCapacity);
+ memcpy(m_inlineBuffer, other.m_inlineBuffer, InlineCapacity);
+ m_buffer = m_inlineBuffer;
+ } else
+ m_buffer = other.m_buffer;
+ m_capacity = other.m_capacity;
+
+ other.m_buffer = nullptr;
+ other.m_capacity = 0;
+ return *this;
}
- bool isAligned(int alignment) const
+ ~AssemblerData()
{
- return !(m_index & (alignment - 1));
+ if (m_buffer && !isInlineBuffer())
+ fastFree(m_buffer);
}
- template<typename IntegralType>
- void putIntegral(IntegralType value)
+ char* buffer() const { return m_buffer; }
+
+ unsigned capacity() const { return m_capacity; }
+
+ void grow(unsigned extraCapacity = 0)
{
- ensureSpace(sizeof(IntegralType));
- putIntegralUnchecked(value);
+ m_capacity = m_capacity + m_capacity / 2 + extraCapacity;
+ if (isInlineBuffer()) {
+ m_buffer = static_cast<char*>(fastMalloc(m_capacity));
+ memcpy(m_buffer, m_inlineBuffer, InlineCapacity);
+ } else
+ m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_capacity));
}
- template<typename IntegralType>
- void putIntegralUnchecked(IntegralType value)
+ private:
+ bool isInlineBuffer() const { return m_buffer == m_inlineBuffer; }
+ char* m_buffer;
+ char m_inlineBuffer[InlineCapacity];
+ unsigned m_capacity;
+ };
+
+ class AssemblerBuffer {
+ public:
+ AssemblerBuffer()
+ : m_storage()
+ , m_index(0)
{
- ASSERT(isAvailable(sizeof(IntegralType)));
- *reinterpret_cast_ptr<IntegralType*>(m_buffer + m_index) = value;
- m_index += sizeof(IntegralType);
+ }
+
+ bool isAvailable(unsigned space)
+ {
+ return m_index + space <= m_storage.capacity();
+ }
+
+ void ensureSpace(unsigned space)
+ {
+ while (!isAvailable(space))
+ outOfLineGrow();
+ }
+
+ bool isAligned(int alignment) const
+ {
+ return !(m_index & (alignment - 1));
}
void putByteUnchecked(int8_t value) { putIntegralUnchecked(value); }
@@ -116,7 +175,7 @@ namespace JSC {
void* data() const
{
- return m_buffer;
+ return m_storage.buffer();
}
size_t codeSize() const
@@ -124,6 +183,15 @@ namespace JSC {
return m_index;
}
+ void setCodeSize(size_t index)
+ {
+ // Warning: Only use this if you know exactly what you are doing.
+ // For example, say you want 40 bytes of nops, it's ok to grow
+ // and then fill 40 bytes of nops using bigger instructions.
+ m_index = index;
+ ASSERT(m_index <= m_storage.capacity());
+ }
+
AssemblerLabel label() const
{
return AssemblerLabel(m_index);
@@ -131,33 +199,104 @@ namespace JSC {
unsigned debugOffset() { return m_index; }
+ AssemblerData&& releaseAssemblerData() { return WTFMove(m_storage); }
+
+ // LocalWriter is a trick to keep the storage buffer and the index
+ // in memory while issuing multiple Stores.
+ // It is created in a block scope and its attribute can stay live
+ // between writes.
+ //
+ // LocalWriter *CANNOT* be mixed with other types of access to AssemblerBuffer.
+ // AssemblerBuffer cannot be used until its LocalWriter goes out of scope.
+ class LocalWriter {
+ public:
+ LocalWriter(AssemblerBuffer& buffer, unsigned requiredSpace)
+ : m_buffer(buffer)
+ {
+ buffer.ensureSpace(requiredSpace);
+ m_storageBuffer = buffer.m_storage.buffer();
+ m_index = buffer.m_index;
+#if !defined(NDEBUG)
+ m_initialIndex = m_index;
+ m_requiredSpace = requiredSpace;
+#endif
+ }
+
+ ~LocalWriter()
+ {
+ ASSERT(m_index - m_initialIndex <= m_requiredSpace);
+ ASSERT(m_buffer.m_index == m_initialIndex);
+ ASSERT(m_storageBuffer == m_buffer.m_storage.buffer());
+ m_buffer.m_index = m_index;
+ }
+
+ void putByteUnchecked(int8_t value) { putIntegralUnchecked(value); }
+ void putShortUnchecked(int16_t value) { putIntegralUnchecked(value); }
+ void putIntUnchecked(int32_t value) { putIntegralUnchecked(value); }
+ void putInt64Unchecked(int64_t value) { putIntegralUnchecked(value); }
+ private:
+ template<typename IntegralType>
+ void putIntegralUnchecked(IntegralType value)
+ {
+ ASSERT(m_index + sizeof(IntegralType) <= m_buffer.m_storage.capacity());
+ *reinterpret_cast_ptr<IntegralType*>(m_storageBuffer + m_index) = value;
+ m_index += sizeof(IntegralType);
+ }
+ AssemblerBuffer& m_buffer;
+ char* m_storageBuffer;
+ unsigned m_index;
+#if !defined(NDEBUG)
+ unsigned m_initialIndex;
+ unsigned m_requiredSpace;
+#endif
+ };
+
protected:
+ template<typename IntegralType>
+ void putIntegral(IntegralType value)
+ {
+ unsigned nextIndex = m_index + sizeof(IntegralType);
+ if (UNLIKELY(nextIndex > m_storage.capacity()))
+ outOfLineGrow();
+ 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.grow(m_capacity);
- m_buffer = m_storage.begin();
+ m_storage.grow(extraCapacity);
}
private:
- Vector<char, inlineCapacity, UnsafeVectorOverflow> m_storage;
- char* m_buffer;
- int m_capacity;
- int m_index;
+ NEVER_INLINE void outOfLineGrow()
+ {
+ m_storage.grow();
+ }
+
+ friend LocalWriter;
+
+ AssemblerData m_storage;
+ unsigned m_index;
};
} // namespace JSC
#endif // ENABLE(ASSEMBLER)
-
-#endif // AssemblerBuffer_h