diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/assembler/AssemblerBuffer.h | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/assembler/AssemblerBuffer.h')
-rw-r--r-- | Source/JavaScriptCore/assembler/AssemblerBuffer.h | 217 |
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 |