/*
 * Copyright (C) 2011-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(DFG_JIT)

#include "DFGCommon.h"
#include "FPRInfo.h"
#include "GPRInfo.h"

namespace JSC { namespace DFG {

// === RegisterBank ===
//
// This class is used to implement the GPR and FPR register banks.
// All registers have two pieces of state associated with them:
// a lock count (used to indicate this register is already in use
// in code generation of the current node, and cannot be spilled or
// allocated as a temporary), and VirtualRegister 'name', recording
// which value (if any) a machine register currently holds.
// Either or both of these pieces of information may be valid for a
// given register. A register may be:
//
//  - unlocked, and unnamed: Available for allocation.
//  - locked, but unnamed:   Already allocated as a temporary or
//                           result for the current node.
//  - unlocked, but named:   Contains the result of a prior operation,
//                           not yet in use for this node,
//  - locked, but named:     Contains the result of a prior operation,
//                           already allocated as a operand to the
//                           current operation.
//
// For every named register we also record a hint value indicating
// the order in which registers should be selected to be spilled;
// registers that can be more cheaply spilled and/or filled should
// be selected first.
//
// Locking register is a strong retention mechanism; a locked register
// will never be reallocated (this is used to ensure the operands to
// the current node are in registers). Naming, conversely, in a weak
// retention mechanism - allocating a register may force a named value
// to be spilled.
//
// All named values must be given a hint that is greater than Min and
// less than Max.
template<class BankInfo>
class RegisterBank {
    typedef typename BankInfo::RegisterType RegID;
    static constexpr size_t NUM_REGS = BankInfo::numberOfRegisters;

    typedef uint32_t SpillHint;
    static constexpr SpillHint SpillHintInvalid = 0xffffffff;

public:
    RegisterBank()
    {
    }

    // Attempt to allocate a register - this function finds an unlocked
    // register, locks it, and returns it. If none can be found, this
    // returns -1 (InvalidGPRReg or InvalidFPRReg).
    RegID tryAllocate()
    {
        VirtualRegister ignored = VirtualRegister();
        
        for (uint32_t i = 0; i < NUM_REGS; ++i) {
            if (!m_data[i].lockCount && !m_data[i].name.isValid())
                return allocateInternal(i, ignored);
        }
        
        return (RegID)-1;
    }

    // Allocate a register - this function finds an unlocked register,
    // locks it, and returns it. If any named registers exist, one
    // of these should be selected to be allocated. If all unlocked
    // registers are named, then one of the named registers will need
    // to be spilled. In this case the register selected to be spilled
    // will be one of the registers that has the lowest 'spillOrder'
    // cost associated with it.
    //
    // This method select the register to be allocated, and calls the
    // private 'allocateInternal' method to update internal data
    // structures accordingly.
    RegID allocate(VirtualRegister &spillMe)
    {
        uint32_t currentLowest = NUM_REGS;
        SpillHint currentSpillOrder = SpillHintInvalid;

        // This loop is broken into two halves, looping from the last allocated
        // register (the register returned last time this method was called) to
        // the maximum register value, then from 0 to the last allocated.
        // This implements a simple round-robin like approach to try to reduce
        // thrash, and minimize time spent scanning locked registers in allocation.
        // If a unlocked and unnamed register is found return it immediately.
        // Otherwise, find the first unlocked register with the lowest spillOrder.
        for (uint32_t i = 0 ; i < NUM_REGS; ++i) {
            // (1) If the current register is locked, it is not a candidate.
            if (m_data[i].lockCount)
                continue;
            // (2) If the current register's spill order is 0, pick this! – unassigned registers have spill order 0.
            SpillHint spillOrder = m_data[i].spillOrder;
            if (spillOrder == SpillHintInvalid)
                return allocateInternal(i, spillMe);
            // If this register is better (has a lower spill order value) than any prior
            // candidate, then record it.
            if (spillOrder < currentSpillOrder) {
                currentSpillOrder = spillOrder;
                currentLowest = i;
            }
        }

        // Deadlock check - this could only occur is all registers are locked!
        ASSERT(currentLowest != NUM_REGS && currentSpillOrder != SpillHintInvalid);
        // There were no available registers; currentLowest will need to be spilled.
        return allocateInternal(currentLowest, spillMe);
    }

    uint32_t lockedCount() const
    {
        uint32_t count = 0;
        for (uint32_t i = 0 ; i < NUM_REGS; ++i) {
            if (m_data[i].lockCount)
                ++count;
        }
        return count;
    }

    // Allocates the given register, even if this will force a spill.
    VirtualRegister allocateSpecific(RegID reg)
    {
        unsigned index = BankInfo::toIndex(reg);

        ++m_data[index].lockCount;
        VirtualRegister name = nameAtIndex(index);
        if (name.isValid())
            releaseAtIndex(index);
        
        return name;
    }

    // retain/release - these methods are used to associate/disassociate names
    // with values in registers. retain should only be called on locked registers.
    void retain(RegID reg, VirtualRegister name, SpillHint spillOrder)
    {
        unsigned index = BankInfo::toIndex(reg);

        // SpillHint must be valid.
        ASSERT(spillOrder != SpillHintInvalid);
        // 'index' must be a valid, locked register.
        ASSERT(index < NUM_REGS);
        ASSERT(m_data[index].lockCount);
        // 'index' should not currently be named, the new name must be valid.
        ASSERT(!m_data[index].name.isValid());
        ASSERT(name.isValid());
        // 'index' should not currently have a spillOrder.
        ASSERT(m_data[index].spillOrder == SpillHintInvalid);

        m_data[index].name = name;
        m_data[index].spillOrder = spillOrder;
    }
    void release(RegID reg)
    {
        releaseAtIndex(BankInfo::toIndex(reg));
    }

    // lock/unlock register, ensures that they are not spilled.
    void lock(RegID reg)
    {
        unsigned index = BankInfo::toIndex(reg);

        ASSERT(index < NUM_REGS);
        ++m_data[index].lockCount;
        ASSERT(m_data[index].lockCount);
    }
    void unlock(RegID reg)
    {
        unsigned index = BankInfo::toIndex(reg);

        ASSERT(index < NUM_REGS);
        ASSERT(m_data[index].lockCount);
        --m_data[index].lockCount;
    }
    bool isLocked(RegID reg) const
    {
        return isLockedAtIndex(BankInfo::toIndex(reg));
    }

    // Get the name (VirtualRegister) associated with the
    // given register (or default VirtualRegister() for none).
    VirtualRegister name(RegID reg) const
    {
        return nameAtIndex(BankInfo::toIndex(reg));
    }
    
    bool isInUse(RegID reg) const
    {
        return isLocked(reg) || name(reg).isValid();
    }
    
    void dump()
    {
        // For each register, print the VirtualRegister 'name'.
        for (uint32_t i =0; i < NUM_REGS; ++i) {
            if (m_data[i].name.isValid())
                dataLogF("[%02d]", m_data[i].name.offset());
            else
                dataLogF("[--]");
        }
        dataLogF("\n");
    }

    class iterator {
    friend class RegisterBank<BankInfo>;
    public:
        VirtualRegister name() const
        {
            return m_bank->nameAtIndex(m_index);
        }

        bool isLocked() const
        {
            return m_bank->isLockedAtIndex(m_index);
        }

        void release() const
        {
            m_bank->releaseAtIndex(m_index);
        }

        RegID regID() const
        {
            return BankInfo::toRegister(m_index);
        }

#ifndef NDEBUG
        const char* debugName() const
        {
            return BankInfo::debugName(regID());
        }
#endif

        iterator& operator++()
        {
            ++m_index;
            return *this;
        }

        bool operator!=(const iterator& other) const
        {
            ASSERT(m_bank == other.m_bank);
            return m_index != other.m_index;
        }

        unsigned index() const
        {
            return m_index;
        }

    private:
        iterator(RegisterBank<BankInfo>* bank, unsigned index)
            : m_bank(bank)
            , m_index(index)
        {
        }

        RegisterBank<BankInfo>* m_bank;
        unsigned m_index;
    };

    iterator begin()
    {
        return iterator(this, 0);
    }

    iterator end()
    {
        return iterator(this, NUM_REGS);
    }

private:
    bool isLockedAtIndex(unsigned index) const
    {
        ASSERT(index < NUM_REGS);
        return m_data[index].lockCount;
    }

    VirtualRegister nameAtIndex(unsigned index) const
    {
        ASSERT(index < NUM_REGS);
        return m_data[index].name;
    }

    void releaseAtIndex(unsigned index)
    {
        // 'index' must be a valid register.
        ASSERT(index < NUM_REGS);
        // 'index' should currently be named.
        ASSERT(m_data[index].name.isValid());
        // 'index' should currently have a valid spill order.
        ASSERT(m_data[index].spillOrder != SpillHintInvalid);

        m_data[index].name = VirtualRegister();
        m_data[index].spillOrder = SpillHintInvalid;
    }

    // Used by 'allocate', above, to update inforamtion in the map.
    RegID allocateInternal(uint32_t i, VirtualRegister &spillMe)
    {
        // 'i' must be a valid, unlocked register.
        ASSERT(i < NUM_REGS && !m_data[i].lockCount);

        // Return the VirtualRegister of the named value currently stored in
        // the register being returned - or default VirtualRegister() if none.
        spillMe = m_data[i].name;

        // Clear any name/spillOrder currently associated with the register,
        m_data[i] = MapEntry();
        // Mark the register as locked (with a lock count of 1).
        m_data[i].lockCount = 1;

        return BankInfo::toRegister(i);
    }

    // === MapEntry ===
    //
    // This structure provides information for an individual machine register
    // being managed by the RegisterBank. For each register we track a lock
    // count, name and spillOrder hint.
    struct MapEntry {
        MapEntry()
            : name(VirtualRegister())
            , spillOrder(SpillHintInvalid)
            , lockCount(0)
        {
        }

        VirtualRegister name;
        SpillHint spillOrder;
        uint32_t lockCount;
    };

    // Holds the current status of all registers.
    MapEntry m_data[NUM_REGS];
};

typedef RegisterBank<GPRInfo>::iterator gpr_iterator;
typedef RegisterBank<FPRInfo>::iterator fpr_iterator;

} } // namespace JSC::DFG

#endif
