1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sw=4 et tw=79:
4 * ***** BEGIN LICENSE BLOCK *****
5 * Copyright (C) 2008 Apple Inc. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 * ***** END LICENSE BLOCK ***** */
30 #ifndef AssemblerBuffer_h
31 #define AssemblerBuffer_h
33 #include "assembler/wtf/Platform.h"
38 #include "assembler/jit/ExecutableAllocator.h"
39 #include "assembler/wtf/Assertions.h"
44 class AssemblerBuffer {
45 static const int inlineCapacity = 256;
48 : m_buffer(m_inlineBuffer)
49 , m_capacity(inlineCapacity)
57 if (m_buffer != m_inlineBuffer)
61 void ensureSpace(int space)
63 if (m_size > m_capacity - space)
67 bool isAligned(int alignment) const
69 return !(m_size & (alignment - 1));
72 void putByteUnchecked(int value)
74 ASSERT(!(m_size > m_capacity - 4));
75 m_buffer[m_size] = char(value);
79 void putByte(int value)
81 if (m_size > m_capacity - 4)
83 putByteUnchecked(value);
86 void putShortUnchecked(int value)
88 ASSERT(!(m_size > m_capacity - 4));
89 *reinterpret_cast<short*>(&m_buffer[m_size]) = short(value);
93 void putShort(int value)
95 if (m_size > m_capacity - 4)
97 putShortUnchecked(value);
100 void putIntUnchecked(int value)
102 ASSERT(!(m_size > m_capacity - 4));
103 *reinterpret_cast<int*>(&m_buffer[m_size]) = value;
107 void putInt64Unchecked(int64_t value)
109 ASSERT(!(m_size > m_capacity - 8));
110 *reinterpret_cast<int64_t*>(&m_buffer[m_size]) = value;
114 void putInt(int value)
116 if (m_size > m_capacity - 4)
118 putIntUnchecked(value);
137 * The user must check for a NULL return value, which means
138 * no code was generated, or there was an OOM.
140 void* executableCopy(ExecutablePool* allocator)
148 void* result = allocator->alloc(m_size);
153 ExecutableAllocator::makeWritable(result, m_size);
155 return memcpy(result, m_buffer, m_size);
158 unsigned char *buffer() const {
160 return reinterpret_cast<unsigned char *>(m_buffer);
164 void append(const char* data, int size)
166 if (m_size > m_capacity - size)
169 // If we OOM and size > inlineCapacity, this would crash.
172 memcpy(m_buffer + m_size, data, size);
177 * OOM handling: This class can OOM in the grow() method trying to
178 * allocate a new buffer. In response to an OOM, we need to avoid
179 * crashing and report the error. We also want to make it so that
180 * users of this class need to check for OOM only at certain points
181 * and not after every operation.
183 * Our strategy for handling an OOM is to set m_oom, and then set
184 * m_size to 0, preserving the current buffer. This way, the user
185 * can continue assembling into the buffer, deferring OOM checking
186 * until the user wants to read code out of the buffer.
188 * See also the |executableCopy| and |buffer| methods.
191 void grow(int extraCapacity = 0)
193 int newCapacity = m_capacity + m_capacity / 2 + extraCapacity;
196 if (m_buffer == m_inlineBuffer) {
197 newBuffer = static_cast<char*>(malloc(newCapacity));
203 memcpy(newBuffer, m_buffer, m_size);
205 newBuffer = static_cast<char*>(realloc(m_buffer, newCapacity));
213 m_buffer = newBuffer;
214 m_capacity = newCapacity;
217 char m_inlineBuffer[inlineCapacity];
226 #endif // ENABLE(ASSEMBLER)
228 #endif // AssemblerBuffer_h