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

#if ENABLE(DFG_JIT)

#include "ArrayPrototype.h"
#include "DFGGraph.h"
#include "DFGInsertionSet.h"
#include "DFGPhase.h"
#include "DFGPredictionPropagationPhase.h"
#include "DFGVariableAccessDataDump.h"
#include "JSCInlines.h"
#include "TypeLocation.h"

namespace JSC { namespace DFG {

class FixupPhase : public Phase {
public:
    FixupPhase(Graph& graph)
        : Phase(graph, "fixup")
        , m_insertionSet(graph)
    {
    }
    
    bool run()
    {
        ASSERT(m_graph.m_fixpointState == BeforeFixpoint);
        ASSERT(m_graph.m_form == ThreadedCPS);
        
        m_profitabilityChanged = false;
        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
            fixupBlock(m_graph.block(blockIndex));
        
        while (m_profitabilityChanged) {
            m_profitabilityChanged = false;
            
            for (unsigned i = m_graph.m_argumentPositions.size(); i--;)
                m_graph.m_argumentPositions[i].mergeArgumentUnboxingAwareness();
            
            for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
                fixupGetAndSetLocalsInBlock(m_graph.block(blockIndex));
        }
        
        for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
            fixupChecksInBlock(m_graph.block(blockIndex));

        m_graph.m_planStage = PlanStage::AfterFixup;

        return true;
    }

private:

    void fixupArithDivInt32(Node* node, Edge& leftChild, Edge& rightChild)
    {
        if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7IDIVSupported()) {
            fixIntOrBooleanEdge(leftChild);
            fixIntOrBooleanEdge(rightChild);
            if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
                node->setArithMode(Arith::Unchecked);
            else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                node->setArithMode(Arith::CheckOverflow);
            else
                node->setArithMode(Arith::CheckOverflowAndNegativeZero);
            return;
        }

        // This will cause conversion nodes to be inserted later.
        fixDoubleOrBooleanEdge(leftChild);
        fixDoubleOrBooleanEdge(rightChild);

        // We don't need to do ref'ing on the children because we're stealing them from
        // the original division.
        Node* newDivision = m_insertionSet.insertNode(m_indexInBlock, SpecBytecodeDouble, *node);
        newDivision->setResult(NodeResultDouble);

        node->setOp(DoubleAsInt32);
        node->children.initialize(Edge(newDivision, DoubleRepUse), Edge(), Edge());
        if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
            node->setArithMode(Arith::CheckOverflow);
        else
            node->setArithMode(Arith::CheckOverflowAndNegativeZero);

    }

    void fixupArithPow(Node* node)
    {
        if (node->child2()->shouldSpeculateInt32OrBooleanForArithmetic()) {
            fixDoubleOrBooleanEdge(node->child1());
            fixIntOrBooleanEdge(node->child2());
            return;
        }

        fixDoubleOrBooleanEdge(node->child1());
        fixDoubleOrBooleanEdge(node->child2());
    }

    void fixupArithDiv(Node* node, Edge& leftChild, Edge& rightChild)
    {
        if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
            fixupArithDivInt32(node, leftChild, rightChild);
            return;
        }
        
        fixDoubleOrBooleanEdge(leftChild);
        fixDoubleOrBooleanEdge(rightChild);
        node->setResult(NodeResultDouble);
    }
    
