| /* | 
 |  * 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 "GetterSetter.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 Inc: | 
 |         case Dec: { | 
 |             if (node->child1()->shouldSpeculateUntypedForArithmetic()) { | 
 |                 fixEdge<UntypedUse>(node->child1()); | 
 |                 break; | 
 |             } | 
 |  | 
 |             Node* nodeConstantOne; | 
 |             if (node->child1()->shouldSpeculateInt32OrBoolean() && node->canSpeculateInt32(FixupPass)) { | 
 |                 node->setOp(op == Inc ? ArithAdd : ArithSub); | 
 |                 node->setArithMode(Arith::CheckOverflow); | 
 |                 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecInt32Only, JSConstant, node->origin, OpInfo(m_graph.freeze(jsNumber(1)))); | 
 |                 node->children.setChild2(Edge(nodeConstantOne)); | 
 |                 fixEdge<Int32Use>(node->child1()); | 
 |                 fixEdge<Int32Use>(node->child2()); | 
 |                 node->setResult(NodeResultInt32); | 
 |             } else if (node->child1()->shouldSpeculateBigInt()) { | 
 |                 // FIXME: the freezing does not appear useful (since the JSCell is kept alive by vm), but it refuses to compile otherwise. | 
 |                 node->setOp(op == Inc ? ValueAdd : ValueSub); | 
 |                 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBigInt, JSConstant, node->origin, OpInfo(m_graph.freeze(vm().bigIntConstantOne.get()))); | 
 |                 node->children.setChild2(Edge(nodeConstantOne)); | 
 |                 fixEdge<BigIntUse>(node->child1()); | 
 |                 fixEdge<BigIntUse>(node->child2()); | 
 |                 // BigInts are currently cells, so the default of NodeResultJS is good here | 
 |             } else if (node->child1()->shouldSpeculateInt52()) { | 
 |                 node->setOp(op == Inc ? ArithAdd : ArithSub); | 
 |                 node->setArithMode(Arith::CheckOverflow); | 
 |                 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecInt32AsInt52, JSConstant, node->origin, OpInfo(m_graph.freeze(jsNumber(1)))); | 
 |                 node->children.setChild2(Edge(nodeConstantOne)); | 
 |                 fixEdge<Int52RepUse>(node->child1()); | 
 |                 fixEdge<Int52RepUse>(node->child2()); | 
 |                 node->setResult(NodeResultInt52); | 
 |             } else { | 
 |                 node->setOp(op == Inc ? ArithAdd : ArithSub); | 
 |                 node->setArithMode(Arith::Unchecked); | 
 |                 nodeConstantOne = m_insertionSet.insertNode(m_indexInBlock, SpecBytecodeDouble, JSConstant, node->origin, OpInfo(m_graph.freeze(jsNumber(1)))); | 
 |                 node->children.setChild2(Edge(nodeConstantOne)); | 
 |                 fixEdge<DoubleRepUse>(node->child1()); | 
 |                 fixEdge<DoubleRepUse>(node->child2()); | 
 |                 node->setResult(NodeResultDouble); | 
 |             } | 
 |             node->clearFlags(NodeMustGenerate); | 
 |             break; | 
 |         } | 
 |  | 
 |         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 ToNumeric: { | 
 |             fixupToNumeric(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 CheckIdent: { | 
 |             if (node->uidOperand()->isSymbol()) | 
 |                 fixEdge<SymbolUse>(node->child1()); | 
 |             else | 
 |                 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 DateGetInt32OrNaN: | 
 |         case DateGetTime: | 
 |             fixEdge<DateObjectUse>(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 FilterGetByStatus: | 
 |         case FilterPutByIdStatus: | 
 |         case FilterInByIdStatus: | 
 |         case InvalidationPoint: | 
 |         case CreateArgumentsButterfly: | 
 |             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 fixupToNumeric(Node* node) | 
 |     { | 
 |         // If the prediction of the child is BigInt, we attempt to convert ToNumeric to Identity, since it can only return a BigInt when fed a BigInt. | 
 |         if (node->child1()->shouldSpeculateBigInt()) { | 
 |             fixEdge<BigIntUse>(node->child1()); | 
 |             node->convertToIdentity(); | 
 |             return; | 
 |         } | 
 |  | 
 |         fixupToNumber(node); | 
 |     } | 
 |  | 
 |     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) | 
 |  |