/*
 * Copyright (C) 2017 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(B3_JIT)

#include "PureNaN.h"
#include <climits>
#include <wtf/BubbleSort.h>
#include <wtf/Insertion.h>
#include <wtf/Vector.h>

namespace JSC { namespace B3 {

class InsertionSet;

template<typename BasicBlock>
class GenericBlockInsertionSet {
public:
    typedef WTF::Insertion<std::unique_ptr<BasicBlock>> BlockInsertion;
    
    GenericBlockInsertionSet(Vector<std::unique_ptr<BasicBlock>>& blocks)
        : m_blocks(blocks)
    {
    }
    
    void insert(BlockInsertion&& insertion)
    {
        m_insertions.append(WTFMove(insertion));
    }

    // Insert a new block at a given index.
    BasicBlock* insert(unsigned index, double frequency = PNaN)
    {
        std::unique_ptr<BasicBlock> block(new BasicBlock(BasicBlock::uninsertedIndex, frequency));
        BasicBlock* result = block.get();
        insert(BlockInsertion(index, WTFMove(block)));
        return result;
    }

    // Inserts a new block before the given block. Usually you will not pass the frequency
    // argument. Passing PNaN causes us to just use the frequency of the 'before' block. That's
    // usually what you want.
    BasicBlock* insertBefore(BasicBlock* before, double frequency = PNaN)
    {
        return insert(before->index(), frequency == frequency ? frequency : before->frequency());
    }

    // Inserts a new block after the given block.
    BasicBlock* insertAfter(BasicBlock* after, double frequency = PNaN)
    {
        return insert(after->index() + 1, frequency == frequency ? frequency : after->frequency());
    }

    bool execute()
    {
        if (m_insertions.isEmpty())
            return false;
        
        // We allow insertions to be given to us in any order. So, we need to sort them before
        // running WTF::executeInsertions. We strongly prefer a stable sort and we want it to be
        // fast, so we use bubble sort.
        bubbleSort(m_insertions.begin(), m_insertions.end());
        
        executeInsertions(m_blocks, m_insertions);
        
        // Prune out empty entries. This isn't strictly necessary but it's
        // healthy to keep the block list from growing.
        m_blocks.removeAllMatching(
            [&] (std::unique_ptr<BasicBlock>& blockPtr) -> bool {
                return !blockPtr;
            });
        
        // Make sure that the blocks know their new indices.
        for (unsigned i = 0; i < m_blocks.size(); ++i)
            m_blocks[i]->m_index = i;
        
        return true;
    }

private:
    Vector<std::unique_ptr<BasicBlock>>& m_blocks;
    Vector<BlockInsertion, 8> m_insertions;
};

} } // namespace JSC::B3

#endif // ENABLE(B3_JIT)