    void fixupArithMul(Node* node, Edge& leftChild, Edge& rightChild)
    {
        if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
            fixIntOrBooleanEdge(leftChild);
            fixIntOrBooleanEdge(rightChild);
            if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
                node->setArithMode(Arith::Unchecked);
            else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()) || leftChild.node() == rightChild.node())
                node->setArithMode(Arith::CheckOverflow);
            else
                node->setArithMode(Arith::CheckOverflowAndNegativeZero);
            return;
        }
        if (m_graph.binaryArithShouldSpeculateInt52(node, FixupPass)) {
            fixEdge<Int52RepUse>(leftChild);
            fixEdge<Int52RepUse>(rightChild);
            if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()) || leftChild.node() == rightChild.node())
                node->setArithMode(Arith::CheckOverflow);
            else
                node->setArithMode(Arith::CheckOverflowAndNegativeZero);
            node->setResult(NodeResultInt52);
            return;
        }

        fixDoubleOrBooleanEdge(leftChild);
        fixDoubleOrBooleanEdge(rightChild);
        node->setResult(NodeResultDouble);
    }

    void fixupBlock(BasicBlock* block)
    {
        if (!block)
            return;
        ASSERT(block->isReachable);
        m_block = block;
        for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
            m_currentNode = block->at(m_indexInBlock);
            fixupNode(m_currentNode);
        }
        m_insertionSet.execute(block);
    }
    
    void fixupNode(Node* node)
    {
        NodeType op = node->op();

        switch (op) {
        case SetLocal: {
            // This gets handled by fixupGetAndSetLocalsInBlock().
            return;
        }

        case ValueSub: {
            Edge& child1 = node->child1();
            Edge& child2 = node->child2();

            if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
                fixEdge<BigIntUse>(child1);
                fixEdge<BigIntUse>(child2);
                break; 
            }
            
            if (Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
                fixEdge<UntypedUse>(child1);
                fixEdge<UntypedUse>(child2);
                break;
            }

            if (attemptToMakeIntegerAdd(node)) {
                // FIXME: Clear ArithSub's NodeMustGenerate when ArithMode is unchecked
                // https://bugs.webkit.org/show_bug.cgi?id=190607
                node->setOp(ArithSub);
                break;
            }

            fixDoubleOrBooleanEdge(node->child1());
            fixDoubleOrBooleanEdge(node->child2());
            node->setOp(ArithSub);
            node->setResult(NodeResultDouble);

            break;
        }

        case ValueBitLShift:
        case ValueBitRShift:
        case ValueBitXor:
        case ValueBitOr:
        case ValueBitAnd: {
            if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
                fixEdge<BigIntUse>(node->child1());
                fixEdge<BigIntUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }

            if (Node::shouldSpeculateUntypedForBitOps(node->child1().node(), node->child2().node())) {
                fixEdge<UntypedUse>(node->child1());
                fixEdge<UntypedUse>(node->child2());
                break;
            }
            
            switch (op) {
            case ValueBitXor:
                node->setOp(ArithBitXor);
                break;
            case ValueBitOr:
                node->setOp(ArithBitOr);
                break;
            case ValueBitAnd:
                node->setOp(ArithBitAnd);
                break;
            case ValueBitLShift:
                node->setOp(ArithBitLShift);
                break;
            case ValueBitRShift:
                node->setOp(ArithBitRShift);
                break;
            default:
                DFG_CRASH(m_graph, node, "Unexpected node during ValueBit operation fixup");
                break;
            }

            node->clearFlags(NodeMustGenerate);
            node->setResult(NodeResultInt32);
            fixIntConvertingEdge(node->child1());
            fixIntConvertingEdge(node->child2());
            break;
        }

        case ValueBitNot: {
            Edge& operandEdge = node->child1();

            if (operandEdge.node()->shouldSpeculateBigInt()) {
                node->clearFlags(NodeMustGenerate);
                fixEdge<BigIntUse>(operandEdge);
            } else if (operandEdge.node()->shouldSpeculateUntypedForBitOps())
                fixEdge<UntypedUse>(operandEdge);
            else {
                node->setOp(ArithBitNot);
                node->setResult(NodeResultInt32);
                node->clearFlags(NodeMustGenerate);
                fixIntConvertingEdge(operandEdge);
            }
            break;
        }

        case ArithBitNot: {
            Edge& operandEdge = node->child1();

            fixIntConvertingEdge(operandEdge);
            break;
        }

        case ArithBitRShift:
        case ArithBitLShift: 
        case ArithBitXor:
        case ArithBitOr:
        case ArithBitAnd: {
            fixIntConvertingEdge(node->child1());
            fixIntConvertingEdge(node->child2());
            break;
        }

        case BitURShift: {
            if (Node::shouldSpeculateUntypedForBitOps(node->child1().node(), node->child2().node())) {
                fixEdge<UntypedUse>(node->child1());
                fixEdge<UntypedUse>(node->child2());
                break;
            }
            fixIntConvertingEdge(node->child1());
            fixIntConvertingEdge(node->child2());
            break;
        }

        case ArithIMul: {
            fixIntConvertingEdge(node->child1());
            fixIntConvertingEdge(node->child2());
            node->setOp(ArithMul);
            node->setArithMode(Arith::Unchecked);
            node->child1().setUseKind(Int32Use);
            node->child2().setUseKind(Int32Use);
            break;
        }

        case ArithClz32: {
            if (node->child1()->shouldSpeculateNotCell()) {
                fixIntConvertingEdge(node->child1());
                node->clearFlags(NodeMustGenerate);
            } else
                fixEdge<UntypedUse>(node->child1());
            break;
        }
            
        case UInt32ToNumber: {
            fixIntConvertingEdge(node->child1());
            if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
                node->convertToIdentity();
            else if (node->canSpeculateInt32(FixupPass))
                node->setArithMode(Arith::CheckOverflow);
            else {
                node->setArithMode(Arith::DoOverflow);
                node->setResult(enableInt52() ? NodeResultInt52 : NodeResultDouble);
            }
            break;
        }

        case ValueNegate: {
            if (node->child1()->shouldSpeculateInt32OrBoolean() && node->canSpeculateInt32(FixupPass)) {
                node->setOp(ArithNegate);
                fixIntOrBooleanEdge(node->child1());
                if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
                    node->setArithMode(Arith::Unchecked);
                else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                    node->setArithMode(Arith::CheckOverflow);
                else
                    node->setArithMode(Arith::CheckOverflowAndNegativeZero);
                node->setResult(NodeResultInt32);
                node->clearFlags(NodeMustGenerate);
                break;
            }
            
            if (m_graph.unaryArithShouldSpeculateInt52(node, FixupPass)) {
                node->setOp(ArithNegate);
                fixEdge<Int52RepUse>(node->child1());
                if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                    node->setArithMode(Arith::CheckOverflow);
                else
                    node->setArithMode(Arith::CheckOverflowAndNegativeZero);
                node->setResult(NodeResultInt52);
                node->clearFlags(NodeMustGenerate);
                break;
            }
            if (node->child1()->shouldSpeculateNotCell()) {
                node->setOp(ArithNegate);
                fixDoubleOrBooleanEdge(node->child1());
                node->setResult(NodeResultDouble);
                node->clearFlags(NodeMustGenerate);
            } else {
                fixEdge<UntypedUse>(node->child1());
                node->setResult(NodeResultJS);
            }
            break;
        }

        case ValueAdd: {
            if (attemptToMakeIntegerAdd(node)) {
                node->setOp(ArithAdd);
                break;
            }
            if (Node::shouldSpeculateNumberOrBooleanExpectingDefined(node->child1().node(), node->child2().node())) {
                fixDoubleOrBooleanEdge(node->child1());
                fixDoubleOrBooleanEdge(node->child2());
                node->setOp(ArithAdd);
                node->setResult(NodeResultDouble);
                break;
            }
            
            if (attemptToMakeFastStringAdd(node))
                break;

            Edge& child1 = node->child1();
            Edge& child2 = node->child2();
            if (child1->shouldSpeculateString() || child2->shouldSpeculateString()) {
                if (child1->shouldSpeculateInt32() || child2->shouldSpeculateInt32()) {
                    auto convertString = [&](Node* node, Edge& edge) {
                        if (edge->shouldSpeculateInt32())
                            convertStringAddUse<Int32Use>(node, edge);
                        else {
                            ASSERT(edge->shouldSpeculateString());
                            convertStringAddUse<StringUse>(node, edge);
                        }
                    };
                    convertString(node, child1);
                    convertString(node, child2);
                    convertToMakeRope(node);
                    break;
                }
            }

            if (Node::shouldSpeculateBigInt(child1.node(), child2.node())) {
                fixEdge<BigIntUse>(child1);
                fixEdge<BigIntUse>(child2);
            } else {
                fixEdge<UntypedUse>(child1);
                fixEdge<UntypedUse>(child2);
            }

            node->setResult(NodeResultJS);
            break;
        }

        case StrCat: {
            if (attemptToMakeFastStringAdd(node))
                break;

            // FIXME: Remove empty string arguments and possibly turn this into a ToString operation. That
            // would require a form of ToString that takes a KnownPrimitiveUse. This is necessary because
            // the implementation of StrCat doesn't dynamically optimize for empty strings.
            // https://bugs.webkit.org/show_bug.cgi?id=148540
            m_graph.doToChildren(
                node,
                [&] (Edge& edge) {
                    fixEdge<KnownPrimitiveUse>(edge);
                    // StrCat automatically coerces the values into strings before concatenating them.
                    // The ECMA spec says that we're not allowed to automatically coerce a Symbol into
                    // a string. If a Symbol is encountered, a TypeError will be thrown. As a result,
                    // our runtime functions for this slow path expect that they will never be passed
                    // Symbols.
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, Check, node->origin,
                        Edge(edge.node(), NotSymbolUse));
                });
            break;
        }
            
        case MakeRope: {
            fixupMakeRope(node);
            break;
        }
            
        case ArithAdd:
        case ArithSub: {
            // FIXME: Clear ArithSub's NodeMustGenerate when ArithMode is unchecked
            // https://bugs.webkit.org/show_bug.cgi?id=190607
            if (attemptToMakeIntegerAdd(node))
                break;
            fixDoubleOrBooleanEdge(node->child1());
            fixDoubleOrBooleanEdge(node->child2());
            node->setResult(NodeResultDouble);
            break;
        }
            
        case ArithNegate: {
            if (node->child1()->shouldSpeculateInt32OrBoolean() && node->canSpeculateInt32(FixupPass)) {
                fixIntOrBooleanEdge(node->child1());
                if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
                    node->setArithMode(Arith::Unchecked);
                else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                    node->setArithMode(Arith::CheckOverflow);
                else
                    node->setArithMode(Arith::CheckOverflowAndNegativeZero);
                node->setResult(NodeResultInt32);
                node->clearFlags(NodeMustGenerate);
                break;
            }
            if (m_graph.unaryArithShouldSpeculateInt52(node, FixupPass)) {
                fixEdge<Int52RepUse>(node->child1());
                if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                    node->setArithMode(Arith::CheckOverflow);
                else
                    node->setArithMode(Arith::CheckOverflowAndNegativeZero);
                node->setResult(NodeResultInt52);
                node->clearFlags(NodeMustGenerate);
                break;
            }

            fixDoubleOrBooleanEdge(node->child1());
            node->setResult(NodeResultDouble);
            node->clearFlags(NodeMustGenerate);
            break;
        }

        case ValueMul: {
            Edge& leftChild = node->child1();
            Edge& rightChild = node->child2();

            if (Node::shouldSpeculateBigInt(leftChild.node(), rightChild.node())) {
                fixEdge<BigIntUse>(node->child1());
                fixEdge<BigIntUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }

            // There are cases where we can have BigInt + Int32 operands reaching ValueMul.
            // Imagine the scenario where ValueMul was never executed, but we can predict types
            // reaching the node:
            //
            // 63: GetLocal(Check:Untyped:@72, JS|MustGen, NonBoolInt32, ...)  predicting NonBoolInt32
            // 64: GetLocal(Check:Untyped:@71, JS|MustGen, BigInt, ...)  predicting BigInt
            // 65: ValueMul(Check:Untyped:@63, Check:Untyped:@64, BigInt|BoolInt32|NonBoolInt32, ...)
            // 
            // In such scenario, we need to emit ValueMul(Untyped, Untyped), so the runtime can throw 
            // an exception whenever it gets excuted.
            if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) {
                fixEdge<UntypedUse>(leftChild);
                fixEdge<UntypedUse>(rightChild);
                break;
            }

            // At this point, all other possible specializations are only handled by ArithMul.
            node->setOp(ArithMul);
            node->setResult(NodeResultNumber);
            fixupArithMul(node, leftChild, rightChild);
            break;
        }

        case ArithMul: {
            Edge& leftChild = node->child1();
            Edge& rightChild = node->child2();

            fixupArithMul(node, leftChild, rightChild);
            break;
        }

        case ValueMod: 
        case ValueDiv: {
            Edge& leftChild = node->child1();
            Edge& rightChild = node->child2();

            if (Node::shouldSpeculateBigInt(leftChild.node(), rightChild.node())) {
                fixEdge<BigIntUse>(leftChild);
                fixEdge<BigIntUse>(rightChild);
                node->clearFlags(NodeMustGenerate);
                break; 
            }

            if (Node::shouldSpeculateUntypedForArithmetic(leftChild.node(), rightChild.node())) {
                fixEdge<UntypedUse>(leftChild);
                fixEdge<UntypedUse>(rightChild);
                break;
            }

            if (op == ValueDiv)
                node->setOp(ArithDiv);
            else
                node->setOp(ArithMod);

            node->setResult(NodeResultNumber);
            fixupArithDiv(node, leftChild, rightChild);
            break;

        }

        case ArithDiv:
        case ArithMod: {
            Edge& leftChild = node->child1();
            Edge& rightChild = node->child2();

            fixupArithDiv(node, leftChild, rightChild);
            break;
        }
            
        case ArithMin:
        case ArithMax: {
            if (m_graph.binaryArithShouldSpeculateInt32(node, FixupPass)) {
                fixIntOrBooleanEdge(node->child1());
                fixIntOrBooleanEdge(node->child2());
                break;
            }
            fixDoubleOrBooleanEdge(node->child1());
            fixDoubleOrBooleanEdge(node->child2());
            node->setResult(NodeResultDouble);
            break;
        }
            
        case ArithAbs: {
            if (node->child1()->shouldSpeculateInt32OrBoolean()
                && node->canSpeculateInt32(FixupPass)) {
                fixIntOrBooleanEdge(node->child1());
                if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
                    node->setArithMode(Arith::Unchecked);
                else
                    node->setArithMode(Arith::CheckOverflow);
                node->clearFlags(NodeMustGenerate);
                node->setResult(NodeResultInt32);
                break;
            }

            if (node->child1()->shouldSpeculateNotCell()) {
                fixDoubleOrBooleanEdge(node->child1());
                node->clearFlags(NodeMustGenerate);
            } else
                fixEdge<UntypedUse>(node->child1());
            node->setResult(NodeResultDouble);
            break;
        }

        case ValuePow: {
            if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
                fixEdge<BigIntUse>(node->child1());
                fixEdge<BigIntUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }

            if (Node::shouldSpeculateUntypedForArithmetic(node->child1().node(), node->child2().node())) {
                fixEdge<UntypedUse>(node->child1());
                fixEdge<UntypedUse>(node->child2());
                break;
            }

            node->setOp(ArithPow);
            node->clearFlags(NodeMustGenerate);
            node->setResult(NodeResultDouble);

            fixupArithPow(node);
            break;
        }

        case ArithPow: {
            fixupArithPow(node);
            break;
        }

        case ArithRandom: {
            node->setResult(NodeResultDouble);
            break;
        }

        case ArithRound:
        case ArithFloor:
        case ArithCeil:
        case ArithTrunc: {
            if (node->child1()->shouldSpeculateInt32OrBoolean() && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
                fixIntOrBooleanEdge(node->child1());
                insertCheck<Int32Use>(node->child1().node());
                node->convertToIdentity();
                break;
            }
            if (node->child1()->shouldSpeculateNotCell()) {
                fixDoubleOrBooleanEdge(node->child1());

                if (isInt32OrBooleanSpeculation(node->getHeapPrediction()) && m_graph.roundShouldSpeculateInt32(node, FixupPass)) {
                    node->setResult(NodeResultInt32);
                    if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                        node->setArithRoundingMode(Arith::RoundingMode::Int32);
                    else
                        node->setArithRoundingMode(Arith::RoundingMode::Int32WithNegativeZeroCheck);
                } else {
                    node->setResult(NodeResultDouble);
                    node->setArithRoundingMode(Arith::RoundingMode::Double);
                }
                node->clearFlags(NodeMustGenerate);
            } else
                fixEdge<UntypedUse>(node->child1());
            break;
        }

        case ArithFRound:
        case ArithSqrt:
        case ArithUnary: {
            Edge& child1 = node->child1();
            if (child1->shouldSpeculateNotCell()) {
                fixDoubleOrBooleanEdge(child1);
                node->clearFlags(NodeMustGenerate);
            } else
                fixEdge<UntypedUse>(child1);
            break;
        }
            
        case LogicalNot: {
            if (node->child1()->shouldSpeculateBoolean()) {
                if (node->child1()->result() == NodeResultBoolean) {
                    // This is necessary in case we have a bytecode instruction implemented by:
                    //
                    // a: CompareEq(...)
                    // b: LogicalNot(@a)
                    //
                    // In that case, CompareEq might have a side-effect. Then, we need to make
                    // sure that we know that Branch does not exit.
                    fixEdge<KnownBooleanUse>(node->child1());
                } else
                    fixEdge<BooleanUse>(node->child1());
            } else if (node->child1()->shouldSpeculateObjectOrOther())
                fixEdge<ObjectOrOtherUse>(node->child1());
            else if (node->child1()->shouldSpeculateInt32OrBoolean())
                fixIntOrBooleanEdge(node->child1());
            else if (node->child1()->shouldSpeculateNumber())
                fixEdge<DoubleRepUse>(node->child1());
            else if (node->child1()->shouldSpeculateString())
                fixEdge<StringUse>(node->child1());
            else if (node->child1()->shouldSpeculateStringOrOther())
                fixEdge<StringOrOtherUse>(node->child1());
            else {
                WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
                if (masqueradesAsUndefinedWatchpoint->isStillValid())
                    m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
            }
            break;
        }

        case CompareEq:
        case CompareLess:
        case CompareLessEq:
        case CompareGreater:
        case CompareGreaterEq: {
            if (node->op() == CompareEq
                && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
                fixEdge<BooleanUse>(node->child1());
                fixEdge<BooleanUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }
            if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
                fixIntOrBooleanEdge(node->child1());
                fixIntOrBooleanEdge(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }
            if (Node::shouldSpeculateInt52(node->child1().node(), node->child2().node())) {
                fixEdge<Int52RepUse>(node->child1());
                fixEdge<Int52RepUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }
            if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
                fixDoubleOrBooleanEdge(node->child1());
                fixDoubleOrBooleanEdge(node->child2());
            }
            if (node->op() != CompareEq
                && node->child1()->shouldSpeculateNotCell()
                && node->child2()->shouldSpeculateNotCell()) {
                if (node->child1()->shouldSpeculateNumberOrBoolean())
                    fixDoubleOrBooleanEdge(node->child1());
                else
                    fixEdge<DoubleRepUse>(node->child1());
                if (node->child2()->shouldSpeculateNumberOrBoolean())
                    fixDoubleOrBooleanEdge(node->child2());
                else
                    fixEdge<DoubleRepUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }
            if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
                fixEdge<StringIdentUse>(node->child1());
                fixEdge<StringIdentUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }
            if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && GPRInfo::numberOfRegisters >= 7) {
                fixEdge<StringUse>(node->child1());
                fixEdge<StringUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }

            if (node->op() != CompareEq)
                break;
            if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
                fixEdge<SymbolUse>(node->child1());
                fixEdge<SymbolUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }
            if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
                fixEdge<ObjectUse>(node->child1());
                fixEdge<ObjectUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }

            // If either child can be proved to be Null or Undefined, comparing them is greatly simplified.
            bool oneArgumentIsUsedAsSpecOther = false;
            if (node->child1()->isUndefinedOrNullConstant()) {
                fixEdge<KnownOtherUse>(node->child1());
                oneArgumentIsUsedAsSpecOther = true;
            } else if (node->child1()->shouldSpeculateOther()) {
                m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
                    Edge(node->child1().node(), OtherUse));
                fixEdge<KnownOtherUse>(node->child1());
                oneArgumentIsUsedAsSpecOther = true;
            }
            if (node->child2()->isUndefinedOrNullConstant()) {
                fixEdge<KnownOtherUse>(node->child2());
                oneArgumentIsUsedAsSpecOther = true;
            } else if (node->child2()->shouldSpeculateOther()) {
                m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin,
                    Edge(node->child2().node(), OtherUse));
                fixEdge<KnownOtherUse>(node->child2());
                oneArgumentIsUsedAsSpecOther = true;
            }
            if (oneArgumentIsUsedAsSpecOther) {
                node->clearFlags(NodeMustGenerate);
                break;
            }

            if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObjectOrOther()) {
                fixEdge<ObjectUse>(node->child1());
                fixEdge<ObjectOrOtherUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }
            if (node->child1()->shouldSpeculateObjectOrOther() && node->child2()->shouldSpeculateObject()) {
                fixEdge<ObjectOrOtherUse>(node->child1());
                fixEdge<ObjectUse>(node->child2());
                node->clearFlags(NodeMustGenerate);
                break;
            }

            break;
        }
            
        case CompareStrictEq:
        case SameValue: {
            fixupCompareStrictEqAndSameValue(node);
            break;
        }

        case StringFromCharCode:
            if (node->child1()->shouldSpeculateInt32()) {
                fixEdge<Int32Use>(node->child1());
                node->clearFlags(NodeMustGenerate);
            } else
                fixEdge<UntypedUse>(node->child1());
            break;

        case StringCharAt:
        case StringCharCodeAt:
        case StringCodePointAt: {
            // Currently we have no good way of refining these.
            ASSERT(node->arrayMode() == ArrayMode(Array::String, Array::Read));
            blessArrayOperation(node->child1(), node->child2(), node->child3());
            fixEdge<KnownStringUse>(node->child1());
            fixEdge<Int32Use>(node->child2());
            break;
        }

        case GetByVal: {
            if (!node->prediction()) {
                m_insertionSet.insertNode(
                    m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
            }
            
            node->setArrayMode(
                node->arrayMode().refine(
                    m_graph, node,
                    m_graph.varArgChild(node, 0)->prediction(),
                    m_graph.varArgChild(node, 1)->prediction(),
                    SpecNone));
            
            blessArrayOperation(m_graph.varArgChild(node, 0), m_graph.varArgChild(node, 1), m_graph.varArgChild(node, 2));
            
            ArrayMode arrayMode = node->arrayMode();
            switch (arrayMode.type()) {
            case Array::Contiguous:
            case Array::Double:
                if (arrayMode.isJSArrayWithOriginalStructure() && arrayMode.speculation() == Array::InBounds) {
                    // Check if SaneChain will work on a per-type basis. Note that:
                    //
                    // 1) We don't want double arrays to sometimes return undefined, since
                    // that would require a change to the return type and it would pessimise
                    // things a lot. So, we'd only want to do that if we actually had
                    // evidence that we could read from a hole. That's pretty annoying.
                    // Likely the best way to handle that case is with an equivalent of
                    // SaneChain for OutOfBounds. For now we just detect when Undefined and
                    // NaN are indistinguishable according to backwards propagation, and just
                    // use SaneChain in that case. This happens to catch a lot of cases.
                    //
                    // 2) We don't want int32 array loads to have to do a hole check just to
                    // coerce to Undefined, since that would mean twice the checks.
                    //
                    // This has two implications. First, we have to do more checks than we'd
                    // like. It's unfortunate that we have to do the hole check. Second,
                    // some accesses that hit a hole will now need to take the full-blown
                    // out-of-bounds slow path. We can fix that with:
                    // https://bugs.webkit.org/show_bug.cgi?id=144668
                    
                    bool canDoSaneChain = false;
                    switch (arrayMode.type()) {
                    case Array::Contiguous:
                        // This is happens to be entirely natural. We already would have
                        // returned any JSValue, and now we'll return Undefined. We still do
                        // the check but it doesn't require taking any kind of slow path.
                        canDoSaneChain = true;
                        break;
                        
                    case Array::Double:
                        if (!(node->flags() & NodeBytecodeUsesAsOther)) {
                            // Holes look like NaN already, so if the user doesn't care
                            // about the difference between Undefined and NaN then we can
                            // do this.
                            canDoSaneChain = true;
                        }
                        break;
                        
                    default:
                        break;
                    }
                    
                    if (canDoSaneChain) {
                        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
                        Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(vm());
                        Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(vm());
                        if (arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
                            && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
                            && globalObject->arrayPrototypeChainIsSane()) {
                            m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
                            m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
                            node->setArrayMode(arrayMode.withSpeculation(Array::SaneChain));
                        }
                    }
                }
                break;
                
            case Array::String:
                if ((node->prediction() & ~SpecString)
                    || m_graph.hasExitSite(node->origin.semantic, OutOfBounds))
                    node->setArrayMode(arrayMode.withSpeculation(Array::OutOfBounds));
                break;
                
            default:
                break;
            }
            
            arrayMode = node->arrayMode();
            switch (arrayMode.type()) {
            case Array::SelectUsingPredictions:
            case Array::Unprofiled:
                RELEASE_ASSERT_NOT_REACHED();
                break;
            case Array::Generic:
                if (m_graph.varArgChild(node, 0)->shouldSpeculateObject()) {
                    if (m_graph.varArgChild(node, 1)->shouldSpeculateString()) {
                        fixEdge<ObjectUse>(m_graph.varArgChild(node, 0));
                        fixEdge<StringUse>(m_graph.varArgChild(node, 1));
                        break;
                    }

                    if (m_graph.varArgChild(node, 1)->shouldSpeculateSymbol()) {
                        fixEdge<ObjectUse>(m_graph.varArgChild(node, 0));
                        fixEdge<SymbolUse>(m_graph.varArgChild(node, 1));
                        break;
                    }
                }
#if USE(JSVALUE32_64)
                fixEdge<CellUse>(m_graph.varArgChild(node, 0)); // Speculating cell due to register pressure on 32-bit.
#endif
                break;
            case Array::ForceExit:
                break;
            case Array::String:
                fixEdge<KnownStringUse>(m_graph.varArgChild(node, 0));
                fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
                break;
            default:
                fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
                fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
                break;
            }
            
            switch (arrayMode.type()) {
            case Array::Double:
                if (!arrayMode.isOutOfBounds())
                    node->setResult(NodeResultDouble);
                break;
                
            case Array::Float32Array:
            case Array::Float64Array:
                node->setResult(NodeResultDouble);
                break;
                
            case Array::Uint32Array:
                if (node->shouldSpeculateInt32())
                    break;
                if (node->shouldSpeculateInt52())
                    node->setResult(NodeResultInt52);
                else
                    node->setResult(NodeResultDouble);
                break;
                
            default:
                break;
            }
            
            break;
        }

        case PutByValDirect:
        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, node,
                    child1->prediction(),
                    child2->prediction(),
                    child3->prediction()));
            
            blessArrayOperation(child1, child2, m_graph.varArgChild(node, 3));
            
            switch (node->arrayMode().modeForPut().type()) {
            case Array::SelectUsingPredictions:
            case Array::SelectUsingArguments:
            case Array::Unprofiled:
            case Array::Undecided:
                RELEASE_ASSERT_NOT_REACHED();
                break;
            case Array::ForceExit:
            case Array::Generic:
                if (child1->shouldSpeculateCell()) {
                    if (child2->shouldSpeculateString()) {
                        fixEdge<CellUse>(child1);
                        fixEdge<StringUse>(child2);
                        break;
                    }

                    if (child2->shouldSpeculateSymbol()) {
                        fixEdge<CellUse>(child1);
                        fixEdge<SymbolUse>(child2);
                        break;
                    }
                }
#if USE(JSVALUE32_64)
                // Due to register pressure on 32-bit, we speculate cell and
                // ignore the base-is-not-cell case entirely by letting the
                // baseline JIT handle it.
                fixEdge<CellUse>(child1);
#endif
                break;
            case Array::Int32:
                fixEdge<KnownCellUse>(child1);
                fixEdge<Int32Use>(child2);
                fixEdge<Int32Use>(child3);
                break;
            case Array::Double:
                fixEdge<KnownCellUse>(child1);
                fixEdge<Int32Use>(child2);
                fixEdge<DoubleRepRealUse>(child3);
                break;
            case Array::Int8Array:
            case Array::Int16Array:
            case Array::Int32Array:
            case Array::Uint8Array:
            case Array::Uint8ClampedArray:
            case Array::Uint16Array:
            case Array::Uint32Array:
                fixEdge<KnownCellUse>(child1);
                fixEdge<Int32Use>(child2);
                if (child3->shouldSpeculateInt32())
                    fixIntOrBooleanEdge(child3);
                else if (child3->shouldSpeculateInt52())
                    fixEdge<Int52RepUse>(child3);
                else
                    fixDoubleOrBooleanEdge(child3);
                break;
            case Array::Float32Array:
            case Array::Float64Array:
                fixEdge<KnownCellUse>(child1);
                fixEdge<Int32Use>(child2);
                fixDoubleOrBooleanEdge(child3);
                break;
            case Array::Contiguous:
            case Array::ArrayStorage:
            case Array::SlowPutArrayStorage:
                fixEdge<KnownCellUse>(child1);
                fixEdge<Int32Use>(child2);
                speculateForBarrier(child3);
                break;
            default:
                fixEdge<KnownCellUse>(child1);
                fixEdge<Int32Use>(child2);
                break;
            }
            break;
        }
            
        case AtomicsAdd:
        case AtomicsAnd:
        case AtomicsCompareExchange:
        case AtomicsExchange:
        case AtomicsLoad:
        case AtomicsOr:
        case AtomicsStore:
        case AtomicsSub:
        case AtomicsXor: {
            Edge& base = m_graph.child(node, 0);
            Edge& index = m_graph.child(node, 1);
            
            bool badNews = false;
            for (unsigned i = numExtraAtomicsArgs(node->op()); i--;) {
                Edge& child = m_graph.child(node, 2 + i);
                // NOTE: DFG is not smart enough to handle double->int conversions in atomics. So, we
                // just call the function when that happens. But the FTL is totally cool with those
                // conversions.
                if (!child->shouldSpeculateInt32()
                    && !child->shouldSpeculateInt52()
                    && !(child->shouldSpeculateNumberOrBoolean() && m_graph.m_plan.isFTL()))
                    badNews = true;
            }
            
            if (badNews) {
                node->setArrayMode(ArrayMode(Array::Generic, node->arrayMode().action()));
                break;
            }
            
            node->setArrayMode(
                node->arrayMode().refine(
                    m_graph, node, base->prediction(), index->prediction()));
            
            if (node->arrayMode().type() == Array::Generic)
                break;
            
            for (unsigned i = numExtraAtomicsArgs(node->op()); i--;) {
                Edge& child = m_graph.child(node, 2 + i);
                if (child->shouldSpeculateInt32())
                    fixIntOrBooleanEdge(child);
                else if (child->shouldSpeculateInt52())
                    fixEdge<Int52RepUse>(child);
                else {
                    RELEASE_ASSERT(child->shouldSpeculateNumberOrBoolean() && m_graph.m_plan.isFTL());
                    fixDoubleOrBooleanEdge(child);
                }
            }
            
            blessArrayOperation(base, index, m_graph.child(node, 2 + numExtraAtomicsArgs(node->op())));
            fixEdge<CellUse>(base);
            fixEdge<Int32Use>(index);
            
            if (node->arrayMode().type() == Array::Uint32Array) {
                // NOTE: This means basically always doing Int52.
                if (node->shouldSpeculateInt52())
                    node->setResult(NodeResultInt52);
                else
                    node->setResult(NodeResultDouble);
            }
            break;
        }
            
        case AtomicsIsLockFree:
            if (node->child1()->shouldSpeculateInt32())
                fixIntOrBooleanEdge(node->child1());
            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.
            Edge& storageEdge = m_graph.varArgChild(node, 0);
            Edge& arrayEdge = m_graph.varArgChild(node, 1);
            unsigned elementOffset = 2;
            unsigned elementCount = node->numChildren() - elementOffset;
            for (unsigned i = 0; i < elementCount; ++i) {
                Edge& element = m_graph.varArgChild(node, i + elementOffset);
                node->setArrayMode(
                    node->arrayMode().refine(
                        m_graph, node,
                        arrayEdge->prediction() & SpecCell,
                        SpecInt32Only,
                        element->prediction()));
            }
            blessArrayOperation(arrayEdge, Edge(), storageEdge);
            fixEdge<KnownCellUse>(arrayEdge);

            // Convert `array.push()` to GetArrayLength.
            if (!elementCount && node->arrayMode().supportsSelfLength()) {
                node->setOpAndDefaultFlags(GetArrayLength);
                node->child1() = arrayEdge;
                node->child2() = storageEdge;
                fixEdge<KnownCellUse>(node->child1());
                break;
            }

            // We do not want to perform osr exit and retry for ArrayPush. We insert Check with appropriate type,
            // and ArrayPush uses the edge as known typed edge. Therefore, ArrayPush do not need to perform type checks.
            for (unsigned i = 0; i < elementCount; ++i) {
                Edge& element = m_graph.varArgChild(node, i + elementOffset);
                switch (node->arrayMode().type()) {
                case Array::Int32:
                    fixEdge<Int32Use>(element);
                    break;
                case Array::Double:
                    fixEdge<DoubleRepRealUse>(element);
                    break;
                case Array::Contiguous:
                case Array::ArrayStorage:
                    speculateForBarrier(element);
                    break;
                default:
                    break;
                }
            }
            break;
        }
            
        case ArrayPop: {
            blessArrayOperation(node->child1(), Edge(), node->child2());
            fixEdge<KnownCellUse>(node->child1());
            break;
        }

        case ArraySlice: {
            fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0));
            if (node->numChildren() >= 3) {
                fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
                if (node->numChildren() == 4)
                    fixEdge<Int32Use>(m_graph.varArgChild(node, 2));
            }
            break;
        }

        case ArrayIndexOf:
            fixupArrayIndexOf(node);
            break;
            
        case RegExpExec:
        case RegExpTest: {
            fixEdge<KnownCellUse>(node->child1());
            
            if (node->child2()->shouldSpeculateRegExpObject()) {
                fixEdge<RegExpObjectUse>(node->child2());

                if (node->child3()->shouldSpeculateString())
                    fixEdge<StringUse>(node->child3());
            }
            break;
        }

        case RegExpMatchFast: {
            fixEdge<KnownCellUse>(node->child1());
            fixEdge<RegExpObjectUse>(node->child2());
            fixEdge<StringUse>(node->child3());
            break;
        }

        case StringReplace:
        case StringReplaceRegExp: {
            if (node->child2()->shouldSpeculateString()) {
                m_insertionSet.insertNode(
                    m_indexInBlock, SpecNone, Check, node->origin,
                    Edge(node->child2().node(), StringUse));
                fixEdge<StringUse>(node->child2());
            } else if (op == StringReplace) {
                if (node->child2()->shouldSpeculateRegExpObject())
                    addStringReplacePrimordialChecks(node->child2().node());
                else 
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
            }

            if (node->child1()->shouldSpeculateString()
                && node->child2()->shouldSpeculateRegExpObject()
                && node->child3()->shouldSpeculateString()) {

                fixEdge<StringUse>(node->child1());
                fixEdge<RegExpObjectUse>(node->child2());
                fixEdge<StringUse>(node->child3());
                break;
            }
            break;
        }
            
        case Branch: {
            if (node->child1()->shouldSpeculateBoolean()) {
                if (node->child1()->result() == NodeResultBoolean) {
                    // This is necessary in case we have a bytecode instruction implemented by:
                    //
                    // a: CompareEq(...)
                    // b: Branch(@a)
                    //
                    // In that case, CompareEq might have a side-effect. Then, we need to make
                    // sure that we know that Branch does not exit.
                    fixEdge<KnownBooleanUse>(node->child1());
                } else
                    fixEdge<BooleanUse>(node->child1());
            } else if (node->child1()->shouldSpeculateObjectOrOther())
                fixEdge<ObjectOrOtherUse>(node->child1());
            else if (node->child1()->shouldSpeculateInt32OrBoolean())
                fixIntOrBooleanEdge(node->child1());
            else if (node->child1()->shouldSpeculateNumber())
                fixEdge<DoubleRepUse>(node->child1());
            else if (node->child1()->shouldSpeculateString())
                fixEdge<StringUse>(node->child1());
            else if (node->child1()->shouldSpeculateStringOrOther())
                fixEdge<StringOrOtherUse>(node->child1());
            else {
                WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
                if (masqueradesAsUndefinedWatchpoint->isStillValid())
                    m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
            }
            break;
        }
            
        case Switch: {
            SwitchData* data = node->switchData();
            switch (data->kind) {
            case SwitchImm:
                if (node->child1()->shouldSpeculateInt32())
                    fixEdge<Int32Use>(node->child1());
                break;
            case SwitchChar:
                if (node->child1()->shouldSpeculateString())
                    fixEdge<StringUse>(node->child1());
                break;
            case SwitchString:
                if (node->child1()->shouldSpeculateStringIdent())
                    fixEdge<StringIdentUse>(node->child1());
                else if (node->child1()->shouldSpeculateString())
                    fixEdge<StringUse>(node->child1());
                break;
            case SwitchCell:
                if (node->child1()->shouldSpeculateCell())
                    fixEdge<CellUse>(node->child1());
                // else it's fine for this to have UntypedUse; we will handle this by just making
                // non-cells take the default case.
                break;
            }
            break;
        }
            
        case ToPrimitive: {
            fixupToPrimitive(node);
            break;
        }

        case ToNumber: {
            fixupToNumber(node);
            break;
        }
            
        case ToString:
        case CallStringConstructor: {
            fixupToStringOrCallStringConstructor(node);
            break;
        }
            
        case NewStringObject: {
            fixEdge<KnownStringUse>(node->child1());
            break;
        }

        case NewSymbol: {
            if (node->child1())
                fixEdge<KnownStringUse>(node->child1());
            break;
        }

        case NewArrayWithSpread: {
            watchHavingABadTime(node);
            
            BitVector* bitVector = node->bitVector();
            for (unsigned i = node->numChildren(); i--;) {
                if (bitVector->get(i))
                    fixEdge<KnownCellUse>(m_graph.m_varArgChildren[node->firstChild() + i]);
                else
                    fixEdge<UntypedUse>(m_graph.m_varArgChildren[node->firstChild() + i]);
            }

            break;
        }

        case Spread: {
            // Note: We care about performing the protocol on our child's global object, not necessarily ours.
            
            watchHavingABadTime(node->child1().node());

            JSGlobalObject* globalObject = m_graph.globalObjectFor(node->child1()->origin.semantic);
            // When we go down the fast path, we don't consult the prototype chain, so we must prove
            // that it doesn't contain any indexed properties, and that any holes will result in
            // jsUndefined().
            Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(vm());
            Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(vm());
            if (node->child1()->shouldSpeculateArray()
                && arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
                && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
                && globalObject->arrayPrototypeChainIsSane()
                && m_graph.isWatchingArrayIteratorProtocolWatchpoint(node->child1().node())
                && m_graph.isWatchingHavingABadTimeWatchpoint(node->child1().node())) {
                m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
                m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
                fixEdge<ArrayUse>(node->child1());
            } else
                fixEdge<CellUse>(node->child1());
            break;
        }
            
        case NewArray: {
            watchHavingABadTime(node);
            
            for (unsigned i = m_graph.varArgNumChildren(node); i--;) {
                node->setIndexingType(
                    leastUpperBoundOfIndexingTypeAndType(
                        node->indexingType(), m_graph.varArgChild(node, i)->prediction()));
            }
            switch (node->indexingType()) {
            case ALL_BLANK_INDEXING_TYPES:
                CRASH();
                break;
            case ALL_UNDECIDED_INDEXING_TYPES:
                if (node->numChildren()) {
                    // This will only happen if the children have no type predictions. We
                    // would have already exited by now, but insert a forced exit just to
                    // be safe.
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
                }
                break;
            case ALL_INT32_INDEXING_TYPES:
                for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
                    fixEdge<Int32Use>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
                break;
            case ALL_DOUBLE_INDEXING_TYPES:
                for (unsigned operandIndex = 0; operandIndex < node->numChildren(); ++operandIndex)
                    fixEdge<DoubleRepRealUse>(m_graph.m_varArgChildren[node->firstChild() + operandIndex]);
                break;
            case ALL_CONTIGUOUS_INDEXING_TYPES:
            case ALL_ARRAY_STORAGE_INDEXING_TYPES:
                break;
            default:
                CRASH();
                break;
            }
            break;
        }
            
        case NewTypedArray: {
            watchHavingABadTime(node);
            
            if (node->child1()->shouldSpeculateInt32()) {
                fixEdge<Int32Use>(node->child1());
                node->clearFlags(NodeMustGenerate);
                break;
            }
            break;
        }
            
        case NewArrayWithSize: {
            watchHavingABadTime(node);
            fixEdge<Int32Use>(node->child1());
            break;
        }

        case NewArrayBuffer: {
            watchHavingABadTime(node);
            break;
        }

        case ToObject: {
            fixupToObject(node);
            break;
        }

        case CallObjectConstructor: {
            fixupCallObjectConstructor(node);
            break;
        }

        case ToThis: {
            fixupToThis(node);
            break;
        }
            
        case PutStructure: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }
            
        case GetClosureVar:
        case GetFromArguments:
        case GetInternalField: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }

        case PutClosureVar:
        case PutToArguments:
        case PutInternalField: {
            fixEdge<KnownCellUse>(node->child1());
            speculateForBarrier(node->child2());
            break;
        }

        case SkipScope:
        case GetScope:
        case GetGetter:
        case GetSetter:
        case GetGlobalObject: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }
            
        case AllocatePropertyStorage:
        case ReallocatePropertyStorage: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }
            
        case NukeStructureAndSetButterfly: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }

        case TryGetById: {
            if (node->child1()->shouldSpeculateCell())
                fixEdge<CellUse>(node->child1());
            break;
        }

        case GetByIdDirect:
        case GetByIdDirectFlush: {
            if (node->child1()->shouldSpeculateCell())
                fixEdge<CellUse>(node->child1());
            break;
        }

        case GetById:
        case GetByIdFlush: {
            // FIXME: This should be done in the ByteCodeParser based on reading the
            // PolymorphicAccess, which will surely tell us that this is a AccessCase::ArrayLength.
            // https://bugs.webkit.org/show_bug.cgi?id=154990
            auto uid = m_graph.identifiers()[node->identifierNumber()];
            if (node->child1()->shouldSpeculateCellOrOther()
                && !m_graph.hasExitSite(node->origin.semantic, BadType)
                && !m_graph.hasExitSite(node->origin.semantic, BadCache)
                && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
                && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
                
                if (uid == vm().propertyNames->length.impl()) {
                    attemptToMakeGetArrayLength(node);
                    break;
                }

                if (uid == vm().propertyNames->lastIndex.impl()
                    && node->child1()->shouldSpeculateRegExpObject()) {
                    node->setOp(GetRegExpObjectLastIndex);
                    node->clearFlags(NodeMustGenerate);
                    fixEdge<RegExpObjectUse>(node->child1());
                    break;
                }
            }

            if (node->child1()->shouldSpeculateNumber()) {
                if (uid == vm().propertyNames->toString.impl()) {
                    if (m_graph.isWatchingNumberToStringWatchpoint(node)) {
                        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
                        if (node->child1()->shouldSpeculateInt32()) {
                            insertCheck<Int32Use>(node->child1().node());
                            m_graph.convertToConstant(node, m_graph.freeze(globalObject->numberProtoToStringFunction()));
                            break;
                        }

                        if (node->child1()->shouldSpeculateInt52()) {
                            insertCheck<Int52RepUse>(node->child1().node());
                            m_graph.convertToConstant(node, m_graph.freeze(globalObject->numberProtoToStringFunction()));
                            break;
                        }

                        ASSERT(node->child1()->shouldSpeculateNumber());
                        insertCheck<DoubleRepUse>(node->child1().node());
                        m_graph.convertToConstant(node, m_graph.freeze(globalObject->numberProtoToStringFunction()));
                        break;
                    }
                }
            }

            if (node->child1()->shouldSpeculateCell())
                fixEdge<CellUse>(node->child1());
            break;
        }
        
        case GetByIdWithThis: {
            if (node->child1()->shouldSpeculateCell() && node->child2()->shouldSpeculateCell()) {
                fixEdge<CellUse>(node->child1());
                fixEdge<CellUse>(node->child2());
            }
            break;
        }

        case PutById:
        case PutByIdFlush:
        case PutByIdDirect: {
            if (node->child1()->shouldSpeculateCellOrOther()
                && !m_graph.hasExitSite(node->origin.semantic, BadType)
                && !m_graph.hasExitSite(node->origin.semantic, BadCache)
                && !m_graph.hasExitSite(node->origin.semantic, BadIndexingType)
                && !m_graph.hasExitSite(node->origin.semantic, ExoticObjectMode)) {
                
                auto uid = m_graph.identifiers()[node->identifierNumber()];
                
                if (uid == vm().propertyNames->lastIndex.impl()
                    && node->child1()->shouldSpeculateRegExpObject()) {
                    node->convertToSetRegExpObjectLastIndex();
                    fixEdge<RegExpObjectUse>(node->child1());
                    speculateForBarrier(node->child2());
                    break;
                }
            }
            
            fixEdge<CellUse>(node->child1());
            break;
        }

        case PutGetterById:
        case PutSetterById: {
            fixEdge<KnownCellUse>(node->child1());
            fixEdge<KnownCellUse>(node->child2());
            break;
        }

        case PutGetterSetterById: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }

        case PutGetterByVal:
        case PutSetterByVal: {
            fixEdge<KnownCellUse>(node->child1());
            fixEdge<KnownCellUse>(node->child3());
            break;
        }

        case GetExecutable: {
            fixEdge<FunctionUse>(node->child1());
            break;
        }

        case OverridesHasInstance:
        case CheckStructure:
        case CheckCell:
        case CreateThis:
        case CreatePromise:
        case CreateGenerator:
        case CreateAsyncGenerator:
        case GetButterfly: {
            fixEdge<CellUse>(node->child1());
            break;
        }

        case ObjectCreate: {
            if (node->child1()->shouldSpeculateObject()) {
                fixEdge<ObjectUse>(node->child1());
                node->clearFlags(NodeMustGenerate);
                break;
            }
            break;
        }

        case ObjectKeys: {
            if (node->child1()->shouldSpeculateObject()) {
                watchHavingABadTime(node);
                fixEdge<ObjectUse>(node->child1());
            }
            break;
        }

        case CheckStringIdent: {
            fixEdge<StringIdentUse>(node->child1());
            break;
        }
            
        case Arrayify:
        case ArrayifyToStructure: {
            fixEdge<CellUse>(node->child1());
            if (node->child2())
                fixEdge<Int32Use>(node->child2());
            break;
        }
            
        case GetByOffset:
        case GetGetterSetterByOffset: {
            if (!node->child1()->hasStorageResult())
                fixEdge<KnownCellUse>(node->child1());
            fixEdge<KnownCellUse>(node->child2());
            break;
        }
            
        case MultiGetByOffset: {
            fixEdge<CellUse>(node->child1());
            break;
        }
            
        case PutByOffset: {
            if (!node->child1()->hasStorageResult())
                fixEdge<KnownCellUse>(node->child1());
            fixEdge<KnownCellUse>(node->child2());
            speculateForBarrier(node->child3());
            break;
        }
            
        case MultiPutByOffset: {
            fixEdge<CellUse>(node->child1());
            break;
        }
            
        case MatchStructure: {
            // FIXME: Introduce a variant of MatchStructure that doesn't do a cell check.
            // https://bugs.webkit.org/show_bug.cgi?id=185784
            fixEdge<CellUse>(node->child1());
            break;
        }
            
        case InstanceOf: {
            if (node->child1()->shouldSpeculateCell()
                && node->child2()->shouldSpeculateCell()
                && is64Bit()) {
                fixEdge<CellUse>(node->child1());
                fixEdge<CellUse>(node->child2());
                break;
            }
            break;
        }

        case InstanceOfCustom:
            fixEdge<CellUse>(node->child2());
            break;

        case InById: {
            fixEdge<CellUse>(node->child1());
            break;
        }

        case InByVal: {
            if (node->child2()->shouldSpeculateInt32()) {
                convertToHasIndexedProperty(node);
                break;
            }

            fixEdge<CellUse>(node->child1());
            break;
        }

        case HasOwnProperty: {
            fixEdge<ObjectUse>(node->child1());
            if (node->child2()->shouldSpeculateString())
                fixEdge<StringUse>(node->child2());
            else if (node->child2()->shouldSpeculateSymbol())
                fixEdge<SymbolUse>(node->child2());
            else
                fixEdge<UntypedUse>(node->child2());
            break;
        }

        case CheckVarargs:
        case Check: {
            m_graph.doToChildren(
                node,
                [&] (Edge& edge) {
                    switch (edge.useKind()) {
                    case NumberUse:
                        if (edge->shouldSpeculateInt32ForArithmetic())
                            edge.setUseKind(Int32Use);
                        break;
                    default:
                        break;
                    }
                    observeUseKindOnEdge(edge);
                });
            break;
        }

        case Phantom:
            // Phantoms are meaningless past Fixup. We recreate them on-demand in the backend.
            node->remove(m_graph);
            break;

        case FiatInt52: {
            RELEASE_ASSERT(enableInt52());
            node->convertToIdentity();
            fixEdge<Int52RepUse>(node->child1());
            node->setResult(NodeResultInt52);
            break;
        }

        case GetArrayLength: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }

        case GetTypedArrayByteOffset: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }

        case CompareBelow:
        case CompareBelowEq: {
            fixEdge<Int32Use>(node->child1());
            fixEdge<Int32Use>(node->child2());
            break;
        }

        case GetPrototypeOf: {
            fixupGetPrototypeOf(node);
            break;
        }

        case Phi:
        case Upsilon:
        case EntrySwitch:
        case GetIndexedPropertyStorage:
        case LastNodeType:
        case CheckTierUpInLoop:
        case CheckTierUpAtReturn:
        case CheckTierUpAndOSREnter:
        case CheckArray:
        case CheckInBounds:
        case ConstantStoragePointer:
        case DoubleAsInt32:
        case ValueToInt32:
        case DoubleRep:
        case ValueRep:
        case Int52Rep:
        case Int52Constant:
        case Identity: // This should have been cleaned up.
        case BooleanToNumber:
        case PhantomNewObject:
        case PhantomNewFunction:
        case PhantomNewGeneratorFunction:
        case PhantomNewAsyncGeneratorFunction:
        case PhantomNewAsyncFunction:
        case PhantomCreateActivation:
        case PhantomDirectArguments:
        case PhantomCreateRest:
        case PhantomSpread:
        case PhantomNewArrayWithSpread:
        case PhantomNewArrayBuffer:
        case PhantomClonedArguments:
        case PhantomNewRegexp:
        case GetMyArgumentByVal:
        case GetMyArgumentByValOutOfBounds:
        case GetVectorLength:
        case PutHint:
        case CheckStructureImmediate:
        case CheckStructureOrEmpty:
        case MaterializeNewObject:
        case MaterializeCreateActivation:
        case PutStack:
        case KillStack:
        case GetStack:
        case StoreBarrier:
        case FencedStoreBarrier:
        case GetRegExpObjectLastIndex:
        case SetRegExpObjectLastIndex:
        case RecordRegExpCachedResult:
        case RegExpExecNonGlobalOrSticky:
        case RegExpMatchFastGlobal:
            // These are just nodes that we don't currently expect to see during fixup.
            // If we ever wanted to insert them prior to fixup, then we just have to create
            // fixup rules for them.
            DFG_CRASH(m_graph, node, "Unexpected node during fixup");
            break;

        case PutGlobalVariable: {
            fixEdge<CellUse>(node->child1());
            speculateForBarrier(node->child2());
            break;
        }

        case IsObject:
            if (node->child1()->shouldSpeculateObject()) {
                m_insertionSet.insertNode(
                    m_indexInBlock, SpecNone, Check, node->origin,
                    Edge(node->child1().node(), ObjectUse));
                m_graph.convertToConstant(node, jsBoolean(true));
                observeUseKindOnNode<ObjectUse>(node);
            }
            break;

        case IsCellWithType: {
            fixupIsCellWithType(node);
            break;
        }

        case GetEnumerableLength: {
            fixEdge<CellUse>(node->child1());
            break;
        }
        case HasGenericProperty: {
            fixEdge<CellUse>(node->child2());
            break;
        }
        case HasStructureProperty: {
            fixEdge<StringUse>(node->child2());
            fixEdge<KnownCellUse>(node->child3());
            break;
        }
        case HasIndexedProperty: {
            node->setArrayMode(
                node->arrayMode().refine(
                    m_graph, node,
                    m_graph.varArgChild(node, 0)->prediction(),
                    m_graph.varArgChild(node, 1)->prediction(),
                    SpecNone));
            
            blessArrayOperation(m_graph.varArgChild(node, 0), m_graph.varArgChild(node, 1), m_graph.varArgChild(node, 2));
            fixEdge<CellUse>(m_graph.varArgChild(node, 0));
            fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
            break;
        }
        case GetDirectPname: {
            Edge& base = m_graph.varArgChild(node, 0);
            Edge& property = m_graph.varArgChild(node, 1);
            Edge& index = m_graph.varArgChild(node, 2);
            Edge& enumerator = m_graph.varArgChild(node, 3);
            fixEdge<CellUse>(base);
            fixEdge<KnownCellUse>(property);
            fixEdge<Int32Use>(index);
            fixEdge<KnownCellUse>(enumerator);
            break;
        }
        case GetPropertyEnumerator: {
            if (node->child1()->shouldSpeculateCell())
                fixEdge<CellUse>(node->child1());
            break;
        }
        case GetEnumeratorStructurePname: {
            fixEdge<KnownCellUse>(node->child1());
            fixEdge<Int32Use>(node->child2());
            break;
        }
        case GetEnumeratorGenericPname: {
            fixEdge<KnownCellUse>(node->child1());
            fixEdge<Int32Use>(node->child2());
            break;
        }
        case ToIndexString: {
            fixEdge<Int32Use>(node->child1());
            break;
        }
        case ProfileType: {
            // We want to insert type checks based on the instructionTypeSet of the TypeLocation, not the globalTypeSet.
            // Because the instructionTypeSet is contained in globalTypeSet, if we produce a type check for
            // type T for the instructionTypeSet, the global type set must also have information for type T.
            // So if it the type check succeeds for type T in the instructionTypeSet, a type check for type T 
            // in the globalTypeSet would've also succeeded.
            // (The other direction does not hold in general).

            RefPtr<TypeSet> typeSet = node->typeLocation()->m_instructionTypeSet;
            RuntimeTypeMask seenTypes = typeSet->seenTypes();
            if (typeSet->doesTypeConformTo(TypeAnyInt)) {
                if (node->child1()->shouldSpeculateInt32()) {
                    fixEdge<Int32Use>(node->child1());
                    node->remove(m_graph);
                    break;
                }

                if (enableInt52()) {
                    fixEdge<AnyIntUse>(node->child1());
                    node->remove(m_graph);
                    break;
                }

                // Must not perform fixEdge<NumberUse> here since the type set only includes TypeAnyInt. Double values should be logged.
            }

            if (typeSet->doesTypeConformTo(TypeNumber | TypeAnyInt)) {
                fixEdge<NumberUse>(node->child1());
                node->remove(m_graph);
            } else if (typeSet->doesTypeConformTo(TypeString)) {
                fixEdge<StringUse>(node->child1());
                node->remove(m_graph);
            } else if (typeSet->doesTypeConformTo(TypeBoolean)) {
                fixEdge<BooleanUse>(node->child1());
                node->remove(m_graph);
            } else if (typeSet->doesTypeConformTo(TypeUndefined | TypeNull) && (seenTypes & TypeUndefined) && (seenTypes & TypeNull)) {
                fixEdge<OtherUse>(node->child1());
                node->remove(m_graph);
            } else if (typeSet->doesTypeConformTo(TypeObject)) {
                StructureSet set;
                {
                    ConcurrentJSLocker locker(typeSet->m_lock);
                    set = typeSet->structureSet(locker);
                }
                if (!set.isEmpty()) {
                    fixEdge<CellUse>(node->child1());
                    node->convertToCheckStructureOrEmpty(m_graph.addStructureSet(set));
                }
            }

            break;
        }

        case CreateClonedArguments: {
            watchHavingABadTime(node);
            break;
        }

        case CreateScopedArguments:
        case CreateActivation:
        case NewFunction:
        case NewGeneratorFunction:
        case NewAsyncGeneratorFunction:
        case NewAsyncFunction: {
            // Child 1 is always the current scope, which is guaranteed to be an object
            // FIXME: should be KnownObjectUse once that exists (https://bugs.webkit.org/show_bug.cgi?id=175689)
            fixEdge<KnownCellUse>(node->child1());
            break;
        }

        case PushWithScope: {
            // Child 1 is always the current scope, which is guaranteed to be an object
            // FIXME: should be KnownObjectUse once that exists (https://bugs.webkit.org/show_bug.cgi?id=175689)
            fixEdge<KnownCellUse>(node->child1());
            if (node->child2()->shouldSpeculateObject())
                fixEdge<ObjectUse>(node->child2());
            break;
        }

        case SetFunctionName: {
            // The first child is guaranteed to be a cell because op_set_function_name is only used
            // on a newly instantiated function object (the first child).
            fixEdge<KnownCellUse>(node->child1());
            fixEdge<UntypedUse>(node->child2());
            break;
        }

        case CreateRest: {
            watchHavingABadTime(node);
            fixEdge<Int32Use>(node->child1());
            break;
        }

        case ResolveScopeForHoistingFuncDeclInEval: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }
        case ResolveScope:
        case GetDynamicVar:
        case PutDynamicVar: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }

        case LogShadowChickenPrologue: {
            fixEdge<KnownCellUse>(node->child1());
            break;
        }
        case LogShadowChickenTail: {
            fixEdge<UntypedUse>(node->child1());
            fixEdge<KnownCellUse>(node->child2());
            break;
        }

        case GetMapBucket:
            if (node->child1().useKind() == MapObjectUse)
                fixEdge<MapObjectUse>(node->child1());
            else if (node->child1().useKind() == SetObjectUse)
                fixEdge<SetObjectUse>(node->child1());
            else
                RELEASE_ASSERT_NOT_REACHED();

