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

#pragma once

#if ENABLE(JIT)

#include "CachedRecovery.h"
#include "CallFrameShuffleData.h"
#include "MacroAssembler.h"
#include "RegisterSet.h"
#include <wtf/Vector.h>

namespace JSC {

class CallFrameShuffler {
    WTF_MAKE_FAST_ALLOCATED;
public:
    CallFrameShuffler(CCallHelpers&, const CallFrameShuffleData&);

    void dump(PrintStream&) const;

    // Any register that has been locked or acquired must be released
    // before calling prepareForTailCall() or prepareForSlowPath().
    void lockGPR(GPRReg gpr)
    {
        ASSERT(!m_lockedRegisters.get(gpr));
        m_lockedRegisters.set(gpr);
        if (verbose)
            dataLog("   * Locking ", gpr, "\n");
    }

    GPRReg acquireGPR()
    {
        ensureGPR();
        GPRReg gpr { getFreeGPR() };
        ASSERT(!m_registers[gpr]);
        lockGPR(gpr);
        return gpr;
    }

    void releaseGPR(GPRReg gpr)
    {
        if (verbose) {
            if (m_lockedRegisters.get(gpr))
                dataLog("   * Releasing ", gpr, "\n");
            else
                dataLog("   * ", gpr, " was not locked\n");
        }
        m_lockedRegisters.clear(gpr);
    }

    void restoreGPR(GPRReg gpr)
    {
        if (!m_newRegisters[gpr])
            return;

        ensureGPR();
#if USE(JSVALUE32_64)
        GPRReg tempGPR { getFreeGPR() };
        lockGPR(tempGPR);
        ensureGPR();
        releaseGPR(tempGPR);
#endif
        emitDisplace(*m_newRegisters[gpr]);
    }

    // You can only take a snapshot if the recovery has not started
    // yet. The only operations that are valid before taking a
    // snapshot are lockGPR(), acquireGPR() and releaseGPR().
    //
    // Locking status is *NOT* preserved by the snapshot: it only
    // contains information about where the
    // arguments/callee/callee-save registers are by taking into
    // account any spilling that acquireGPR() could have done.
    CallFrameShuffleData snapshot() const
    {
        ASSERT(isUndecided());

        CallFrameShuffleData data;
        data.numLocals = numLocals();
        data.numPassedArgs = m_numPassedArgs;
        data.callee = getNew(VirtualRegister { CallFrameSlot::callee })->recovery();
        data.args.resize(argCount());
        for (size_t i = 0; i < argCount(); ++i)
            data.args[i] = getNew(virtualRegisterForArgument(i))->recovery();
        for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
            CachedRecovery* cachedRecovery { m_newRegisters[reg] };
            if (!cachedRecovery)
                continue;

#if USE(JSVALUE64)
            data.registers[reg] = cachedRecovery->recovery();
#else
            RELEASE_ASSERT_NOT_REACHED();
#endif
        }
        return data;
    }

    // Ask the shuffler to put the callee into some registers once the
    // shuffling is done. You should call this before any of the
    // prepare() methods, and must not take a snapshot afterwards, as
    // this would crash 32bits platforms.
    void setCalleeJSValueRegs(JSValueRegs jsValueRegs)
    {
        ASSERT(isUndecided());
        ASSERT(!getNew(jsValueRegs));
        CachedRecovery* cachedRecovery { getNew(VirtualRegister(CallFrameSlot::callee)) };
        ASSERT(cachedRecovery);
        addNew(jsValueRegs, cachedRecovery->recovery());
    }

