1/* 2 * Copyright (C) 2008, 2012 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 "ExecutableAllocator.h" 32#include "JITCompilationEffort.h" 33#include "VM.h" 34#include "stdint.h" 35#include <string.h> 36#include <wtf/Assertions.h> 37#include <wtf/FastMalloc.h> 38#include <wtf/StdLibExtras.h> 39 40namespace JSC { 41 42 struct AssemblerLabel { 43 AssemblerLabel() 44 : m_offset(std::numeric_limits<uint32_t>::max()) 45 { 46 } 47 48 explicit AssemblerLabel(uint32_t offset) 49 : m_offset(offset) 50 { 51 } 52 53 bool isSet() const { return (m_offset != std::numeric_limits<uint32_t>::max()); } 54 55 AssemblerLabel labelAtOffset(int offset) const 56 { 57 return AssemblerLabel(m_offset + offset); 58 } 59 60 uint32_t m_offset; 61 }; 62 63 class AssemblerBuffer { 64 static const int inlineCapacity = 128; 65 public: 66 AssemblerBuffer() 67 : m_storage(inlineCapacity) 68 , m_buffer(m_storage.begin()) 69 , m_capacity(inlineCapacity) 70 , m_index(0) 71 { 72 } 73 74 ~AssemblerBuffer() 75 { 76 } 77 78 bool isAvailable(int space) 79 { 80 return m_index + space <= m_capacity; 81 } 82 83 void ensureSpace(int space) 84 { 85 if (!isAvailable(space)) 86 grow(); 87 } 88 89 bool isAligned(int alignment) const 90 { 91 return !(m_index & (alignment - 1)); 92 } 93 94 template<typename IntegralType> 95 void putIntegral(IntegralType value) 96 { 97 ensureSpace(sizeof(IntegralType)); 98 putIntegralUnchecked(value); 99 } 100 101 template<typename IntegralType> 102 void putIntegralUnchecked(IntegralType value) 103 { 104 ASSERT(isAvailable(sizeof(IntegralType))); 105 *reinterpret_cast_ptr<IntegralType*>(m_buffer + m_index) = value; 106 m_index += sizeof(IntegralType); 107 } 108 109 void putByteUnchecked(int8_t value) { putIntegralUnchecked(value); } 110 void putByte(int8_t value) { putIntegral(value); } 111 void putShortUnchecked(int16_t value) { putIntegralUnchecked(value); } 112 void putShort(int16_t value) { putIntegral(value); } 113 void putIntUnchecked(int32_t value) { putIntegralUnchecked(value); } 114 void putInt(int32_t value) { putIntegral(value); } 115 void putInt64Unchecked(int64_t value) { putIntegralUnchecked(value); } 116 void putInt64(int64_t value) { putIntegral(value); } 117 118 void* data() const 119 { 120 return m_buffer; 121 } 122 123 size_t codeSize() const 124 { 125 return m_index; 126 } 127 128 AssemblerLabel label() const 129 { 130 return AssemblerLabel(m_index); 131 } 132 133 PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort) 134 { 135 if (!m_index) 136 return 0; 137 138 RefPtr<ExecutableMemoryHandle> result = vm.executableAllocator.allocate(vm, m_index, ownerUID, effort); 139 140 if (!result) 141 return 0; 142 143 ExecutableAllocator::makeWritable(result->start(), result->sizeInBytes()); 144 145 memcpy(result->start(), m_buffer, m_index); 146 147 return result.release(); 148 } 149 150 unsigned debugOffset() { return m_index; } 151 152 protected: 153 void append(const char* data, int size) 154 { 155 if (!isAvailable(size)) 156 grow(size); 157 158 memcpy(m_buffer + m_index, data, size); 159 m_index += size; 160 } 161 162 void grow(int extraCapacity = 0) 163 { 164 m_capacity += m_capacity / 2 + extraCapacity; 165 166 m_storage.grow(m_capacity); 167 m_buffer = m_storage.begin(); 168 } 169 170 private: 171 Vector<char, inlineCapacity, UnsafeVectorOverflow> m_storage; 172 char* m_buffer; 173 int m_capacity; 174 int m_index; 175 }; 176 177} // namespace JSC 178 179#endif // ENABLE(ASSEMBLER) 180 181#endif // AssemblerBuffer_h 182