#if USE(JSVALUE64)
            if (node->child2()->shouldSpeculateBoolean())
                fixEdge<BooleanUse>(node->child2());
            else if (node->child2()->shouldSpeculateInt32())
                fixEdge<Int32Use>(node->child2());
            else if (node->child2()->shouldSpeculateSymbol())
                fixEdge<SymbolUse>(node->child2());
            else if (node->child2()->shouldSpeculateObject())
                fixEdge<ObjectUse>(node->child2());
            else if (node->child2()->shouldSpeculateString())
                fixEdge<StringUse>(node->child2());
            else if (node->child2()->shouldSpeculateCell())
                fixEdge<CellUse>(node->child2());
            else
                fixEdge<UntypedUse>(node->child2());
#else
            fixEdge<UntypedUse>(node->child2());
#endif // USE(JSVALUE64)

            fixEdge<Int32Use>(node->child3());
            break;

        case GetMapBucketHead:
            if (node->child1().useKind() == MapObjectUse)
                fixEdge<MapObjectUse>(node->child1());
            else if (node->child1().useKind() == SetObjectUse)
                fixEdge<SetObjectUse>(node->child1());
            else
                RELEASE_ASSERT_NOT_REACHED();
            break;

        case GetMapBucketNext:
        case LoadKeyFromMapBucket:
        case LoadValueFromMapBucket:
            fixEdge<CellUse>(node->child1());
            break;

        case MapHash: {
#if USE(JSVALUE64)
            if (node->child1()->shouldSpeculateBoolean()) {
                fixEdge<BooleanUse>(node->child1());
                break;
            }

            if (node->child1()->shouldSpeculateInt32()) {
                fixEdge<Int32Use>(node->child1());
                break;
            }

            if (node->child1()->shouldSpeculateSymbol()) {
                fixEdge<SymbolUse>(node->child1());
                break;
            }

            if (node->child1()->shouldSpeculateObject()) {
                fixEdge<ObjectUse>(node->child1());
                break;
            }

            if (node->child1()->shouldSpeculateString()) {
                fixEdge<StringUse>(node->child1());
                break;
            }

            if (node->child1()->shouldSpeculateCell()) {
                fixEdge<CellUse>(node->child1());
                break;
            }

            fixEdge<UntypedUse>(node->child1());
#else
            fixEdge<UntypedUse>(node->child1());
#endif // USE(JSVALUE64)
            break;
        }

        case NormalizeMapKey: {
            fixupNormalizeMapKey(node);
            break;
        }

        case WeakMapGet: {
            if (node->child1().useKind() == WeakMapObjectUse)
                fixEdge<WeakMapObjectUse>(node->child1());
            else if (node->child1().useKind() == WeakSetObjectUse)
                fixEdge<WeakSetObjectUse>(node->child1());
            else
                RELEASE_ASSERT_NOT_REACHED();
            fixEdge<ObjectUse>(node->child2());
            fixEdge<Int32Use>(node->child3());
            break;
        }

        case SetAdd: {
            fixEdge<SetObjectUse>(node->child1());
            fixEdge<Int32Use>(node->child3());
            break;
        }

        case MapSet: {
            fixEdge<MapObjectUse>(m_graph.varArgChild(node, 0));
            fixEdge<Int32Use>(m_graph.varArgChild(node, 3));
            break;
        }

        case WeakSetAdd: {
            fixEdge<WeakSetObjectUse>(node->child1());
            fixEdge<ObjectUse>(node->child2());
            fixEdge<Int32Use>(node->child3());
            break;
        }

        case WeakMapSet: {
            fixEdge<WeakMapObjectUse>(m_graph.varArgChild(node, 0));
            fixEdge<ObjectUse>(m_graph.varArgChild(node, 1));
            fixEdge<Int32Use>(m_graph.varArgChild(node, 3));
            break;
        }

        case DefineDataProperty: {
            fixEdge<CellUse>(m_graph.varArgChild(node, 0));
            Edge& propertyEdge = m_graph.varArgChild(node, 1);
            if (propertyEdge->shouldSpeculateSymbol())
                fixEdge<SymbolUse>(propertyEdge);
            else if (propertyEdge->shouldSpeculateStringIdent())
                fixEdge<StringIdentUse>(propertyEdge);
            else if (propertyEdge->shouldSpeculateString())
                fixEdge<StringUse>(propertyEdge);
            else
                fixEdge<UntypedUse>(propertyEdge);
            fixEdge<UntypedUse>(m_graph.varArgChild(node, 2));
            fixEdge<Int32Use>(m_graph.varArgChild(node, 3));
            break;
        }

        case StringValueOf: {
            fixupStringValueOf(node);
            break;
        }

        case StringSlice: {
            fixEdge<StringUse>(node->child1());
            fixEdge<Int32Use>(node->child2());
            if (node->child3())
                fixEdge<Int32Use>(node->child3());
            break;
        }

        case ToLowerCase: {
            // We currently only support StringUse since that will ensure that
            // ToLowerCase is a pure operation. If we decide to update this with
            // more types in the future, we need to ensure that the clobberize rules
            // are correct.
            fixEdge<StringUse>(node->child1());
            break;
        }

        case NumberToStringWithRadix: {
            if (node->child1()->shouldSpeculateInt32())
                fixEdge<Int32Use>(node->child1());
            else if (node->child1()->shouldSpeculateInt52())
                fixEdge<Int52RepUse>(node->child1());
            else
                fixEdge<DoubleRepUse>(node->child1());
            fixEdge<Int32Use>(node->child2());
            break;
        }

        case DefineAccessorProperty: {
            fixEdge<CellUse>(m_graph.varArgChild(node, 0));
            Edge& propertyEdge = m_graph.varArgChild(node, 1);
            if (propertyEdge->shouldSpeculateSymbol())
                fixEdge<SymbolUse>(propertyEdge);
            else if (propertyEdge->shouldSpeculateStringIdent())
                fixEdge<StringIdentUse>(propertyEdge);
            else if (propertyEdge->shouldSpeculateString())
                fixEdge<StringUse>(propertyEdge);
            else
                fixEdge<UntypedUse>(propertyEdge);
            fixEdge<CellUse>(m_graph.varArgChild(node, 2));
            fixEdge<CellUse>(m_graph.varArgChild(node, 3));
            fixEdge<Int32Use>(m_graph.varArgChild(node, 4));
            break;
        }

        case CheckSubClass: {
            fixupCheckSubClass(node);
            break;
        }

        case CallDOMGetter: {
            DOMJIT::CallDOMGetterSnippet* snippet = node->callDOMGetterData()->snippet;
            fixEdge<CellUse>(node->child1()); // DOM.
            if (snippet && snippet->requireGlobalObject)
                fixEdge<KnownCellUse>(node->child2()); // GlobalObject.
            break;
        }

        case CallDOM: {
            fixupCallDOM(node);
            break;
        }

        case Call: {
            attemptToMakeCallDOM(node);
            break;
        }

        case ParseInt: {
            if (node->child1()->shouldSpeculateInt32() && !node->child2()) {
                fixEdge<Int32Use>(node->child1());
                node->convertToIdentity();
                break;
            }

            if (node->child1()->shouldSpeculateString()) {
                fixEdge<StringUse>(node->child1());
                node->clearFlags(NodeMustGenerate);
            }

            if (node->child2())
                fixEdge<Int32Use>(node->child2());

            break;
        }

        case IdentityWithProfile: {
            node->clearFlags(NodeMustGenerate);
            break;
        }

        case ThrowStaticError:
            fixEdge<StringUse>(node->child1());
            break;

        case NumberIsInteger:
            if (node->child1()->shouldSpeculateInt32()) {
                m_insertionSet.insertNode(
                    m_indexInBlock, SpecNone, Check, node->origin,
                    Edge(node->child1().node(), Int32Use));
                m_graph.convertToConstant(node, jsBoolean(true));
                break;
            }
            break;

        case SetCallee:
            fixEdge<CellUse>(node->child1());
            break;

        case DataViewGetInt:
        case DataViewGetFloat: {
            fixEdge<DataViewObjectUse>(node->child1());
            fixEdge<Int32Use>(node->child2());
            if (node->child3())
                fixEdge<BooleanUse>(node->child3());

            if (node->op() == DataViewGetInt) {
                DataViewData data = node->dataViewData();
                switch (data.byteSize) {
                case 1:
                case 2:
                    node->setResult(NodeResultInt32);
                    break;
                case 4:
                    if (data.isSigned)
                        node->setResult(NodeResultInt32);
                    else
                        node->setResult(NodeResultInt52);
                    break;
                default:
                    RELEASE_ASSERT_NOT_REACHED();
                }
            }
            break;
        }

        case DataViewSet: {
            fixEdge<DataViewObjectUse>(m_graph.varArgChild(node, 0));
            fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
            if (m_graph.varArgChild(node, 3))
                fixEdge<BooleanUse>(m_graph.varArgChild(node, 3));
            
            DataViewData data = node->dataViewData();
            Edge& valueToStore = m_graph.varArgChild(node, 2);
            if (data.isFloatingPoint)
                fixEdge<DoubleRepUse>(valueToStore);
            else {
                switch (data.byteSize) {
                case 1:
                case 2:
                    fixEdge<Int32Use>(valueToStore);
                    break;
                case 4:
                    if (data.isSigned)
                        fixEdge<Int32Use>(valueToStore);
                    else
                        fixEdge<Int52RepUse>(valueToStore);
                    break;
                }
            }
            break;
        }

