/*
 * Copyright (C) 2013, 2015-2016 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 "FTLAbbreviatedTypes.h"
#include "FTLOutput.h"
#include "FTLTypedPointer.h"
#include "Options.h"

namespace JSC { namespace FTL {

AbstractHeap::AbstractHeap(AbstractHeap* parent, const char* heapName, ptrdiff_t offset)
    : m_offset(offset)
    , m_heapName(heapName)
{
    changeParent(parent);
}

void AbstractHeap::changeParent(AbstractHeap* parent)
{
    if (m_parent) {
        bool result = m_parent->m_children.removeFirst(this);
        RELEASE_ASSERT(result);
    }

    m_parent = parent;

    if (parent) {
        ASSERT(!m_parent->m_children.contains(this));
        m_parent->m_children.append(this);
    }
}

void AbstractHeap::compute(unsigned begin)
{
    // This recursively computes the ranges of the tree. This solves the following constraints
    // in linear time:
    //
    // - A node's end is greater than its begin.
    // - A node's begin is greater than or equal to its parent's begin.
    // - A node's end is less than or equal to its parent's end.
    // - The ranges are as small as possible.
    //
    // It's OK to recurse because we keep the depth of our abstract heap hierarchy fairly sane.
    // I think that it gets 4 deep at most.

    if (m_children.isEmpty()) {
        // Must special-case leaves so that they use just one slot on the number line.
        m_range = B3::HeapRange(begin);
        return;
    }

    unsigned current = begin;
    for (AbstractHeap* child : m_children) {
        child->compute(current);
        current = child->range().end();
    }

    m_range = B3::HeapRange(begin, current);
}

void AbstractHeap::shallowDump(PrintStream& out) const
{
    out.print(heapName(), "(", m_offset, ")");
    if (m_range)
        out.print("<", m_range, ">");
}

void AbstractHeap::dump(PrintStream& out) const
{
    shallowDump(out);
    if (m_parent)
        out.print("->", *m_parent);
}

void AbstractHeap::deepDump(PrintStream& out, unsigned indent) const
{
    auto printIndent = [&] () {
        for (unsigned i = indent; i--;)
            out.print("    ");
    };

    printIndent();
    shallowDump(out);

    if (m_children.isEmpty()) {
        out.print("\n");
        return;
    }

    out.print(":\n");
    for (AbstractHeap* child : m_children)
        child->deepDump(out, indent + 1);
}

void AbstractHeap::badRangeError() const
{
    dataLog("Heap does not have range: ", *this, "\n");
    RELEASE_ASSERT_NOT_REACHED();
}

IndexedAbstractHeap::IndexedAbstractHeap(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)
{
}

IndexedAbstractHeap::~IndexedAbstractHeap()
{
}

TypedPointer IndexedAbstractHeap::baseIndex(Output& out, LValue base, LValue index, JSValue indexAsConstant, ptrdiff_t offset, LValue mask)
{
    if (indexAsConstant.isInt32())
        return out.address(base, at(indexAsConstant.asInt32()), offset);

    if (mask)
        index = out.bitAnd(mask, index);
    LValue result = out.add(base, out.mul(index, out.constIntPtr(m_elementSize)));
    
    return TypedPointer(atAnyIndex(), out.addPtr(result, m_offset + offset));
}

const AbstractHeap& IndexedAbstractHeap::atSlow(ptrdiff_t index)
{
    ASSERT(static_cast<size_t>(index) >= m_smallIndices.size());
    
    if (UNLIKELY(!m_largeIndices))
        m_largeIndices = makeUnique<MapType>();

    std::unique_ptr<AbstractHeap>& field = m_largeIndices->add(index, nullptr).iterator->value;
    if (!field) {
        field = makeUnique<AbstractHeap>();
        initialize(*field, index);
    }

    return *field;
}

void IndexedAbstractHeap::initialize(AbstractHeap& 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 naming convention comes from our previous use of LLVM. It's not clear that we need
    // it anymore, though it is sort of nifty. Basically, B3 doesn't need string names for
    // abstract heaps, but the fact that we have a reasonably efficient way to always name the
    // heaps will probably come in handy for debugging.
    
    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();
}

void IndexedAbstractHeap::dump(PrintStream& out)
{
    out.print("Indexed:", atAnyIndex());
}

NumberedAbstractHeap::NumberedAbstractHeap(AbstractHeap* heap, const char* heapName)
    : m_indexedHeap(heap, heapName, 0, 1)
{
}

NumberedAbstractHeap::~NumberedAbstractHeap()
{
}

void NumberedAbstractHeap::dump(PrintStream& out)
{
    out.print("Numbered: ", atAnyNumber());
}

AbsoluteAbstractHeap::AbsoluteAbstractHeap(AbstractHeap* heap, const char* heapName)
    : m_indexedHeap(heap, heapName, 0, 1)
{
}

AbsoluteAbstractHeap::~AbsoluteAbstractHeap()
{
}

void AbsoluteAbstractHeap::dump(PrintStream& out)
{
    out.print("Absolute:", atAnyAddress());
}

} } // namespace JSC::FTL

#endif // ENABLE(FTL_JIT)

