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

#include "config.h"
#include "DFGPutStackSinkingPhase.h"

#if ENABLE(DFG_JIT)

#include "DFGBlockMapInlines.h"
#include "DFGGraph.h"
#include "DFGInsertionSet.h"
#include "DFGPhase.h"
#include "DFGPreciseLocalClobberize.h"
#include "DFGSSACalculator.h"
#include "DFGValidate.h"
#include "JSCInlines.h"
#include "OperandsInlines.h"

namespace JSC { namespace DFG {

namespace {

class PutStackSinkingPhase : public Phase {
    static constexpr bool verbose = false;
public:
    PutStackSinkingPhase(Graph& graph)
        : Phase(graph, "PutStack sinking")
    {
    }
    
    bool run()
    {
        // FIXME: One of the problems of this approach is that it will create a duplicate Phi graph
        // for sunken PutStacks in the presence of interesting control flow merges, and where the
        // value being PutStack'd is also otherwise live in the DFG code. We could work around this
        // by doing the sinking over CPS, or maybe just by doing really smart hoisting. It's also
        // possible that the duplicate Phi graph can be deduplicated by B3. It would be best if we
        // could observe that there is already a Phi graph in place that does what we want. In
        // principle if we have a request to place a Phi at a particular place, we could just check
        // if there is already a Phi that does what we want. Because PutStackSinkingPhase runs just
        // after SSA conversion, we have almost a guarantee that the Phi graph we produce here would
        // be trivially redundant to the one we already have.
        
        // FIXME: This phase doesn't adequately use KillStacks. KillStack can be viewed as a def.
        // This is mostly inconsequential; it would be a bug to have a local live at a KillStack.
        // More important is that KillStack should swallow any deferral. After a KillStack, the
        // local should behave like a TOP deferral because it would be invalid for anyone to trust
        // the stack. It's not clear to me if this is important or not.
        // https://bugs.webkit.org/show_bug.cgi?id=145296
        
        if (verbose) {
            dataLog("Graph before PutStack sinking:\n");
            m_graph.dump();
        }

        m_graph.ensureSSADominators();
        
        SSACalculator ssaCalculator(m_graph);
        InsertionSet insertionSet(m_graph);
        
        // First figure out where various locals are live.
        BlockMap<Operands<bool>> liveAtHead(m_graph);
        BlockMap<Operands<bool>> liveAtTail(m_graph);
        
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
            liveAtHead[block] = Operands<bool>(OperandsLike, block->variablesAtHead, false);
            liveAtTail[block] = Operands<bool>(OperandsLike, block->variablesAtHead, false);
        }
        
        bool changed;
        do {
            changed = false;
            
            for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
                BasicBlock* block = m_graph.block(blockIndex);
                if (!block)
                    continue;
                
                Operands<bool> live = liveAtTail[block];
                for (unsigned nodeIndex = block->size(); nodeIndex--;) {
                    Node* node = block->at(nodeIndex);
                    if (verbose)
                        dataLog("Live at ", node, ": ", live, "\n");
                    
                    Vector<Operand, 4> reads;
                    Vector<Operand, 4> writes;
                    auto escapeHandler = [&] (Operand operand) {
                        if (operand.isHeader())
                            return;
                        if (verbose)
                            dataLog("    ", operand, " is live at ", node, "\n");
                        reads.append(operand);
                    };

                    auto writeHandler = [&] (Operand operand) {
                        if (operand.isHeader())
                            return;
                        auto op = node->op();
                        RELEASE_ASSERT(op == PutStack || op == LoadVarargs || op == ForwardVarargs || op == KillStack);
                        writes.append(operand);
                    };

                    preciseLocalClobberize(
                        m_graph, node, escapeHandler, writeHandler,
                        [&] (Operand, LazyNode) { });

                    for (Operand operand : writes)
                        live.operand(operand) = false;
                    for (Operand operand : reads)
                        live.operand(operand) = true;
                }
                
                if (live == liveAtHead[block])
                    continue;
                
                liveAtHead[block] = live;
                changed = true;
                
                for (BasicBlock* predecessor : block->predecessors) {
                    for (size_t i = live.size(); i--;)
                        liveAtTail[predecessor][i] |= live[i];
                }
            }
            
        } while (changed);
        
