1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #ifndef AssemblerBuffer_h 27 #define AssemblerBuffer_h 28 29 #if ENABLE(ASSEMBLER) 30 31 #include "stdint.h" 32 #include <string.h> 33 #include <jit/ExecutableAllocator.h> 34 #include <wtf/Assertions.h> 35 #include <wtf/FastMalloc.h> 36 #include <wtf/StdLibExtras.h> 37 38 namespace JSC { 39 40 class AssemblerBuffer { 41 static const int inlineCapacity = 128 - sizeof(char*) - 2 * sizeof(int); 42 public: AssemblerBuffer()43 AssemblerBuffer() 44 : m_buffer(m_inlineBuffer) 45 , m_capacity(inlineCapacity) 46 , m_size(0) 47 { 48 COMPILE_ASSERT(sizeof(AssemblerBuffer) == 128, AssemblerBuffer_should_be_128_bytes); 49 } 50 ~AssemblerBuffer()51 ~AssemblerBuffer() 52 { 53 if (m_buffer != m_inlineBuffer) 54 fastFree(m_buffer); 55 } 56 ensureSpace(int space)57 void ensureSpace(int space) 58 { 59 if (m_size > m_capacity - space) 60 grow(); 61 } 62 isAligned(int alignment)63 bool isAligned(int alignment) const 64 { 65 return !(m_size & (alignment - 1)); 66 } 67 putByteUnchecked(int value)68 void putByteUnchecked(int value) 69 { 70 ASSERT(!(m_size > m_capacity - 4)); 71 m_buffer[m_size] = value; 72 m_size++; 73 } 74 putByte(int value)75 void putByte(int value) 76 { 77 if (m_size > m_capacity - 4) 78 grow(); 79 putByteUnchecked(value); 80 } 81 putShortUnchecked(int value)82 void putShortUnchecked(int value) 83 { 84 ASSERT(!(m_size > m_capacity - 4)); 85 *reinterpret_cast_ptr<short*>(&m_buffer[m_size]) = value; 86 m_size += 2; 87 } 88 putShort(int value)89 void putShort(int value) 90 { 91 if (m_size > m_capacity - 4) 92 grow(); 93 putShortUnchecked(value); 94 } 95 putIntUnchecked(int value)96 void putIntUnchecked(int value) 97 { 98 ASSERT(!(m_size > m_capacity - 4)); 99 *reinterpret_cast_ptr<int*>(&m_buffer[m_size]) = value; 100 m_size += 4; 101 } 102 putInt64Unchecked(int64_t value)103 void putInt64Unchecked(int64_t value) 104 { 105 ASSERT(!(m_size > m_capacity - 8)); 106 *reinterpret_cast_ptr<int64_t*>(&m_buffer[m_size]) = value; 107 m_size += 8; 108 } 109 putInt(int value)110 void putInt(int value) 111 { 112 if (m_size > m_capacity - 4) 113 grow(); 114 putIntUnchecked(value); 115 } 116 117 template<typename IntegralType> putIntegral(IntegralType value)118 void putIntegral(IntegralType value) 119 { 120 if (m_size > m_capacity - sizeof(IntegralType)) 121 grow(); 122 putIntegralUnchecked(value); 123 } 124 125 template<typename IntegralType> putIntegralUnchecked(IntegralType value)126 void putIntegralUnchecked(IntegralType value) 127 { 128 *reinterpret_cast_ptr<IntegralType*>(&m_buffer[m_size]) = value; 129 m_size += sizeof(IntegralType); 130 } 131 data()132 void* data() const 133 { 134 return m_buffer; 135 } 136 size()137 int size() const 138 { 139 return m_size; 140 } 141 executableCopy(ExecutablePool * allocator)142 void* executableCopy(ExecutablePool* allocator) 143 { 144 if (!m_size) 145 return 0; 146 147 void* result = allocator->alloc(m_size); 148 149 if (!result) 150 return 0; 151 152 ExecutableAllocator::makeWritable(result, m_size); 153 154 return memcpy(result, m_buffer, m_size); 155 } 156 rewindToOffset(int offset)157 void rewindToOffset(int offset) 158 { 159 ASSERT(offset >= 0); 160 m_size = offset; 161 } 162 163 #ifndef NDEBUG debugOffset()164 unsigned debugOffset() { return m_size; } 165 #endif 166 167 protected: append(const char * data,int size)168 void append(const char* data, int size) 169 { 170 if (m_size > m_capacity - size) 171 grow(size); 172 173 memcpy(m_buffer + m_size, data, size); 174 m_size += size; 175 } 176 177 void grow(int extraCapacity = 0) 178 { 179 m_capacity += m_capacity / 2 + extraCapacity; 180 181 if (m_buffer == m_inlineBuffer) { 182 char* newBuffer = static_cast<char*>(fastMalloc(m_capacity)); 183 m_buffer = static_cast<char*>(memcpy(newBuffer, m_buffer, m_size)); 184 } else 185 m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_capacity)); 186 } 187 188 char m_inlineBuffer[inlineCapacity]; 189 char* m_buffer; 190 int m_capacity; 191 int m_size; 192 }; 193 194 } // namespace JSC 195 196 #endif // ENABLE(ASSEMBLER) 197 198 #endif // AssemblerBuffer_h 199