    // Ask the suhffler to assume the callee has already be checked to
    // be a cell. This is a no-op on 64bit platforms, but allows to
    // free up a GPR on 32bit platforms.
    // You obviously must have ensured that this is the case before
    // running any of the prepare methods.
    void assumeCalleeIsCell()
    {
#if USE(JSVALUE32_64)
        CachedRecovery& calleeCachedRecovery = *getNew(VirtualRegister(CallFrameSlot::callee));
        switch (calleeCachedRecovery.recovery().technique()) {
        case InPair:
            updateRecovery(
                calleeCachedRecovery,
                ValueRecovery::inGPR(
                    calleeCachedRecovery.recovery().payloadGPR(),
                    DataFormatCell));
            break;
        case DisplacedInJSStack:
            updateRecovery(
                calleeCachedRecovery,
                ValueRecovery::displacedInJSStack(
                    calleeCachedRecovery.recovery().virtualRegister(),
                    DataFormatCell));
            break;
        case InFPR:
        case UnboxedCellInGPR:
        case CellDisplacedInJSStack:
            break;
        case Constant:
            ASSERT(calleeCachedRecovery.recovery().constant().isCell());
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
#endif
    }

    // This will emit code to build the new frame over the old one.
    void prepareForTailCall();

    // This will emit code to build the new frame as if performing a
    // regular call. However, the callee save registers will be
    // restored, and any locals (not the header or arguments) of the
    // current frame can be overwritten.
    //
    // A frame built using prepareForSlowPath() should be used either
    // to throw an exception in, or destroyed using
    // CCallHelpers::prepareForTailCallSlow() followed by a tail call.
    void prepareForSlowPath();

private:
    static const bool verbose = false;

    CCallHelpers& m_jit;

    void prepareAny();

    void spill(CachedRecovery&);

    // "box" is arguably a bad name here. The meaning is that after
    // calling emitBox(), your ensure that subsequently calling
    // emitStore() will be able to store the value without additional
    // transformation. In particular, this is a no-op for constants,
    // and is a complete no-op on 32bits since any unboxed value can
    // still be stored by storing the payload and a statically known
    // tag.
    void emitBox(CachedRecovery&);

    bool canBox(CachedRecovery& cachedRecovery)
    {
        if (cachedRecovery.boxingRequiresGPR() && getFreeGPR() == InvalidGPRReg)
            return false;

        if (cachedRecovery.boxingRequiresFPR() && getFreeFPR() == InvalidFPRReg)
            return false;

        return true;
    }

    void ensureBox(CachedRecovery& cachedRecovery)
    {
        if (canBox(cachedRecovery))
            return;

        if (cachedRecovery.boxingRequiresGPR())
            ensureGPR();

        if (cachedRecovery.boxingRequiresFPR())
            ensureFPR();
    }

    void emitLoad(CachedRecovery&);

    bool canLoad(CachedRecovery&);

    void ensureLoad(CachedRecovery& cachedRecovery)
    {
        if (canLoad(cachedRecovery))
            return;

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

        if (cachedRecovery.loadsIntoFPR()) {
            if (cachedRecovery.loadsIntoGPR())
                ensureRegister();
            else
                ensureFPR();
        } else
            ensureGPR();
    }

    bool canLoadAndBox(CachedRecovery& cachedRecovery)
    {
        // We don't have interfering loads & boxes
        ASSERT(!cachedRecovery.loadsIntoFPR() || !cachedRecovery.boxingRequiresFPR());
        ASSERT(!cachedRecovery.loadsIntoGPR() || !cachedRecovery.boxingRequiresGPR());

        return canLoad(cachedRecovery) && canBox(cachedRecovery);
    }

    DataFormat emitStore(CachedRecovery&, MacroAssembler::Address);

    void emitDisplace(CachedRecovery&);

    void emitDeltaCheck();

    Bag<CachedRecovery> m_cachedRecoveries;

    void updateRecovery(CachedRecovery& cachedRecovery, ValueRecovery recovery)
    {
        clearCachedRecovery(cachedRecovery.recovery());
        cachedRecovery.setRecovery(recovery);
        setCachedRecovery(recovery, &cachedRecovery);
    }

    CachedRecovery* getCachedRecovery(ValueRecovery);

    CachedRecovery* setCachedRecovery(ValueRecovery, CachedRecovery*);

    void clearCachedRecovery(ValueRecovery recovery)
    {
        if (!recovery.isConstant())
            setCachedRecovery(recovery, nullptr);
    }

    CachedRecovery* addCachedRecovery(ValueRecovery recovery)
    {
        if (recovery.isConstant())
            return m_cachedRecoveries.add(recovery);
        CachedRecovery* cachedRecovery = getCachedRecovery(recovery);
        if (!cachedRecovery)
            return setCachedRecovery(recovery, m_cachedRecoveries.add(recovery));
        return cachedRecovery;
    }

    // This is the current recoveries present in the old frame's
    // slots. A null CachedRecovery means we can trash the current
    // value as we don't care about it.
    Vector<CachedRecovery*> m_oldFrame;

    int numLocals() const
    {
        return m_oldFrame.size() - CallerFrameAndPC::sizeInRegisters;
    }

    CachedRecovery* getOld(VirtualRegister reg) const
    {
        return m_oldFrame[CallerFrameAndPC::sizeInRegisters - reg.offset() - 1];
    }

    void setOld(VirtualRegister reg, CachedRecovery* cachedRecovery)
    {
        m_oldFrame[CallerFrameAndPC::sizeInRegisters - reg.offset() - 1] = cachedRecovery;
    }

    VirtualRegister firstOld() const
    {
        return VirtualRegister { static_cast<int>(-numLocals()) };
    }

    VirtualRegister lastOld() const
    {
        return VirtualRegister { CallerFrameAndPC::sizeInRegisters - 1 };
    }

    bool isValidOld(VirtualRegister reg) const
    {
        return reg >= firstOld() && reg <= lastOld();
    }

    bool m_didExtendFrame { false };

    void extendFrameIfNeeded();

    // This stores, for each slot in the new frame, information about
    // the recovery for the value that should eventually go into that
    // slot.
    //
    // Once the slot has been written, the corresponding entry in
    // m_newFrame will be empty.
    Vector<CachedRecovery*> m_newFrame;

    size_t argCount() const
    {
        return m_newFrame.size() - CallFrame::headerSizeInRegisters;
    }

    CachedRecovery* getNew(VirtualRegister newRegister) const
    {
        return m_newFrame[newRegister.offset()];
    }

    void setNew(VirtualRegister newRegister, CachedRecovery* cachedRecovery)
    {
        m_newFrame[newRegister.offset()] = cachedRecovery;
    }

    void addNew(VirtualRegister newRegister, ValueRecovery recovery)
    {
        CachedRecovery* cachedRecovery = addCachedRecovery(recovery);
        cachedRecovery->addTarget(newRegister);
        setNew(newRegister, cachedRecovery);
    }

    VirtualRegister firstNew() const
    {
        return VirtualRegister { 0 };
    }

    VirtualRegister lastNew() const
    {
        return VirtualRegister { static_cast<int>(m_newFrame.size()) - 1 };
    }

    bool isValidNew(VirtualRegister reg) const
    {
        return reg >= firstNew() && reg <= lastNew();
    }


    int m_alignedOldFrameSize;
    int m_alignedNewFrameSize;

    // This is the distance, in slots, between the base of the new
    // frame and the base of the old frame. It could be negative when
    // preparing for a tail call to a function with smaller argument
    // count.
    //
    // We will overwrite this appropriately for slow path calls, but
    // we initialize it as if doing a fast path for the spills we
    // could do while undecided (typically while calling acquireGPR()
    // for a polymorphic call).
    int m_frameDelta;

    VirtualRegister newAsOld(VirtualRegister reg) const
    {
        return reg - m_frameDelta;
    }

    // This stores the set of locked registers, i.e. registers for
    // which we have an implicit requirement that they are not changed.
    //
    // This will usually contains the link register on architectures
    // that have one, any scratch register used by the macro assembler
    // (e.g. r11 on X86_64), as well as any register that we use for
    // addressing (see m_oldFrameBase and m_newFrameBase).
    //
    // We also use this to lock registers temporarily, for instance to
    // ensure that we have at least 2 available registers for loading
    // a pair on 32bits.
    mutable RegisterSet m_lockedRegisters;

    // This stores the current recoveries present in registers. A null
    // CachedRecovery means we can trash the current value as we don't
    // care about it. 
    RegisterMap<CachedRecovery*> m_registers;

#if USE(JSVALUE64)
    mutable GPRReg m_tagTypeNumber;

    bool tryAcquireTagTypeNumber();
#endif

    // This stores, for each register, information about the recovery
    // for the value that should eventually go into that register. The
    // only registers that have a target recovery will be callee-save
    // registers, as well as possibly one JSValueRegs for holding the
    // callee.
    //
    // Once the correct value has been put into the registers, and
    // contrary to what we do with m_newFrame, we keep the entry in
    // m_newRegisters to simplify spilling.
    RegisterMap<CachedRecovery*> m_newRegisters;

    template<typename CheckFunctor>
    Reg getFreeRegister(const CheckFunctor& check) const
    {
        Reg nonTemp { };
        for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
            if (m_lockedRegisters.get(reg))
                continue;

            if (!check(reg))
                continue;

            if (!m_registers[reg]) {
                if (!m_newRegisters[reg])
                    return reg;
                if (!nonTemp)
                    nonTemp = reg;
            }
        }

#if USE(JSVALUE64)
        if (!nonTemp && m_tagTypeNumber != InvalidGPRReg && check(Reg { m_tagTypeNumber })) {
            ASSERT(m_lockedRegisters.get(m_tagTypeNumber));
            m_lockedRegisters.clear(m_tagTypeNumber);
            nonTemp = Reg { m_tagTypeNumber };
            m_tagTypeNumber = InvalidGPRReg;
        }
#endif
        return nonTemp;
    }