        // All of the arguments should be live at head of root. Note that we may find that some
        // locals are live at head of root. This seems wrong but isn't. This will happen for example
        // if the function accesses closure variable #42 for some other function and we either don't
        // have variable #42 at all or we haven't set it at root, for whatever reason. Basically this
        // arises since our aliasing for closure variables is conservatively based on variable number
        // and ignores the owning symbol table. We should probably fix this eventually and make our
        // aliasing more precise.
        //
        // For our purposes here, the imprecision in the aliasing is harmless. It just means that we
        // may not do as much Phi pruning as we wanted.
        for (size_t i = liveAtHead.atIndex(0).numberOfArguments(); i--;)
            DFG_ASSERT(m_graph, nullptr, liveAtHead.atIndex(0).argument(i));
        
        // Next identify where we would want to sink PutStacks to. We say that there is a deferred
        // flush if we had a PutStack with a given FlushFormat but it hasn't been materialized yet.
        // Deferrals have the following lattice; but it's worth noting that the TOP part of the
        // lattice serves an entirely different purpose than the rest of the lattice: it just means
        // that we're in a region of code where nobody should have been relying on the value. The
        // rest of the lattice means that we either have a PutStack that is deferred (i.e. still
        // needs to be executed) or there isn't one (because we've alraedy executed it).
        //
        // Bottom:
        //     Represented as DeadFlush. 
        //     Means that all previous PutStacks have been executed so there is nothing deferred.
        //     During merging this is subordinate to the other kinds of deferrals, because it
        //     represents the fact that we've already executed all necessary PutStacks. This implies
        //     that there *had* been some PutStacks that we should have executed.
        //
        // Top:
        //     Represented as ConflictingFlush.
        //     Represents the fact that we know, via forward flow, that there isn't any value in the
        //     given local that anyone should have been relying on. This comes into play at the
        //     prologue (because in SSA form at the prologue no local has any value) or when we merge
        //     deferrals for different formats's. A lexical scope in which a local had some semantic
        //     meaning will by this point share the same format; if we had stores from different
        //     lexical scopes that got merged together then we may have a conflicting format. Hence
        //     a conflicting format proves that we're no longer in an area in which the variable was
        //     in scope. Note that this is all approximate and only precise enough to later answer
        //     questions pertinent to sinking. For example, this doesn't always detect when a local
        //     is no longer semantically relevant - we may well have a deferral from inside some
        //     inlined call survive outside of that inlined code, and this is generally OK. In the
        //     worst case it means that we might think that a deferral that is actually dead must
        //     still be executed. But we usually catch that with liveness. Liveness usually catches
        //     such cases, but that's not guaranteed since liveness is conservative.
        //
        //     What Top does give us is detects situations where we both don't need to care about a
        //     deferral and there is no way that we could reason about it anyway. If we merged
        //     deferrals for different formats then we wouldn't know the format to use. So, we use
        //     Top in that case because that's also a case where we know that we can ignore the
        //     deferral.
        //
        // Deferral with a concrete format:
        //     Represented by format values other than DeadFlush or ConflictingFlush.
        //     Represents the fact that the original code would have done a PutStack but we haven't
        //     identified an operation that would have observed that PutStack.
        //
        // We need to be precise about liveness in this phase because not doing so
        // could cause us to insert a PutStack before a node we thought may escape a 
        // value that it doesn't really escape. Sinking this PutStack above such a node may
        // cause us to insert a GetStack that we forward to the Phi we're feeding into the
        // sunken PutStack. Inserting such a GetStack could cause us to load garbage and
        // can confuse the AI to claim untrue things (like that the program will exit when
        // it really won't).
        BlockMap<Operands<FlushFormat>> deferredAtHead(m_graph);
        BlockMap<Operands<FlushFormat>> deferredAtTail(m_graph);
        
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
            deferredAtHead[block] =
                Operands<FlushFormat>(OperandsLike, block->variablesAtHead);
            deferredAtTail[block] =
                Operands<FlushFormat>(OperandsLike, block->variablesAtHead);
        }

        for (unsigned local = deferredAtHead.atIndex(0).numberOfLocals(); local--;)
            deferredAtHead.atIndex(0).local(local) = ConflictingFlush;
        
