1/* 2 * Copyright (C) 2013 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#include "config.h" 27#include "FTLAbstractHeap.h" 28 29#if ENABLE(FTL_JIT) 30 31#include "FTLAbbreviations.h" 32#include "FTLAbstractHeapRepository.h" 33#include "FTLOutput.h" 34#include "FTLTypedPointer.h" 35#include "JSCInlines.h" 36#include "Options.h" 37 38namespace JSC { namespace FTL { 39 40LValue AbstractHeap::tbaaMetadataSlow(const AbstractHeapRepository& repository) const 41{ 42 m_tbaaMetadata = mdNode( 43 repository.m_context, 44 mdString(repository.m_context, m_heapName), 45 m_parent->tbaaMetadata(repository)); 46 return m_tbaaMetadata; 47} 48 49void AbstractHeap::decorateInstruction(LValue instruction, const AbstractHeapRepository& repository) const 50{ 51 if (!Options::useFTLTBAA()) 52 return; 53 setMetadata(instruction, repository.m_tbaaKind, tbaaMetadata(repository)); 54} 55 56IndexedAbstractHeap::IndexedAbstractHeap(LContext context, AbstractHeap* parent, const char* heapName, ptrdiff_t offset, size_t elementSize) 57 : m_heapForAnyIndex(parent, heapName) 58 , m_heapNameLength(strlen(heapName)) 59 , m_offset(offset) 60 , m_elementSize(elementSize) 61 , m_scaleTerm(0) 62 , m_canShift(false) 63{ 64 // See if there is a common shift amount we could use instead of multiplying. Don't 65 // try too hard. This is just a speculative optimization to reduce load on LLVM. 66 for (unsigned i = 0; i < 4; ++i) { 67 if (1U << i == m_elementSize) { 68 if (i) 69 m_scaleTerm = constInt(intPtrType(context), i, ZeroExtend); 70 m_canShift = true; 71 break; 72 } 73 } 74 75 if (!m_canShift) 76 m_scaleTerm = constInt(intPtrType(context), m_elementSize, ZeroExtend); 77} 78 79IndexedAbstractHeap::~IndexedAbstractHeap() 80{ 81} 82 83TypedPointer IndexedAbstractHeap::baseIndex(Output& out, LValue base, LValue index, JSValue indexAsConstant, ptrdiff_t offset) 84{ 85 if (indexAsConstant.isInt32()) 86 return out.address(base, at(indexAsConstant.asInt32()), offset); 87 88 LValue result; 89 if (m_canShift) { 90 if (!m_scaleTerm) 91 result = out.add(base, index); 92 else 93 result = out.add(base, out.shl(index, m_scaleTerm)); 94 } else 95 result = out.add(base, out.mul(index, m_scaleTerm)); 96 97 return TypedPointer(atAnyIndex(), out.addPtr(result, m_offset + offset)); 98} 99 100const AbstractField& IndexedAbstractHeap::atSlow(ptrdiff_t index) 101{ 102 ASSERT(static_cast<size_t>(index) >= m_smallIndices.size()); 103 104 if (UNLIKELY(!m_largeIndices)) 105 m_largeIndices = adoptPtr(new MapType()); 106 107 std::unique_ptr<AbstractField>& field = m_largeIndices->add(index, nullptr).iterator->value; 108 if (!field) { 109 field = std::make_unique<AbstractField>(); 110 initialize(*field, index); 111 } 112 113 return *field; 114} 115 116void IndexedAbstractHeap::initialize(AbstractField& field, ptrdiff_t signedIndex) 117{ 118 // Build up a name of the form: 119 // 120 // heapName_hexIndex 121 // 122 // or: 123 // 124 // heapName_neg_hexIndex 125 // 126 // For example if you access an indexed heap called FooBar at index 5, you'll 127 // get: 128 // 129 // FooBar_5 130 // 131 // Or if you access an indexed heap called Blah at index -10, you'll get: 132 // 133 // Blah_neg_A 134 // 135 // This is important because LLVM uses the string to distinguish the types. 136 137 static const char* negSplit = "_neg_"; 138 static const char* posSplit = "_"; 139 140 bool negative; 141 size_t index; 142 if (signedIndex < 0) { 143 negative = true; 144 index = -signedIndex; 145 } else { 146 negative = false; 147 index = signedIndex; 148 } 149 150 for (unsigned power = 4; power <= sizeof(void*) * 8; power += 4) { 151 if (isGreaterThanNonZeroPowerOfTwo(index, power)) 152 continue; 153 154 unsigned numHexlets = power >> 2; 155 156 size_t stringLength = m_heapNameLength + (negative ? strlen(negSplit) : strlen(posSplit)) + numHexlets; 157 char* characters; 158 m_largeIndexNames.append(CString::newUninitialized(stringLength, characters)); 159 160 memcpy(characters, m_heapForAnyIndex.heapName(), m_heapNameLength); 161 if (negative) 162 memcpy(characters + m_heapNameLength, negSplit, strlen(negSplit)); 163 else 164 memcpy(characters + m_heapNameLength, posSplit, strlen(posSplit)); 165 166 size_t accumulator = index; 167 for (unsigned i = 0; i < numHexlets; ++i) { 168 characters[stringLength - i - 1] = lowerNibbleToASCIIHexDigit(accumulator); 169 accumulator >>= 4; 170 } 171 172 field.initialize(&m_heapForAnyIndex, characters, m_offset + signedIndex * m_elementSize); 173 return; 174 } 175 176 RELEASE_ASSERT_NOT_REACHED(); 177} 178 179NumberedAbstractHeap::NumberedAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName) 180 : m_indexedHeap(context, heap, heapName, 0, 1) 181{ 182} 183 184NumberedAbstractHeap::~NumberedAbstractHeap() 185{ 186} 187 188AbsoluteAbstractHeap::AbsoluteAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName) 189 : m_indexedHeap(context, heap, heapName, 0, 1) 190{ 191} 192 193AbsoluteAbstractHeap::~AbsoluteAbstractHeap() 194{ 195} 196 197} } // namespace JSC::FTL 198 199#endif // ENABLE(FTL_JIT) 200 201