#if !ASSERT_DISABLED
        // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
        case SetArgumentDefinitely:
        case SetArgumentMaybe:
        case JSConstant:
        case LazyJSConstant:
        case DoubleConstant:
        case GetLocal:
        case GetCallee:
        case GetArgumentCountIncludingThis:
        case SetArgumentCountIncludingThis:
        case GetRestLength:
        case GetArgument:
        case Flush:
        case PhantomLocal:
        case GetGlobalVar:
        case GetGlobalLexicalVariable:
        case NotifyWrite:
        case DirectCall:
        case CheckTypeInfoFlags:
        case TailCallInlinedCaller:
        case DirectTailCallInlinedCaller:
        case Construct:
        case DirectConstruct:
        case CallVarargs:
        case CallEval:
        case TailCallVarargsInlinedCaller:
        case ConstructVarargs:
        case CallForwardVarargs:
        case ConstructForwardVarargs:
        case TailCallForwardVarargs:
        case TailCallForwardVarargsInlinedCaller:
        case LoadVarargs:
        case ForwardVarargs:
        case ProfileControlFlow:
        case NewObject:
        case NewPromise:
        case NewGenerator:
        case NewAsyncGenerator:
        case NewRegexp:
        case DeleteById:
        case DeleteByVal:
        case IsTypedArrayView:
        case IsEmpty:
        case IsUndefined:
        case IsUndefinedOrNull:
        case IsBoolean:
        case IsNumber:
        case IsObjectOrNull:
        case IsFunction:
        case CreateDirectArguments:
        case Jump:
        case Return:
        case TailCall:
        case DirectTailCall:
        case TailCallVarargs:
        case Throw:
        case CountExecution:
        case SuperSamplerBegin:
        case SuperSamplerEnd:
        case ForceOSRExit:
        case CheckBadCell:
        case CheckNotEmpty:
        case AssertNotEmpty:
        case CheckTraps:
        case Unreachable:
        case ExtractOSREntryLocal:
        case ExtractCatchLocal:
        case ClearCatchLocals:
        case LoopHint:
        case MovHint:
        case InitializeEntrypointArguments:
        case ZombieHint:
        case ExitOK:
        case BottomValue:
        case TypeOf:
        case PutByIdWithThis:
        case PutByValWithThis:
        case GetByValWithThis:
        case CompareEqPtr:
        case NumberToStringWithValidRadixConstant:
        case GetGlobalThis:
        case ExtractValueFromWeakMapGet:
        case CPUIntrinsic:
        case FilterCallLinkStatus:
        case FilterGetByIdStatus:
        case FilterPutByIdStatus:
        case FilterInByIdStatus:
        case InvalidationPoint:
            break;