        do {
            changed = false;
            
            for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
                Operands<FlushFormat> deferred = deferredAtHead[block];
                
                for (Node* node : *block) {
                    if (verbose)
                        dataLog("Deferred at ", node, ":", deferred, "\n");
                    
                    if (node->op() == GetStack) {
                        // Handle the case that the input doesn't match our requirements. This is
                        // really a bug, but it's a benign one if we simply don't run this phase.
                        // It usually arises because of patterns like:
                        //
                        // if (thing)
                        //     PutStack()
                        // ...
                        // if (thing)
                        //     GetStack()
                        //
                        // Or:
                        //
                        // if (never happens)
                        //     GetStack()
                        //
                        // Because this phase runs early in SSA, it should be sensible to enforce
                        // that no such code pattern has arisen yet. So, when validation is
                        // enabled, we assert that we aren't seeing this. But with validation
                        // disabled we silently let this fly and we just abort this phase.
                        // FIXME: Get rid of all remaining cases of conflicting GetStacks.
                        // https://bugs.webkit.org/show_bug.cgi?id=150398

                        bool isConflicting =
                            deferred.operand(node->stackAccessData()->operand) == ConflictingFlush;
                        
                        if (validationEnabled())
                            DFG_ASSERT(m_graph, node, !isConflicting);

                        if (isConflicting) {
                            // Oh noes! Abort!!
                            return false;
                        }

                        // A GetStack doesn't affect anything, since we know which local we are reading
                        // from.
                        continue;
                    } else if (node->op() == PutStack) {
                        Operand operand = node->stackAccessData()->operand;
                        dataLogLnIf(verbose, "Setting flush format for ", node, " at operand ", operand);
                        deferred.operand(operand) = node->stackAccessData()->format;
                        continue;
                    } else if (node->op() == KillStack) {
                        // We don't want to sink a PutStack past a KillStack.
                        if (verbose)
                            dataLogLn("Killing stack for ", node->unlinkedOperand());
                        deferred.operand(node->unlinkedOperand()) = ConflictingFlush;
                        continue;
                    }
                    
                    auto escapeHandler = [&] (Operand operand) {
                        if (verbose)
                            dataLog("For ", node, " escaping ", operand, "\n");
                        if (operand.isHeader())
                            return;
                        // We will materialize just before any reads.
                        deferred.operand(operand) = DeadFlush;
                    };

                    auto writeHandler = [&] (Operand operand) {
                        ASSERT(!operand.isTmp());
                        if (operand.isHeader())
                            return;
                        RELEASE_ASSERT(node->op() == VarargsLength || node->op() == LoadVarargs || node->op() == ForwardVarargs);
                        dataLogLnIf(verbose, "Writing dead flush for ", node, " at operand ", operand);
                        deferred.operand(operand) = DeadFlush;
                    };
                    
                    preciseLocalClobberize(
                        m_graph, node, escapeHandler, writeHandler,
                        [&] (Operand, LazyNode) { });
                }
                
                if (deferred == deferredAtTail[block])
                    continue;
                
                deferredAtTail[block] = deferred;
                changed = true;
                
                for (BasicBlock* successor : block->successors()) {
                    for (size_t i = deferred.size(); i--;) {
                        if (verbose)
                            dataLog("Considering ", deferred.operandForIndex(i), " at ", pointerDump(block), "->", pointerDump(successor), ": ", deferred[i], " and ", deferredAtHead[successor][i], " merges to ");

                        deferredAtHead[successor][i] =
                            merge(deferredAtHead[successor][i], deferred[i]);
                        
                        if (verbose)
                            dataLog(deferredAtHead[successor][i], "\n");
                    }
                }
            }
            
        } while (changed);
        
        // We wish to insert PutStacks at all of the materialization points, which are defined
        // implicitly as the places where we set deferred to Dead while it was previously not Dead.
        // To do this, we may need to build some Phi functions to handle stuff like this:
        //
        // Before:
        //
        //     if (p)
        //         PutStack(r42, @x)
        //     else
        //         PutStack(r42, @y)
        //
        // After:
        //
        //     if (p)
        //         Upsilon(@x, ^z)
        //     else
        //         Upsilon(@y, ^z)
        //     z: Phi()
        //     PutStack(r42, @z)
        //
        // This means that we have an SSACalculator::Variable for each local, and a Def is any
        // PutStack in the original program. The original PutStacks will simply vanish.
        
        Operands<SSACalculator::Variable*> operandToVariable(
            OperandsLike, m_graph.block(0)->variablesAtHead);
        Vector<Operand> indexToOperand;
        for (size_t i = m_graph.block(0)->variablesAtHead.size(); i--;) {
            Operand operand = m_graph.block(0)->variablesAtHead.operandForIndex(i);

            SSACalculator::Variable* variable = ssaCalculator.newVariable();
            operandToVariable.operand(operand) = variable;
            ASSERT(indexToOperand.size() == variable->index());
            indexToOperand.append(operand);
        }
        
