/* * Copyright (C) 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "FTLAbstractHeap.h" #if ENABLE(FTL_JIT) #include "FTLAbbreviations.h" #include "FTLAbstractHeapRepository.h" #include "FTLOutput.h" #include "FTLTypedPointer.h" #include "Operations.h" #include "Options.h" namespace JSC { namespace FTL { LValue AbstractHeap::tbaaMetadataSlow(const AbstractHeapRepository& repository) const { m_tbaaMetadata = mdNode( repository.m_context, mdString(repository.m_context, m_heapName), m_parent->tbaaMetadata(repository)); return m_tbaaMetadata; } void AbstractHeap::decorateInstruction(LValue instruction, const AbstractHeapRepository& repository) const { if (!Options::useFTLTBAA()) return; setMetadata(instruction, repository.m_tbaaKind, tbaaMetadata(repository)); } IndexedAbstractHeap::IndexedAbstractHeap(LContext context, AbstractHeap* parent, const char* heapName, size_t elementSize) : m_heapForAnyIndex(parent, heapName) , m_heapNameLength(strlen(heapName)) , m_elementSize(elementSize) , m_scaleTerm(0) , m_canShift(false) { // See if there is a common shift amount we could use instead of multiplying. Don't // try too hard. This is just a speculative optimization to reduce load on LLVM. for (unsigned i = 0; i < 4; ++i) { if ((1 << i) == m_elementSize) { if (i) m_scaleTerm = constInt(intPtrType(context), i, ZeroExtend); m_canShift = true; break; } } if (!m_canShift) m_scaleTerm = constInt(intPtrType(context), m_elementSize, ZeroExtend); } IndexedAbstractHeap::~IndexedAbstractHeap() { } TypedPointer IndexedAbstractHeap::baseIndex(Output& out, LValue base, LValue index, JSValue indexAsConstant, ptrdiff_t offset) { if (indexAsConstant.isInt32()) return out.address(base, at(indexAsConstant.asInt32()), offset); LValue result; if (m_canShift) { if (!m_scaleTerm) result = out.add(base, index); else result = out.add(base, out.shl(index, m_scaleTerm)); } else result = out.add(base, out.mul(index, m_scaleTerm)); return TypedPointer(atAnyIndex(), out.addPtr(result, offset)); } const AbstractField& IndexedAbstractHeap::atSlow(ptrdiff_t index) { ASSERT(static_cast(index) >= m_smallIndices.size()); if (UNLIKELY(!m_largeIndices)) m_largeIndices = adoptPtr(new MapType()); std::unique_ptr& field = m_largeIndices->add(index, nullptr).iterator->value; if (!field) { field = std::make_unique(); initialize(*field, index); } return *field; } void IndexedAbstractHeap::initialize(AbstractField& field, ptrdiff_t signedIndex) { // Build up a name of the form: // // heapName_hexIndex // // or: // // heapName_neg_hexIndex // // For example if you access an indexed heap called FooBar at index 5, you'll // get: // // FooBar_5 // // Or if you access an indexed heap called Blah at index -10, you'll get: // // Blah_neg_A // // This is important because LLVM uses the string to distinguish the types. static const char* negSplit = "_neg_"; static const char* posSplit = "_"; bool negative; size_t index; if (signedIndex < 0) { negative = true; index = -signedIndex; } else { negative = false; index = signedIndex; } for (unsigned power = 4; power <= sizeof(void*) * 8; power += 4) { if (isGreaterThanNonZeroPowerOfTwo(index, power)) continue; unsigned numHexlets = power >> 2; size_t stringLength = m_heapNameLength + (negative ? strlen(negSplit) : strlen(posSplit)) + numHexlets; char* characters; m_largeIndexNames.append(CString::newUninitialized(stringLength, characters)); memcpy(characters, m_heapForAnyIndex.heapName(), m_heapNameLength); if (negative) memcpy(characters + m_heapNameLength, negSplit, strlen(negSplit)); else memcpy(characters + m_heapNameLength, posSplit, strlen(posSplit)); size_t accumulator = index; for (unsigned i = 0; i < numHexlets; ++i) { characters[stringLength - i - 1] = lowerNibbleToASCIIHexDigit(accumulator); accumulator >>= 4; } field.initialize(&m_heapForAnyIndex, characters, signedIndex * m_elementSize); return; } RELEASE_ASSERT_NOT_REACHED(); } NumberedAbstractHeap::NumberedAbstractHeap( LContext context, AbstractHeap* heap, const char* heapName) : m_indexedHeap(context, heap, heapName, 1) { } NumberedAbstractHeap::~NumberedAbstractHeap() { } AbsoluteAbstractHeap::AbsoluteAbstractHeap( LContext context, AbstractHeap* heap, const char* heapName) : m_indexedHeap(context, heap, heapName, 1) { } AbsoluteAbstractHeap::~AbsoluteAbstractHeap() { } } } // namespace JSC::FTL #endif // ENABLE(FTL_JIT)