/*
 * Copyright (C) 2012 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 "DFGFixupPhase.h"

#if ENABLE(DFG_JIT)

#include "DFGGraph.h"
#include "DFGInsertionSet.h"
#include "DFGPhase.h"

namespace JSC { namespace DFG {

class FixupPhase : public Phase {
public:
    FixupPhase(Graph& graph)
        : Phase(graph, "fixup")
    {
    }
    
    bool run()
    {
        for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex)
            fixupBlock(m_graph.m_blocks[blockIndex].get());
        return true;
    }

private:
    void fixupBlock(BasicBlock* block)
    {
        if (!block)
            return;
        ASSERT(block->isReachable);
        m_block = block;
        for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
            m_compileIndex = block->at(m_indexInBlock);
            fixupNode(m_graph[m_compileIndex]);
        }
        m_insertionSet.execute(*block);
    }
    
    void fixupNode(Node& node)
    {
        if (!node.shouldGenerate())
            return;
        
        NodeType op = node.op();

#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        dataLogF("   %s @%u: ", Graph::opName(op), m_compileIndex);
#endif
        
        switch (op) {
        case GetById: {
            if (m_graph.m_fixpointState > BeforeFixpoint)
                break;
            
            Node* nodePtr = &node;
            
            if (!isInt32Speculation(m_graph[m_compileIndex].prediction()))
                break;
            if (codeBlock()->identifier(nodePtr->identifierNumber()) != globalData().propertyNames->length)
                break;
            ArrayProfile* arrayProfile = 
                m_graph.baselineCodeBlockFor(nodePtr->codeOrigin)->getArrayProfile(
                    nodePtr->codeOrigin.bytecodeIndex);
            ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions);
            if (arrayProfile) {
                arrayProfile->computeUpdatedPrediction(m_graph.baselineCodeBlockFor(node.codeOrigin));
                arrayMode = ArrayMode::fromObserved(arrayProfile, Array::Read, false);
                arrayMode = arrayMode.refine(
                    m_graph[node.child1()].prediction(),
                    m_graph[m_compileIndex].prediction());
                if (arrayMode.supportsLength() && arrayProfile->hasDefiniteStructure()) {
                    m_graph.ref(nodePtr->child1());
                    Node checkStructure(CheckStructure, nodePtr->codeOrigin, OpInfo(m_graph.addStructureSet(arrayProfile->expectedStructure())), nodePtr->child1().index());
                    checkStructure.ref();
                    NodeIndex checkStructureIndex = m_graph.size();
                    m_graph.append(checkStructure);
                    m_insertionSet.append(m_indexInBlock, checkStructureIndex);
                    nodePtr = &m_graph[m_compileIndex];
                }
            } else {
                arrayMode = arrayMode.refine(
                    m_graph[node.child1()].prediction(),
                    m_graph[m_compileIndex].prediction());
            }
            if (!arrayMode.supportsLength())
                break;
            nodePtr->setOp(GetArrayLength);
            ASSERT(nodePtr->flags() & NodeMustGenerate);
            nodePtr->clearFlags(NodeMustGenerate | NodeClobbersWorld);
            m_graph.deref(m_compileIndex);
            nodePtr->setArrayMode(arrayMode);
            
            NodeIndex storage = checkArray(arrayMode, nodePtr->codeOrigin, nodePtr->child1().index(), NoNode, lengthNeedsStorage, nodePtr->shouldGenerate());
            if (storage == NoNode)
                break;
            
            nodePtr = &m_graph[m_compileIndex];
            nodePtr->children.child2() = Edge(storage);
            break;
        }
        case GetIndexedPropertyStorage: {
            ASSERT(node.arrayMode().canCSEStorage());
            break;
        }
        case GetByVal: {
            node.setArrayMode(
                node.arrayMode().refine(
                    m_graph[node.child1()].prediction(),
                    m_graph[node.child2()].prediction(),
                    SpecNone, node.flags()));
            
            blessArrayOperation(node.child1(), node.child2(), 2);
            
            Node* nodePtr = &m_graph[m_compileIndex];
            ArrayMode arrayMode = nodePtr->arrayMode();
            if (arrayMode.type() == Array::Double
                && arrayMode.arrayClass() == Array::OriginalArray
                && arrayMode.speculation() == Array::InBounds
                && arrayMode.conversion() == Array::AsIs
                && m_graph.globalObjectFor(nodePtr->codeOrigin)->arrayPrototypeChainIsSane()
                && !(nodePtr->flags() & NodeUsedAsOther))
                nodePtr->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
            
            break;
        }
        case StringCharAt:
        case StringCharCodeAt: {
            // Currently we have no good way of refining these.
            ASSERT(node.arrayMode() == ArrayMode(Array::String));
            blessArrayOperation(node.child1(), node.child2(), 2);
            break;
        }
            
        case ArrayPush: {
            // May need to refine the array mode in case the value prediction contravenes
            // the array prediction. For example, we may have evidence showing that the
            // array is in Int32 mode, but the value we're storing is likely to be a double.
            // Then we should turn this into a conversion to Double array followed by the
            // push. On the other hand, we absolutely don't want to refine based on the
            // base prediction. If it has non-cell garbage in it, then we want that to be
            // ignored. That's because ArrayPush can't handle any array modes that aren't
            // array-related - so if refine() turned this into a "Generic" ArrayPush then
            // that would break things.
            node.setArrayMode(
                node.arrayMode().refine(
                    m_graph[node.child1()].prediction() & SpecCell,
                    SpecInt32,
                    m_graph[node.child2()].prediction()));
            blessArrayOperation(node.child1(), Edge(), 2);
            
            Node* nodePtr = &m_graph[m_compileIndex];
            switch (nodePtr->arrayMode().type()) {
            case Array::Double:
                fixDoubleEdge(1);
                break;
            default:
                break;
            }
            break;
        }
            
        case ArrayPop: {
            blessArrayOperation(node.child1(), Edge(), 1);
            break;
        }
            
        case ValueToInt32: {
            if (m_graph[node.child1()].shouldSpeculateNumber()
                && node.mustGenerate()) {
                node.clearFlags(NodeMustGenerate);
                m_graph.deref(m_compileIndex);
            }
            break;
        }
            
        case BitAnd:
        case BitOr:
        case BitXor:
        case BitRShift:
        case BitLShift:
        case BitURShift: {
            fixIntEdge(node.children.child1());
            fixIntEdge(node.children.child2());
            break;
        }
            
        case CompareEq:
        case CompareLess:
        case CompareLessEq:
        case CompareGreater:
        case CompareGreaterEq:
        case CompareStrictEq: {
            if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]))
                break;
            if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
                break;
            fixDoubleEdge(0);
            fixDoubleEdge(1);
            break;
        }
            
        case LogicalNot: {
            if (m_graph[node.child1()].shouldSpeculateInteger())
                break;
            if (!m_graph[node.child1()].shouldSpeculateNumber())
                break;
            fixDoubleEdge(0);
            break;
        }
            
        case Branch: {
            if (!m_graph[node.child1()].shouldSpeculateInteger()
                && m_graph[node.child1()].shouldSpeculateNumber())
                fixDoubleEdge(0);

            Node& myNode = m_graph[m_compileIndex]; // reload because the graph may have changed
            Edge logicalNotEdge = myNode.child1();
            Node& logicalNot = m_graph[logicalNotEdge];
            if (logicalNot.op() == LogicalNot
                && logicalNot.adjustedRefCount() == 1) {
                Edge newChildEdge = logicalNot.child1();
                if (m_graph[newChildEdge].hasBooleanResult()) {
                    m_graph.ref(newChildEdge);
                    m_graph.deref(logicalNotEdge);
                    myNode.children.setChild1(newChildEdge);
                    
                    BlockIndex toBeTaken = myNode.notTakenBlockIndex();
                    BlockIndex toBeNotTaken = myNode.takenBlockIndex();
                    myNode.setTakenBlockIndex(toBeTaken);
                    myNode.setNotTakenBlockIndex(toBeNotTaken);
                }
            }
            break;
        }
            
        case SetLocal: {
            if (node.variableAccessData()->isCaptured())
                break;
            if (!node.variableAccessData()->shouldUseDoubleFormat())
                break;
            fixDoubleEdge(0);
            break;
        }
            
        case ArithAdd:
        case ValueAdd: {
            if (m_graph.addShouldSpeculateInteger(node))
                break;
            if (!Node::shouldSpeculateNumberExpectingDefined(m_graph[node.child1()], m_graph[node.child2()]))
                break;
            fixDoubleEdge(0);
            fixDoubleEdge(1);
            break;
        }
            
        case ArithSub: {
            if (m_graph.addShouldSpeculateInteger(node)
                && node.canSpeculateInteger())
                break;
            fixDoubleEdge(0);
            fixDoubleEdge(1);
            break;
        }
            
        case ArithNegate: {
            if (m_graph.negateShouldSpeculateInteger(node))
                break;
            fixDoubleEdge(0);
            break;
        }
            
        case ArithMin:
        case ArithMax:
        case ArithMod: {
            if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
                && node.canSpeculateInteger())
                break;
            fixDoubleEdge(0);
            fixDoubleEdge(1);
            break;
        }
            
        case ArithMul: {
            if (m_graph.mulShouldSpeculateInteger(node))
                break;
            fixDoubleEdge(0);
            fixDoubleEdge(1);
            break;
        }

        case ArithDiv: {
            if (Node::shouldSpeculateIntegerForArithmetic(m_graph[node.child1()], m_graph[node.child2()])
                && node.canSpeculateInteger()) {
                if (isX86())
                    break;
                fixDoubleEdge(0);
                fixDoubleEdge(1);
                
                Node& oldDivision = m_graph[m_compileIndex];
                
                Node newDivision = oldDivision;
                newDivision.setRefCount(2);
                newDivision.predict(SpecDouble);
                NodeIndex newDivisionIndex = m_graph.size();
                
                oldDivision.setOp(DoubleAsInt32);
                oldDivision.children.initialize(Edge(newDivisionIndex, DoubleUse), Edge(), Edge());
                
                m_graph.append(newDivision);
                m_insertionSet.append(m_indexInBlock, newDivisionIndex);
                
                break;
            }
            fixDoubleEdge(0);
            fixDoubleEdge(1);
            break;
        }
            
        case ArithAbs: {
            if (m_graph[node.child1()].shouldSpeculateIntegerForArithmetic()
                && node.canSpeculateInteger())
                break;
            fixDoubleEdge(0);
            break;
        }
            
        case ArithSqrt: {
            fixDoubleEdge(0);
            break;
        }
            
        case PutByVal:
        case PutByValAlias: {
            Edge child1 = m_graph.varArgChild(node, 0);
            Edge child2 = m_graph.varArgChild(node, 1);
            Edge child3 = m_graph.varArgChild(node, 2);

            node.setArrayMode(
                node.arrayMode().refine(
                    m_graph[child1].prediction(),
                    m_graph[child2].prediction(),
                    m_graph[child3].prediction()));
            
            blessArrayOperation(child1, child2, 3);
            
            Node* nodePtr = &m_graph[m_compileIndex];
            
            switch (nodePtr->arrayMode().modeForPut().type()) {
            case Array::Double:
                fixDoubleEdge(2);
                break;
            case Array::Int8Array:
            case Array::Int16Array:
            case Array::Int32Array:
            case Array::Uint8Array:
            case Array::Uint8ClampedArray:
            case Array::Uint16Array:
            case Array::Uint32Array:
                if (!m_graph[child3].shouldSpeculateInteger())
                    fixDoubleEdge(2);
                break;
            case Array::Float32Array:
            case Array::Float64Array:
                fixDoubleEdge(2);
                break;
            default:
                break;
            }
            break;
        }
            
        case NewArray: {
            for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
                node.setIndexingType(
                    leastUpperBoundOfIndexingTypeAndType(
                        node.indexingType(), m_graph[m_graph.varArgChild(node, i)].prediction()));
            }
            if (node.indexingType() == ArrayWithDouble) {
                for (unsigned i = m_graph.varArgNumChildren(node); i--;)
                    fixDoubleEdge(i);
            }
            break;
        }
            
        default:
            break;
        }

#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        if (!(node.flags() & NodeHasVarArgs)) {
            dataLogF("new children: ");
            node.dumpChildren(WTF::dataFile());
        }
        dataLogF("\n");
#endif
    }
    
    NodeIndex addNode(const Node& node, bool shouldGenerate)
    {
        NodeIndex nodeIndex = m_graph.size();
        m_graph.append(node);
        m_insertionSet.append(m_indexInBlock, nodeIndex);
        if (shouldGenerate)
            m_graph[nodeIndex].ref();
        return nodeIndex;
    }
    
    NodeIndex checkArray(ArrayMode arrayMode, CodeOrigin codeOrigin, NodeIndex array, NodeIndex index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage, bool shouldGenerate = true)
    {
        ASSERT(arrayMode.isSpecific());
        
        m_graph.ref(array);

        Structure* structure = arrayMode.originalArrayStructure(m_graph, codeOrigin);
        
        if (arrayMode.doesConversion()) {
            if (index != NoNode)
                m_graph.ref(index);
            
            if (structure) {
                if (m_indexInBlock > 0) {
                    // If the previous node was a CheckStructure inserted because of stuff
                    // that the array profile told us, then remove it.
                    Node& previousNode = m_graph[m_block->at(m_indexInBlock - 1)];
                    if (previousNode.op() == CheckStructure
                        && previousNode.child1() == array
                        && previousNode.codeOrigin == codeOrigin)
                        previousNode.setOpAndDefaultFlags(Phantom);
                }
                
                Node arrayify(ArrayifyToStructure, codeOrigin, OpInfo(structure), OpInfo(arrayMode.asWord()), array, index);
                arrayify.ref();
                NodeIndex arrayifyIndex = m_graph.size();
                m_graph.append(arrayify);
                m_insertionSet.append(m_indexInBlock, arrayifyIndex);
            } else {
                Node arrayify(Arrayify, codeOrigin, OpInfo(arrayMode.asWord()), array, index);
                arrayify.ref();
                NodeIndex arrayifyIndex = m_graph.size();
                m_graph.append(arrayify);
                m_insertionSet.append(m_indexInBlock, arrayifyIndex);
            }
        } else {
            if (structure) {
                Node checkStructure(CheckStructure, codeOrigin, OpInfo(m_graph.addStructureSet(structure)), array);
                checkStructure.ref();
                NodeIndex checkStructureIndex = m_graph.size();
                m_graph.append(checkStructure);
                m_insertionSet.append(m_indexInBlock, checkStructureIndex);
            } else {
                Node checkArray(CheckArray, codeOrigin, OpInfo(arrayMode.asWord()), array);
                checkArray.ref();
                NodeIndex checkArrayIndex = m_graph.size();
                m_graph.append(checkArray);
                m_insertionSet.append(m_indexInBlock, checkArrayIndex);
            }
        }
        
        if (!storageCheck(arrayMode))
            return NoNode;
        
        if (shouldGenerate)
            m_graph.ref(array);
        
        if (arrayMode.usesButterfly())
            return addNode(Node(GetButterfly, codeOrigin, array), shouldGenerate);
        
        return addNode(Node(GetIndexedPropertyStorage, codeOrigin, OpInfo(arrayMode.asWord()), array), shouldGenerate);
    }
    
    void blessArrayOperation(Edge base, Edge index, unsigned storageChildIdx)
    {
        if (m_graph.m_fixpointState > BeforeFixpoint)
            return;
            
        Node* nodePtr = &m_graph[m_compileIndex];
        
        switch (nodePtr->arrayMode().type()) {
        case Array::ForceExit: {
            Node forceExit(ForceOSRExit, nodePtr->codeOrigin);
            forceExit.ref();
            NodeIndex forceExitIndex = m_graph.size();
            m_graph.append(forceExit);
            m_insertionSet.append(m_indexInBlock, forceExitIndex);
            return;
        }
            
        case Array::SelectUsingPredictions:
        case Array::Unprofiled:
            ASSERT_NOT_REACHED();
            return;
            
        case Array::Generic:
            return;
            
        default: {
            NodeIndex storage = checkArray(nodePtr->arrayMode(), nodePtr->codeOrigin, base.index(), index.indexUnchecked());
            if (storage == NoNode)
                return;
            
            m_graph.child(m_graph[m_compileIndex], storageChildIdx) = Edge(storage);
            return;
        } }
    }
    
    void fixIntEdge(Edge& edge)
    {
        Node& node = m_graph[edge];
        if (node.op() != ValueToInt32)
            return;
        
        if (!m_graph[node.child1()].shouldSpeculateInteger())
            return;
        
        Edge oldEdge = edge;
        Edge newEdge = node.child1();
        
        m_graph.ref(newEdge);
        m_graph.deref(oldEdge);
        
        edge = newEdge;
    }
    
    void fixDoubleEdge(unsigned childIndex)
    {
        Node& source = m_graph[m_compileIndex];
        Edge& edge = m_graph.child(source, childIndex);
        
        if (!m_graph[edge].shouldSpeculateInteger()) {
            edge.setUseKind(DoubleUse);
            return;
        }
        
        NodeIndex resultIndex = (NodeIndex)m_graph.size();
        
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
        dataLogF("(replacing @%u->@%u with @%u->@%u) ",
                m_compileIndex, edge.index(), m_compileIndex, resultIndex);
#endif
        
        // Fix the edge up here because it's a reference that will be clobbered by
        // the append() below.
        NodeIndex oldIndex = edge.index();
        edge = Edge(resultIndex, DoubleUse);

        m_graph.append(Node(Int32ToDouble, source.codeOrigin, oldIndex));
        m_insertionSet.append(m_indexInBlock, resultIndex);
        
        Node& int32ToDouble = m_graph[resultIndex];
        int32ToDouble.predict(SpecDouble);
        int32ToDouble.ref();
    }

    BasicBlock* m_block;
    unsigned m_indexInBlock;
    NodeIndex m_compileIndex;
    InsertionSet<NodeIndex> m_insertionSet;
};
    
bool performFixup(Graph& graph)
{
    SamplingRegion samplingRegion("DFG Fixup Phase");
    return runPhase<FixupPhase>(graph);
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

