/*
 * Copyright (C) 2015-2019 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 "CallFrameShuffler.h"

#if ENABLE(JIT) && USE(JSVALUE64)

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

namespace JSC {

DataFormat CallFrameShuffler::emitStore(
    CachedRecovery& cachedRecovery, MacroAssembler::Address address)
{
    ASSERT(!cachedRecovery.recovery().isInJSStack());

    switch (cachedRecovery.recovery().technique()) {
    case InGPR:
        m_jit.storePtr(cachedRecovery.recovery().gpr(), address);
        return DataFormatJS;
    case UnboxedInt32InGPR:
        m_jit.store32(cachedRecovery.recovery().gpr(), address.withOffset(PayloadOffset));
        return DataFormatInt32;
    case UnboxedInt52InGPR:
        m_jit.rshift64(MacroAssembler::TrustedImm32(JSValue::int52ShiftAmount),
            cachedRecovery.recovery().gpr());
        FALLTHROUGH;
    case UnboxedStrictInt52InGPR:
        m_jit.storePtr(cachedRecovery.recovery().gpr(), address);
        return DataFormatStrictInt52;
    case UnboxedBooleanInGPR:
        m_jit.storePtr(cachedRecovery.recovery().gpr(), address);
        return DataFormatBoolean;
    case UnboxedCellInGPR:
        m_jit.storePtr(cachedRecovery.recovery().gpr(), address);
        return DataFormatCell;
    case UnboxedDoubleInFPR:
        m_jit.storeDouble(cachedRecovery.recovery().fpr(), address);
        return DataFormatDouble;
    case InFPR:
        m_jit.storeDouble(cachedRecovery.recovery().fpr(), address);
        return DataFormatJS;
    case Constant:
        m_jit.storeTrustedValue(cachedRecovery.recovery().constant(), address);
        return DataFormatJS;
    default:
        RELEASE_ASSERT_NOT_REACHED();
    }
}

void CallFrameShuffler::emitBox(CachedRecovery& cachedRecovery)
{
    ASSERT(canBox(cachedRecovery));
    if (cachedRecovery.recovery().isConstant())
        return;

    if (cachedRecovery.recovery().isInGPR()) {
        switch (cachedRecovery.recovery().dataFormat()) {
        case DataFormatInt32:
            if (verbose)
                dataLog("   * Boxing ", cachedRecovery.recovery());
            m_jit.zeroExtend32ToWord(
                cachedRecovery.recovery().gpr(),
                cachedRecovery.recovery().gpr());
            m_lockedRegisters.set(cachedRecovery.recovery().gpr());
            if (tryAcquireNumberTagRegister())
                m_jit.or64(m_numberTagRegister, cachedRecovery.recovery().gpr());
            else {
                // We have to do this the hard way
                m_jit.or64(MacroAssembler::TrustedImm64(JSValue::NumberTag),
                    cachedRecovery.recovery().gpr());
            }
            m_lockedRegisters.clear(cachedRecovery.recovery().gpr());
            cachedRecovery.setRecovery(
                ValueRecovery::inGPR(cachedRecovery.recovery().gpr(), DataFormatJS));
            if (verbose)
                dataLog(" into ", cachedRecovery.recovery(), "\n");
            return;
        case DataFormatInt52:
            if (verbose)
                dataLog("   * Boxing ", cachedRecovery.recovery());
            m_jit.rshift64(MacroAssembler::TrustedImm32(JSValue::int52ShiftAmount),
                cachedRecovery.recovery().gpr());
            cachedRecovery.setRecovery(
                ValueRecovery::inGPR(cachedRecovery.recovery().gpr(), DataFormatStrictInt52));
            if (verbose)
                dataLog(" into ", cachedRecovery.recovery(), "\n");
            FALLTHROUGH;
        case DataFormatStrictInt52: {
            if (verbose)
                dataLog("   * Boxing ", cachedRecovery.recovery());
            FPRReg resultFPR = getFreeFPR();
            ASSERT(resultFPR != InvalidFPRReg);
            m_jit.convertInt64ToDouble(cachedRecovery.recovery().gpr(), resultFPR);
            updateRecovery(cachedRecovery, ValueRecovery::inFPR(resultFPR, DataFormatDouble));
            if (verbose)
                dataLog(" into ", cachedRecovery.recovery(), "\n");
            break;
        }
        case DataFormatBoolean:
            if (verbose)
                dataLog("   * Boxing ", cachedRecovery.recovery());
            m_jit.add32(MacroAssembler::TrustedImm32(JSValue::ValueFalse),
                cachedRecovery.recovery().gpr());
            cachedRecovery.setRecovery(
                ValueRecovery::inGPR(cachedRecovery.recovery().gpr(), DataFormatJS));
            if (verbose)
                dataLog(" into ", cachedRecovery.recovery(), "\n");
            return;
        default:
            return;
        }
    }

    if (cachedRecovery.recovery().isInFPR()) {
        if (cachedRecovery.recovery().dataFormat() == DataFormatDouble) {
            if (verbose)
                dataLog("   * Boxing ", cachedRecovery.recovery());
            GPRReg resultGPR = cachedRecovery.wantedJSValueRegs().gpr();
            if (resultGPR == InvalidGPRReg || m_registers[resultGPR])
                resultGPR = getFreeGPR();
            ASSERT(resultGPR != InvalidGPRReg);
            m_jit.purifyNaN(cachedRecovery.recovery().fpr());
            m_jit.moveDoubleTo64(cachedRecovery.recovery().fpr(), resultGPR);
            m_lockedRegisters.set(resultGPR);
            if (tryAcquireNumberTagRegister())
                m_jit.sub64(m_numberTagRegister, resultGPR);
            else
                m_jit.sub64(MacroAssembler::TrustedImm64(JSValue::NumberTag), resultGPR);
            m_lockedRegisters.clear(resultGPR);
            updateRecovery(cachedRecovery, ValueRecovery::inGPR(resultGPR, DataFormatJS));
            if (verbose)
                dataLog(" into ", cachedRecovery.recovery(), "\n");
            return;
        }
        ASSERT(cachedRecovery.recovery().dataFormat() == DataFormatJS);
        return;
    }

    RELEASE_ASSERT_NOT_REACHED();
}

void CallFrameShuffler::emitLoad(CachedRecovery& cachedRecovery)
{
    if (!cachedRecovery.recovery().isInJSStack())
        return;

    if (verbose)
        dataLog("   * Loading ", cachedRecovery.recovery(), " into ");

    VirtualRegister reg = cachedRecovery.recovery().virtualRegister();
    MacroAssembler::Address address { addressForOld(reg) };
    bool tryFPR { true };
    GPRReg resultGPR { cachedRecovery.wantedJSValueRegs().gpr() };

    // If we want a GPR and it's available, that's better than loading
    // into an FPR.
    if (resultGPR != InvalidGPRReg && !m_registers[resultGPR]
        && !m_lockedRegisters.get(resultGPR) && cachedRecovery.loadsIntoGPR())
        tryFPR = false;

    // Otherwise, we prefer loading into FPRs if possible
    if (tryFPR && cachedRecovery.loadsIntoFPR()) {
        FPRReg resultFPR { cachedRecovery.wantedFPR() };
        if (resultFPR == InvalidFPRReg || m_registers[resultFPR] || m_lockedRegisters.get(resultFPR))
            resultFPR = getFreeFPR();
        if (resultFPR != InvalidFPRReg) {
            m_jit.loadDouble(address, resultFPR);
            DataFormat dataFormat = DataFormatJS;
            // We could be transforming a DataFormatCell into a
            // DataFormatJS here - but that's OK.
            if (cachedRecovery.recovery().dataFormat() == DataFormatDouble)
                dataFormat = DataFormatDouble;
            updateRecovery(cachedRecovery,
                ValueRecovery::inFPR(resultFPR, dataFormat));
            if (verbose)
                dataLog(cachedRecovery.recovery(), "\n");
            if (reg == newAsOld(dangerFrontier()))
                updateDangerFrontier();
            return;
        }
    }

    ASSERT(cachedRecovery.loadsIntoGPR());
    if (resultGPR == InvalidGPRReg || m_registers[resultGPR] || m_lockedRegisters.get(resultGPR))
        resultGPR = getFreeGPR();
    ASSERT(resultGPR != InvalidGPRReg);
    m_jit.loadPtr(address, resultGPR);
    updateRecovery(cachedRecovery,
        ValueRecovery::inGPR(resultGPR, cachedRecovery.recovery().dataFormat()));
    if (verbose)
        dataLog(cachedRecovery.recovery(), "\n");
    if (reg == newAsOld(dangerFrontier()))
        updateDangerFrontier();
}

bool CallFrameShuffler::canLoad(CachedRecovery& cachedRecovery)
{
    if (!cachedRecovery.recovery().isInJSStack())
        return true;

    ASSERT(cachedRecovery.loadsIntoFPR() || cachedRecovery.loadsIntoGPR());

    if (cachedRecovery.loadsIntoFPR() && getFreeFPR() != InvalidFPRReg)
        return true;

    if (cachedRecovery.loadsIntoGPR() && getFreeGPR() != InvalidGPRReg)
        return true;

    return false;
}

void CallFrameShuffler::emitDisplace(CachedRecovery& cachedRecovery)
{
    Reg wantedReg;
    if (!(wantedReg = Reg { cachedRecovery.wantedJSValueRegs().gpr() }))
        wantedReg = Reg { cachedRecovery.wantedFPR() };
    ASSERT(wantedReg);
    ASSERT(!m_lockedRegisters.get(wantedReg));

    if (CachedRecovery* current = m_registers[wantedReg]) {
        if (current == &cachedRecovery) {
            if (verbose)
                dataLog("   + ", wantedReg, " is OK\n");
            return;
        }
        // We could do a more complex thing by finding cycles
        // etc. in that case.
        // However, ending up in this situation will be super
        // rare, and should actually be outright impossible for
        // non-FTL tiers, since:
        //  (a) All doubles have been converted into JSValues with
        //      ValueRep nodes, so FPRs are initially free
        //
        //  (b) The only recoveries with wanted registers are the
        //      callee (which always starts out in a register) and
        //      the callee-save registers
        //
        //  (c) The callee-save registers are the first things we
        //      load (after the return PC), and they are loaded as JSValues
        //
        //  (d) We prefer loading JSValues into FPRs if their
        //      wanted GPR is not available
        //
        //  (e) If we end up spilling some registers with a
        //      target, we won't load them again before the very
        //      end of the algorithm
        //
        // Combined, this means that we will never load a recovery
        // with a wanted GPR into any GPR other than its wanted
        // GPR. The callee could however have been initially in
        // one of the callee-save registers - but since the wanted
        // GPR for the callee is always regT0, it will be the
        // first one to be displaced, and we won't see it when
        // handling any of the callee-save registers.
        //
        // Thus, the only way we could ever reach this path is in
        // the FTL, when there is so much pressure that we
        // absolutely need to load the callee-save registers into
        // different GPRs initially but not enough pressure to
        // then have to spill all of them. And even in that case,
        // depending on the order in which B3 saves the
        // callee-saves, we will probably still be safe. Anyway,
        // the couple extra move instructions compared to an
        // efficient cycle-based algorithm are not going to hurt
        // us.
        if (wantedReg.isFPR()) {
            FPRReg tempFPR = getFreeFPR();
            if (verbose)
                dataLog("  * Moving ", wantedReg, " into ", tempFPR, "\n");
            m_jit.moveDouble(wantedReg.fpr(), tempFPR);
            updateRecovery(*current,
                ValueRecovery::inFPR(tempFPR, current->recovery().dataFormat()));
        } else {
            GPRReg tempGPR = getFreeGPR();
            if (verbose)
                dataLog("  * Moving ", wantedReg.gpr(), " into ", tempGPR, "\n");
            m_jit.move(wantedReg.gpr(), tempGPR);
            updateRecovery(*current,
                ValueRecovery::inGPR(tempGPR, current->recovery().dataFormat()));
        }
    }
    ASSERT(!m_registers[wantedReg]);

    if (cachedRecovery.recovery().isConstant()) {
        // We only care about callee saves for wanted FPRs, and those are never constants
        ASSERT(wantedReg.isGPR());
        if (verbose)
            dataLog("   * Loading ", cachedRecovery.recovery().constant(), " into ", wantedReg, "\n");
        m_jit.moveTrustedValue(cachedRecovery.recovery().constant(), JSValueRegs { wantedReg.gpr() });
        updateRecovery(
            cachedRecovery,
            ValueRecovery::inRegister(wantedReg, DataFormatJS));
    } else if (cachedRecovery.recovery().isInGPR()) {
        if (verbose)
            dataLog("   * Moving ", cachedRecovery.recovery(), " into ", wantedReg, "\n");
        if (wantedReg.isGPR())
            m_jit.move(cachedRecovery.recovery().gpr(), wantedReg.gpr());
        else
            m_jit.move64ToDouble(cachedRecovery.recovery().gpr(), wantedReg.fpr());
        RELEASE_ASSERT(cachedRecovery.recovery().dataFormat() == DataFormatJS);
        updateRecovery(cachedRecovery,
            ValueRecovery::inRegister(wantedReg, DataFormatJS));
    } else {
        ASSERT(cachedRecovery.recovery().isInFPR());
        if (cachedRecovery.recovery().dataFormat() == DataFormatDouble) {
            // We only care about callee saves for wanted FPRs, and those are always DataFormatJS
            ASSERT(wantedReg.isGPR());
            // This will automatically pick the wanted GPR
            emitBox(cachedRecovery);
        } else {
            if (verbose)
                dataLog("   * Moving ", cachedRecovery.recovery().fpr(), " into ", wantedReg, "\n");
            if (wantedReg.isGPR())
                m_jit.moveDoubleTo64(cachedRecovery.recovery().fpr(), wantedReg.gpr());
            else
                m_jit.moveDouble(cachedRecovery.recovery().fpr(), wantedReg.fpr());
            RELEASE_ASSERT(cachedRecovery.recovery().dataFormat() == DataFormatJS);
            updateRecovery(cachedRecovery,
                ValueRecovery::inRegister(wantedReg, DataFormatJS));
        }
    }

    ASSERT(m_registers[wantedReg] == &cachedRecovery);
}
    
bool CallFrameShuffler::tryAcquireNumberTagRegister()
{
    if (m_numberTagRegister != InvalidGPRReg)
        return true;

    m_numberTagRegister = getFreeGPR();

    if (m_numberTagRegister == InvalidGPRReg)
        return false;

    m_lockedRegisters.set(m_numberTagRegister);
    m_jit.move(MacroAssembler::TrustedImm64(JSValue::NumberTag), m_numberTagRegister);
    return true;
}

} // namespace JSC

#endif // ENABLE(JIT) && USE(JSVALUE64)