#else
        default:
            break;
#endif
        }
    }

    void watchHavingABadTime(Node* node)
    {
        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);

        // If this global object is not having a bad time, watch it. We go down this path anytime the code
        // does an array allocation. The types of array allocations may change if we start to have a bad
        // time. It's easier to reason about this if we know that whenever the types change after we start
        // optimizing, the code just gets thrown out. Doing this at FixupPhase is just early enough, since
        // prior to this point nobody should have been doing optimizations based on the indexing type of
        // the allocation.
        if (!globalObject->isHavingABadTime()) {
            m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
            m_graph.freeze(globalObject);
        }
    }
    
    template<UseKind useKind>
    void createToString(Node* node, Edge& edge)
    {
        Node* toString = m_insertionSet.insertNode(
            m_indexInBlock, SpecString, ToString, node->origin,
            Edge(edge.node(), useKind));
        switch (useKind) {
        case Int32Use:
        case Int52RepUse:
        case DoubleRepUse:
        case NotCellUse:
            toString->clearFlags(NodeMustGenerate);
            break;
        default:
            break;
        }
        edge.setNode(toString);
    }
    
    template<UseKind useKind>
    void attemptToForceStringArrayModeByToStringConversion(ArrayMode& arrayMode, Node* node)
    {
        ASSERT(arrayMode == ArrayMode(Array::Generic, Array::Read) || arrayMode == ArrayMode(Array::Generic, Array::OriginalNonArray, Array::Read));
        
        if (!m_graph.canOptimizeStringObjectAccess(node->origin.semantic))
            return;
        
        addCheckStructureForOriginalStringObjectUse(useKind, node->origin, node->child1().node());
        createToString<useKind>(node, node->child1());
        arrayMode = ArrayMode(Array::String, Array::Read);
    }

    void addCheckStructureForOriginalStringObjectUse(UseKind useKind, const NodeOrigin& origin, Node* node)
    {
        RELEASE_ASSERT(useKind == StringObjectUse || useKind == StringOrStringObjectUse);

        StructureSet set;
        set.add(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
        if (useKind == StringOrStringObjectUse)
            set.add(vm().stringStructure.get());

        m_insertionSet.insertNode(
            m_indexInBlock, SpecNone, CheckStructure, origin,
            OpInfo(m_graph.addStructureSet(set)), Edge(node, CellUse));
    }
    
    template<UseKind useKind>
    void convertStringAddUse(Node* node, Edge& edge)
    {
        if (useKind == StringUse) {
            observeUseKindOnNode<StringUse>(edge.node());
            m_insertionSet.insertNode(
                m_indexInBlock, SpecNone, Check, node->origin,
                Edge(edge.node(), StringUse));
            edge.setUseKind(KnownStringUse);
            return;
        }
        
        observeUseKindOnNode<useKind>(edge.node());
        createToString<useKind>(node, edge);
    }
    
    void convertToMakeRope(Node* node)
    {
        node->setOpAndDefaultFlags(MakeRope);
        fixupMakeRope(node);
    }
    
    void fixupMakeRope(Node* node)
    {
        for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
            Edge& edge = node->children.child(i);
            if (!edge)
                break;
            edge.setUseKind(KnownStringUse);
            JSString* string = edge->dynamicCastConstant<JSString*>(vm());
            if (!string)
                continue;
            if (string->length())
                continue;
            
            // Don't allow the MakeRope to have zero children.
            if (!i && !node->child2())
                break;
            
            node->children.removeEdge(i--);
        }
        
        if (!node->child2()) {
            ASSERT(!node->child3());
            node->convertToIdentity();
        }
    }

    void fixupIsCellWithType(Node* node)
    {
        Optional<SpeculatedType> filter = node->speculatedTypeForQuery();
        if (filter) {
            switch (filter.value()) {
            case SpecString:
                if (node->child1()->shouldSpeculateString()) {
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, Check, node->origin,
                        Edge(node->child1().node(), StringUse));
                    m_graph.convertToConstant(node, jsBoolean(true));
                    observeUseKindOnNode<StringUse>(node);
                    return;
                }
                break;

            case SpecProxyObject:
                if (node->child1()->shouldSpeculateProxyObject()) {
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, Check, node->origin,
                        Edge(node->child1().node(), ProxyObjectUse));
                    m_graph.convertToConstant(node, jsBoolean(true));
                    observeUseKindOnNode<ProxyObjectUse>(node);
                    return;
                }
                break;

            case SpecRegExpObject:
                if (node->child1()->shouldSpeculateRegExpObject()) {
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, Check, node->origin,
                        Edge(node->child1().node(), RegExpObjectUse));
                    m_graph.convertToConstant(node, jsBoolean(true));
                    observeUseKindOnNode<RegExpObjectUse>(node);
                    return;
                }
                break;

            case SpecArray:
                if (node->child1()->shouldSpeculateArray()) {
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, Check, node->origin,
                        Edge(node->child1().node(), ArrayUse));
                    m_graph.convertToConstant(node, jsBoolean(true));
                    observeUseKindOnNode<ArrayUse>(node);
                    return;
                }
                break;

            case SpecDerivedArray:
                if (node->child1()->shouldSpeculateDerivedArray()) {
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, Check, node->origin,
                        Edge(node->child1().node(), DerivedArrayUse));
                    m_graph.convertToConstant(node, jsBoolean(true));
                    observeUseKindOnNode<DerivedArrayUse>(node);
                    return;
                }
                break;
            }
        }

        if (node->child1()->shouldSpeculateCell()) {
            fixEdge<CellUse>(node->child1());
            return;
        }

        if (node->child1()->shouldSpeculateNotCell()) {
            m_insertionSet.insertNode(
                m_indexInBlock, SpecNone, Check, node->origin,
                Edge(node->child1().node(), NotCellUse));
            m_graph.convertToConstant(node, jsBoolean(false));
            observeUseKindOnNode<NotCellUse>(node);
            return;
        }
    }

    void fixupGetPrototypeOf(Node* node)
    {
        // Reflect.getPrototypeOf only accepts Objects. For Reflect.getPrototypeOf, ByteCodeParser attaches ObjectUse edge filter before fixup phase.
        if (node->child1().useKind() != ObjectUse) {
            if (node->child1()->shouldSpeculateString()) {
                insertCheck<StringUse>(node->child1().node());
                m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->stringPrototype()));
                return;
            }
            if (node->child1()->shouldSpeculateInt32()) {
                insertCheck<Int32Use>(node->child1().node());
                m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->numberPrototype()));
                return;
            }
            if (node->child1()->shouldSpeculateInt52()) {
                insertCheck<Int52RepUse>(node->child1().node());
                m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->numberPrototype()));
                return;
            }
            if (node->child1()->shouldSpeculateNumber()) {
                insertCheck<NumberUse>(node->child1().node());
                m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->numberPrototype()));
                return;
            }
            if (node->child1()->shouldSpeculateSymbol()) {
                insertCheck<SymbolUse>(node->child1().node());
                m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->symbolPrototype()));
                return;
            }
            if (node->child1()->shouldSpeculateBoolean()) {
                insertCheck<BooleanUse>(node->child1().node());
                m_graph.convertToConstant(node, m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic)->booleanPrototype()));
                return;
            }
        }

        if (node->child1()->shouldSpeculateFinalObject()) {
            fixEdge<FinalObjectUse>(node->child1());
            node->clearFlags(NodeMustGenerate);
            return;
        }
        if (node->child1()->shouldSpeculateArray()) {
            fixEdge<ArrayUse>(node->child1());
            node->clearFlags(NodeMustGenerate);
            return;
        }
        if (node->child1()->shouldSpeculateFunction()) {
            fixEdge<FunctionUse>(node->child1());
            node->clearFlags(NodeMustGenerate);
            return;
        }
    }

    void fixupToThis(Node* node)
    {
        bool isStrictMode = m_graph.isStrictModeFor(node->origin.semantic);

        if (isStrictMode) {
            if (node->child1()->shouldSpeculateBoolean()) {
                fixEdge<BooleanUse>(node->child1());
                node->convertToIdentity();
                return;
            }

            if (node->child1()->shouldSpeculateInt32()) {
                fixEdge<Int32Use>(node->child1());
                node->convertToIdentity();
                return;
            }

            if (node->child1()->shouldSpeculateInt52()) {
                fixEdge<Int52RepUse>(node->child1());
                node->convertToIdentity();
                node->setResult(NodeResultInt52);
                return;
            }

            if (node->child1()->shouldSpeculateNumber()) {
                fixEdge<DoubleRepUse>(node->child1());
                node->convertToIdentity();
                node->setResult(NodeResultDouble);
                return;
            }

            if (node->child1()->shouldSpeculateSymbol()) {
                fixEdge<SymbolUse>(node->child1());
                node->convertToIdentity();
                return;
            }

            if (node->child1()->shouldSpeculateStringIdent()) {
                fixEdge<StringIdentUse>(node->child1());
                node->convertToIdentity();
                return;
            }

            if (node->child1()->shouldSpeculateString()) {
                fixEdge<StringUse>(node->child1());
                node->convertToIdentity();
                return;
            }
            
            if (node->child1()->shouldSpeculateBigInt()) {
                fixEdge<BigIntUse>(node->child1());
                node->convertToIdentity();
                return;
            }
        }

        if (node->child1()->shouldSpeculateOther()) {
            if (isStrictMode) {
                fixEdge<OtherUse>(node->child1());
                node->convertToIdentity();
                return;
            }

            m_insertionSet.insertNode(
                m_indexInBlock, SpecNone, Check, node->origin,
                Edge(node->child1().node(), OtherUse));
            observeUseKindOnNode<OtherUse>(node->child1().node());
            m_graph.convertToConstant(
                node, m_graph.globalThisObjectFor(node->origin.semantic));
            return;
        }

        // FIXME: This should cover other use cases but we don't have use kinds for them. It's not critical,
        // however, since we cover all the missing cases in constant folding.
        // https://bugs.webkit.org/show_bug.cgi?id=157213
        if (node->child1()->shouldSpeculateStringObject()) {
            fixEdge<StringObjectUse>(node->child1());
            node->convertToIdentity();
            return;
        }

        if (isFinalObjectSpeculation(node->child1()->prediction())) {
            fixEdge<FinalObjectUse>(node->child1());
            node->convertToIdentity();
            return;
        }
    }
    
    void fixupToPrimitive(Node* node)
    {
        if (node->child1()->shouldSpeculateInt32()) {
            fixEdge<Int32Use>(node->child1());
            node->convertToIdentity();
            return;
        }
        
        if (node->child1()->shouldSpeculateString()) {
            fixEdge<StringUse>(node->child1());
            node->convertToIdentity();
            return;
        }
        
        if (node->child1()->shouldSpeculateStringObject()
            && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
            addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, node->child1().node());
            fixEdge<StringObjectUse>(node->child1());
            node->convertToToString();
            return;
        }
        
        if (node->child1()->shouldSpeculateStringOrStringObject()
            && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
            addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, node->child1().node());
            fixEdge<StringOrStringObjectUse>(node->child1());
            node->convertToToString();
            return;
        }
    }

    void fixupToNumber(Node* node)
    {
        // At first, attempt to fold Boolean or Int32 to Int32.
        if (node->child1()->shouldSpeculateInt32OrBoolean()) {
            if (isInt32Speculation(node->getHeapPrediction())) {
                fixIntOrBooleanEdge(node->child1());
                node->convertToIdentity();
                return;
            }
        }

        // If the prediction of the child is Number, we attempt to convert ToNumber to Identity.
        if (node->child1()->shouldSpeculateNumber()) {
            if (isInt32Speculation(node->getHeapPrediction())) {
                // If the both predictions of this node and the child is Int32, we just convert ToNumber to Identity, that's simple.
                if (node->child1()->shouldSpeculateInt32()) {
                    fixEdge<Int32Use>(node->child1());
                    node->convertToIdentity();
                    return;
                }

                // The another case is that the predicted type of the child is Int32, but the heap prediction tell the users that this will produce non Int32 values.
                // In that case, let's receive the child value as a Double value and convert it to Int32. This case happens in misc-bugs-847389-jpeg2000.
                fixEdge<DoubleRepUse>(node->child1());
                node->setOp(DoubleAsInt32);
                if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
                    node->setArithMode(Arith::CheckOverflow);
                else
                    node->setArithMode(Arith::CheckOverflowAndNegativeZero);
                return;
            }

            fixEdge<DoubleRepUse>(node->child1());
            node->convertToIdentity();
            node->setResult(NodeResultDouble);
            return;
        }

        fixEdge<UntypedUse>(node->child1());
        node->setResult(NodeResultJS);
    }

    void fixupToObject(Node* node)
    {
        if (node->child1()->shouldSpeculateObject()) {
            fixEdge<ObjectUse>(node->child1());
            node->convertToIdentity();
            return;
        }

        // ToObject(Null/Undefined) can throw an error. We can emit filters to convert ToObject to CallObjectConstructor.

        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);

        if (node->child1()->shouldSpeculateString()) {
            insertCheck<StringUse>(node->child1().node());
            fixEdge<KnownStringUse>(node->child1());
            node->convertToNewStringObject(m_graph.registerStructure(globalObject->stringObjectStructure()));
            return;
        }

        if (node->child1()->shouldSpeculateSymbol()) {
            insertCheck<SymbolUse>(node->child1().node());
            node->convertToCallObjectConstructor(m_graph.freeze(globalObject));
            return;
        }

        if (node->child1()->shouldSpeculateNumber()) {
            insertCheck<NumberUse>(node->child1().node());
            node->convertToCallObjectConstructor(m_graph.freeze(globalObject));
            return;
        }

        if (node->child1()->shouldSpeculateBoolean()) {
            insertCheck<BooleanUse>(node->child1().node());
            node->convertToCallObjectConstructor(m_graph.freeze(globalObject));
            return;
        }

        fixEdge<UntypedUse>(node->child1());
    }

    void fixupCallObjectConstructor(Node* node)
    {
        if (node->child1()->shouldSpeculateObject()) {
            fixEdge<ObjectUse>(node->child1());
            node->convertToIdentity();
            return;
        }

        if (node->child1()->shouldSpeculateString()) {
            auto* globalObject = jsCast<JSGlobalObject*>(node->cellOperand()->cell());
            insertCheck<StringUse>(node->child1().node());
            fixEdge<KnownStringUse>(node->child1());
            node->convertToNewStringObject(m_graph.registerStructure(globalObject->stringObjectStructure()));
            return;
        }

        // While ToObject(Null/Undefined) throws an error, CallObjectConstructor(Null/Undefined) generates a new empty object.
        if (node->child1()->shouldSpeculateOther()) {
            insertCheck<OtherUse>(node->child1().node());
            node->convertToNewObject(m_graph.registerStructure(jsCast<JSGlobalObject*>(node->cellOperand()->cell())->objectStructureForObjectConstructor()));
            return;
        }

        fixEdge<UntypedUse>(node->child1());
    }
    
    void fixupToStringOrCallStringConstructor(Node* node)
    {
        if (node->child1()->shouldSpeculateString()) {
            fixEdge<StringUse>(node->child1());
            node->convertToIdentity();
            return;
        }
        
        if (node->child1()->shouldSpeculateStringObject()
            && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
            addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, node->child1().node());
            fixEdge<StringObjectUse>(node->child1());
            return;
        }
        
        if (node->child1()->shouldSpeculateStringOrStringObject()
            && m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
            addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, node->child1().node());
            fixEdge<StringOrStringObjectUse>(node->child1());
            return;
        }
        
        if (node->child1()->shouldSpeculateCell()) {
            fixEdge<CellUse>(node->child1());
            return;
        }

        if (node->child1()->shouldSpeculateInt32()) {
            fixEdge<Int32Use>(node->child1());
            node->clearFlags(NodeMustGenerate);
            return;
        }

        if (node->child1()->shouldSpeculateInt52()) {
            fixEdge<Int52RepUse>(node->child1());
            node->clearFlags(NodeMustGenerate);
            return;
        }

        if (node->child1()->shouldSpeculateNumber()) {
            fixEdge<DoubleRepUse>(node->child1());
            node->clearFlags(NodeMustGenerate);
            return;
        }

        // ToString(Symbol) throws an error. So if the child1 can include Symbols,
        // we need to care about it in the clobberize. In the following case,
        // since NotCellUse edge filter is used and this edge filters Symbols,
        // we can say that ToString never throws an error!
        if (node->child1()->shouldSpeculateNotCell()) {
            fixEdge<NotCellUse>(node->child1());
            node->clearFlags(NodeMustGenerate);
            return;
        }
    }

    void fixupStringValueOf(Node* node)
    {
        if (node->child1()->shouldSpeculateString()) {
            fixEdge<StringUse>(node->child1());
            node->convertToIdentity();
            return;
        }

        if (node->child1()->shouldSpeculateStringObject()) {
            fixEdge<StringObjectUse>(node->child1());
            node->convertToToString();
            // It does not need to look up a toString property for the StringObject case. So we can clear NodeMustGenerate.
            node->clearFlags(NodeMustGenerate);
            return;
        }

        if (node->child1()->shouldSpeculateStringOrStringObject()) {
            fixEdge<StringOrStringObjectUse>(node->child1());
            node->convertToToString();
            // It does not need to look up a toString property for the StringObject case. So we can clear NodeMustGenerate.
            node->clearFlags(NodeMustGenerate);
            return;
        }
    }

    bool attemptToMakeFastStringAdd(Node* node)
    {
        bool goodToGo = true;
        m_graph.doToChildren(
            node,
            [&] (Edge& edge) {
                if (edge->shouldSpeculateString())
                    return;
                if (m_graph.canOptimizeStringObjectAccess(node->origin.semantic)) {
                    if (edge->shouldSpeculateStringObject())
                        return;
                    if (edge->shouldSpeculateStringOrStringObject())
                        return;
                }
                goodToGo = false;
            });
        if (!goodToGo)
            return false;

        m_graph.doToChildren(
            node,
            [&] (Edge& edge) {
                if (edge->shouldSpeculateString()) {
                    convertStringAddUse<StringUse>(node, edge);
                    return;
                }
                if (!Options::useConcurrentJIT())
                    ASSERT(m_graph.canOptimizeStringObjectAccess(node->origin.semantic));
                if (edge->shouldSpeculateStringObject()) {
                    addCheckStructureForOriginalStringObjectUse(StringObjectUse, node->origin, edge.node());
                    convertStringAddUse<StringObjectUse>(node, edge);
                    return;
                }
                if (edge->shouldSpeculateStringOrStringObject()) {
                    addCheckStructureForOriginalStringObjectUse(StringOrStringObjectUse, node->origin, edge.node());
                    convertStringAddUse<StringOrStringObjectUse>(node, edge);
                    return;
                }
                RELEASE_ASSERT_NOT_REACHED();
            });
        
        convertToMakeRope(node);
        return true;
    }

    void fixupGetAndSetLocalsInBlock(BasicBlock* block)
    {
        if (!block)
            return;
        ASSERT(block->isReachable);
        m_block = block;
        for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
            Node* node = m_currentNode = block->at(m_indexInBlock);
            if (node->op() != SetLocal && node->op() != GetLocal)
                continue;
            
            VariableAccessData* variable = node->variableAccessData();
            switch (node->op()) {
            case GetLocal:
                switch (variable->flushFormat()) {
                case FlushedDouble:
                    node->setResult(NodeResultDouble);
                    break;
                case FlushedInt52:
                    node->setResult(NodeResultInt52);
                    break;
                default:
                    break;
                }
                break;
                
            case SetLocal:
                // NOTE: Any type checks we put here may get hoisted by fixupChecksInBlock(). So, if we
                // add new type checking use kind for SetLocals, we need to modify that code as well.
                
                switch (variable->flushFormat()) {
                case FlushedJSValue:
                    break;
                case FlushedDouble:
                    fixEdge<DoubleRepUse>(node->child1());
                    break;
                case FlushedInt32:
                    fixEdge<Int32Use>(node->child1());
                    break;
                case FlushedInt52:
                    fixEdge<Int52RepUse>(node->child1());
                    break;
                case FlushedCell:
                    fixEdge<CellUse>(node->child1());
                    break;
                case FlushedBoolean:
                    fixEdge<BooleanUse>(node->child1());
                    break;
                default:
                    RELEASE_ASSERT_NOT_REACHED();
                    break;
                }
                break;
                
            default:
                RELEASE_ASSERT_NOT_REACHED();
                break;
            }
        }
        m_insertionSet.execute(block);
    }
    
    void addStringReplacePrimordialChecks(Node* searchRegExp)
    {
        Node* node = m_currentNode;

        // Check that structure of searchRegExp is RegExp object
        m_insertionSet.insertNode(
            m_indexInBlock, SpecNone, Check, node->origin,
            Edge(searchRegExp, RegExpObjectUse));

        auto emitPrimordialCheckFor = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
            unsigned index = m_graph.identifiers().ensure(propertyUID);

            Node* actualProperty = m_insertionSet.insertNode(
                m_indexInBlock, SpecNone, TryGetById, node->origin,
                OpInfo(index), OpInfo(SpecFunction), Edge(searchRegExp, CellUse));

            m_insertionSet.insertNode(
                m_indexInBlock, SpecNone, CheckCell, node->origin,
                OpInfo(m_graph.freeze(primordialProperty)), Edge(actualProperty, CellUse));
        };

        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);

        // Check that searchRegExp.exec is the primordial RegExp.prototype.exec
        emitPrimordialCheckFor(globalObject->regExpProtoExecFunction(), vm().propertyNames->exec.impl());
        // Check that searchRegExp.global is the primordial RegExp.prototype.global
        emitPrimordialCheckFor(globalObject->regExpProtoGlobalGetter(), vm().propertyNames->global.impl());
        // Check that searchRegExp.unicode is the primordial RegExp.prototype.unicode
        emitPrimordialCheckFor(globalObject->regExpProtoUnicodeGetter(), vm().propertyNames->unicode.impl());
        // Check that searchRegExp[Symbol.match] is the primordial RegExp.prototype[Symbol.replace]
        emitPrimordialCheckFor(globalObject->regExpProtoSymbolReplaceFunction(), vm().propertyNames->replaceSymbol.impl());
    }

    Node* checkArray(ArrayMode arrayMode, const NodeOrigin& origin, Node* array, Node* index, bool (*storageCheck)(const ArrayMode&) = canCSEStorage)
    {
        ASSERT(arrayMode.isSpecific());
        
        if (arrayMode.type() == Array::String) {
            m_insertionSet.insertNode(
                m_indexInBlock, SpecNone, Check, origin, Edge(array, StringUse));
        } else {
            // Note that we only need to be using a structure check if we opt for SaneChain, since
            // that needs to protect against JSArray's __proto__ being changed.
            Structure* structure = arrayMode.originalArrayStructure(m_graph, origin.semantic);
        
            Edge indexEdge = index ? Edge(index, Int32Use) : Edge();
            
            if (arrayMode.doesConversion()) {
                if (structure) {
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, ArrayifyToStructure, origin,
                        OpInfo(m_graph.registerStructure(structure)), OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
                } else {
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, Arrayify, origin,
                        OpInfo(arrayMode.asWord()), Edge(array, CellUse), indexEdge);
                }
            } else {
                if (structure) {
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, CheckStructure, origin,
                        OpInfo(m_graph.addStructureSet(structure)), Edge(array, CellUse));
                } else {
                    m_insertionSet.insertNode(
                        m_indexInBlock, SpecNone, CheckArray, origin,
                        OpInfo(arrayMode.asWord()), Edge(array, CellUse));
                }
            }
        }
        
        if (!storageCheck(arrayMode))
            return nullptr;
        
        if (arrayMode.usesButterfly()) {
            return m_insertionSet.insertNode(
                m_indexInBlock, SpecNone, GetButterfly, origin, Edge(array, CellUse));
        }
        
        return m_insertionSet.insertNode(
            m_indexInBlock, SpecNone, GetIndexedPropertyStorage, origin,
            OpInfo(arrayMode.asWord()), Edge(array, KnownCellUse));
    }
    
    void blessArrayOperation(Edge base, Edge index, Edge& storageChild)
    {
        Node* node = m_currentNode;
        
        switch (node->arrayMode().type()) {
        case Array::ForceExit: {
            m_insertionSet.insertNode(
                m_indexInBlock, SpecNone, ForceOSRExit, node->origin);
            return;
        }
            
        case Array::SelectUsingPredictions:
        case Array::Unprofiled:
            RELEASE_ASSERT_NOT_REACHED();
            return;
            
        case Array::Generic:
            return;
            
        default: {
            Node* storage = checkArray(node->arrayMode(), node->origin, base.node(), index.node());
            if (!storage)
                return;
            
            storageChild = Edge(storage);
            return;
        } }
    }
    
    bool alwaysUnboxSimplePrimitives()
    {
#if USE(JSVALUE64)
        return false;
#else
        // Any boolean, int, or cell value is profitable to unbox on 32-bit because it
        // reduces traffic.
        return true;
#endif
    }

    template<UseKind useKind>
    void observeUseKindOnNode(Node* node)
    {
        if (useKind == UntypedUse)
            return;
        observeUseKindOnNode(node, useKind);
    }

    void observeUseKindOnEdge(Edge edge)
    {
        observeUseKindOnNode(edge.node(), edge.useKind());
    }

    void observeUseKindOnNode(Node* node, UseKind useKind)
    {
        if (node->op() != GetLocal)
            return;
        
        // FIXME: The way this uses alwaysUnboxSimplePrimitives() is suspicious.
        // https://bugs.webkit.org/show_bug.cgi?id=121518
        
        VariableAccessData* variable = node->variableAccessData();
        switch (useKind) {
        case Int32Use:
        case KnownInt32Use:
            if (alwaysUnboxSimplePrimitives()
                || isInt32Speculation(variable->prediction()))
                m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
            break;
        case NumberUse:
        case RealNumberUse:
        case DoubleRepUse:
        case DoubleRepRealUse:
            if (variable->doubleFormatState() == UsingDoubleFormat)
                m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
            break;
        case BooleanUse:
        case KnownBooleanUse:
            if (alwaysUnboxSimplePrimitives()
                || isBooleanSpeculation(variable->prediction()))
                m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
            break;
        case Int52RepUse:
            if (!isInt32Speculation(variable->prediction()) && isInt32OrInt52Speculation(variable->prediction()))
                m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
            break;
        case CellUse:
        case KnownCellUse:
        case ObjectUse:
        case FunctionUse:
        case StringUse:
        case KnownStringUse:
        case SymbolUse:
        case BigIntUse:
        case StringObjectUse:
        case StringOrStringObjectUse:
            if (alwaysUnboxSimplePrimitives()
                || isCellSpeculation(variable->prediction()))
                m_profitabilityChanged |= variable->mergeIsProfitableToUnbox(true);
            break;
        default:
            break;
        }
    }
    
    template<UseKind useKind>
    void fixEdge(Edge& edge)
    {
        observeUseKindOnNode<useKind>(edge.node());
        edge.setUseKind(useKind);
    }
    
    unsigned indexForChecks()
    {
        unsigned index = m_indexInBlock;
        while (!m_block->at(index)->origin.exitOK)
            index--;
        return index;
    }
    
    NodeOrigin originForCheck(unsigned index)
    {
        return m_block->at(index)->origin.withSemantic(m_currentNode->origin.semantic);
    }
    
    void speculateForBarrier(Edge value)
    {
        // Currently, the DFG won't take advantage of this speculation. But, we want to do it in
        // the DFG anyway because if such a speculation would be wrong, we want to know before
        // we do an expensive compile.
        
        if (value->shouldSpeculateInt32()) {
            insertCheck<Int32Use>(value.node());
            return;
        }
            
        if (value->shouldSpeculateBoolean()) {
            insertCheck<BooleanUse>(value.node());
            return;
        }
            
        if (value->shouldSpeculateOther()) {
            insertCheck<OtherUse>(value.node());
            return;
        }
            
        if (value->shouldSpeculateNumber()) {
            insertCheck<NumberUse>(value.node());
            return;
        }
            
        if (value->shouldSpeculateNotCell()) {
            insertCheck<NotCellUse>(value.node());
            return;
        }
    }
    
    template<UseKind useKind>
    void insertCheck(Node* node)
    {
        observeUseKindOnNode<useKind>(node);
        unsigned index = indexForChecks();
        m_insertionSet.insertNode(index, SpecNone, Check, originForCheck(index), Edge(node, useKind));
    }

    void fixIntConvertingEdge(Edge& edge)
    {
        Node* node = edge.node();
        if (node->shouldSpeculateInt32OrBoolean()) {
            fixIntOrBooleanEdge(edge);
            return;
        }
        
        UseKind useKind;
        if (node->shouldSpeculateInt52())
            useKind = Int52RepUse;
        else if (node->shouldSpeculateNumber())
            useKind = DoubleRepUse;
        else
            useKind = NotCellUse;
        Node* newNode = m_insertionSet.insertNode(
            m_indexInBlock, SpecInt32Only, ValueToInt32, m_currentNode->origin,
            Edge(node, useKind));
        observeUseKindOnNode(node, useKind);
        
        edge = Edge(newNode, KnownInt32Use);
    }
    
    void fixIntOrBooleanEdge(Edge& edge)
    {
        Node* node = edge.node();
        if (!node->sawBooleans()) {
            fixEdge<Int32Use>(edge);
            return;
        }
        
        UseKind useKind;
        if (node->shouldSpeculateBoolean())
            useKind = BooleanUse;
        else
            useKind = UntypedUse;
        Node* newNode = m_insertionSet.insertNode(
            m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
            Edge(node, useKind));
        observeUseKindOnNode(node, useKind);
        
        edge = Edge(newNode, Int32Use);
    }
    
    void fixDoubleOrBooleanEdge(Edge& edge)
    {
        Node* node = edge.node();
        if (!node->sawBooleans()) {
            fixEdge<DoubleRepUse>(edge);
            return;
        }
        
        UseKind useKind;
        if (node->shouldSpeculateBoolean())
            useKind = BooleanUse;
        else
            useKind = UntypedUse;
        Node* newNode = m_insertionSet.insertNode(
            m_indexInBlock, SpecInt32Only, BooleanToNumber, m_currentNode->origin,
            Edge(node, useKind));
        observeUseKindOnNode(node, useKind);
        
        edge = Edge(newNode, DoubleRepUse);
    }
    
    void truncateConstantToInt32(Edge& edge)
    {
        Node* oldNode = edge.node();
        
        JSValue value = oldNode->asJSValue();
        if (value.isInt32())
            return;
        
        value = jsNumber(JSC::toInt32(value.asNumber()));
        ASSERT(value.isInt32());
        edge.setNode(m_insertionSet.insertNode(
            m_indexInBlock, SpecInt32Only, JSConstant, m_currentNode->origin,
            OpInfo(m_graph.freeze(value))));
    }
    
    void truncateConstantsIfNecessary(Node* node, AddSpeculationMode mode)
    {
        if (mode != SpeculateInt32AndTruncateConstants)
            return;
        
        ASSERT(node->child1()->hasConstant() || node->child2()->hasConstant());
        if (node->child1()->hasConstant())
            truncateConstantToInt32(node->child1());
        else
            truncateConstantToInt32(node->child2());
    }

    bool attemptToMakeIntegerAdd(Node* node)
    {
        AddSpeculationMode mode = m_graph.addSpeculationMode(node, FixupPass);
        if (mode != DontSpeculateInt32) {
            truncateConstantsIfNecessary(node, mode);
            fixIntOrBooleanEdge(node->child1());
            fixIntOrBooleanEdge(node->child2());
            if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
                node->setArithMode(Arith::Unchecked);
            else
                node->setArithMode(Arith::CheckOverflow);
            return true;
        }
        
        if (m_graph.addShouldSpeculateInt52(node)) {
            fixEdge<Int52RepUse>(node->child1());
            fixEdge<Int52RepUse>(node->child2());
            node->setArithMode(Arith::CheckOverflow);
            node->setResult(NodeResultInt52);
            return true;
        }
        
        return false;
    }
    
    bool attemptToMakeGetArrayLength(Node* node)
    {
        if (!isInt32Speculation(node->prediction()))
            return false;
        CodeBlock* profiledBlock = m_graph.baselineCodeBlockFor(node->origin.semantic);
        ArrayProfile* arrayProfile = 
            profiledBlock->getArrayProfile(node->origin.semantic.bytecodeIndex());
        ArrayMode arrayMode = ArrayMode(Array::SelectUsingPredictions, Array::Read);
        if (arrayProfile) {
            ConcurrentJSLocker locker(profiledBlock->m_lock);
            arrayProfile->computeUpdatedPrediction(locker, profiledBlock);
            arrayMode = ArrayMode::fromObserved(locker, arrayProfile, Array::Read, false);
            if (arrayMode.type() == Array::Unprofiled) {
                // For normal array operations, it makes sense to treat Unprofiled
                // accesses as ForceExit and get more data rather than using
                // predictions and then possibly ending up with a Generic. But here,
                // we treat anything that is Unprofiled as Generic and keep the
                // GetById. I.e. ForceExit = Generic. So, there is no harm - and only
                // profit - from treating the Unprofiled case as
                // SelectUsingPredictions.
                arrayMode = ArrayMode(Array::SelectUsingPredictions, Array::Read);
            }
        }
            
        arrayMode = arrayMode.refine(
            m_graph, node, node->child1()->prediction(), node->prediction());
            
        if (arrayMode.type() == Array::Generic) {
            // Check if the input is something that we can't get array length for, but for which we
            // could insert some conversions in order to transform it into something that we can do it
            // for.
            if (node->child1()->shouldSpeculateStringObject())
                attemptToForceStringArrayModeByToStringConversion<StringObjectUse>(arrayMode, node);
            else if (node->child1()->shouldSpeculateStringOrStringObject())
                attemptToForceStringArrayModeByToStringConversion<StringOrStringObjectUse>(arrayMode, node);
        }
            
        if (!arrayMode.supportsSelfLength())
            return false;
        
        convertToGetArrayLength(node, arrayMode);
        return true;
    }

    void convertToGetArrayLength(Node* node, ArrayMode arrayMode)
    {
        node->setOp(GetArrayLength);
        node->clearFlags(NodeMustGenerate);
        fixEdge<KnownCellUse>(node->child1());
        node->setArrayMode(arrayMode);
            
        Node* storage = checkArray(arrayMode, node->origin, node->child1().node(), 0, lengthNeedsStorage);
        if (!storage)
            return;
            
        node->child2() = Edge(storage);
    }
    
    Node* prependGetArrayLength(NodeOrigin origin, Node* child, ArrayMode arrayMode)
    {
        Node* storage = checkArray(arrayMode, origin, child, 0, lengthNeedsStorage);
        return m_insertionSet.insertNode(
            m_indexInBlock, SpecInt32Only, GetArrayLength, origin,
            OpInfo(arrayMode.asWord()), Edge(child, KnownCellUse), Edge(storage));
    }

    void convertToHasIndexedProperty(Node* node)
    {
        node->setOp(HasIndexedProperty);
        node->clearFlags(NodeMustGenerate);

        {
            unsigned firstChild = m_graph.m_varArgChildren.size();
            unsigned numChildren = 3;
            m_graph.m_varArgChildren.append(node->child1());
            m_graph.m_varArgChildren.append(node->child2());
            m_graph.m_varArgChildren.append(Edge());
            node->mergeFlags(NodeHasVarArgs);
            node->children = AdjacencyList(AdjacencyList::Variable, firstChild, numChildren);
        }

        node->setArrayMode(
            node->arrayMode().refine(
                m_graph, node,
                m_graph.varArgChild(node, 0)->prediction(),
                m_graph.varArgChild(node, 1)->prediction(),
                SpecNone));
        node->setInternalMethodType(PropertySlot::InternalMethodType::HasProperty);

        blessArrayOperation(m_graph.varArgChild(node, 0), m_graph.varArgChild(node, 1), m_graph.varArgChild(node, 2));

        fixEdge<CellUse>(m_graph.varArgChild(node, 0));
        fixEdge<Int32Use>(m_graph.varArgChild(node, 1));
    }

    void fixupNormalizeMapKey(Node* node)
    {
        if (node->child1()->shouldSpeculateBoolean()) {
            fixEdge<BooleanUse>(node->child1());
            node->convertToIdentity();
            return;
        }

        if (node->child1()->shouldSpeculateInt32()) {
            fixEdge<Int32Use>(node->child1());
            node->convertToIdentity();
            return;
        }

        if (node->child1()->shouldSpeculateSymbol()) {
            fixEdge<SymbolUse>(node->child1());
            node->convertToIdentity();
            return;
        }

        if (node->child1()->shouldSpeculateObject()) {
            fixEdge<ObjectUse>(node->child1());
            node->convertToIdentity();
            return;
        }

        if (node->child1()->shouldSpeculateString()) {
            fixEdge<StringUse>(node->child1());
            node->convertToIdentity();
            return;
        }

        if (node->child1()->shouldSpeculateCell()) {
            fixEdge<CellUse>(node->child1());
            node->convertToIdentity();
            return;
        }

        fixEdge<UntypedUse>(node->child1());
    }

    bool attemptToMakeCallDOM(Node* node)
    {
        if (m_graph.hasExitSite(node->origin.semantic, BadType))
            return false;

        const DOMJIT::Signature* signature = node->signature();
        if (!signature)
            return false;

        {
            unsigned index = 0;
            bool shouldConvertToCallDOM = true;
            m_graph.doToChildren(node, [&](Edge& edge) {
                // Callee. Ignore this. DFGByteCodeParser already emit appropriate checks.
                if (!index)
                    return;

                if (index == 1) {
                    // DOM node case.
                    if (edge->shouldSpeculateNotCell())
                        shouldConvertToCallDOM = false;
                } else {
                    switch (signature->arguments[index - 2]) {
                    case SpecString:
                        if (edge->shouldSpeculateNotString())
                            shouldConvertToCallDOM = false;
                        break;
                    case SpecInt32Only:
                        if (edge->shouldSpeculateNotInt32())
                            shouldConvertToCallDOM = false;
                        break;
                    case SpecBoolean:
                        if (edge->shouldSpeculateNotBoolean())
                            shouldConvertToCallDOM = false;
                        break;
                    default:
                        RELEASE_ASSERT_NOT_REACHED();
                        break;
                    }
                }
                ++index;
            });
            if (!shouldConvertToCallDOM)
                return false;
        }

        Node* thisNode = m_graph.varArgChild(node, 1).node();
        Node* checkSubClass = m_insertionSet.insertNode(m_indexInBlock, SpecNone, CheckSubClass, node->origin, OpInfo(signature->classInfo), Edge(thisNode));
        node->convertToCallDOM(m_graph);
        fixupCheckSubClass(checkSubClass);
        fixupCallDOM(node);
        return true;
    }

    void fixupCheckSubClass(Node* node)
    {
        fixEdge<CellUse>(node->child1());
    }

    void fixupCallDOM(Node* node)
    {
        const DOMJIT::Signature* signature = node->signature();
        auto fixup = [&](Edge& edge, unsigned argumentIndex) {
            if (!edge)
                return;
            switch (signature->arguments[argumentIndex]) {
            case SpecString:
                fixEdge<StringUse>(edge);
                break;
            case SpecInt32Only:
                fixEdge<Int32Use>(edge);
                break;
            case SpecBoolean:
                fixEdge<BooleanUse>(edge);
                break;
            default:
                RELEASE_ASSERT_NOT_REACHED();
                break;
            }
        };
        fixEdge<CellUse>(node->child1()); // DOM.
        fixup(node->child2(), 0);
        fixup(node->child3(), 1);
    }

    void fixupArrayIndexOf(Node* node)
    {
        Edge& array = m_graph.varArgChild(node, 0);
        Edge& storage = m_graph.varArgChild(node, node->numChildren() == 3 ? 2 : 3);
        blessArrayOperation(array, Edge(), storage);
        ASSERT_WITH_MESSAGE(storage.node(), "blessArrayOperation for ArrayIndexOf must set Butterfly for storage edge.");

        Edge& searchElement = m_graph.varArgChild(node, 1);

        // Constant folding.
        switch (node->arrayMode().type()) {
        case Array::Double:
        case Array::Int32: {
            if (searchElement->shouldSpeculateCell()) {
                m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin, Edge(searchElement.node(), CellUse));
                m_graph.convertToConstant(node, jsNumber(-1));
                observeUseKindOnNode<CellUse>(searchElement.node());
                return;
            }

            if (searchElement->shouldSpeculateOther()) {
                m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin, Edge(searchElement.node(), OtherUse));
                m_graph.convertToConstant(node, jsNumber(-1));
                observeUseKindOnNode<OtherUse>(searchElement.node());
                return;
            }

            if (searchElement->shouldSpeculateBoolean()) {
                m_insertionSet.insertNode(m_indexInBlock, SpecNone, Check, node->origin, Edge(searchElement.node(), BooleanUse));
                m_graph.convertToConstant(node, jsNumber(-1));
                observeUseKindOnNode<BooleanUse>(searchElement.node());
                return;
            }
            break;
        }
        default:
            break;
        }

        fixEdge<KnownCellUse>(array);
        if (node->numChildren() == 4)
            fixEdge<Int32Use>(m_graph.varArgChild(node, 2));

        switch (node->arrayMode().type()) {
        case Array::Double: {
            if (searchElement->shouldSpeculateNumber())
                fixEdge<DoubleRepUse>(searchElement);
            return;
        }
        case Array::Int32: {
            if (searchElement->shouldSpeculateInt32())
                fixEdge<Int32Use>(searchElement);
            return;
        }
        case Array::Contiguous: {
            if (searchElement->shouldSpeculateString())
                fixEdge<StringUse>(searchElement);
            else if (searchElement->shouldSpeculateSymbol())
                fixEdge<SymbolUse>(searchElement);
            else if (searchElement->shouldSpeculateOther())
                fixEdge<OtherUse>(searchElement);
            else if (searchElement->shouldSpeculateObject())
                fixEdge<ObjectUse>(searchElement);
            return;
        }
        default:
            RELEASE_ASSERT_NOT_REACHED();
            return;
        }
    }

    void fixupCompareStrictEqAndSameValue(Node* node)
    {
        ASSERT(node->op() == SameValue || node->op() == CompareStrictEq);

        if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
            fixEdge<BooleanUse>(node->child1());
            fixEdge<BooleanUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
            fixEdge<Int32Use>(node->child1());
            fixEdge<Int32Use>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (Node::shouldSpeculateInt52(node->child1().node(), node->child2().node())) {
            fixEdge<Int52RepUse>(node->child1());
            fixEdge<Int52RepUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
            fixEdge<DoubleRepUse>(node->child1());
            fixEdge<DoubleRepUse>(node->child2());
            // Do not convert SameValue to CompareStrictEq in this case since SameValue(NaN, NaN) and SameValue(-0, +0)
            // are not the same to CompareStrictEq(NaN, NaN) and CompareStrictEq(-0, +0).
            return;
        }
        if (Node::shouldSpeculateSymbol(node->child1().node(), node->child2().node())) {
            fixEdge<SymbolUse>(node->child1());
            fixEdge<SymbolUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (Node::shouldSpeculateBigInt(node->child1().node(), node->child2().node())) {
            fixEdge<BigIntUse>(node->child1());
            fixEdge<BigIntUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
            fixEdge<StringIdentUse>(node->child1());
            fixEdge<StringIdentUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (node->child1()->shouldSpeculateString() && node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 7) || m_graph.m_plan.isFTL())) {
            fixEdge<StringUse>(node->child1());
            fixEdge<StringUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }

        if (node->op() == SameValue) {
            if (node->child1()->shouldSpeculateObject()) {
                fixEdge<ObjectUse>(node->child1());
                node->setOpAndDefaultFlags(CompareStrictEq);
                return;
            }
            if (node->child2()->shouldSpeculateObject()) {
                fixEdge<ObjectUse>(node->child2());
                node->setOpAndDefaultFlags(CompareStrictEq);
                return;
            }
        } else {
            WatchpointSet* masqueradesAsUndefinedWatchpoint = m_graph.globalObjectFor(node->origin.semantic)->masqueradesAsUndefinedWatchpoint();
            if (masqueradesAsUndefinedWatchpoint->isStillValid()) {
                if (node->child1()->shouldSpeculateObject()) {
                    m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
                    fixEdge<ObjectUse>(node->child1());
                    return;
                }
                if (node->child2()->shouldSpeculateObject()) {
                    m_graph.watchpoints().addLazily(masqueradesAsUndefinedWatchpoint);
                    fixEdge<ObjectUse>(node->child2());
                    return;
                }
            } else if (node->child1()->shouldSpeculateObject() && node->child2()->shouldSpeculateObject()) {
                fixEdge<ObjectUse>(node->child1());
                fixEdge<ObjectUse>(node->child2());
                return;
            }
        }

        if (node->child1()->shouldSpeculateSymbol()) {
            fixEdge<SymbolUse>(node->child1());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (node->child2()->shouldSpeculateSymbol()) {
            fixEdge<SymbolUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (node->child1()->shouldSpeculateMisc()) {
            fixEdge<MiscUse>(node->child1());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (node->child2()->shouldSpeculateMisc()) {
            fixEdge<MiscUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (node->child1()->shouldSpeculateStringIdent()
            && node->child2()->shouldSpeculateNotStringVar()) {
            fixEdge<StringIdentUse>(node->child1());
            fixEdge<NotStringVarUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (node->child2()->shouldSpeculateStringIdent()
            && node->child1()->shouldSpeculateNotStringVar()) {
            fixEdge<StringIdentUse>(node->child2());
            fixEdge<NotStringVarUse>(node->child1());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (node->child1()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || m_graph.m_plan.isFTL())) {
            fixEdge<StringUse>(node->child1());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
        if (node->child2()->shouldSpeculateString() && ((GPRInfo::numberOfRegisters >= 8) || m_graph.m_plan.isFTL())) {
            fixEdge<StringUse>(node->child2());
            node->setOpAndDefaultFlags(CompareStrictEq);
            return;
        }
    }

    void fixupChecksInBlock(BasicBlock* block)
    {
        if (!block)
            return;
        ASSERT(block->isReachable);
        m_block = block;
        unsigned indexForChecks = UINT_MAX;
        NodeOrigin originForChecks;
        for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
            Node* node = block->at(indexInBlock);

            // If this is a node at which we could exit, then save its index. If nodes after this one
            // cannot exit, then we will hoist checks to here.
            if (node->origin.exitOK) {
                indexForChecks = indexInBlock;
                originForChecks = node->origin;
            }

            originForChecks = originForChecks.withSemantic(node->origin.semantic);
            
            // First, try to relax the representational demands of each node, in order to have
            // fewer conversions.
            switch (node->op()) {
            case MovHint:
            case Check:
            case CheckVarargs:
                m_graph.doToChildren(
                    node,
                    [&] (Edge& edge) {
                        switch (edge.useKind()) {
                        case DoubleRepUse:
                        case DoubleRepRealUse:
                            if (edge->hasDoubleResult())
                                break;
            
                            if (edge->hasInt52Result())
                                edge.setUseKind(Int52RepUse);
                            else if (edge.useKind() == DoubleRepUse)
                                edge.setUseKind(NumberUse);
                            break;
            
                        case Int52RepUse:
                            // Nothing we can really do.
                            break;
            
                        case UntypedUse:
                        case NumberUse:
                            if (edge->hasDoubleResult())
                                edge.setUseKind(DoubleRepUse);
                            else if (edge->hasInt52Result())
                                edge.setUseKind(Int52RepUse);
                            break;
            
                        case RealNumberUse:
                            if (edge->hasDoubleResult())
                                edge.setUseKind(DoubleRepRealUse);
                            else if (edge->hasInt52Result())
                                edge.setUseKind(Int52RepUse);
                            break;
            
                        default:
                            break;
                        }
                    });
                break;
                
            case ValueToInt32:
                if (node->child1().useKind() == DoubleRepUse
                    && !node->child1()->hasDoubleResult()) {
                    node->child1().setUseKind(NumberUse);
                    break;
                }
                break;
                
            default:
                break;
            }

            // Now, insert type conversions if necessary.
            m_graph.doToChildren(
                node,
                [&] (Edge& edge) {
                    Node* result = nullptr;

                    switch (edge.useKind()) {
                    case DoubleRepUse:
                    case DoubleRepRealUse:
                    case DoubleRepAnyIntUse: {
                        if (edge->hasDoubleResult())
                            break;
            
                        ASSERT(indexForChecks != UINT_MAX);
                        if (edge->isNumberConstant()) {
                            result = m_insertionSet.insertNode(
                                indexForChecks, SpecBytecodeDouble, DoubleConstant, originForChecks,
                                OpInfo(m_graph.freeze(jsDoubleNumber(edge->asNumber()))));
                        } else if (edge->hasInt52Result()) {
                            result = m_insertionSet.insertNode(
                                indexForChecks, SpecAnyIntAsDouble, DoubleRep, originForChecks,
                                Edge(edge.node(), Int52RepUse));
                        } else {
                            UseKind useKind;
                            if (edge->shouldSpeculateDoubleReal())
                                useKind = RealNumberUse;
                            else if (edge->shouldSpeculateNumber())
                                useKind = NumberUse;
                            else
                                useKind = NotCellUse;

                            result = m_insertionSet.insertNode(
                                indexForChecks, SpecBytecodeDouble, DoubleRep, originForChecks,
                                Edge(edge.node(), useKind));
                        }

                        edge.setNode(result);
                        break;
                    }
            
                    case Int52RepUse: {
                        if (edge->hasInt52Result())
                            break;
            
                        ASSERT(indexForChecks != UINT_MAX);
                        if (edge->isAnyIntConstant()) {
                            result = m_insertionSet.insertNode(
                                indexForChecks, SpecInt52Any, Int52Constant, originForChecks,
                                OpInfo(edge->constant()));
                        } else if (edge->hasDoubleResult()) {
                            result = m_insertionSet.insertNode(
                                indexForChecks, SpecInt52Any, Int52Rep, originForChecks,
                                Edge(edge.node(), DoubleRepAnyIntUse));
                        } else if (edge->shouldSpeculateInt32ForArithmetic()) {
                            result = m_insertionSet.insertNode(
                                indexForChecks, SpecInt32Only, Int52Rep, originForChecks,
                                Edge(edge.node(), Int32Use));
                        } else {
                            result = m_insertionSet.insertNode(
                                indexForChecks, SpecInt52Any, Int52Rep, originForChecks,
                                Edge(edge.node(), AnyIntUse));
                        }

                        edge.setNode(result);
                        break;
                    }

                    default: {
                        if (!edge->hasDoubleResult() && !edge->hasInt52Result())
                            break;
            
                        ASSERT(indexForChecks != UINT_MAX);
                        if (edge->hasDoubleResult()) {
                            result = m_insertionSet.insertNode(
                                indexForChecks, SpecBytecodeDouble, ValueRep, originForChecks,
                                Edge(edge.node(), DoubleRepUse));
                        } else {
                            result = m_insertionSet.insertNode(
                                indexForChecks, SpecInt32Only | SpecAnyIntAsDouble, ValueRep,
                                originForChecks, Edge(edge.node(), Int52RepUse));
                        }

                        edge.setNode(result);
                        break;
                    } }

                    // It's remotely possible that this node cannot do type checks, but we now have a
                    // type check on this node. We don't have to handle the general form of this
                    // problem. It only arises when ByteCodeParser emits an immediate SetLocal, rather
                    // than a delayed one. So, we only worry about those checks that we may have put on
                    // a SetLocal. Note that "indexForChecks != indexInBlock" is just another way of
                    // saying "!node->origin.exitOK".
                    if (indexForChecks != indexInBlock && mayHaveTypeCheck(edge.useKind())) {
                        UseKind knownUseKind;
                        
                        switch (edge.useKind()) {
                        case Int32Use:
                            knownUseKind = KnownInt32Use;
                            break;
                        case CellUse:
                            knownUseKind = KnownCellUse;
                            break;
                        case BooleanUse:
                            knownUseKind = KnownBooleanUse;
                            break;
                        default:
                            // This can only arise if we have a Check node, and in that case, we can
                            // just remove the original check.
                            DFG_ASSERT(m_graph, node, node->op() == Check, node->op(), edge.useKind());
                            knownUseKind = UntypedUse;
                            break;
                        }

                        ASSERT(indexForChecks != UINT_MAX);
                        m_insertionSet.insertNode(
                            indexForChecks, SpecNone, Check, originForChecks, edge);

                        edge.setUseKind(knownUseKind);
                    }
                });
        }
        
        m_insertionSet.execute(block);
    }
    
    BasicBlock* m_block;
    unsigned m_indexInBlock;
    Node* m_currentNode;
    InsertionSet m_insertionSet;
    bool m_profitabilityChanged;
};
    
bool performFixup(Graph& graph)
{
    return runPhase<FixupPhase>(graph);
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)

