/*
 * 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 "JSCInlines.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.zeroExtend32ToPtr(
                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)