    GPRReg getFreeTempGPR() const
    {
        Reg freeTempGPR { getFreeRegister([this] (Reg reg) { return reg.isGPR() && !m_newRegisters[reg]; }) };
        if (!freeTempGPR)
            return InvalidGPRReg;
        return freeTempGPR.gpr();
    }

    GPRReg getFreeGPR() const
    {
        Reg freeGPR { getFreeRegister([] (Reg reg) { return reg.isGPR(); }) };
        if (!freeGPR)
            return InvalidGPRReg;
        return freeGPR.gpr();
    }

    FPRReg getFreeFPR() const
    {
        Reg freeFPR { getFreeRegister([] (Reg reg) { return reg.isFPR(); }) };
        if (!freeFPR)
            return InvalidFPRReg;
        return freeFPR.fpr();
    }

    bool hasFreeRegister() const
    {
        return static_cast<bool>(getFreeRegister([] (Reg) { return true; }));
    }

    // This frees up a register satisfying the check functor (this
    // functor could theoretically have any kind of logic, but it must
    // ensure that it will only return true for registers - spill
    // assumes and asserts that it is passed a cachedRecovery stored in a
    // register).
    template<typename CheckFunctor>
    void ensureRegister(const CheckFunctor& check)
    {
        // If we can spill a callee-save, that's best, because it will
        // free up a register that would otherwise been taken for the
        // longest amount of time.
        //
        // We could try to bias towards those that are not in their
        // target registers yet, but the gain is probably super
        // small. Unless you have a huge number of argument (at least
        // around twice the number of available registers on your
        // architecture), no spilling is going to take place anyways.
        for (Reg reg = Reg::first(); reg <= Reg::last(); reg = reg.next()) {
            if (m_lockedRegisters.get(reg))
                continue;

            CachedRecovery* cachedRecovery { m_newRegisters[reg] };
            if (!cachedRecovery)
                continue;

            if (check(*cachedRecovery)) {
                if (verbose)
                    dataLog("  ", cachedRecovery->recovery(), " looks like a good spill candidate\n");
                spill(*cachedRecovery);
                return;
            }
        }

        // We use the cachedRecovery associated with the first new slot we
        // can, because that is the one for which a write will be
        // possible the latest, i.e. that is the one that we would
        // have had to retain in registers for the longest.
        for (VirtualRegister reg = firstNew(); reg <= lastNew(); reg += 1) {
            CachedRecovery* cachedRecovery { getNew(reg) };
            if (!cachedRecovery)
                continue;

            if (check(*cachedRecovery)) {
                spill(*cachedRecovery);
                return;
            }
        }

        RELEASE_ASSERT_NOT_REACHED();
    }