        HashSet<Node*> putStacksToSink;
        
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
            for (Node* node : *block) {
                switch (node->op()) {
                case PutStack:
                    putStacksToSink.add(node);
                    ssaCalculator.newDef(
                        operandToVariable.operand(node->stackAccessData()->operand),
                        block, node->child1().node());
                    break;
                case GetStack:
                    ssaCalculator.newDef(
                        operandToVariable.operand(node->stackAccessData()->operand),
                        block, node);
                    break;
                default:
                    break;
                }
            }
        }
        
        ssaCalculator.computePhis(
            [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Node* {
                Operand operand = indexToOperand[variable->index()];
                
                if (!liveAtHead[block].operand(operand))
                    return nullptr;
                
                FlushFormat format = deferredAtHead[block].operand(operand);

                // We could have an invalid deferral because liveness is imprecise.
                if (!isConcrete(format))
                    return nullptr;

                if (verbose)
                    dataLog("Adding Phi for ", operand, " at ", pointerDump(block), "\n");
                
                Node* phiNode = m_graph.addNode(SpecHeapTop, Phi, block->at(0)->origin.withInvalidExit());
                phiNode->mergeFlags(resultFor(format));
                return phiNode;
            });
        
        Operands<Node*> mapping(OperandsLike, m_graph.block(0)->variablesAtHead);
        Operands<FlushFormat> deferred;
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
            mapping.fill(nullptr);
            
            for (size_t i = mapping.size(); i--;) {
                Operand operand(mapping.operandForIndex(i));
                
                SSACalculator::Variable* variable = operandToVariable.operand(operand);
                SSACalculator::Def* def = ssaCalculator.reachingDefAtHead(block, variable);
                if (!def)
                    continue;
                
                mapping.operand(operand) = def->value();
            }
            
            if (verbose)
                dataLog("Mapping at top of ", pointerDump(block), ": ", mapping, "\n");
            
            for (SSACalculator::Def* phiDef : ssaCalculator.phisForBlock(block)) {
                Operand operand = indexToOperand[phiDef->variable()->index()];
                
                insertionSet.insert(0, phiDef->value());
                
                if (verbose)
                    dataLog("   Mapping ", operand, " to ", phiDef->value(), "\n");
                mapping.operand(operand) = phiDef->value();
            }
            
            deferred = deferredAtHead[block];
            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
                Node* node = block->at(nodeIndex);
                if (verbose)
                    dataLog("Deferred at ", node, ":", deferred, "\n");
                
                switch (node->op()) {
                case PutStack: {
                    StackAccessData* data = node->stackAccessData();
                    Operand operand = data->operand;
                    deferred.operand(operand) = data->format;
                    if (verbose)
                        dataLog("   Mapping ", operand, " to ", node->child1().node(), " at ", node, "\n");
                    mapping.operand(operand) = node->child1().node();
                    break;
                }
                    
                case GetStack: {
                    StackAccessData* data = node->stackAccessData();
                    FlushFormat format = deferred.operand(data->operand);
                    if (!isConcrete(format)) {
                        DFG_ASSERT(
                            m_graph, node,
                            deferred.operand(data->operand) != ConflictingFlush, deferred.operand(data->operand));
                        
                        // This means there is no deferral. No deferral means that the most
                        // authoritative value for this stack slot is what is stored in the stack. So,
                        // keep the GetStack.
                        mapping.operand(data->operand) = node;
                        break;
                    }
                    
                    // We have a concrete deferral, which means a PutStack that hasn't executed yet. It
                    // would have stored a value with a certain format. That format must match our
                    // format. But more importantly, we can simply use the value that the PutStack would
                    // have stored and get rid of the GetStack.
                    DFG_ASSERT(m_graph, node, format == data->format, format, data->format);
                    
                    Node* incoming = mapping.operand(data->operand);
                    node->child1() = incoming->defaultEdge();
                    node->convertToIdentity();
                    break;
                }

                case KillStack: {
                    deferred.operand(node->unlinkedOperand()) = ConflictingFlush;
                    break;
                }
                
                default: {
                    auto escapeHandler = [&] (Operand operand) {
                        if (verbose)
                            dataLog("For ", node, " escaping ", operand, "\n");

                        if (operand.isHeader())
                            return;
                    
                        FlushFormat format = deferred.operand(operand);
                        if (!isConcrete(format)) {
                            // It's dead now, rather than conflicting.
                            deferred.operand(operand) = DeadFlush;
                            return;
                        }
                    
                        // Gotta insert a PutStack.
                        if (verbose)
                            dataLog("Inserting a PutStack for ", operand, " at ", node, "\n");

                        Node* incoming = mapping.operand(operand);
                        DFG_ASSERT(m_graph, node, incoming);
                    
                        insertionSet.insertNode(
                            nodeIndex, SpecNone, PutStack, node->origin,
                            OpInfo(m_graph.m_stackAccessData.add(operand, format)),
                            Edge(incoming, uncheckedUseKindFor(format)));
                    
                        deferred.operand(operand) = DeadFlush;
                    };

                    auto writeHandler = [&] (Operand operand) {
                        if (operand.isHeader())
                            return;
                        // LoadVarargs and ForwardVarargs are unconditional writes to the stack
                        // locations they claim to write to. They do not read from the stack 
                        // locations they write to. This makes those stack locations dead right 
                        // before a LoadVarargs/ForwardVarargs. This means we should never sink
                        // PutStacks right to this point.
                        RELEASE_ASSERT(node->op() == VarargsLength || node->op() == LoadVarargs || node->op() == ForwardVarargs);
                        deferred.operand(operand) = DeadFlush;
                    };

                    preciseLocalClobberize(
                        m_graph, node, escapeHandler, writeHandler,
                        [&] (Operand, LazyNode) { });
                    break;
                } }
            }
            
            NodeAndIndex terminal = block->findTerminal();
            size_t upsilonInsertionPoint = terminal.index;
            NodeOrigin upsilonOrigin = terminal.node->origin;
            for (BasicBlock* successorBlock : block->successors()) {
                for (SSACalculator::Def* phiDef : ssaCalculator.phisForBlock(successorBlock)) {
                    Node* phiNode = phiDef->value();
                    SSACalculator::Variable* variable = phiDef->variable();
                    Operand operand = indexToOperand[variable->index()];
                    if (verbose)
                        dataLog("Creating Upsilon for ", operand, " at ", pointerDump(block), "->", pointerDump(successorBlock), "\n");
                    FlushFormat format = deferredAtHead[successorBlock].operand(operand);
                    DFG_ASSERT(m_graph, nullptr, isConcrete(format), format);
                    UseKind useKind = uncheckedUseKindFor(format);
                    
                    // We need to get a value for the stack slot. This phase doesn't really have a
                    // good way of determining if a stack location got clobbered. It just knows if
                    // there is a deferral. The lack of a deferral might mean that a PutStack or
                    // GetStack had never happened, or it might mean that the value was read, or
                    // that it was written. It's OK for us to make some bad decisions here, since
                    // GCSE will clean it up anyway.
                    Node* incoming;
                    if (isConcrete(deferred.operand(operand))) {
                        incoming = mapping.operand(operand);
                        DFG_ASSERT(m_graph, phiNode, incoming);
                    } else {
                        // Issue a GetStack to get the value. This might introduce some redundancy
                        // into the code, but if it's bad enough, GCSE will clean it up.
                        incoming = insertionSet.insertNode(
                            upsilonInsertionPoint, SpecNone, GetStack, upsilonOrigin,
                            OpInfo(m_graph.m_stackAccessData.add(operand, format)));
                        incoming->setResult(resultFor(format));
                    }
                    
                    insertionSet.insertNode(
                        upsilonInsertionPoint, SpecNone, Upsilon, upsilonOrigin,
                        OpInfo(phiNode), Edge(incoming, useKind));
                }
            }
            
            insertionSet.execute(block);
        }
        
        // Finally eliminate the sunken PutStacks by turning them into Checks. This keeps whatever
        // type check they were doing.
        for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
            for (auto* node : *block) {
                if (!putStacksToSink.contains(node))
                    continue;
                
                node->remove(m_graph);
            }
        }
        
        if (verbose) {
            dataLog("Graph after PutStack sinking:\n");
            m_graph.dump();
        }
        
        return true;
    }
};

} // anonymous namespace
    
bool performPutStackSinking(Graph& graph)
{
    return runPhase<PutStackSinkingPhase>(graph);
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

