X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4be4e30906bcb8ee30b4d189205cb70bad6707ce..81345200c95645a1b0d2635520f96ad55dfde63f:/ftl/FTLAbstractHeap.cpp diff --git a/ftl/FTLAbstractHeap.cpp b/ftl/FTLAbstractHeap.cpp new file mode 100644 index 0000000..dfbbeb1 --- /dev/null +++ b/ftl/FTLAbstractHeap.cpp @@ -0,0 +1,200 @@ +/* + * 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 "JSCInlines.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, ptrdiff_t offset, size_t elementSize) + : m_heapForAnyIndex(parent, heapName) + , m_heapNameLength(strlen(heapName)) + , m_offset(offset) + , 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 (1U << 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, m_offset + 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, m_offset + signedIndex * m_elementSize); + return; + } + + RELEASE_ASSERT_NOT_REACHED(); +} + +NumberedAbstractHeap::NumberedAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName) + : m_indexedHeap(context, heap, heapName, 0, 1) +{ +} + +NumberedAbstractHeap::~NumberedAbstractHeap() +{ +} + +AbsoluteAbstractHeap::AbsoluteAbstractHeap(LContext context, AbstractHeap* heap, const char* heapName) + : m_indexedHeap(context, heap, heapName, 0, 1) +{ +} + +AbsoluteAbstractHeap::~AbsoluteAbstractHeap() +{ +} + +} } // namespace JSC::FTL + +#endif // ENABLE(FTL_JIT) +