    void ensureRegister()
    {
        if (hasFreeRegister())
            return;

        if (verbose)
            dataLog("  Finding a register to spill\n");
        ensureRegister(
            [this] (const CachedRecovery& cachedRecovery) {
                if (cachedRecovery.recovery().isInGPR())
                    return !m_lockedRegisters.get(cachedRecovery.recovery().gpr());
                if (cachedRecovery.recovery().isInFPR())
                    return !m_lockedRegisters.get(cachedRecovery.recovery().fpr());
#if USE(JSVALUE32_64)
                if (cachedRecovery.recovery().technique() == InPair) {
                    return !m_lockedRegisters.get(cachedRecovery.recovery().tagGPR())
                        && !m_lockedRegisters.get(cachedRecovery.recovery().payloadGPR());
                }
#endif
                return false;
            });
    }

    void ensureTempGPR()
    {
        if (getFreeTempGPR() != InvalidGPRReg)
            return;

        if (verbose)
            dataLog("  Finding a temp GPR to spill\n");
        ensureRegister(
            [this] (const CachedRecovery& cachedRecovery) {
                if (cachedRecovery.recovery().isInGPR()) {
                    return !m_lockedRegisters.get(cachedRecovery.recovery().gpr()) 
                        && !m_newRegisters[cachedRecovery.recovery().gpr()];
                }
#if USE(JSVALUE32_64)
                if (cachedRecovery.recovery().technique() == InPair) {
                    return !m_lockedRegisters.get(cachedRecovery.recovery().tagGPR())
                        && !m_lockedRegisters.get(cachedRecovery.recovery().payloadGPR())
                        && !m_newRegisters[cachedRecovery.recovery().tagGPR()]
                        && !m_newRegisters[cachedRecovery.recovery().payloadGPR()];
                }
#endif
                return false;
            });
    }

