/*
 * 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. AND ITS CONTRIBUTORS ``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 ITS 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 "DFGStoreBarrierInsertionPhase.h"

#if ENABLE(DFG_JIT)

#include "DFGAbstractInterpreterInlines.h"
#include "DFGBlockMapInlines.h"
#include "DFGDoesGC.h"
#include "DFGGraph.h"
#include "DFGInPlaceAbstractState.h"
#include "DFGInsertionSet.h"
#include "DFGPhase.h"
#include "JSCInlines.h"
#include <wtf/CommaPrinter.h>
#include <wtf/HashSet.h>

namespace JSC { namespace DFG {

namespace {

namespace DFGStoreBarrierInsertionPhaseInternal {
static constexpr bool verbose = false;
}

enum class PhaseMode {
    // Does only a local analysis for store barrier insertion and assumes that pointers live
    // from predecessor blocks may need barriers. Assumes CPS conventions. Does not use AI for
    // eliminating store barriers, but does a best effort to eliminate barriers when you're
    // storing a non-cell value by using Node::result() and by looking at constants. The local
    // analysis is based on GC epochs, so it will eliminate a lot of locally redundant barriers.
    Fast,
        
    // Does a global analysis for store barrier insertion. Reuses the GC-epoch-based analysis
    // used by Fast, but adds a conservative merge rule for propagating information from one
    // block to the next. This will ensure for example that if a value V coming from multiple
    // predecessors in B didn't need any more barriers at the end of each predecessor (either
    // because it was the last allocated object in that predecessor or because it just had a
    // barrier executed), then until we hit another GC point in B, we won't need another barrier
    // on V. Uses AI for eliminating barriers when we know that the value being stored is not a
    // cell. Assumes SSA conventions.
    Global
};

template<PhaseMode mode>
class StoreBarrierInsertionPhase : public Phase {
public:
    StoreBarrierInsertionPhase(Graph& graph)
        : Phase(graph, mode == PhaseMode::Fast ? "fast store barrier insertion" : "global store barrier insertion")
        , m_insertionSet(graph)
    {
    }
    
    bool run()
    {
        if (DFGStoreBarrierInsertionPhaseInternal::verbose) {
            dataLog("Starting store barrier insertion:\n");
            m_graph.dump();
        }
        
        switch (mode) {
        case PhaseMode::Fast: {
            DFG_ASSERT(m_graph, nullptr, m_graph.m_form != SSA);
            
            m_graph.clearEpochs();
            for (BasicBlock* block : m_graph.blocksInNaturalOrder())
                handleBlock(block);
            return true;
        }
            
        case PhaseMode::Global: {
            DFG_ASSERT(m_graph, nullptr, m_graph.m_form == SSA);

            m_state = makeUnique<InPlaceAbstractState>(m_graph);
            m_interpreter = makeUnique<AbstractInterpreter<InPlaceAbstractState>>(m_graph, *m_state);
            
            m_isConverged = false;
            
            // First run the analysis. Inside basic blocks we use an epoch-based analysis that
            // is very precise. At block boundaries, we just propagate which nodes may need a
            // barrier. This gives us a very nice bottom->top fixpoint: we start out assuming
            // that no node needs any barriers at block boundaries, and then we converge
            // towards believing that all nodes need barriers. "Needing a barrier" is like
            // saying that the node is in a past epoch. "Not needing a barrier" is like saying
            // that the node is in the current epoch.
            m_stateAtHead = makeUnique<BlockMap<HashSet<Node*>>>(m_graph);
            m_stateAtTail = makeUnique<BlockMap<HashSet<Node*>>>(m_graph);
            
            BlockList postOrder = m_graph.blocksInPostOrder();
            
            bool changed = true;
            while (changed) {
                changed = false;
                
                // Intentional backwards loop because we are using RPO.
                for (unsigned blockIndex = postOrder.size(); blockIndex--;) {
                    BasicBlock* block = postOrder[blockIndex];
                    
                    if (!handleBlock(block)) {
                        // If the block didn't finish, then it cannot affect the fixpoint.
                        continue;
                    }
                    
                    // Construct the state-at-tail based on the epochs of live nodes and the
                    // current epoch. We grow state-at-tail monotonically to ensure convergence.
                    bool thisBlockChanged = false;
                    for (NodeFlowProjection node : block->ssa->liveAtTail) {
                        if (node.kind() == NodeFlowProjection::Shadow)
                            continue;
                        if (node->epoch() != m_currentEpoch) {
                            // If the node is older than the current epoch, then we may need to
                            // run a barrier on it in the future. So, add it to the state.
                            thisBlockChanged |= m_stateAtTail->at(block).add(node.node()).isNewEntry;
                        }
                    }
                    
                    if (!thisBlockChanged) {
                        // This iteration didn't learn anything new about this block.
                        continue;
                    }
                    
                    // Changed things. Make sure that we loop one more time.
                    changed = true;
                    
                    for (BasicBlock* successor : block->successors()) {
                        for (Node* node : m_stateAtTail->at(block))
                            m_stateAtHead->at(successor).add(node);
                    }
                }
            }
            
            // Tell handleBlock() that it's time to actually insert barriers for real.
            m_isConverged = true;
            
            for (BasicBlock* block : m_graph.blocksInNaturalOrder())
                handleBlock(block);
            
            return true;
        } }
        
        RELEASE_ASSERT_NOT_REACHED();
        return false;
    }

private:
    bool handleBlock(BasicBlock* block)
    {
        if (DFGStoreBarrierInsertionPhaseInternal::verbose) {
            dataLog("Dealing with block ", pointerDump(block), "\n");
            if (reallyInsertBarriers())
                dataLog("    Really inserting barriers.\n");
        }
        
        m_currentEpoch = Epoch::first();
        
        if (mode == PhaseMode::Global) {
            if (!block->cfaHasVisited)
                return false;
            m_state->beginBasicBlock(block);
            
            for (NodeFlowProjection node : block->ssa->liveAtHead) {
                if (node.kind() == NodeFlowProjection::Shadow)
                    continue;
                if (m_stateAtHead->at(block).contains(node.node())) {
                    // If previous blocks tell us that this node may need a barrier in the
                    // future, then put it in the ancient primordial epoch. This forces us to
                    // emit a barrier on any possibly-cell store, regardless of the epoch of the
                    // stored value.
                    node->setEpoch(Epoch());
                } else {
                    // If previous blocks aren't requiring us to run a barrier on this node,
                    // then put it in the current epoch. This means that we will skip barriers
                    // on this node so long as we don't allocate. It also means that we won't
                    // run barriers on stores to on one such node into another such node. That's
                    // fine, because nodes would be excluded from the state set if at the tails
                    // of all predecessors they always had the current epoch.
                    node->setEpoch(m_currentEpoch);
                }
            }
        }

        bool result = true;
        
        for (m_nodeIndex = 0; m_nodeIndex < block->size(); ++m_nodeIndex) {
            m_node = block->at(m_nodeIndex);
            
            if (DFGStoreBarrierInsertionPhaseInternal::verbose) {
                dataLog(
                    "    ", m_currentEpoch, ": Looking at node ", m_node, " with children: ");
                CommaPrinter comma;
                m_graph.doToChildren(
                    m_node,
                    [&] (Edge edge) {
                        dataLog(comma, edge, " (", edge->epoch(), ")");
                    });
                dataLog("\n");
            }
            
            if (mode == PhaseMode::Global) {
                // Execute edges separately because we don't want to insert barriers if the
                // operation doing the store does a check that ensures that the child is not
                // a cell.
                m_interpreter->startExecuting();
                m_interpreter->executeEdges(m_node);
            }
            
            switch (m_node->op()) {
            case PutByValDirect:
            case PutByVal:
            case PutByValAlias: {
                switch (m_node->arrayMode().modeForPut().type()) {
                case Array::Generic:
                case Array::BigInt64Array:
                case Array::BigUint64Array: {
                    Edge child1 = m_graph.varArgChild(m_node, 0);
                    if (!m_graph.m_slowPutByVal.contains(m_node) && (child1.useKind() == CellUse || child1.useKind() == KnownCellUse))
                        // FIXME: there are some cases where we can avoid a store barrier by considering the value https://bugs.webkit.org/show_bug.cgi?id=230377
                        considerBarrier(child1);
                    break;
                }
                case Array::Contiguous:
                case Array::ArrayStorage:
                case Array::SlowPutArrayStorage: {
                    Edge child1 = m_graph.varArgChild(m_node, 0);
                    Edge child3 = m_graph.varArgChild(m_node, 2);
                    considerBarrier(child1, child3);
                    break;
                }
                default:
                    break;
                }
                break;
            }
                
            case ArrayPush: {
                switch (m_node->arrayMode().type()) {
                case Array::Contiguous:
                case Array::ArrayStorage: {
                    unsigned elementOffset = 2;
                    unsigned elementCount = m_node->numChildren() - elementOffset;
                    Edge& arrayEdge = m_graph.varArgChild(m_node, 1);
                    for (unsigned i = 0; i < elementCount; ++i) {
                        Edge& element = m_graph.varArgChild(m_node, i + elementOffset);
                        considerBarrier(arrayEdge, element);
                    }
                    break;
                }
                default:
                    break;
                }
                break;
            }
                
            case PutPrivateName: {
                if (!m_graph.m_slowPutByVal.contains(m_node) && (m_node->child1().useKind() == CellUse || m_node->child1().useKind() == KnownCellUse))
                    // FIXME: there are some cases where we can avoid a store barrier by considering the value https://bugs.webkit.org/show_bug.cgi?id=230377
                    considerBarrier(m_node->child1());
                break;
            }

            case PutPrivateNameById: {
                // We emit IC code when we have a non-null cacheableIdentifier and we need to introduce a
                // barrier for it. On PutPrivateName, we perform store barrier during slow path execution.
                considerBarrier(m_node->child1());
                break;
            }

            case SetPrivateBrand:
            case PutById:
            case PutByIdFlush:
            case PutByIdDirect:
            case PutStructure: {
                considerBarrier(m_node->child1());
                break;
            }

            case DeleteById:
            case DeleteByVal: {
                // If child1 is not a cell-speculated, we call a generic implementation which emits write-barrier in C++ side.
                // FIXME: We should consider accept base:UntypedUse.
                // https://bugs.webkit.org/show_bug.cgi?id=209396
                if (isCell(m_node->child1().useKind()))
                    considerBarrier(m_node->child1());
                break;
            }

            case RegExpTestInline: {
                considerBarrier(m_node->child1());
                break;
            }

            case RecordRegExpCachedResult: {
                considerBarrier(m_graph.varArgChild(m_node, 0));
                break;
            }

            case PutClosureVar:
            case PutToArguments:
            case SetRegExpObjectLastIndex:
            case PutInternalField: {
                considerBarrier(m_node->child1(), m_node->child2());
                break;
            }
                
            case MultiPutByOffset:
            case MultiDeleteByOffset: {
                considerBarrier(m_node->child1());
                break;
            }
                
            case PutByOffset: {
                considerBarrier(m_node->child2(), m_node->child3());
                break;
            }
                
            case PutGlobalVariable: {
                considerBarrier(m_node->child1(), m_node->child2());
                break;
            }
                
            case SetFunctionName: {
                considerBarrier(m_node->child1(), m_node->child2());
                break;
            }
                
            case NukeStructureAndSetButterfly: {
                considerBarrier(m_node->child1());
                break;
            }

            default:
                break;
            }
            
            if (doesGC(m_graph, m_node))
                m_currentEpoch.bump();
            
            switch (m_node->op()) {
            case NewObject:
            case NewGenerator:
            case NewAsyncGenerator:
            case NewArray:
            case NewArrayWithSize:
            case NewArrayBuffer:
            case NewInternalFieldObject:
            case NewTypedArray:
            case NewRegexp:
            case NewStringObject:
            case NewSymbol:
            case MaterializeNewObject:
            case MaterializeCreateActivation:
            case MakeRope:
            case CreateActivation:
            case CreateDirectArguments:
            case CreateScopedArguments:
            case CreateClonedArguments:
            case CreateArgumentsButterfly:
            case NewFunction:
            case NewGeneratorFunction:
            case NewAsyncGeneratorFunction:
            case NewAsyncFunction:
            case AllocatePropertyStorage:
            case ReallocatePropertyStorage:
                // Nodes that allocate get to set their epoch because for those nodes we know
                // that they will be the newest object in the heap.
                m_node->setEpoch(m_currentEpoch);
                break;
                
            case Upsilon:
                // Assume the worst for Phis so that we don't have to worry about Phi shadows.
                m_node->phi()->setEpoch(Epoch());
                m_node->setEpoch(Epoch());
                break;
                
            default:
                // For nodes that aren't guaranteed to allocate, we say that their return value
                // (if there is one) could be arbitrarily old.
                m_node->setEpoch(Epoch());
                break;
            }
            
            if (DFGStoreBarrierInsertionPhaseInternal::verbose) {
                dataLog(
                    "    ", m_currentEpoch, ": Done with node ", m_node, " (", m_node->epoch(),
                    ") with children: ");
                CommaPrinter comma;
                m_graph.doToChildren(
                    m_node,
                    [&] (Edge edge) {
                        dataLog(comma, edge, " (", edge->epoch(), ")");
                    });
                dataLog("\n");
            }
            
            if (mode == PhaseMode::Global) {
                if (!m_interpreter->executeEffects(m_nodeIndex, m_node)) {
                    result = false;
                    break;
                }
            }
        }
        
        if (mode == PhaseMode::Global)
            m_state->reset();

        if (reallyInsertBarriers())
            m_insertionSet.execute(block);
        
        return result;
    }
    
    void considerBarrier(Edge base, Edge child)
    {
        if (DFGStoreBarrierInsertionPhaseInternal::verbose)
            dataLog("        Considering adding barrier ", base, " => ", child, "\n");
        
        // We don't need a store barrier if the child is guaranteed to not be a cell.
        switch (mode) {
        case PhaseMode::Fast: {
            // Don't try too hard because it's too expensive to run AI.
            if (child->hasConstant()) {
                if (!child->asJSValue().isCell()) {
                    if (DFGStoreBarrierInsertionPhaseInternal::verbose)
                        dataLog("            Rejecting because of constant type.\n");
                    return;
                }
            } else {
                switch (child->result()) {
                case NodeResultNumber:
                case NodeResultDouble:
                case NodeResultInt32:
                case NodeResultInt52:
                case NodeResultBoolean:
                    if (DFGStoreBarrierInsertionPhaseInternal::verbose)
                        dataLog("            Rejecting because of result type.\n");
                    return;
                default:
                    break;
                }
            }
            break;
        }
            
        case PhaseMode::Global: {
            // Go into rage mode to eliminate any chance of a barrier with a non-cell child. We
            // can afford to keep around AI in Global mode.
            if (!m_interpreter->needsTypeCheck(child, ~SpecCell)) {
                if (DFGStoreBarrierInsertionPhaseInternal::verbose)
                    dataLog("            Rejecting because of AI type.\n");
                return;
            }
            break;
        } }
        
        considerBarrier(base);
    }
    
    void considerBarrier(Edge base)
    {
        if (DFGStoreBarrierInsertionPhaseInternal::verbose)
            dataLog("        Considering adding barrier on ", base, "\n");
        
        // We don't need a store barrier if the epoch of the base is identical to the current
        // epoch. That means that we either just allocated the object and so it's guaranteed to
        // be in newgen, or we just ran a barrier on it so it's guaranteed to be remembered
        // already.
        if (base->epoch() == m_currentEpoch) {
            if (DFGStoreBarrierInsertionPhaseInternal::verbose)
                dataLog("            Rejecting because it's in the current epoch.\n");
            return;
        }
        
        if (DFGStoreBarrierInsertionPhaseInternal::verbose)
            dataLog("            Inserting barrier.\n");
        insertBarrier(m_nodeIndex + 1, base);
    }

    void insertBarrier(unsigned nodeIndex, Edge base)
    {
        // This is just our way of saying that barriers are not redundant with each other according
        // to forward analysis: if we proved one time that a barrier was necessary then it'll for
        // sure be necessary next time.
        base->setEpoch(Epoch());

        // If we're in global mode, we should only insert the barriers once we have converged.
        if (!reallyInsertBarriers())
            return;
        
        // FIXME: We could support StoreBarrier(UntypedUse:). That would be sort of cool.
        // But right now we don't need it.
        // https://bugs.webkit.org/show_bug.cgi?id=209396

        DFG_ASSERT(m_graph, m_node, isCell(base.useKind()), m_node->op(), base.useKind());
        
        // Barriers are always inserted after the node that they service. Therefore, we always know
        // that the thing is a cell now.
        base.setUseKind(KnownCellUse);
        
        NodeOrigin origin = m_node->origin;
        if (clobbersExitState(m_graph, m_node))
            origin = origin.withInvalidExit();
        
        m_insertionSet.insertNode(nodeIndex, SpecNone, FencedStoreBarrier, origin, base);
    }
    
    bool reallyInsertBarriers()
    {
        return mode == PhaseMode::Fast || m_isConverged;
    }
    
    InsertionSet m_insertionSet;
    Epoch m_currentEpoch;
    unsigned m_nodeIndex;
    Node* m_node;
    
    // Things we only use in Global mode.
    std::unique_ptr<InPlaceAbstractState> m_state;
    std::unique_ptr<AbstractInterpreter<InPlaceAbstractState>> m_interpreter;
    std::unique_ptr<BlockMap<HashSet<Node*>>> m_stateAtHead;
    std::unique_ptr<BlockMap<HashSet<Node*>>> m_stateAtTail;
    bool m_isConverged;
};

} // anonymous namespace

bool performFastStoreBarrierInsertion(Graph& graph)
{
    return runPhase<StoreBarrierInsertionPhase<PhaseMode::Fast>>(graph);
}

bool performGlobalStoreBarrierInsertion(Graph& graph)
{
    return runPhase<StoreBarrierInsertionPhase<PhaseMode::Global>>(graph);
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

