/*
 * Copyright (C) 2016-2020 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 "ArithProfile.h"

#include "CCallHelpers.h"
#include "JSCJSValueInlines.h"

namespace JSC {

#if ENABLE(JIT)
template<typename BitfieldType>
void ArithProfile<BitfieldType>::emitObserveResult(CCallHelpers& jit, JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode)
{
    if (!shouldEmitSetDouble() && !shouldEmitSetNonNumeric() && !shouldEmitSetHeapBigInt() && !shouldEmitSetBigInt32())
        return;

    CCallHelpers::JumpList done;
    CCallHelpers::JumpList nonNumeric;

    done.append(jit.branchIfInt32(regs, mode));
    CCallHelpers::Jump notDouble = jit.branchIfNotDoubleKnownNotInt32(regs, mode);
    emitSetDouble(jit);
    done.append(jit.jump());

    notDouble.link(&jit);

#if USE(BIGINT32)
    CCallHelpers::Jump notBigInt32 = jit.branchIfNotBigInt32(regs, tempGPR, mode);
    emitSetBigInt32(jit);
    done.append(jit.jump());
    notBigInt32.link(&jit);
#else
    UNUSED_PARAM(tempGPR);
#endif

    nonNumeric.append(jit.branchIfNotCell(regs, mode));
    nonNumeric.append(jit.branchIfNotHeapBigInt(regs.payloadGPR()));
    emitSetHeapBigInt(jit);
    done.append(jit.jump());

    nonNumeric.link(&jit);
    emitSetNonNumeric(jit);

    done.link(&jit);
}

template<typename BitfieldType>
bool ArithProfile<BitfieldType>::shouldEmitSetDouble() const
{
    BitfieldType mask = ObservedResults::Int32Overflow | ObservedResults::Int52Overflow | ObservedResults::NegZeroDouble | ObservedResults::NonNegZeroDouble;
    return (m_bits & mask) != mask;
}

template<typename BitfieldType>
void ArithProfile<BitfieldType>::emitSetDouble(CCallHelpers& jit) const
{
    if (shouldEmitSetDouble())
        emitUnconditionalSet(jit, ObservedResults::Int32Overflow | ObservedResults::Int52Overflow | ObservedResults::NegZeroDouble | ObservedResults::NonNegZeroDouble);
}

template<typename BitfieldType>
bool ArithProfile<BitfieldType>::shouldEmitSetNonNumeric() const
{
    BitfieldType mask = ObservedResults::NonNumeric;
    return (m_bits & mask) != mask;
}

template<typename BitfieldType>
void ArithProfile<BitfieldType>::emitSetNonNumeric(CCallHelpers& jit) const
{
    if (shouldEmitSetNonNumeric())
        emitUnconditionalSet(jit, ObservedResults::NonNumeric);
}

template<typename BitfieldType>
bool ArithProfile<BitfieldType>::shouldEmitSetBigInt32() const
{
#if USE(BIGINT32)
    BitfieldType mask = ObservedResults::BigInt32;
    return (m_bits & mask) != mask;
#else
    return false;
#endif
}

template<typename BitfieldType>
bool ArithProfile<BitfieldType>::shouldEmitSetHeapBigInt() const
{
    BitfieldType mask = ObservedResults::HeapBigInt;
    return (m_bits & mask) != mask;
}

template<typename BitfieldType>
void ArithProfile<BitfieldType>::emitSetHeapBigInt(CCallHelpers& jit) const
{
    if (shouldEmitSetHeapBigInt())
        emitUnconditionalSet(jit, ObservedResults::HeapBigInt);
}

#if USE(BIGINT32)
template<typename BitfieldType>
void ArithProfile<BitfieldType>::emitSetBigInt32(CCallHelpers& jit) const
{
    if (shouldEmitSetBigInt32())
        emitUnconditionalSet(jit, ObservedResults::BigInt32);
}
#endif

template<typename BitfieldType>
void ArithProfile<BitfieldType>::emitUnconditionalSet(CCallHelpers& jit, BitfieldType mask) const
{
    static_assert(std::is_same<BitfieldType, uint16_t>::value);
    jit.or16(CCallHelpers::TrustedImm32(mask), CCallHelpers::AbsoluteAddress(addressOfBits()));
}

// Generate the implementations of the functions above for UnaryArithProfile/BinaryArithProfile
// If changing the size of either, add the corresponding lines here.
template class ArithProfile<uint16_t>;
#endif // ENABLE(JIT)

} // namespace JSC

namespace WTF {
    
using namespace JSC;

template <typename T>
void printInternal(PrintStream& out, const ArithProfile<T>& profile)
{
    const char* separator = "";

    out.print("Result:<");
    if (!profile.didObserveNonInt32()) {
        out.print("Int32");
        separator = "|";
    } else {
        if (profile.didObserveNegZeroDouble()) {
            out.print(separator, "NegZeroDouble");
            separator = "|";
        }
        if (profile.didObserveNonNegZeroDouble()) {
            out.print(separator, "NonNegZeroDouble");
            separator = "|";
        }
        if (profile.didObserveNonNumeric()) {
            out.print(separator, "NonNumeric");
            separator = "|";
        }
        if (profile.didObserveInt32Overflow()) {
            out.print(separator, "Int32Overflow");
            separator = "|";
        }
        if (profile.didObserveInt52Overflow()) {
            out.print(separator, "Int52Overflow");
            separator = "|";
        }
        if (profile.didObserveHeapBigInt()) {
            out.print(separator, "HeapBigInt");
            separator = "|";
        }
        if (profile.didObserveBigInt32()) {
            out.print(separator, "BigInt32");
            separator = "|";
        }
    }
    out.print(">");
}

void printInternal(PrintStream& out, const UnaryArithProfile& profile)
{
    printInternal(out, static_cast<ArithProfile<UnaryArithProfileBase>>(profile));

    out.print(" Arg ObservedType:<");
    out.print(profile.argObservedType());
    out.print(">");
}

void printInternal(PrintStream& out, const BinaryArithProfile& profile)
{
    printInternal(out, static_cast<ArithProfile<UnaryArithProfileBase>>(profile));

    if (profile.tookSpecialFastPath())
        out.print(" Took special fast path.");

    out.print(" LHS ObservedType:<");
    out.print(profile.lhsObservedType());
    out.print("> RHS ObservedType:<");
    out.print(profile.rhsObservedType());
    out.print(">");
}

void printInternal(PrintStream& out, const JSC::ObservedType& observedType)
{
    const char* separator = "";
    if (observedType.sawInt32()) {
        out.print(separator, "Int32");
        separator = "|";
    }
    if (observedType.sawNumber()) {
        out.print(separator, "Number");
        separator = "|";
    }
    if (observedType.sawNonNumber()) {
        out.print(separator, "NonNumber");
        separator = "|";
    }
}

} // namespace WTF