    void ensureGPR()
    {
        if (getFreeGPR() != InvalidGPRReg)
            return;

        if (verbose)
            dataLog("  Finding a GPR to spill\n");
        ensureRegister(
            [this] (const CachedRecovery& cachedRecovery) {
                if (cachedRecovery.recovery().isInGPR())
                    return !m_lockedRegisters.get(cachedRecovery.recovery().gpr());
#if USE(JSVALUE32_64)
                if (cachedRecovery.recovery().technique() == InPair) {
                    return !m_lockedRegisters.get(cachedRecovery.recovery().tagGPR())
                        && !m_lockedRegisters.get(cachedRecovery.recovery().payloadGPR());
                }
#endif
                return false;
            });
    }

    void ensureFPR()
    {
        if (getFreeFPR() != InvalidFPRReg)
            return;

        if (verbose)
            dataLog("  Finding an FPR to spill\n");
        ensureRegister(
            [this] (const CachedRecovery& cachedRecovery) {
                if (cachedRecovery.recovery().isInFPR())
                    return !m_lockedRegisters.get(cachedRecovery.recovery().fpr());
                return false;
            });
    }

    CachedRecovery* getNew(JSValueRegs jsValueRegs) const
    {
#if USE(JSVALUE64)
        return m_newRegisters[jsValueRegs.gpr()];
#else
        ASSERT(
            jsValueRegs.tagGPR() == InvalidGPRReg || jsValueRegs.payloadGPR() == InvalidGPRReg
            || m_newRegisters[jsValueRegs.payloadGPR()] == m_newRegisters[jsValueRegs.tagGPR()]);
        if (jsValueRegs.payloadGPR() == InvalidGPRReg)
            return m_newRegisters[jsValueRegs.tagGPR()];
        return m_newRegisters[jsValueRegs.payloadGPR()];
#endif
    }

    void addNew(JSValueRegs jsValueRegs, ValueRecovery recovery)
    {
        ASSERT(jsValueRegs && !getNew(jsValueRegs));
        CachedRecovery* cachedRecovery = addCachedRecovery(recovery);
#if USE(JSVALUE64)
        if (cachedRecovery->wantedJSValueRegs())
            m_newRegisters[cachedRecovery->wantedJSValueRegs().gpr()] = nullptr;
        m_newRegisters[jsValueRegs.gpr()] = cachedRecovery;
#else
        if (JSValueRegs oldRegs { cachedRecovery->wantedJSValueRegs() }) {
            if (oldRegs.payloadGPR())
                m_newRegisters[oldRegs.payloadGPR()] = nullptr;
            if (oldRegs.tagGPR())
                m_newRegisters[oldRegs.tagGPR()] = nullptr;
        }
        if (jsValueRegs.payloadGPR() != InvalidGPRReg)
            m_newRegisters[jsValueRegs.payloadGPR()] = cachedRecovery;
        if (jsValueRegs.tagGPR() != InvalidGPRReg)
            m_newRegisters[jsValueRegs.tagGPR()] = cachedRecovery;
#endif
        ASSERT(!cachedRecovery->wantedJSValueRegs());
        cachedRecovery->setWantedJSValueRegs(jsValueRegs);
    }

    void addNew(FPRReg fpr, ValueRecovery recovery)
    {
        ASSERT(fpr != InvalidFPRReg && !m_newRegisters[fpr]);
        CachedRecovery* cachedRecovery = addCachedRecovery(recovery);
        m_newRegisters[fpr] = cachedRecovery;
        ASSERT(cachedRecovery->wantedFPR() == InvalidFPRReg);
        cachedRecovery->setWantedFPR(fpr);
    }

