/*
 * 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. 
 */

#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 constexpr 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_numberTagRegister;

    bool tryAcquireNumberTagRegister();
#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_numberTagRegister != InvalidGPRReg && check(Reg { m_numberTagRegister })) {
            ASSERT(m_lockedRegisters.get(m_numberTagRegister));
            m_lockedRegisters.clear(m_numberTagRegister);
            nonTemp = Reg { m_numberTagRegister };
            m_numberTagRegister = 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)