    // m_oldFrameBase is the register relative to which we access
    // slots in the old call frame, with an additional offset of
    // m_oldFrameOffset.
    //
    //  - For an actual tail call, m_oldFrameBase is the stack
    //    pointer, and m_oldFrameOffset is the number of locals of the
    //    tail caller's frame. We use such stack pointer-based
    //    addressing because it allows us to load the tail caller's
    //    caller's frame pointer in the frame pointer register
    //    immediately instead of awkwardly keeping it around on the
    //    stack.
    //
    //  - For a slow path call, m_oldFrameBase is just the frame
    //    pointer, and m_oldFrameOffset is 0.
    GPRReg m_oldFrameBase { MacroAssembler::framePointerRegister };
    int m_oldFrameOffset { 0 };

    MacroAssembler::Address addressForOld(VirtualRegister reg) const
    {
        return MacroAssembler::Address(m_oldFrameBase,
            (m_oldFrameOffset + reg.offset()) * sizeof(Register));
    }

    // m_newFrameBase is the register relative to which we access
    // slots in the new call frame, and we always make it point to
    // wherever the stack pointer will be right before making the
    // actual call/jump. The actual base of the new frame is at offset
    // m_newFrameOffset relative to m_newFrameBase.
    //
    //  - For an actual tail call, m_newFrameBase is computed
    //    dynamically, and m_newFrameOffset varies between 0 and -2
    //    depending on the architecture's calling convention (see
    //    prepareForTailCall).
    //
    //  - For a slow path call, m_newFrameBase is the actual stack
    //    pointer, and m_newFrameOffset is - CallerFrameAndPCSize,
    //    following the convention for a regular call.
    GPRReg m_newFrameBase { InvalidGPRReg };
    int m_newFrameOffset { 0};

    bool isUndecided() const
    {
        return m_newFrameBase == InvalidGPRReg;
    }

    bool isSlowPath() const
    {
        return m_newFrameBase == MacroAssembler::stackPointerRegister;
    }

    MacroAssembler::Address addressForNew(VirtualRegister reg) const
    {
        return MacroAssembler::Address(m_newFrameBase,
            (m_newFrameOffset + reg.offset()) * sizeof(Register));
    }

    // We use a concept of "danger zone". The danger zone consists of
    // all the writes in the new frame that could overlap with reads
    // in the old frame.
    //
    // Because we could have a higher actual number of arguments than
    // parameters, when preparing a tail call, we need to assume that
    // writing to a slot on the new frame could overlap not only with
    // the corresponding slot in the old frame, but also with any slot
    // above it. Thus, the danger zone consists of all writes between
    // the first write and what I call the "danger frontier": the
    // highest slot in the old frame we still care about. Thus, the
    // danger zone contains all the slots between the first slot of
    // the new frame and the danger frontier. Because the danger
    // frontier is related to the new frame, it is stored as a virtual
    // register *in the new frame*.
    VirtualRegister m_dangerFrontier;

    VirtualRegister dangerFrontier() const
    {
        ASSERT(!isUndecided());

        return m_dangerFrontier;
    }

    bool isDangerNew(VirtualRegister reg) const
    {
        ASSERT(!isUndecided() && isValidNew(reg));
        return reg <= dangerFrontier();
    }

    void updateDangerFrontier()
    {
        ASSERT(!isUndecided());

        m_dangerFrontier = firstNew() - 1;
        for (VirtualRegister reg = lastNew(); reg >= firstNew(); reg -= 1) {
            if (!getNew(reg) || !isValidOld(newAsOld(reg)) || !getOld(newAsOld(reg)))
                continue;

            m_dangerFrontier = reg;
            if (verbose)
                dataLog("  Danger frontier now at NEW ", m_dangerFrontier, "\n");
            break;
        }
        if (verbose)
            dataLog("  All clear! Danger zone is empty.\n");
    }

    // A safe write is a write that never writes into the danger zone.
    bool hasOnlySafeWrites(CachedRecovery& cachedRecovery) const
    {
        for (VirtualRegister target : cachedRecovery.targets()) {
            if (isDangerNew(target))
                return false;
        }
        return true;
    }

    // You must ensure that there is no dangerous writes before
    // calling this function.
    bool tryWrites(CachedRecovery&);

    // This function tries to ensure that there is no longer any
    // possible safe write, i.e. all remaining writes are either to
    // the danger zone or callee save restorations.
    //
    // It returns false if it was unable to perform some safe writes
    // due to high register pressure.
    bool performSafeWrites();
    
    unsigned m_numPassedArgs { UINT_MAX };
};

} // namespace JSC

#endif // ENABLE(JIT)
