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

#pragma once

#if ENABLE(DFG_JIT)

#include "ArrayConstructor.h"
#include "ArrayPrototype.h"
#include "CacheableIdentifierInlines.h"
#include "DFGAbstractInterpreter.h"
#include "DFGAbstractInterpreterClobberState.h"
#include "DOMJITGetterSetter.h"
#include "DOMJITSignature.h"
#include "GetByStatus.h"
#include "GetterSetter.h"
#include "HashMapImpl.h"
#include "JITOperations.h"
#include "JSAsyncGenerator.h"
#include "JSGenerator.h"
#include "JSImmutableButterfly.h"
#include "JSInternalPromise.h"
#include "JSInternalPromiseConstructor.h"
#include "JSPromiseConstructor.h"
#include "MathCommon.h"
#include "NumberConstructor.h"
#include "PutByIdStatus.h"
#include "StringObject.h"
#include "StructureCache.h"
#include "StructureRareDataInlines.h"
#include <wtf/BooleanLattice.h>
#include <wtf/CheckedArithmetic.h>

namespace JSC { namespace DFG {

template<typename AbstractStateType>
AbstractInterpreter<AbstractStateType>::AbstractInterpreter(Graph& graph, AbstractStateType& state)
    : m_codeBlock(graph.m_codeBlock)
    , m_graph(graph)
    , m_vm(m_graph.m_vm)
    , m_state(state)
{
    if (m_graph.m_form == SSA)
        m_phiChildren = makeUnique<PhiChildren>(m_graph);
}

template<typename AbstractStateType>
AbstractInterpreter<AbstractStateType>::~AbstractInterpreter()
{
}

template<typename AbstractStateType>
typename AbstractInterpreter<AbstractStateType>::BooleanResult
AbstractInterpreter<AbstractStateType>::booleanResult(
    Node* node, AbstractValue& value)
{
    JSValue childConst = value.value();
    if (childConst) {
        if (childConst.toBoolean(m_codeBlock->globalObjectFor(node->origin.semantic)))
            return DefinitelyTrue;
        return DefinitelyFalse;
    }

    // Next check if we can fold because we know that the source is an object or string and does not equal undefined.
    if (isCellSpeculation(value.m_type) && !value.m_structure.isTop()) {
        bool allTrue = true;
        for (unsigned i = value.m_structure.size(); i--;) {
            RegisteredStructure structure = value.m_structure[i];
            if (structure->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
                || structure->typeInfo().type() == StringType) {
                allTrue = false;
                break;
            }
        }
        if (allTrue)
            return DefinitelyTrue;
    }
    
    return UnknownBooleanResult;
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::startExecuting()
{
    ASSERT(m_state.block());
    ASSERT(m_state.isValid());
    
    m_state.setClobberState(AbstractInterpreterClobberState::NotClobbered);
}

template<typename AbstractStateType>
class AbstractInterpreterExecuteEdgesFunc {
public:
    AbstractInterpreterExecuteEdgesFunc(AbstractInterpreter<AbstractStateType>& interpreter)
        : m_interpreter(interpreter)
    {
    }
    
    // This func is manually written out so that we can put ALWAYS_INLINE on it.
    ALWAYS_INLINE void operator()(Edge& edge) const
    {
        m_interpreter.filterEdgeByUse(edge);
    }
    
private:
    AbstractInterpreter<AbstractStateType>& m_interpreter;
};

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
{
    m_graph.doToChildren(node, AbstractInterpreterExecuteEdgesFunc<AbstractStateType>(*this));
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::executeKnownEdgeTypes(Node* node)
{
    // Some use kinds are required to not have checks, because we know somehow that the incoming
    // value will already have the type we want. In those cases, AI may not be smart enough to
    // prove that this is indeed the case. But the existance of the edge is enough to prove that
    // it is indeed the case. Taking advantage of this is not optional, since otherwise the DFG
    // and FTL backends may emit checks in a node that lacks a valid exit origin.
    m_graph.doToChildren(
        node,
        [&] (Edge& edge) {
            if (mayHaveTypeCheck(edge.useKind()))
                return;
            
            filterEdgeByUse(edge);
        });
}

template<typename AbstractStateType>
ALWAYS_INLINE void AbstractInterpreter<AbstractStateType>::filterByType(Edge& edge, SpeculatedType type)
{
    AbstractValue& value = m_state.forNodeWithoutFastForward(edge);
    if (value.isType(type)) {
        m_state.setProofStatus(edge, IsProved);
        return;
    }
    m_state.setProofStatus(edge, NeedsCheck);
    m_state.fastForwardAndFilterUnproven(value, type);
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::verifyEdge(Node* node, Edge edge)
{
    if (!(m_state.forNodeWithoutFastForward(edge).m_type & ~typeFilterFor(edge.useKind())))
        return;
    
    DFG_CRASH(m_graph, node, toCString("Edge verification error: ", node, "->", edge, " was expected to have type ", SpeculationDump(typeFilterFor(edge.useKind())), " but has type ", SpeculationDump(forNode(edge).m_type), " (", forNode(edge).m_type, ")").data(), AbstractInterpreterInvalidType, node->op(), edge->op(), edge.useKind(), forNode(edge).m_type);
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::verifyEdges(Node* node)
{
    DFG_NODE_DO_TO_CHILDREN(m_graph, node, verifyEdge);
}

enum class ToThisResult {
    Identity,
    Undefined,
    GlobalThis,
    Dynamic,
};
inline ToThisResult isToThisAnIdentity(VM& vm, ECMAMode ecmaMode, AbstractValue& valueForNode)
{
    // We look at the type first since that will cover most cases and does not require iterating all the structures.
    if (ecmaMode.isStrict()) {
        if (valueForNode.m_type && !(valueForNode.m_type & SpecObjectOther))
            return ToThisResult::Identity;
    } else {
        if (valueForNode.m_type && !(valueForNode.m_type & (~SpecObject | SpecObjectOther)))
            return ToThisResult::Identity;
    }

    if (JSValue value = valueForNode.value()) {
        if (value.isCell()) {
            auto* toThisMethod = value.asCell()->classInfo(vm)->methodTable.toThis;
            if (toThisMethod == &JSObject::toThis)
                return ToThisResult::Identity;
            if (toThisMethod == &JSScope::toThis) {
                if (ecmaMode.isStrict())
                    return ToThisResult::Undefined;
                return ToThisResult::GlobalThis;
            }
        }
    }

    if ((ecmaMode.isStrict() || (valueForNode.m_type && !(valueForNode.m_type & ~SpecObject))) && valueForNode.m_structure.isFinite()) {
        bool allStructuresAreJSScope = !valueForNode.m_structure.isClear();
        bool overridesToThis = false;
        valueForNode.m_structure.forEach([&](RegisteredStructure structure) {
            TypeInfo type = structure->typeInfo();
            ASSERT(type.isObject() || type.type() == StringType || type.type() == SymbolType || type.type() == HeapBigIntType);
            if (!ecmaMode.isStrict())
                ASSERT(type.isObject());
            // We don't need to worry about strings/symbols here since either:
            // 1) We are in strict mode and strings/symbols are not wrapped
            // 2) The AI has proven that the type of this is a subtype of object
            if (type.isObject() && type.overridesToThis())
                overridesToThis = true;

            // If all the structures are JSScope's ones, we know the details of JSScope::toThis() operation.
            allStructuresAreJSScope &= structure->classInfo()->methodTable.toThis == JSScope::info()->methodTable.toThis;
        });
        if (!overridesToThis)
            return ToThisResult::Identity;
        if (allStructuresAreJSScope) {
            if (ecmaMode.isStrict())
                return ToThisResult::Undefined;
            return ToThisResult::GlobalThis;
        }
    }

    return ToThisResult::Dynamic;
}

template<typename AbstractStateType>
bool AbstractInterpreter<AbstractStateType>::handleConstantBinaryBitwiseOp(Node* node)
{
    JSValue left = forNode(node->child1()).value();
    JSValue right = forNode(node->child2()).value();
    if (left && right && left.isInt32() && right.isInt32()) {
        int32_t a = left.asInt32();
        int32_t b = right.asInt32();
        if (node->isBinaryUseKind(UntypedUse))
            didFoldClobberWorld();
        NodeType op = node->op();
        switch (op) {
        case ValueBitAnd:
        case ArithBitAnd:
            setConstant(node, JSValue(a & b));
            break;
        case ValueBitOr:
        case ArithBitOr:
            setConstant(node, JSValue(a | b));
            break;
        case ValueBitXor:
        case ArithBitXor:
            setConstant(node, JSValue(a ^ b));
            break;
        case ArithBitRShift:
        case ValueBitRShift:
            setConstant(node, JSValue(a >> (static_cast<uint32_t>(b) & 0x1f)));
            break;
        case ValueBitLShift:
        case ArithBitLShift:
            setConstant(node, JSValue(a << (static_cast<uint32_t>(b) & 0x1f)));
            break;
        case BitURShift:
            setConstant(node, JSValue(static_cast<int32_t>(static_cast<uint32_t>(a) >> (static_cast<uint32_t>(b) & 0x1f))));
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }

        return true;
    }

    return false;
}

template<typename AbstractStateType>
bool AbstractInterpreter<AbstractStateType>::handleConstantDivOp(Node* node)
{
    JSValue left = forNode(node->child1()).value();
    JSValue right = forNode(node->child2()).value();

    if (left && right) {
        NodeType op = node->op();
        bool isDivOperation = op == ValueDiv || op == ArithDiv;

        // Only possible case of ValueOp below is UntypedUse,
        // so we need to reflect clobberize rules.
        bool isClobbering = op == ValueDiv || op == ValueMod;

        if (left.isInt32() && right.isInt32()) {
            double doubleResult;
            if (isDivOperation)
                doubleResult = left.asNumber() / right.asNumber();
            else
                doubleResult = fmod(left.asNumber(), right.asNumber());

            if (node->hasArithMode()) {
                if (!shouldCheckOverflow(node->arithMode()))
                    doubleResult = toInt32(doubleResult);
                else if (!shouldCheckNegativeZero(node->arithMode()))
                    doubleResult += 0; // Sanitizes zero.
            }

            JSValue valueResult = jsNumber(doubleResult);
            if (valueResult.isInt32()) {
                if (isClobbering)
                    didFoldClobberWorld();
                setConstant(node, valueResult);
                return true;
            }
        } else if (left.isNumber() && right.isNumber()) {
            if (isClobbering)
                didFoldClobberWorld();

            if (isDivOperation) {
                if (op == ValueDiv)
                    setConstant(node, jsNumber(left.asNumber() / right.asNumber()));
                else
                    setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
            } else {
                if (op == ValueMod)
                    setConstant(node, jsNumber(fmod(left.asNumber(), right.asNumber())));
                else
                    setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
            }

            return true;
        }
    }

    return false;
}

template<typename AbstractStateType>
bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimit, Node* node)
{
    verifyEdges(node);
    
    m_state.createValueForNode(node);
    
    switch (node->op()) {
    case JSConstant:
    case DoubleConstant:
    case Int52Constant: {
        setBuiltInConstant(node, *node->constant());
        break;
    }

    case LazyJSConstant: {
        LazyJSValue value = node->lazyJSValue();
        switch (value.kind()) {
        case LazyJSValue::KnownValue:
            setConstant(node, value.value()->value());
            break;
        case LazyJSValue::SingleCharacterString:
        case LazyJSValue::KnownStringImpl:
        case LazyJSValue::NewStringImpl:
            setTypeForNode(node, SpecString);
            break;
        }
        break;
    }

    case IdentityWithProfile:
    case Identity: {
        setForNode(node, forNode(node->child1()));
        if (forNode(node).value())
            m_state.setShouldTryConstantFolding(true);
        break;
    }
        
    case ExtractCatchLocal:
    case ExtractOSREntryLocal: {
        makeBytecodeTopForNode(node);
        break;
    }
            
    case GetLocal: {
        VariableAccessData* variableAccessData = node->variableAccessData();
        AbstractValue value = m_state.operand(variableAccessData->operand());
        // The value in the local should already be checked.
        DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat())));
        if (value.value())
            m_state.setShouldTryConstantFolding(true);
        setForNode(node, value);
        break;
    }
        
    case GetStack: {
        StackAccessData* data = node->stackAccessData();
        AbstractValue value = m_state.operand(data->operand);
        // The value in the local should already be checked.
        DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format)));
        if (value.value())
            m_state.setShouldTryConstantFolding(true);
        setForNode(node, value);
        break;
    }
        
    case SetLocal: {
        m_state.operand(node->operand()) = forNode(node->child1());
        break;
    }
        
    case PutStack: {
        m_state.operand(node->stackAccessData()->operand) = forNode(node->child1());
        break;
    }
        
    case MovHint: {
        // Don't need to do anything. A MovHint only informs us about what would have happened
        // in bytecode, but this code is just concerned with what is actually happening during
        // DFG execution.
        break;
    }

    case KillStack: {
        // This is just a hint telling us that the OSR state of the local is no longer inside the
        // flushed data.
        break;
    }
        
    case SetArgumentDefinitely:
    case SetArgumentMaybe:
        // Assert that the state of arguments has been set. SetArgumentDefinitely/SetArgumentMaybe means
        // that someone set the argument values out-of-band, and currently this always means setting to a
        // non-clear value.
        ASSERT(!m_state.operand(node->operand()).isClear());
        break;

    case InitializeEntrypointArguments: {
        unsigned entrypointIndex = node->entrypointIndex();
        const Vector<FlushFormat>& argumentFormats = m_graph.m_argumentFormats[entrypointIndex];
        for (unsigned argument = 0; argument < argumentFormats.size(); ++argument) {
            AbstractValue& value = m_state.argument(argument);
            switch (argumentFormats[argument]) {
            case FlushedInt32:
                value.setNonCellType(SpecInt32Only);
                break;
            case FlushedBoolean:
                value.setNonCellType(SpecBoolean);
                break;
            case FlushedCell:
                value.setType(m_graph, SpecCellCheck);
                break;
            case FlushedJSValue:
                value.makeBytecodeTop();
                break;
            default:
                DFG_CRASH(m_graph, node, "Bad flush format for argument");
                break;
            }
        }
        break;
    }

    case VarargsLength: {
        clobberWorld();
        setTypeForNode(node, SpecInt32Only);
        break;
    }

    case LoadVarargs:
    case ForwardVarargs: {
        // FIXME: ForwardVarargs should check if the count becomes known, and if it does, it should turn
        // itself into a straight-line sequence of GetStack/PutStack.
        // https://bugs.webkit.org/show_bug.cgi?id=143071
        switch (node->op()) {
        case LoadVarargs:
            clobberWorld();
            break;
        case ForwardVarargs:
            break;
        default:
            DFG_CRASH(m_graph, node, "Bad opcode");
            break;
        }
        LoadVarargsData* data = node->loadVarargsData();
        m_state.operand(data->count).setNonCellType(SpecInt32Only);
        for (unsigned i = data->limit - 1; i--;)
            m_state.operand(data->start + i).makeHeapTop();
        break;
    }

    case ValueBitNot: {
        JSValue operand = forNode(node->child1()).value();
        if (operand && operand.isInt32()) {
            didFoldClobberWorld();
            int32_t a = operand.asInt32();
            setConstant(node, JSValue(~a));
            break;
        }

        if (node->child1().useKind() == BigInt32Use) {
#if USE(BIGINT32)
            setTypeForNode(node, SpecBigInt32);
#else
            RELEASE_ASSERT_NOT_REACHED();
#endif
        } else if (node->child1().useKind() == HeapBigIntUse) {
            // FIXME: We will want an arithmetic mode here that allows us to speculate or dictate
            // the format of our result:
            // https://bugs.webkit.org/show_bug.cgi?id=210982
            setTypeForNode(node, SpecBigInt);
        } else if (node->child1().useKind() == AnyBigIntUse)
            setTypeForNode(node, SpecBigInt);
        else {
            clobberWorld();
            setTypeForNode(node, SpecInt32Only | SpecBigInt);
        }

        break;
    }

    case ArithBitNot: {
        JSValue operand = forNode(node->child1()).value();
        if (operand && operand.isInt32()) {
            int32_t a = operand.asInt32();
            setConstant(node, JSValue(~a));
            break;
        }

        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }

    case ValueBitXor:
    case ValueBitAnd:
    case ValueBitOr:
    case ValueBitRShift:
    case ValueBitLShift: {
        if (handleConstantBinaryBitwiseOp(node))
            break;

        // FIXME: this use of binaryUseKind means that we cannot specialize to (for example) a HeapBigInt left-operand and a BigInt32 right-operand.
        // https://bugs.webkit.org/show_bug.cgi?id=210977
        if (node->binaryUseKind() == BigInt32Use) {
#if USE(BIGINT32)
            switch (node->op()) {
            case ValueBitXor:
            case ValueBitAnd:
            case ValueBitOr:
                setTypeForNode(node, SpecBigInt32);
                break;

            // FIXME: We should have inlined implementation that always returns BigInt32.
            // https://bugs.webkit.org/show_bug.cgi?id=210847
            case ValueBitRShift:
            case ValueBitLShift:
                setTypeForNode(node, SpecBigInt);
                break;
            default:
                DFG_CRASH(m_graph, node, "Incorrect DFG op");
            }
#else
            DFG_CRASH(m_graph, node, "No BigInt32 support");
#endif
        } else if (node->isBinaryUseKind(HeapBigIntUse)) {
            // FIXME: We will want an arithmetic mode here that allows us to speculate or dictate
            // the format of our result:
            // https://bugs.webkit.org/show_bug.cgi?id=210982
            setTypeForNode(node, SpecBigInt);
        } else if (node->binaryUseKind() == AnyBigIntUse)
            setTypeForNode(node, SpecBigInt);
        else {
            clobberWorld();
            setTypeForNode(node, SpecInt32Only | SpecBigInt);
        }
        break;
    }
            
    case ArithBitAnd:
    case ArithBitOr:
    case ArithBitXor:
    case ArithBitRShift:
    case ArithBitLShift:
    case BitURShift: {
        if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
            clobberWorld();
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        }

        if (handleConstantBinaryBitwiseOp(node))
            break;
        
        if (node->op() == ArithBitAnd
            && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
                isBoolInt32Speculation(forNode(node->child2()).m_type))) {
            setNonCellTypeForNode(node, SpecBoolInt32);
            break;
        }
        
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }
        
    case UInt32ToNumber: {
        JSValue child = forNode(node->child1()).value();
        if (doesOverflow(node->arithMode())) {
            if (enableInt52()) {
                if (child && child.isAnyInt()) {
                    int64_t machineInt = child.asAnyInt();
                    setConstant(node, jsNumber(static_cast<uint32_t>(machineInt)));
                    break;
                }
                setNonCellTypeForNode(node, SpecInt52Any);
                break;
            }
            if (child && child.isInt32()) {
                uint32_t value = child.asInt32();
                setConstant(node, jsNumber(value));
                break;
            }
            setNonCellTypeForNode(node, SpecAnyIntAsDouble);
            break;
        }
        if (child && child.isInt32()) {
            int32_t value = child.asInt32();
            if (value >= 0) {
                setConstant(node, jsNumber(value));
                break;
            }
        }
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }
        
    case BooleanToNumber: {
        JSValue concreteValue = forNode(node->child1()).value();
        if (concreteValue) {
            if (concreteValue.isBoolean())
                setConstant(node, jsNumber(concreteValue.asBoolean()));
            else
                setConstant(node, *m_graph.freeze(concreteValue));
            break;
        }
        AbstractValue& value = forNode(node);
        value = forNode(node->child1());
        if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
            m_state.setShouldTryConstantFolding(true);
        if (value.m_type & SpecBoolean) {
            value.merge(SpecBoolInt32);
            value.filter(~SpecBoolean);
        }
        break;
    }
            
    case DoubleAsInt32: {
        JSValue child = forNode(node->child1()).value();
        if (child && child.isNumber()) {
            double asDouble = child.asNumber();
            int32_t asInt = JSC::toInt32(asDouble);
            if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) {
                setConstant(node, JSValue(asInt));
                break;
            }
        }
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }
            
    case ValueToInt32: {
        JSValue child = forNode(node->child1()).value();
        if (child) {
            if (child.isNumber()) {
                if (child.isInt32())
                    setConstant(node, child);
                else
                    setConstant(node, JSValue(JSC::toInt32(child.asDouble())));
                break;
            }
            if (child.isBoolean()) {
                setConstant(node, jsNumber(child.asBoolean()));
                break;
            }
            if (child.isUndefinedOrNull()) {
                setConstant(node, jsNumber(0));
                break;
            }
        }
        
        if (isBooleanSpeculation(forNode(node->child1()).m_type)) {
            setNonCellTypeForNode(node, SpecBoolInt32);
            break;
        }
        
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }
        
    case DoubleRep: {
        JSValue child = forNode(node->child1()).value();
        if (Optional<double> number = child.toNumberFromPrimitive()) {
            setConstant(node, jsDoubleNumber(*number));
            break;
        }

        SpeculatedType type = forNode(node->child1()).m_type;
        switch (node->child1().useKind()) {
        case NotCellNorBigIntUse: {
            if (type & SpecOther) {
                type &= ~SpecOther;
                type |= SpecDoublePureNaN | SpecBoolInt32; // Null becomes zero, undefined becomes NaN.
            }
            if (type & SpecBoolean) {
                type &= ~SpecBoolean;
                type |= SpecBoolInt32; // True becomes 1, false becomes 0.
            }
            type &= SpecBytecodeNumber;
            break;
        }

        case Int52RepUse:
        case NumberUse:
        case RealNumberUse:
            break;

        default:
            RELEASE_ASSERT_NOT_REACHED();
        }
        setNonCellTypeForNode(node, type);
        forNode(node).fixTypeForRepresentation(m_graph, node);
        break;
    }
        
    case Int52Rep: {
        JSValue child = forNode(node->child1()).value();
        if (child && child.isAnyInt()) {
            setConstant(node, child);
            break;
        }

        setTypeForNode(node, forNode(node->child1()).m_type);
        forNode(node).fixTypeForRepresentation(m_graph, node);
        break;
    }
        
    case ValueRep: {
        JSValue value = forNode(node->child1()).value();
        if (value) {
            setConstant(node, value);
            break;
        }
        
        setTypeForNode(node, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
        forNode(node).fixTypeForRepresentation(m_graph, node);
        break;
    }

    case ValueSub:
    case ValueAdd: {
        if (node->isBinaryUseKind(HeapBigIntUse)) {
            // FIXME: We will want an arithmetic mode here that allows us to speculate or dictate
            // the format of our result:
            // https://bugs.webkit.org/show_bug.cgi?id=210982
            setTypeForNode(node, SpecBigInt);
        } else if (node->isBinaryUseKind(AnyBigIntUse))
            setTypeForNode(node, SpecBigInt);
        else if (node->isBinaryUseKind(BigInt32Use))
            setTypeForNode(node, SpecBigInt32);
        else {
            DFG_ASSERT(m_graph, node, node->binaryUseKind() == UntypedUse);
            clobberWorld();
            // FIXME: do we really need SpecString here for ValueSub? It seems like we only need it for ValueAdd.
            setTypeForNode(node, SpecString | SpecBytecodeNumber | SpecBigInt);
        }
        break;
    }

    case StrCat: {
        setTypeForNode(node, SpecString);
        break;
    }
        
    case ArithAdd: {
        JSValue left = forNode(node->child1()).value();
        JSValue right = forNode(node->child2()).value();
        switch (node->binaryUseKind()) {
        case Int32Use:
            if (left && right && left.isInt32() && right.isInt32()) {
                if (!shouldCheckOverflow(node->arithMode())) {
                    setConstant(node, jsNumber(left.asInt32() + right.asInt32()));
                    break;
                }
                JSValue result = jsNumber(left.asNumber() + right.asNumber());
                if (result.isInt32()) {
                    setConstant(node, result);
                    break;
                }
            }
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Int52RepUse:
            if (left && right && left.isAnyInt() && right.isAnyInt()) {
                JSValue result = jsNumber(left.asAnyInt() + right.asAnyInt());
                if (result.isAnyInt()) {
                    setConstant(node, result);
                    break;
                }
            }
            setNonCellTypeForNode(node, SpecInt52Any);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
                break;
            }
            setNonCellTypeForNode(node, 
                typeOfDoubleSum(
                    forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }
        
    case AtomicsIsLockFree: {
        if (node->child1().useKind() != Int32Use)
            clobberWorld();
        setNonCellTypeForNode(node, SpecBoolInt32);
        break;
    }

    case ArithClz32: {
        JSValue operand = forNode(node->child1()).value();
        if (Optional<double> number = operand.toNumberFromPrimitive()) {
            switch (node->child1().useKind()) {
            case Int32Use:
            case KnownInt32Use:
                break;
            default:
                didFoldClobberWorld();
                break;
            }
            uint32_t value = toUInt32(*number);
            setConstant(node, jsNumber(clz(value)));
            break;
        }
        switch (node->child1().useKind()) {
        case Int32Use:
        case KnownInt32Use:
            break;
        default:
            clobberWorld();
            break;
        }
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }

    case MakeRope: {
        unsigned numberOfRemovedChildren = 0;
        for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
            Edge& edge = node->children.child(i);
            if (!edge)
                break;
            JSValue childConstant = m_state.forNode(edge).value();
            if (!childConstant)
                continue;
            if (!childConstant.isString())
                continue;
            if (asString(childConstant)->length())
                continue;
            ++numberOfRemovedChildren;
        }

        if (numberOfRemovedChildren)
            m_state.setShouldTryConstantFolding(true);
        setForNode(node, m_vm.stringStructure.get());
        break;
    }
            
    case ArithSub: {
        JSValue left = forNode(node->child1()).value();
        JSValue right = forNode(node->child2()).value();
        switch (node->binaryUseKind()) {
        case Int32Use:
            if (left && right && left.isInt32() && right.isInt32()) {
                if (!shouldCheckOverflow(node->arithMode())) {
                    setConstant(node, jsNumber(left.asInt32() - right.asInt32()));
                    break;
                }
                JSValue result = jsNumber(left.asNumber() - right.asNumber());
                if (result.isInt32()) {
                    setConstant(node, result);
                    break;
                }
            }
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Int52RepUse:
            if (left && right && left.isAnyInt() && right.isAnyInt()) {
                JSValue result = jsNumber(left.asAnyInt() - right.asAnyInt());
                if (result.isAnyInt()) {
                    setConstant(node, result);
                    break;
                }
            }
            setNonCellTypeForNode(node, SpecInt52Any);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
                break;
            }
            setNonCellTypeForNode(node, 
                typeOfDoubleDifference(
                    forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            break;
        case UntypedUse:
            clobberWorld();
            setNonCellTypeForNode(node, SpecBytecodeNumber);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }
        
    case ValueNegate: {
        // FIXME: we could do much smarter things for BigInts, see ValueAdd/ValueSub.
        clobberWorld();
        setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
        break;
    }

    case ArithNegate: {
        JSValue child = forNode(node->child1()).value();
        switch (node->child1().useKind()) {
        case Int32Use:
            if (child && child.isInt32()) {
                if (!shouldCheckOverflow(node->arithMode())) {
                    setConstant(node, jsNumber(-child.asInt32()));
                    break;
                }
                double doubleResult;
                if (shouldCheckNegativeZero(node->arithMode()))
                    doubleResult = -child.asNumber();
                else
                    doubleResult = 0 - child.asNumber();
                JSValue valueResult = jsNumber(doubleResult);
                if (valueResult.isInt32()) {
                    setConstant(node, valueResult);
                    break;
                }
            }
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Int52RepUse:
            if (child && child.isAnyInt()) {
                double doubleResult;
                if (shouldCheckNegativeZero(node->arithMode()))
                    doubleResult = -child.asNumber();
                else
                    doubleResult = 0 - child.asNumber();
                JSValue valueResult = jsNumber(doubleResult);
                if (valueResult.isAnyInt()) {
                    setConstant(node, valueResult);
                    break;
                }
            }
            setNonCellTypeForNode(node, SpecInt52Any);
            break;
        case DoubleRepUse:
            if (child && child.isNumber()) {
                setConstant(node, jsDoubleNumber(-child.asNumber()));
                break;
            }
            setNonCellTypeForNode(node, 
                typeOfDoubleNegation(
                    forNode(node->child1()).m_type));
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }

    case Inc:
    case Dec: {
        // FIXME: support some form of constant folding here.
        // https://bugs.webkit.org/show_bug.cgi?id=204258
        switch (node->child1().useKind()) {
        case Int32Use:
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Int52RepUse:
            setNonCellTypeForNode(node, SpecInt52Any);
            break;
        case DoubleRepUse:
            setNonCellTypeForNode(node, typeOfDoubleIncOrDec(forNode(node->child1()).m_type));
            break;
        case HeapBigIntUse:
            // FIXME: We will want an arithmetic mode here that allows us to speculate or dictate
            // the format of our result:
            // https://bugs.webkit.org/show_bug.cgi?id=210982
            setTypeForNode(node, SpecBigInt);
            break;
        case AnyBigIntUse:
        case BigInt32Use:
            setTypeForNode(node, SpecBigInt);
            break;
        default:
            setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
            clobberWorld(); // Because of the call to ToNumeric()
            break;
        }
        break;
    }
        
    case ValuePow: {
        JSValue childX = forNode(node->child1()).value();
        JSValue childY = forNode(node->child2()).value();
        if (childX && childY && childX.isNumber() && childY.isNumber()) {
            // We need to call `didFoldClobberWorld` here because this path is only possible
            // when node->useKind is UntypedUse. In the case of AnyBigIntUse or friends, children will be
            // cleared by `AbstractInterpreter::executeEffects`.
            didFoldClobberWorld();
            // Our boxing scheme here matches what we do in operationValuePow.
            setConstant(node, jsNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
            break;
        }

        if (node->isBinaryUseKind(HeapBigIntUse)) {
            // FIXME: We will want an arithmetic mode here that allows us to speculate or dictate
            // the format of our result:
            // https://bugs.webkit.org/show_bug.cgi?id=210982
            setTypeForNode(node, SpecBigInt);
        } else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
            setTypeForNode(node, SpecBigInt);
        else {
            clobberWorld();
            setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
        }
        break;
    }

    case ValueMul: {
        // FIXME: why is this code not shared with ValueSub?
        if (node->isBinaryUseKind(HeapBigIntUse)) {
            // FIXME: We will want an arithmetic mode here that allows us to speculate or dictate
            // the format of our result:
            // https://bugs.webkit.org/show_bug.cgi?id=210982
            setTypeForNode(node, SpecBigInt);
        } else if (node->isBinaryUseKind(AnyBigIntUse))
            setTypeForNode(node, SpecBigInt);
        else if (node->isBinaryUseKind(BigInt32Use))
            setTypeForNode(node, SpecBigInt32);
        else {
            clobberWorld();
            setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
        }
        break;
    }

    case ArithMul: {
        JSValue left = forNode(node->child1()).value();
        JSValue right = forNode(node->child2()).value();
        switch (node->binaryUseKind()) {
        case Int32Use:
            if (left && right && left.isInt32() && right.isInt32()) {
                if (!shouldCheckOverflow(node->arithMode())) {
                    setConstant(node, jsNumber(left.asInt32() * right.asInt32()));
                    break;
                }
                double doubleResult = left.asNumber() * right.asNumber();
                if (!shouldCheckNegativeZero(node->arithMode()))
                    doubleResult += 0; // Sanitizes zero.
                JSValue valueResult = jsNumber(doubleResult);
                if (valueResult.isInt32()) {
                    setConstant(node, valueResult);
                    break;
                }
            }
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Int52RepUse:
            if (left && right && left.isAnyInt() && right.isAnyInt()) {
                double doubleResult = left.asNumber() * right.asNumber();
                if (!shouldCheckNegativeZero(node->arithMode()))
                    doubleResult += 0;
                JSValue valueResult = jsNumber(doubleResult);
                if (valueResult.isAnyInt()) {
                    setConstant(node, valueResult);
                    break;
                }
            }
            setNonCellTypeForNode(node, SpecInt52Any);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
                break;
            }
            setNonCellTypeForNode(node, 
                typeOfDoubleProduct(
                    forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }
        
    case ValueMod:
    case ValueDiv: {
        if (handleConstantDivOp(node))
            break;

        if (node->isBinaryUseKind(HeapBigIntUse)) {
            // FIXME: We will want an arithmetic mode here that allows us to speculate or dictate
            // the format of our result:
            // https://bugs.webkit.org/show_bug.cgi?id=210982
            setTypeForNode(node, SpecBigInt);
        } else if (node->binaryUseKind() == AnyBigIntUse || node->binaryUseKind() == BigInt32Use)
            setTypeForNode(node, SpecBigInt);
        else {
            clobberWorld();
            setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
        }
        break;
    }

    case ArithMod:
    case ArithDiv: {
        if (handleConstantDivOp(node))
            break;

        switch (node->binaryUseKind()) {
        case Int32Use:
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case DoubleRepUse:
            if (node->op() == ArithDiv) {
                setNonCellTypeForNode(node, 
                    typeOfDoubleQuotient(
                        forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            } else {
                setNonCellTypeForNode(node, 
                    typeOfDoubleBinaryOp(
                        forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            }
            
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }

    case ArithMin: {
        JSValue left = forNode(node->child1()).value();
        JSValue right = forNode(node->child2()).value();
        switch (node->binaryUseKind()) {
        case Int32Use:
            if (left && right && left.isInt32() && right.isInt32()) {
                setConstant(node, jsNumber(std::min(left.asInt32(), right.asInt32())));
                break;
            }
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                double a = left.asNumber();
                double b = right.asNumber();
                setConstant(node, jsDoubleNumber(a < b ? a : (b <= a ? b : a + b)));
                break;
            }
            setNonCellTypeForNode(node, 
                typeOfDoubleMinMax(
                    forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }
            
    case ArithMax: {
        JSValue left = forNode(node->child1()).value();
        JSValue right = forNode(node->child2()).value();
        switch (node->binaryUseKind()) {
        case Int32Use:
            if (left && right && left.isInt32() && right.isInt32()) {
                setConstant(node, jsNumber(std::max(left.asInt32(), right.asInt32())));
                break;
            }
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                double a = left.asNumber();
                double b = right.asNumber();
                setConstant(node, jsDoubleNumber(a > b ? a : (b >= a ? b : a + b)));
                break;
            }
            setNonCellTypeForNode(node, 
                typeOfDoubleMinMax(
                    forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }
            
    case ArithAbs: {
        JSValue child = forNode(node->child1()).value();
        switch (node->child1().useKind()) {
        case Int32Use:
            if (Optional<double> number = child.toNumberFromPrimitive()) {
                JSValue result = jsNumber(fabs(*number));
                if (result.isInt32()) {
                    setConstant(node, result);
                    break;
                }
            }
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case DoubleRepUse:
            if (Optional<double> number = child.toNumberFromPrimitive()) {
                setConstant(node, jsDoubleNumber(fabs(*number)));
                break;
            }
            setNonCellTypeForNode(node, typeOfDoubleAbs(forNode(node->child1()).m_type));
            break;
        default:
            DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
            clobberWorld();
            setNonCellTypeForNode(node, SpecBytecodeNumber);
            break;
        }
        break;
    }

    case ArithPow: {
        JSValue childY = forNode(node->child2()).value();
        if (childY && childY.isNumber()) {
            if (!childY.asNumber()) {
                setConstant(node, jsDoubleNumber(1));
                break;
            }

            JSValue childX = forNode(node->child1()).value();
            if (childX && childX.isNumber()) {
                setConstant(node, jsDoubleNumber(operationMathPow(childX.asNumber(), childY.asNumber())));
                break;
            }
        }
        setNonCellTypeForNode(node, typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
        break;
    }

    case ArithRandom: {
        setNonCellTypeForNode(node, SpecDoubleReal);
        break;
    }

    case ArithRound:
    case ArithFloor:
    case ArithCeil:
    case ArithTrunc: {
        JSValue operand = forNode(node->child1()).value();
        if (Optional<double> number = operand.toNumberFromPrimitive()) {
            if (node->child1().useKind() != DoubleRepUse)
                didFoldClobberWorld();
            
            double roundedValue = 0;
            if (node->op() == ArithRound)
                roundedValue = jsRound(*number);
            else if (node->op() == ArithFloor)
                roundedValue = floor(*number);
            else if (node->op() == ArithCeil)
                roundedValue = ceil(*number);
            else {
                ASSERT(node->op() == ArithTrunc);
                roundedValue = trunc(*number);
            }

            if (node->child1().useKind() == UntypedUse) {
                setConstant(node, jsNumber(roundedValue));
                break;
            }
            if (producesInteger(node->arithRoundingMode())) {
                int32_t roundedValueAsInt32 = static_cast<int32_t>(roundedValue);
                if (roundedValueAsInt32 == roundedValue) {
                    if (shouldCheckNegativeZero(node->arithRoundingMode())) {
                        if (roundedValueAsInt32 || !std::signbit(roundedValue)) {
                            setConstant(node, jsNumber(roundedValueAsInt32));
                            break;
                        }
                    } else {
                        setConstant(node, jsNumber(roundedValueAsInt32));
                        break;
                    }
                }
            } else {
                setConstant(node, jsDoubleNumber(roundedValue));
                break;
            }
        }
        if (node->child1().useKind() == DoubleRepUse) {
            if (producesInteger(node->arithRoundingMode()))
                setNonCellTypeForNode(node, SpecInt32Only);
            else if (node->child1().useKind() == DoubleRepUse)
                setNonCellTypeForNode(node, typeOfDoubleRounding(forNode(node->child1()).m_type));
        } else {
            DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
            clobberWorld();
            setNonCellTypeForNode(node, SpecBytecodeNumber);
        }
        break;
    }
            
    case ArithSqrt:
        executeDoubleUnaryOpEffects(node, sqrt);
        break;

    case ArithFRound:
        executeDoubleUnaryOpEffects(node, [](double value) -> double { return static_cast<float>(value); });
        break;
        
    case ArithUnary:
        executeDoubleUnaryOpEffects(node, arithUnaryFunction(node->arithUnaryType()));
        break;
            
    case LogicalNot: {
        switch (booleanResult(node, forNode(node->child1()))) {
        case DefinitelyTrue:
            setConstant(node, jsBoolean(false));
            break;
        case DefinitelyFalse:
            setConstant(node, jsBoolean(true));
            break;
        default:
            setNonCellTypeForNode(node, SpecBoolean);
            break;
        }
        break;
    }

    case MapHash: {
        if (JSValue key = forNode(node->child1()).value()) {
            if (Optional<uint32_t> hash = concurrentJSMapHash(key)) {
                // Although C++ code uses uint32_t for the hash, the closest type in DFG IR is Int32
                // and that's what MapHash returns. So, we have to cast to int32_t to avoid large
                // unsigned values becoming doubles. This casting between signed and unsigned
                // happens in the assembly code we emit when we don't constant fold this node.
                setConstant(node, jsNumber(static_cast<int32_t>(*hash)));
                break;
            }
        }
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }

    case NormalizeMapKey: {
        if (JSValue key = forNode(node->child1()).value()) {
            setConstant(node, *m_graph.freeze(normalizeMapKey(key)));
            break;
        }

        SpeculatedType typeMaybeNormalized = (SpecFullNumber & ~SpecInt32Only);
        if (!(forNode(node->child1()).m_type & typeMaybeNormalized)) {
            m_state.setShouldTryConstantFolding(true);
            forNode(node) = forNode(node->child1());
            break;
        }

        makeHeapTopForNode(node);
        break;
    }

    case StringValueOf: {
        clobberWorld();
        setTypeForNode(node, SpecString);
        break;
    }

    case StringSlice: {
        setTypeForNode(node, SpecString);
        break;
    }

    case ToLowerCase: {
        setTypeForNode(node, SpecString);
        break;
    }

    case LoadKeyFromMapBucket:
    case LoadValueFromMapBucket:
    case ExtractValueFromWeakMapGet:
        makeHeapTopForNode(node);
        break;

    case GetMapBucket:
    case GetMapBucketHead:
        if (node->child1().useKind() == MapObjectUse)
            setForNode(node, m_vm.hashMapBucketMapStructure.get());
        else {
            ASSERT(node->child1().useKind() == SetObjectUse);
            setForNode(node, m_vm.hashMapBucketSetStructure.get());
        }
        break;

    case GetMapBucketNext:
        if (node->bucketOwnerType() == BucketOwnerType::Map)
            setForNode(node, m_vm.hashMapBucketMapStructure.get());
        else {
            ASSERT(node->bucketOwnerType() == BucketOwnerType::Set);
            setForNode(node, m_vm.hashMapBucketSetStructure.get());
        }
        break;

    case SetAdd:
        setForNode(node, m_vm.hashMapBucketSetStructure.get());
        break;

    case MapSet:
        setForNode(node, m_vm.hashMapBucketMapStructure.get());
        break;

    case WeakSetAdd:
    case WeakMapSet:
        break;

    case WeakMapGet:
        makeBytecodeTopForNode(node);
        break;

    case IsEmpty:
    case IsUndefined:
    case IsUndefinedOrNull:
    case IsBoolean:
    case IsNumber:
    case IsBigInt:
    case NumberIsInteger:
    case IsObject:
    case IsObjectOrNull:
    case IsFunction:
    case IsConstructor:
    case IsCellWithType:
    case IsTypedArrayView: {
        AbstractValue child = forNode(node->child1());
        if (child.value()) {
            bool constantWasSet = true;
            switch (node->op()) {
            case IsCellWithType:
                setConstant(node, jsBoolean(child.value().isCell() && child.value().asCell()->type() == node->queriedType()));
                break;
            case IsUndefined:
                setConstant(node, jsBoolean(
                    child.value().isCell()
                    ? child.value().asCell()->structure(m_vm)->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
                    : child.value().isUndefined()));
                break;
            case IsUndefinedOrNull:
                setConstant(node, jsBoolean(child.value().isUndefinedOrNull()));
                break;
            case IsBoolean:
                setConstant(node, jsBoolean(child.value().isBoolean()));
                break;
            case IsNumber:
                setConstant(node, jsBoolean(child.value().isNumber()));
                break;
            case IsBigInt:
                setConstant(node, jsBoolean(child.value().isBigInt()));
                break;
            case NumberIsInteger:
                setConstant(node, jsBoolean(NumberConstructor::isIntegerImpl(child.value())));
                break;
            case IsObject:
                setConstant(node, jsBoolean(child.value().isObject()));
                break;
            case IsObjectOrNull:
                if (child.value().isObject()) {
                    JSObject* object = asObject(child.value());
                    if (object->type() == JSFunctionType)
                        setConstant(node, jsBoolean(false));
                    else if (!(object->inlineTypeFlags() & OverridesGetCallData))
                        setConstant(node, jsBoolean(!child.value().asCell()->structure(m_vm)->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))));
                    else {
                        // FIXME: This could just call getCallData.
                        // https://bugs.webkit.org/show_bug.cgi?id=144457
                        constantWasSet = false;
                    }
                } else
                    setConstant(node, jsBoolean(child.value().isNull()));
                break;
            case IsFunction:
                if (child.value().isObject()) {
                    JSObject* object = asObject(child.value());
                    if (object->type() == JSFunctionType)
                        setConstant(node, jsBoolean(true));
                    else if (!(object->inlineTypeFlags() & OverridesGetCallData))
                        setConstant(node, jsBoolean(false));
                    else {
                        // FIXME: This could just call getCallData.
                        // https://bugs.webkit.org/show_bug.cgi?id=144457
                        constantWasSet = false;
                    }
                } else
                    setConstant(node, jsBoolean(false));
                break;
            case IsConstructor:
                setConstant(node, jsBoolean(child.value().isConstructor(m_vm)));
                break;
            case IsEmpty:
                setConstant(node, jsBoolean(child.value().isEmpty()));
                break;
            case IsTypedArrayView:
                setConstant(node, jsBoolean(child.value().isObject() && isTypedView(child.value().getObject()->classInfo(m_vm)->typedArrayStorageType)));
                break;
            default:
                constantWasSet = false;
                break;
            }
            if (constantWasSet)
                break;
        }

        if (!(child.m_type & ~SpecCell)) {
            if (child.m_structure.isFinite()) {
                bool constantWasSet = false;
                switch (node->op()) {
                case IsCellWithType: {
                    bool ok = true;
                    Optional<bool> result;
                    child.m_structure.forEach(
                        [&] (RegisteredStructure structure) {
                            bool matched = structure->typeInfo().type() == node->queriedType();
                            if (!result)
                                result = matched;
                            else {
                                if (result.value() != matched)
                                    ok = false;
                            }
                        });
                    if (ok && result) {
                        setConstant(node, jsBoolean(result.value()));
                        constantWasSet = true;
                    }
                    break;
                }
                default:
                    break;
                }
                if (constantWasSet)
                    break;
            }
        }

        // FIXME: This code should really use AbstractValue::isType() and
        // AbstractValue::couldBeType().
        // https://bugs.webkit.org/show_bug.cgi?id=146870
        
        bool constantWasSet = false;
        switch (node->op()) {
        case IsEmpty: {
            if (child.m_type && !(child.m_type & SpecEmpty)) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }

            if (child.m_type && !(child.m_type & ~SpecEmpty)) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }

            break;
        }
        case IsUndefined:
            // FIXME: Use the masquerades-as-undefined watchpoint thingy.
            // https://bugs.webkit.org/show_bug.cgi?id=144456
            
            if (!(child.m_type & (SpecOther | SpecObjectOther))) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            
            break;
        case IsUndefinedOrNull:
            if (!(child.m_type & ~SpecOther)) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }

            if (!(child.m_type & SpecOther)) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            break;
        case IsBoolean:
            if (!(child.m_type & ~SpecBoolean)) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }
            
            if (!(child.m_type & SpecBoolean)) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            
            break;
        case IsNumber:
            if (!(child.m_type & ~SpecFullNumber)) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }
            
            if (!(child.m_type & SpecFullNumber)) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            
            break;
        case IsBigInt:
            if (!(child.m_type & ~SpecBigInt)) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }

            if (!(child.m_type & SpecBigInt)) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }

            // FIXME: if the SpeculatedType informs us that we won't have a BigInt32 (or that we won't have a HeapBigInt), then we can transform this node into a IsCellWithType(HeapBigIntType) (or a hypothetical IsBigInt32 node).

            break;
        case NumberIsInteger:
            if (!(child.m_type & ~SpecInt32Only)) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }
            
            if (!(child.m_type & SpecFullNumber)) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            
            break;

        case IsObject:
            if (!(child.m_type & ~SpecObject)) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }
            
            if (!(child.m_type & SpecObject)) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            
            break;
        case IsObjectOrNull:
            // FIXME: Use the masquerades-as-undefined watchpoint thingy.
            // https://bugs.webkit.org/show_bug.cgi?id=144456
            
            // These expressions are complicated to parse. A helpful way to parse this is that
            // "!(T & ~S)" means "T is a subset of S". Conversely, "!(T & S)" means "T is a
            // disjoint set from S". Things like "T - S" means that, provided that S is a
            // subset of T, it's the "set of all things in T but not in S". Things like "T | S"
            // mean the "union of T and S".
            
            // Is the child's type an object that isn't an other-object (i.e. object that could
            // have masquaredes-as-undefined traps) and isn't a function?  Then: we should fold
            // this to true.
            if (!(child.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }
            
            // Is the child's type definitely not either of: an object that isn't a function,
            // or either undefined or null?  Then: we should fold this to false.  This means
            // for example that if it's any non-function object, including those that have
            // masquerades-as-undefined traps, then we don't fold. It also means we won't fold
            // if it's undefined-or-null, since the type bits don't distinguish between
            // undefined (which should fold to false) and null (which should fold to true).
            if (!(child.m_type & ((SpecObject - SpecFunction) | SpecOther))) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            
            break;
        case IsFunction:
            if (!(child.m_type & ~SpecFunction)) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }
            
            if (!(child.m_type & (SpecFunction | SpecObjectOther | SpecProxyObject))) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            break;
        case IsConstructor:
            // FIXME: We can speculate constructability from child's m_structure.
            // https://bugs.webkit.org/show_bug.cgi?id=211796
            if (!(child.m_type & (SpecFunction | SpecProxyObject))) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }

            break;
        case IsCellWithType: {
            Optional<SpeculatedType> filter = node->speculatedTypeForQuery();
            if (!filter) {
                if (!(child.m_type & SpecCell)) {
                    setConstant(node, jsBoolean(false));
                    constantWasSet = true;
                }
                break;
            }
            if (!(child.m_type & ~filter.value())) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }
            if (!(child.m_type & filter.value())) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            break;
        }

        case IsTypedArrayView:
            if (!(child.m_type & ~SpecTypedArrayView)) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }
            if (!(child.m_type & SpecTypedArrayView)) {
                setConstant(node, jsBoolean(false));
                constantWasSet = true;
                break;
            }
            break;

        default:
            break;
        }
        if (constantWasSet)
            break;
        
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }

    case TypeOf: {
        JSValue child = forNode(node->child1()).value();
        AbstractValue& abstractChild = forNode(node->child1());
        if (child) {
            JSValue typeString = jsTypeStringForValue(m_vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
            setConstant(node, *m_graph.freeze(typeString));
            break;
        }
        
        if (isFullNumberSpeculation(abstractChild.m_type)) {
            setConstant(node, *m_graph.freeze(m_vm.smallStrings.numberString()));
            break;
        }
        
        if (isStringSpeculation(abstractChild.m_type)) {
            setConstant(node, *m_graph.freeze(m_vm.smallStrings.stringString()));
            break;
        }

        // FIXME: We could use the masquerades-as-undefined watchpoint here.
        // https://bugs.webkit.org/show_bug.cgi?id=144456
        if (!(abstractChild.m_type & ~(SpecObject - SpecObjectOther - SpecFunction))) {
            setConstant(node, *m_graph.freeze(m_vm.smallStrings.objectString()));
            break;
        }
        
        if (isFunctionSpeculation(abstractChild.m_type)) {
            setConstant(node, *m_graph.freeze(m_vm.smallStrings.functionString()));
            break;
        }
        
        if (isBooleanSpeculation(abstractChild.m_type)) {
            setConstant(node, *m_graph.freeze(m_vm.smallStrings.booleanString()));
            break;
        }

        if (isSymbolSpeculation(abstractChild.m_type)) {
            setConstant(node, *m_graph.freeze(m_vm.smallStrings.symbolString()));
            break;
        }

        if (isBigIntSpeculation(abstractChild.m_type)) {
            setConstant(node, *m_graph.freeze(m_vm.smallStrings.bigintString()));
            break;
        }

        setTypeForNode(node, SpecStringIdent);
        break;
    }

    case CompareBelow:
    case CompareBelowEq: {
        JSValue leftConst = forNode(node->child1()).value();
        JSValue rightConst = forNode(node->child2()).value();
        if (leftConst && rightConst) {
            if (leftConst.isInt32() && rightConst.isInt32()) {
                uint32_t a = static_cast<uint32_t>(leftConst.asInt32());
                uint32_t b = static_cast<uint32_t>(rightConst.asInt32());
                switch (node->op()) {
                case CompareBelow:
                    setConstant(node, jsBoolean(a < b));
                    break;
                case CompareBelowEq:
                    setConstant(node, jsBoolean(a <= b));
                    break;
                default:
                    RELEASE_ASSERT_NOT_REACHED();
                    break;
                }
                break;
            }
        }

        if (node->child1() == node->child2()) {
            switch (node->op()) {
            case CompareBelow:
                setConstant(node, jsBoolean(false));
                break;
            case CompareBelowEq:
                setConstant(node, jsBoolean(true));
                break;
            default:
                DFG_CRASH(m_graph, node, "Unexpected node type");
                break;
            }
            break;
        }
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }

    case CompareLess:
    case CompareLessEq:
    case CompareGreater:
    case CompareGreaterEq:
    case CompareEq: {
        bool isClobbering = node->isBinaryUseKind(UntypedUse);
        
        if (isClobbering)
            didFoldClobberWorld();
        
        JSValue leftConst = forNode(node->child1()).value();
        JSValue rightConst = forNode(node->child2()).value();
        if (leftConst && rightConst) {
            if (leftConst.isNumber() && rightConst.isNumber()) {
                auto compareNumber = [&](double a, double b) {
                    switch (node->op()) {
                    case CompareLess:
                        return jsBoolean(a < b);
                    case CompareLessEq:
                        return jsBoolean(a <= b);
                    case CompareGreater:
                        return jsBoolean(a > b);
                    case CompareGreaterEq:
                        return jsBoolean(a >= b);
                    case CompareEq:
                        return jsBoolean(a == b);
                    default:
                        RELEASE_ASSERT_NOT_REACHED();
                        break;
                    }
                };
                double a = leftConst.asNumber();
                double b = rightConst.asNumber();
                setConstant(node, compareNumber(a, b));
                break;
            }

            if (leftConst.isBigInt() && rightConst.isBigInt()) {
                switch (node->op()) {
                case CompareLess:
                    setConstant(node, jsBoolean(bigIntCompareResult(compareBigInt(leftConst, rightConst), JSBigInt::ComparisonMode::LessThan)));
                    break;
                case CompareLessEq:
                    setConstant(node, jsBoolean(bigIntCompareResult(compareBigInt(leftConst, rightConst), JSBigInt::ComparisonMode::LessThanOrEqual)));
                    break;
                case CompareGreater:
                    setConstant(node, jsBoolean(bigIntCompareResult(compareBigInt(rightConst, leftConst), JSBigInt::ComparisonMode::LessThan)));
                    break;
                case CompareGreaterEq:
                    setConstant(node, jsBoolean(bigIntCompareResult(compareBigInt(rightConst, leftConst), JSBigInt::ComparisonMode::LessThanOrEqual)));
                    break;
                case CompareEq:
                    setConstant(node, jsBoolean(compareBigInt(leftConst, rightConst) == JSBigInt::ComparisonResult::Equal));
                    break;
                default:
                    RELEASE_ASSERT_NOT_REACHED();
                    break;
                }
                break;
            }
            
            if (leftConst.isString() && rightConst.isString()) {
                const StringImpl* a = asString(leftConst)->tryGetValueImpl();
                const StringImpl* b = asString(rightConst)->tryGetValueImpl();
                if (a && b) {
                    bool result;
                    if (node->op() == CompareEq)
                        result = WTF::equal(a, b);
                    else if (node->op() == CompareLess)
                        result = codePointCompare(a, b) < 0;
                    else if (node->op() == CompareLessEq)
                        result = codePointCompare(a, b) <= 0;
                    else if (node->op() == CompareGreater)
                        result = codePointCompare(a, b) > 0;
                    else if (node->op() == CompareGreaterEq)
                        result = codePointCompare(a, b) >= 0;
                    else
                        RELEASE_ASSERT_NOT_REACHED();
                    setConstant(node, jsBoolean(result));
                    break;
                }
            }

            if (node->op() == CompareEq && leftConst.isSymbol() && rightConst.isSymbol()) {
                setConstant(node, jsBoolean(asSymbol(leftConst) == asSymbol(rightConst)));
                break;
            }
        }
        
        if (node->op() == CompareEq) {
            SpeculatedType leftType = forNode(node->child1()).m_type;
            SpeculatedType rightType = forNode(node->child2()).m_type;
            if (!valuesCouldBeEqual(leftType, rightType)) {
                setConstant(node, jsBoolean(false));
                break;
            }

            if (leftType == SpecOther)
                std::swap(leftType, rightType);
            if (rightType == SpecOther) {
                // Undefined and Null are always equal when compared to eachother.
                if (!(leftType & ~SpecOther)) {
                    setConstant(node, jsBoolean(true));
                    break;
                }

                // Any other type compared to Null or Undefined is always false
                // as long as the MasqueradesAsUndefined watchpoint is valid.
                //
                // MasqueradesAsUndefined only matters for SpecObjectOther, other
                // cases are always "false".
                if (!(leftType & (SpecObjectOther | SpecOther))) {
                    setConstant(node, jsBoolean(false));
                    break;
                }

                if (!(leftType & SpecOther) && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic)) {
                    JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
                    m_graph.watchpoints().addLazily(globalObject->masqueradesAsUndefinedWatchpoint());
                    setConstant(node, jsBoolean(false));
                    break;
                }
            }
        }
        
        if (node->child1() == node->child2()) {
            if (node->isBinaryUseKind(Int32Use) ||
                node->isBinaryUseKind(Int52RepUse) ||
                node->isBinaryUseKind(BigInt32Use) ||
                node->isBinaryUseKind(HeapBigIntUse) ||
                node->isBinaryUseKind(AnyBigIntUse) ||
                node->isBinaryUseKind(StringUse) ||
                node->isBinaryUseKind(BooleanUse) ||
                node->isBinaryUseKind(SymbolUse) ||
                node->isBinaryUseKind(StringIdentUse) ||
                node->isBinaryUseKind(ObjectUse) ||
                node->isBinaryUseKind(ObjectUse, ObjectOrOtherUse) ||
                node->isBinaryUseKind(ObjectOrOtherUse, ObjectUse)) {
                switch (node->op()) {
                case CompareLess:
                case CompareGreater:
                    setConstant(node, jsBoolean(false));
                    break;
                case CompareLessEq:
                case CompareGreaterEq:
                case CompareEq:
                    setConstant(node, jsBoolean(true));
                    break;
                default:
                    DFG_CRASH(m_graph, node, "Unexpected node type");
                    break;
                }
                break;
            }
        }

        if (isClobbering)
            clobberWorld();
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }
            
    case CompareStrictEq:
    case SameValue: {
        Node* leftNode = node->child1().node();
        Node* rightNode = node->child2().node();
        JSValue left = forNode(leftNode).value();
        JSValue right = forNode(rightNode).value();
        if (left && right) {
            if (left.isString() && right.isString()) {
                // We need this case because JSValue::strictEqual is otherwise too racy for
                // string comparisons.
                const StringImpl* a = asString(left)->tryGetValueImpl();
                const StringImpl* b = asString(right)->tryGetValueImpl();
                if (a && b) {
                    setConstant(node, jsBoolean(WTF::equal(a, b)));
                    break;
                }
            } else {
                if (node->op() == CompareStrictEq)
                    setConstant(node, jsBoolean(JSValue::strictEqual(nullptr, left, right)));
                else
                    setConstant(node, jsBoolean(sameValue(nullptr, left, right)));
                break;
            }
        }

        // FIXME: why is this check here, and not later (after the type-based replacement by false).
        // Saam seems to agree that the two checks could be switched, I'll try that in a separate patch
        if (node->isBinaryUseKind(UntypedUse)) {
            auto isNonStringAndNonBigIntCellConstant = [] (JSValue value) {
                return value && value.isCell() && !value.isString() && !value.isHeapBigInt();
            };

            if (isNonStringAndNonBigIntCellConstant(left) || isNonStringAndNonBigIntCellConstant(right)) {
                m_state.setShouldTryConstantFolding(true);
                setNonCellTypeForNode(node, SpecBoolean);
                break;
            }
        }
        
        SpeculatedType leftLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(leftNode).m_type);
        SpeculatedType rightLUB = leastUpperBoundOfStrictlyEquivalentSpeculations(forNode(rightNode).m_type);
        if (!(leftLUB & rightLUB)) {
            setConstant(node, jsBoolean(false));
            break;
        }
        
        if (node->child1() == node->child2()) {
            // FIXME: Is there any case not involving NaN where x === x is not guaranteed to return true?
            // If not I might slightly simplify that check.
            if (node->isBinaryUseKind(BooleanUse)
                || node->isBinaryUseKind(Int32Use)
                || node->isBinaryUseKind(Int52RepUse)
                || node->isBinaryUseKind(StringUse)
                || node->isBinaryUseKind(StringIdentUse)
                || node->isBinaryUseKind(SymbolUse)
                || node->isBinaryUseKind(ObjectUse)
                || node->isBinaryUseKind(MiscUse, UntypedUse)
                || node->isBinaryUseKind(UntypedUse, MiscUse)
                || node->isBinaryUseKind(StringIdentUse, NotStringVarUse)
                || node->isBinaryUseKind(NotStringVarUse, StringIdentUse)
                || node->isBinaryUseKind(StringUse, UntypedUse)
                || node->isBinaryUseKind(UntypedUse, StringUse)
                || node->isBinaryUseKind(BigInt32Use)
                || node->isBinaryUseKind(HeapBigIntUse)
                || node->isBinaryUseKind(AnyBigIntUse)) {
                setConstant(node, jsBoolean(true));
                break;
            }
        }

        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }
        
    case CompareEqPtr: {
        Node* childNode = node->child1().node();
        JSValue childValue = forNode(childNode).value();
        if (childValue) {
            setConstant(node, jsBoolean(childValue.isCell() && childValue.asCell() == node->cellOperand()->cell()));
            break;
        }
        
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }
        
    case StringCharCodeAt:
    case StringCodePointAt:
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
        
    case StringFromCharCode:
        switch (node->child1().useKind()) {
        case Int32Use:
            break;
        case UntypedUse:
            clobberWorld();
            break;
        default:
            DFG_CRASH(m_graph, node, "Bad use kind");
            break;
        }
        setTypeForNode(node, SpecString);
        break;

    case StringCharAt:
        setForNode(node, m_vm.stringStructure.get());
        break;
            
    case GetByVal:
    case AtomicsAdd:
    case AtomicsAnd:
    case AtomicsCompareExchange:
    case AtomicsExchange:
    case AtomicsLoad:
    case AtomicsOr:
    case AtomicsStore:
    case AtomicsSub:
    case AtomicsXor: {
        if (node->op() == GetByVal) {
            auto foldGetByValOnConstantProperty = [&] (Edge& arrayEdge, Edge& indexEdge) {
                // FIXME: We can expand this for non x86 environments.
                // https://bugs.webkit.org/show_bug.cgi?id=134641
                if (!isX86())
                    return false;

                AbstractValue& arrayValue = forNode(arrayEdge);

                // Check the structure set is finite. This means that this constant's structure is watched and guaranteed the one of this set.
                // When the structure is changed, this code should be invalidated. This is important since the following code relies on the
                // constant object's is not changed.
                if (!arrayValue.m_structure.isFinite())
                    return false;

                JSValue arrayConstant = arrayValue.value();
                if (!arrayConstant)
                    return false;

                JSObject* array = jsDynamicCast<JSObject*>(m_vm, arrayConstant);
                if (!array)
                    return false;

                JSValue indexConstant = forNode(indexEdge).value();
                if (!indexConstant || !indexConstant.isInt32() || indexConstant.asInt32() < 0)
                    return false;
                uint32_t index = indexConstant.asUInt32();

                // Check that the early StructureID is not nuked, get the butterfly, and check the late StructureID again.
                // And we check the indexing mode of the structure. If the indexing mode is CoW, the butterfly is
                // definitely JSImmutableButterfly.
                StructureID structureIDEarly = array->structureID();
                if (isNuked(structureIDEarly))
                    return false;

                if (node->arrayMode().arrayClass() == Array::OriginalCopyOnWriteArray) {

                    WTF::loadLoadFence();
                    Butterfly* butterfly = array->butterfly();

                    WTF::loadLoadFence();
                    StructureID structureIDLate = array->structureID();

                    if (structureIDEarly != structureIDLate)
                        return false;

                    Structure* structure = m_vm.getStructure(structureIDLate);
                    switch (node->arrayMode().type()) {
                    case Array::Int32:
                    case Array::Contiguous:
                    case Array::Double:
                        if (structure->indexingMode() != (toIndexingShape(node->arrayMode().type()) | CopyOnWrite | IsArray))
                            return false;
                        break;
                    default:
                        return false;
                    }
                    ASSERT(isCopyOnWrite(structure->indexingMode()));

                    JSImmutableButterfly* immutableButterfly = JSImmutableButterfly::fromButterfly(butterfly);
                    if (index < immutableButterfly->length()) {
                        JSValue value = immutableButterfly->get(index);
                        ASSERT(value);
                        if (value.isCell())
                            setConstant(node, *m_graph.freeze(value.asCell()));
                        else
                            setConstant(node, value);
                        return true;
                    }

                    if (node->arrayMode().isOutOfBounds()) {
                        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
                        Structure* arrayPrototypeStructure = globalObject->arrayPrototype()->structure(m_vm);
                        Structure* objectPrototypeStructure = globalObject->objectPrototype()->structure(m_vm);
                        if (arrayPrototypeStructure->transitionWatchpointSetIsStillValid()
                            && objectPrototypeStructure->transitionWatchpointSetIsStillValid()
                            && globalObject->arrayPrototypeChainIsSane()) {
                            m_graph.registerAndWatchStructureTransition(arrayPrototypeStructure);
                            m_graph.registerAndWatchStructureTransition(objectPrototypeStructure);
                            // Note that Array::Double and Array::Int32 return JSValue if array mode is OutOfBounds.
                            setConstant(node, jsUndefined());
                            return true;
                        }
                    }
                    return false;
                }

                if (node->arrayMode().type() == Array::ArrayStorage || node->arrayMode().type() == Array::SlowPutArrayStorage) {
                    JSValue value;
                    {
                        // ArrayStorage's Butterfly can be half-broken state.
                        auto locker = holdLock(array->cellLock());

                        WTF::loadLoadFence();
                        Butterfly* butterfly = array->butterfly();

                        WTF::loadLoadFence();
                        StructureID structureIDLate = array->structureID();

                        if (structureIDEarly != structureIDLate)
                            return false;

                        Structure* structure = m_vm.getStructure(structureIDLate);
                        if (!hasAnyArrayStorage(structure->indexingMode()))
                            return false;

                        if (structure->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero())
                            return false;

                        ArrayStorage* storage = butterfly->arrayStorage();
                        if (index >= storage->length())
                            return false;

                        if (index < storage->vectorLength())
                            return false;

                        SparseArrayValueMap* map = storage->m_sparseMap.get();
                        if (!map)
                            return false;

                        value = map->getConcurrently(index);
                    }
                    if (!value)
                        return false;

                    if (value.isCell())
                        setConstant(node, *m_graph.freeze(value.asCell()));
                    else
                        setConstant(node, value);
                    return true;
                }

                return false;
            };

            bool didFold = false;
            switch (node->arrayMode().type()) {
            case Array::Generic:
            case Array::Int32:
            case Array::Double:
            case Array::Contiguous:
            case Array::ArrayStorage:
            case Array::SlowPutArrayStorage:
                if (foldGetByValOnConstantProperty(m_graph.child(node, 0), m_graph.child(node, 1))) {
                    if (!node->arrayMode().isInBounds())
                        didFoldClobberWorld();
                    didFold = true;
                }
                break;
            default:
                break;
            }

            if (didFold)
                break;
        }

        if (node->op() != GetByVal) {
            unsigned numExtraArgs = numExtraAtomicsArgs(node->op());
            Edge storageEdge = m_graph.child(node, 2 + numExtraArgs);
            if (!storageEdge)
                clobberWorld();
        }
        switch (node->arrayMode().type()) {
        case Array::SelectUsingPredictions:
        case Array::Unprofiled:
        case Array::SelectUsingArguments:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        case Array::ForceExit:
            m_state.setIsValid(false);
            break;
        case Array::Undecided: {
            JSValue index = forNode(m_graph.child(node, 1)).value();
            if (index && index.isInt32() && index.asInt32() >= 0) {
                setConstant(node, jsUndefined());
                break;
            }
            setNonCellTypeForNode(node, SpecOther);
            break;
        }
        case Array::Generic:
            clobberWorld();
            makeHeapTopForNode(node);
            break;
        case Array::String:
            if (node->arrayMode().isOutOfBounds()) {
                // If the watchpoint was still valid we could totally set this to be
                // SpecString | SpecOther. Except that we'd have to be careful. If we
                // tested the watchpoint state here then it could change by the time
                // we got to the backend. So to do this right, we'd have to get the
                // fixup phase to check the watchpoint state and then bake into the
                // GetByVal operation the fact that we're using a watchpoint, using
                // something like Array::SaneChain (except not quite, because that
                // implies an in-bounds access). None of this feels like it's worth it,
                // so we're going with TOP for now. The same thing applies to
                // clobbering the world.
                clobberWorld();
                makeHeapTopForNode(node);
            } else
                setForNode(node, m_vm.stringStructure.get());
            break;
        case Array::DirectArguments:
        case Array::ScopedArguments:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld();
            makeHeapTopForNode(node);
            break;
        case Array::Int32:
            if (node->arrayMode().isOutOfBounds()) {
                clobberWorld();
                makeHeapTopForNode(node);
            } else
                setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Array::Double:
            if (node->arrayMode().isOutOfBounds()) {
                clobberWorld();
                makeHeapTopForNode(node);
            } else if (node->arrayMode().isSaneChain())
                setNonCellTypeForNode(node, SpecBytecodeDouble);
            else
                setNonCellTypeForNode(node, SpecDoubleReal);
            break;
        case Array::Contiguous:
        case Array::ArrayStorage:
        case Array::SlowPutArrayStorage:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld();
            makeHeapTopForNode(node);
            break;
        case Array::Int8Array:
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Array::Int16Array:
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Array::Int32Array:
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Array::Uint8Array:
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Array::Uint8ClampedArray:
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Array::Uint16Array:
            setNonCellTypeForNode(node, SpecInt32Only);
            break;
        case Array::Uint32Array:
            if (node->shouldSpeculateInt32())
                setNonCellTypeForNode(node, SpecInt32Only);
            else if (node->shouldSpeculateInt52())
                setNonCellTypeForNode(node, SpecInt52Any);
            else
                setNonCellTypeForNode(node, SpecAnyIntAsDouble);
            break;
        case Array::Float32Array:
            setNonCellTypeForNode(node, SpecFullDouble);
            break;
        case Array::Float64Array:
            setNonCellTypeForNode(node, SpecFullDouble);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }
            
    case PutByValDirect:
    case PutByVal:
    case PutByValAlias: {
        switch (node->arrayMode().modeForPut().type()) {
        case Array::ForceExit:
            m_state.setIsValid(false);
            break;
        case Array::Generic:
            clobberWorld();
            break;
        case Array::Int32:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld();
            break;
        case Array::Double:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld();
            break;
        case Array::Contiguous:
        case Array::ArrayStorage:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld();
            break;
        case Array::SlowPutArrayStorage:
            if (node->arrayMode().mayStoreToHole())
                clobberWorld();
            break;
        default:
            break;
        }
        break;
    }
            
    case ArrayPush:
        clobberWorld();
        setNonCellTypeForNode(node, SpecBytecodeNumber);
        break;

    case ArraySlice: {
        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);

        // FIXME: We could do better here if we prove that the
        // incoming value has only a single structure.
        RegisteredStructureSet structureSet;
        structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithInt32)));
        structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithContiguous)));
        structureSet.add(m_graph.registerStructure(globalObject->originalArrayStructureForIndexingType(ArrayWithDouble)));

        setForNode(node, structureSet);
        break;
    }

    case ArrayIndexOf: {
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }
            
    case ArrayPop:
        clobberWorld();
        makeHeapTopForNode(node);
        break;
        
    case GetMyArgumentByVal:
    case GetMyArgumentByValOutOfBounds: {
        JSValue index = forNode(node->child2()).m_value;
        InlineCallFrame* inlineCallFrame = node->child1()->origin.semantic.inlineCallFrame();

        if (index && index.isUInt32()) {
            // This pretends to return TOP for accesses that are actually proven out-of-bounds because
            // that's the conservative thing to do. Otherwise we'd need to write more code to mark such
            // paths as unreachable, or to return undefined. We could implement that eventually.

            Checked<unsigned, RecordOverflow> argumentIndexChecked = index.asUInt32();
            argumentIndexChecked += node->numberOfArgumentsToSkip();
            unsigned argumentIndex;
            if (argumentIndexChecked.safeGet(argumentIndex) != CheckedState::DidOverflow) {
                if (inlineCallFrame) {
                    if (argumentIndex < static_cast<unsigned>(inlineCallFrame->argumentCountIncludingThis - 1)) {
                        setForNode(node, m_state.operand(
                            virtualRegisterForArgumentIncludingThis(argumentIndex + 1) + inlineCallFrame->stackOffset));
                        m_state.setShouldTryConstantFolding(true);
                        break;
                    }
                } else {
                    if (argumentIndex < m_state.numberOfArguments() - 1) {
                        setForNode(node, m_state.argument(argumentIndex + 1));
                        m_state.setShouldTryConstantFolding(true);
                        break;
                    }
                }
            }
        }
        
        if (inlineCallFrame) {
            // We have a bound on the types even though it's random access. Take advantage of this.
            
            AbstractValue result;
            for (unsigned i = 1 + node->numberOfArgumentsToSkip(); i < inlineCallFrame->argumentCountIncludingThis; ++i) {
                result.merge(
                    m_state.operand(
                        virtualRegisterForArgumentIncludingThis(i) + inlineCallFrame->stackOffset));
            }
            
            if (node->op() == GetMyArgumentByValOutOfBounds)
                result.merge(SpecOther);
            
            if (result.value())
                m_state.setShouldTryConstantFolding(true);
            
            setForNode(node, result);
            break;
        }
        
        makeHeapTopForNode(node);
        break;
    }
            
    case RegExpExec:
    case RegExpExecNonGlobalOrSticky:
        if (node->op() == RegExpExec) {
            // Even if we've proven known input types as RegExpObject and String,
            // accessing lastIndex is effectful if it's a global regexp.
            clobberWorld();
        }

        if (JSValue globalObjectValue = forNode(node->child1()).m_value) {
            if (JSGlobalObject* globalObject = jsDynamicCast<JSGlobalObject*>(m_vm, globalObjectValue)) {
                if (!globalObject->isHavingABadTime()) {
                    m_graph.watchpoints().addLazily(globalObject->havingABadTimeWatchpoint());
                    RegisteredStructureSet structureSet;
                    structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayStructure()));
                    setForNode(node, structureSet);
                    forNode(node).merge(SpecOther);
                    break;
                }
            }
        }
        setTypeForNode(node, SpecOther | SpecArray);
        break;

    case RegExpTest:
        // Even if we've proven known input types as RegExpObject and String,
        // accessing lastIndex is effectful if it's a global regexp.
        clobberWorld();
        setNonCellTypeForNode(node, SpecBoolean);
        break;

    case RegExpMatchFast:
        ASSERT(node->child2().useKind() == RegExpObjectUse);
        ASSERT(node->child3().useKind() == StringUse || node->child3().useKind() == KnownStringUse);
        setTypeForNode(node, SpecOther | SpecArray);
        break;

    case RegExpMatchFastGlobal:
        ASSERT(node->child2().useKind() == StringUse || node->child2().useKind() == KnownStringUse);
        setTypeForNode(node, SpecOther | SpecArray);
        break;
            
    case StringReplace:
    case StringReplaceRegExp:
        if (node->child1().useKind() == StringUse
            && node->child2().useKind() == RegExpObjectUse
            && node->child3().useKind() == StringUse) {
            // This doesn't clobber the world. It just reads and writes regexp state.
        } else
            clobberWorld();
        setForNode(node, m_vm.stringStructure.get());
        break;

    case Jump:
        break;
            
    case Branch: {
        Node* child = node->child1().node();
        BooleanResult result = booleanResult(node, forNode(child));
        if (result == DefinitelyTrue) {
            m_state.setBranchDirection(TakeTrue);
            break;
        }
        if (result == DefinitelyFalse) {
            m_state.setBranchDirection(TakeFalse);
            break;
        }
        // FIXME: The above handles the trivial cases of sparse conditional
        // constant propagation, but we can do better:
        // We can specialize the source variable's value on each direction of
        // the branch.
        m_state.setBranchDirection(TakeBoth);
        break;
    }
        
    case Switch: {
        // Nothing to do for now.
        // FIXME: Do sparse conditional things.
        break;
    }

    case EntrySwitch:
        break;

    case Return:
        m_state.setIsValid(false);
        break;

    case Throw:
    case ThrowStaticError:
    case TailCall:
    case DirectTailCall:
    case TailCallVarargs:
    case TailCallForwardVarargs:
        clobberWorld();
        m_state.setIsValid(false);
        break;
        
    case ToPrimitive: {
        JSValue childConst = forNode(node->child1()).value();
        if (childConst && childConst.isNumber()) {
            didFoldClobberWorld();
            setConstant(node, childConst);
            break;
        }
        
        ASSERT(node->child1().useKind() == UntypedUse);
        
        if (!(forNode(node->child1()).m_type & ~(SpecFullNumber | SpecBoolean | SpecString | SpecSymbol | SpecBigInt))) {
            m_state.setShouldTryConstantFolding(true);
            didFoldClobberWorld();
            setForNode(node, forNode(node->child1()));
            break;
        }
        
        clobberWorld();
        
        setTypeForNode(node, SpecHeapTop & ~SpecObject);
        break;
    }

    case ToPropertyKey: {
        if (!(forNode(node->child1()).m_type & ~(SpecString | SpecSymbol))) {
            m_state.setShouldTryConstantFolding(true);
            didFoldClobberWorld();
            setForNode(node, forNode(node->child1()));
            break;
        }

        clobberWorld();

        setTypeForNode(node, SpecString | SpecSymbol);
        break;
    }

    case ToNumber: {
        JSValue childConst = forNode(node->child1()).value();
        if (childConst && childConst.isNumber()) {
            didFoldClobberWorld();
            setConstant(node, childConst);
            break;
        }

        ASSERT(node->child1().useKind() == UntypedUse);

        if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
            m_state.setShouldTryConstantFolding(true);
            didFoldClobberWorld();
            setForNode(node, forNode(node->child1()));
            break;
        }

        clobberWorld();
        setNonCellTypeForNode(node, SpecBytecodeNumber);
        break;
    }

    case ToNumeric: {
        JSValue childConst = forNode(node->child1()).value();
        if (childConst && (childConst.isNumber() || childConst.isBigInt())) {
            didFoldClobberWorld();
            setConstant(node, childConst);
            break;
        }

        ASSERT(node->child1().useKind() == UntypedUse);

        if (!(forNode(node->child1()).m_type & ~(SpecBytecodeNumber | SpecBigInt))) {
            m_state.setShouldTryConstantFolding(true);
            didFoldClobberWorld();
            setForNode(node, forNode(node->child1()));
            break;
        }

        clobberWorld();
        setTypeForNode(node, SpecBytecodeNumber | SpecBigInt);
        break;
    }

    case CallNumberConstructor: {
        JSValue childConst = forNode(node->child1()).value();
        if (childConst) {
            if (childConst.isNumber()) {
                if (node->child1().useKind() == UntypedUse)
                    didFoldClobberWorld();
                setConstant(node, childConst);
                break;
            }
#if USE(BIGINT32)
            if (childConst.isBigInt32()) {
                if (node->child1().useKind() == UntypedUse)
                    didFoldClobberWorld();
                setConstant(node, jsNumber(childConst.bigInt32AsInt32()));
                break;
            }
#endif
        }

        ASSERT(node->child1().useKind() == UntypedUse || node->child1().useKind() == BigInt32Use);

        if (!(forNode(node->child1()).m_type & ~SpecBytecodeNumber)) {
            m_state.setShouldTryConstantFolding(true);
            if (node->child1().useKind() == UntypedUse)
                didFoldClobberWorld();
            setForNode(node, forNode(node->child1()));
            break;
        }

        if (node->child1().useKind() == BigInt32Use) {
            setTypeForNode(node, SpecInt32Only);
            break;
        }

        clobberWorld();
        setNonCellTypeForNode(node, SpecBytecodeNumber);
        break;
    }
        
    case ToString:
    case CallStringConstructor: {
        switch (node->child1().useKind()) {
        case StringObjectUse:
        case StringOrStringObjectUse:
        case Int32Use:
        case Int52RepUse:
        case DoubleRepUse:
        case NotCellUse:
            break;
        case CellUse:
        case UntypedUse:
            clobberWorld();
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        setForNode(node, m_vm.stringStructure.get());
        break;
    }

    case NumberToStringWithRadix: {
        JSValue radixValue = forNode(node->child2()).m_value;
        if (radixValue && radixValue.isInt32()) {
            int32_t radix = radixValue.asInt32();
            if (2 <= radix && radix <= 36) {
                m_state.setShouldTryConstantFolding(true);
                didFoldClobberWorld();
                setForNode(node, m_graph.m_vm.stringStructure.get());
                break;
            }
        }
        clobberWorld();
        setForNode(node, m_graph.m_vm.stringStructure.get());
        break;
    }

    case NumberToStringWithValidRadixConstant: {
        setForNode(node, m_graph.m_vm.stringStructure.get());
        break;
    }
        
    case NewStringObject: {
        ASSERT(node->structure()->classInfo() == StringObject::info());
        setForNode(node, node->structure());
        break;
    }

    case NewSymbol: {
        setForNode(node, m_vm.symbolStructure.get());
        break;
    }
            
    case NewArray:
        ASSERT(node->indexingMode() == node->indexingType()); // Copy on write arrays should only be created by NewArrayBuffer.
        setForNode(node,
            m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
        break;

    case NewArrayWithSpread:
        if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
            // We've compiled assuming we're not having a bad time, so to be consistent
            // with StructureRegisterationPhase we must say we produce an original array
            // allocation structure.
#if USE(JSVALUE64)
            BitVector* bitVector = node->bitVector();
            if (node->numChildren() == 1 && bitVector->get(0)) {
                Edge use = m_graph.varArgChild(node, 0);
                if (use->op() == PhantomSpread) {
                    if (use->child1()->op() == PhantomNewArrayBuffer) {
                        auto* immutableButterfly = use->child1()->castOperand<JSImmutableButterfly*>();
                        if (hasContiguous(immutableButterfly->indexingType())) {
                            m_state.setShouldTryConstantFolding(true);
                            setForNode(node, m_graph.globalObjectFor(node->origin.semantic)->originalArrayStructureForIndexingType(CopyOnWriteArrayWithContiguous));
                            break;
                        }
                    }
                } else {
                    setForNode(node, m_graph.globalObjectFor(node->origin.semantic)->originalArrayStructureForIndexingType(CopyOnWriteArrayWithContiguous));
                    break;
                }
            }
#endif
            setForNode(node, m_graph.globalObjectFor(node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous));
        } else {
            setForNode(node, 
                m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous));
        }

        break;

    case Spread:
        switch (node->child1()->op()) {
        case PhantomNewArrayBuffer:
        case PhantomCreateRest:
            break;
        default:
            if (!m_graph.canDoFastSpread(node, forNode(node->child1())))
                clobberWorld();
            else
                didFoldClobberWorld();
            break;
        }

        setForNode(node, m_vm.immutableButterflyStructures[arrayIndexFromIndexingType(CopyOnWriteArrayWithContiguous) - NumberOfIndexingShapes].get());
        break;
        
    case NewArrayBuffer:
        setForNode(node,
            m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingMode()));
        break;

    case NewArrayWithSize:
        setTypeForNode(node, SpecArray);
        break;
        
    case NewTypedArray:
        switch (node->child1().useKind()) {
        case Int32Use:
            break;
        case UntypedUse:
            clobberWorld();
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        setForNode(node, 
            m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(
                node->typedArrayType()));
        break;
        
    case NewRegexp:
        setForNode(node, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
        break;
            
    case ToThis: {
        AbstractValue& source = forNode(node->child1());
        AbstractValue& destination = forNode(node);
        ECMAMode ecmaMode = node->ecmaMode();

        ToThisResult result = isToThisAnIdentity(m_vm, ecmaMode, source);
        switch (result) {
        case ToThisResult::Identity:
            m_state.setShouldTryConstantFolding(true);
            destination = source;
            break;
        case ToThisResult::Undefined:
            setConstant(node, jsUndefined());
            break;
        case ToThisResult::GlobalThis:
            m_state.setShouldTryConstantFolding(true);
            destination.setType(m_graph, SpecObject);
            break;
        case ToThisResult::Dynamic:
            if (ecmaMode.isStrict())
                destination.makeHeapTop();
            else {
                destination = source;
                destination.merge(SpecObject);
            }
            break;
        }
        break;
    }

    case CreateThis: {
        if (JSValue base = forNode(node->child1()).m_value) {
            if (auto* function = jsDynamicCast<JSFunction*>(m_vm, base)) {
                if (FunctionRareData* rareData = function->rareData()) {
                    if (rareData->allocationProfileWatchpointSet().isStillValid()) {
                        if (Structure* structure = rareData->objectAllocationStructure()) {
                            m_graph.freeze(rareData);
                            m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
                            m_state.setShouldTryConstantFolding(true);
                            didFoldClobberWorld();
                            setForNode(node, structure);
                            break;
                        }
                    }
                }
            }
        }
        clobberWorld();
        setTypeForNode(node, SpecFinalObject);
        break;
    }

    case CreatePromise: {
        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
        if (JSValue base = forNode(node->child1()).m_value) {
            if (base == (node->isInternalPromise() ? globalObject->internalPromiseConstructor() : globalObject->promiseConstructor())) {
                m_state.setShouldTryConstantFolding(true);
                didFoldClobberWorld();
                setForNode(node, node->isInternalPromise() ? globalObject->internalPromiseStructure() : globalObject->promiseStructure());
                break;
            }
            if (auto* function = jsDynamicCast<JSFunction*>(m_graph.m_vm, base)) {
                if (FunctionRareData* rareData = function->rareData()) {
                    if (rareData->allocationProfileWatchpointSet().isStillValid()) {
                        Structure* structure = rareData->internalFunctionAllocationStructure();
                        if (structure
                            && structure->classInfo() == (node->isInternalPromise() ? JSInternalPromise::info() : JSPromise::info())
                            && structure->globalObject() == globalObject
                            && rareData->allocationProfileWatchpointSet().isStillValid()) {
                            m_graph.freeze(rareData);
                            m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
                            m_state.setShouldTryConstantFolding(true);
                            didFoldClobberWorld();
                            setForNode(node, structure);
                            break;
                        }
                    }
                }
            }
        }
        clobberWorld();
        setTypeForNode(node, SpecPromiseObject);
        break;
    }

    case CreateGenerator:
    case CreateAsyncGenerator: {
        auto tryToFold = [&] (const ClassInfo* classInfo) -> bool {
            JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
            if (JSValue base = forNode(node->child1()).m_value) {
                if (auto* function = jsDynamicCast<JSFunction*>(m_graph.m_vm, base)) {
                    if (FunctionRareData* rareData = function->rareData()) {
                        if (rareData->allocationProfileWatchpointSet().isStillValid()) {
                            Structure* structure = rareData->internalFunctionAllocationStructure();
                            if (structure
                                && structure->classInfo() == classInfo
                                && structure->globalObject() == globalObject
                                && rareData->allocationProfileWatchpointSet().isStillValid()) {
                                m_graph.freeze(rareData);
                                m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
                                m_state.setShouldTryConstantFolding(true);
                                didFoldClobberWorld();
                                setForNode(node, structure);
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        };

        bool found = false;
        switch (node->op()) {
        case CreateGenerator:
            found = tryToFold(JSGenerator::info());
            break;
        case CreateAsyncGenerator:
            found = tryToFold(JSAsyncGenerator::info());
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        if (found)
            break;
        clobberWorld();
        setTypeForNode(node, SpecObjectOther);
        break;
    }

    case NewGenerator:
    case NewAsyncGenerator:    
    case NewInternalFieldObject:
    case NewObject:
    case MaterializeNewInternalFieldObject:
        ASSERT(!!node->structure().get());
        setForNode(node, node->structure());
        break;

    case ObjectCreate: {
        if (JSValue base = forNode(node->child1()).m_value) {
            JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
            Structure* structure = nullptr;
            if (base.isNull())
                structure = globalObject->nullPrototypeObjectStructure();
            else if (base.isObject())
                structure = m_vm.structureCache.emptyObjectStructureConcurrently(globalObject, base.getObject(), JSFinalObject::defaultInlineCapacity());
            
            if (structure) {
                m_state.setShouldTryConstantFolding(true);
                if (node->child1().useKind() == UntypedUse)
                    didFoldClobberWorld();
                setForNode(node, structure);
                break;
            }
        }
        if (node->child1().useKind() == UntypedUse)
            clobberWorld();
        setTypeForNode(node, SpecFinalObject);
        break;
    }

    case ObjectKeys: {
        if (node->child1().useKind() == ObjectUse) {
            auto& structureSet = forNode(node->child1()).m_structure;
            if (structureSet.isFinite() && structureSet.size() == 1) {
                RegisteredStructure structure = structureSet.onlyStructure();
                if (auto* rareData = structure->rareDataConcurrently()) {
                    if (!!rareData->cachedOwnKeysConcurrently()) {
                        if (m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
                            m_state.setShouldTryConstantFolding(true);
                            didFoldClobberWorld();
                            setTypeForNode(node, SpecArray);
                            break;
                        }
                    }
                }
            }
        }

        clobberWorld();
        setTypeForNode(node, SpecArray);
        break;
    }

    case ToObject:
    case CallObjectConstructor: {
        AbstractValue& source = forNode(node->child1());
        AbstractValue& destination = forNode(node);

        if (!(source.m_type & ~SpecObject)) {
            m_state.setShouldTryConstantFolding(true);
            if (node->op() == ToObject)
                didFoldClobberWorld();
            destination = source;
            break;
        }

        if (node->op() == ToObject)
            clobberWorld();
        setTypeForNode(node, SpecObject);
        break;
    }

    case PhantomNewObject:
    case PhantomNewFunction:
    case PhantomNewGeneratorFunction:
    case PhantomNewAsyncGeneratorFunction:
    case PhantomNewAsyncFunction:
    case PhantomCreateActivation:
    case PhantomDirectArguments:
    case PhantomClonedArguments:
    case PhantomCreateRest:
    case PhantomSpread:
    case PhantomNewArrayWithSpread:
    case PhantomNewArrayBuffer:
    case PhantomNewInternalFieldObject:
    case PhantomNewRegexp:
    case BottomValue: {
        clearForNode(node);
        break;
    }

    case PutHint:
        break;
        
    case MaterializeNewObject: {
        setForNode(node, node->structureSet());
        break;
    }

    case PushWithScope:
        // We don't use the more precise withScopeStructure() here because it is a LazyProperty and may not yet be allocated.
        setTypeForNode(node, SpecObjectOther);
        break;

    case CreateActivation:
    case MaterializeCreateActivation:
        setForNode(node, 
            m_codeBlock->globalObjectFor(node->origin.semantic)->activationStructure());
        break;
        
    case CreateDirectArguments:
        setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->directArgumentsStructure());
        break;
        
    case CreateScopedArguments:
        setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->scopedArgumentsStructure());
        break;
        
    case CreateClonedArguments:
        if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
            setTypeForNode(node, SpecObject);
            break;
        }
        setForNode(node, m_codeBlock->globalObjectFor(node->origin.semantic)->clonedArgumentsStructure());
        break;

    case CreateArgumentsButterfly:
        setForNode(node, m_vm.immutableButterflyStructures[arrayIndexFromIndexingType(CopyOnWriteArrayWithContiguous) - NumberOfIndexingShapes].get());
        break;

    case NewGeneratorFunction:
        setForNode(node, 
            m_codeBlock->globalObjectFor(node->origin.semantic)->generatorFunctionStructure());
        break;

    case NewAsyncGeneratorFunction:
        setForNode(node, 
            m_codeBlock->globalObjectFor(node->origin.semantic)->asyncGeneratorFunctionStructure());
        break;

    case NewAsyncFunction:
        setForNode(node, 
            m_codeBlock->globalObjectFor(node->origin.semantic)->asyncFunctionStructure());
        break;

    case NewFunction: {
        JSGlobalObject* globalObject = m_codeBlock->globalObjectFor(node->origin.semantic);
        Structure* structure = JSFunction::selectStructureForNewFuncExp(globalObject, node->castOperand<FunctionExecutable*>());
        setForNode(node, structure);
        break;
    }
        
    case GetCallee:
        if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_vm, m_codeBlock->ownerExecutable())) {
            if (JSFunction* function = executable->singleton().inferredValue()) {
                m_graph.watchpoints().addLazily(executable);
                setConstant(node, *m_graph.freeze(function));
                break;
            }
        }
        setTypeForNode(node, SpecFunction | SpecObjectOther);
        break;
        
    case GetArgumentCountIncludingThis:
        setTypeForNode(node, SpecInt32Only);
        break;

    case SetCallee:
    case SetArgumentCountIncludingThis:
        break;
        
    case GetRestLength:
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
        
    case GetGetter: {
        if (JSValue base = forNode(node->child1()).m_value) {
            GetterSetter* getterSetter = jsDynamicCast<GetterSetter*>(m_vm, base);
            if (getterSetter && !getterSetter->isGetterNull()) {
                setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
                break;
            }
        }
        
        setTypeForNode(node, SpecObject);
        break;
    }
        
    case GetSetter: {
        if (JSValue base = forNode(node->child1()).m_value) {
            GetterSetter* getterSetter = jsDynamicCast<GetterSetter*>(m_vm, base);
            if (getterSetter && !getterSetter->isSetterNull()) {
                setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
                break;
            }
        }
        
        setTypeForNode(node, SpecObject);
        break;
    }
        
    case GetScope:
        if (JSValue base = forNode(node->child1()).m_value) {
            if (JSFunction* function = jsDynamicCast<JSFunction*>(m_vm, base)) {
                setConstant(node, *m_graph.freeze(function->scope()));
                break;
            }
        }
        setTypeForNode(node, SpecObjectOther);
        break;

    case SkipScope: {
        if (JSValue child = forNode(node->child1()).value()) {
            if (JSScope* scope = jsDynamicCast<JSScope*>(m_vm, child)) {
                if (JSScope* nextScope = scope->next()) {
                    setConstant(node, *m_graph.freeze(JSValue(nextScope)));
                    break;
                }
            }
        }
        setTypeForNode(node, SpecObjectOther);
        break;
    }

    case GetGlobalObject: {
        JSValue child = forNode(node->child1()).value();
        if (child) {
            setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject(m_vm))));
            break;
        }

        if (forNode(node->child1()).m_structure.isFinite()) {
            JSGlobalObject* globalObject = nullptr;
            bool ok = true;
            forNode(node->child1()).m_structure.forEach(
                [&] (RegisteredStructure structure) {
                    if (!globalObject)
                        globalObject = structure->globalObject();
                    else if (globalObject != structure->globalObject())
                        ok = false;
                });
            if (globalObject && ok) {
                setConstant(node, *m_graph.freeze(JSValue(globalObject)));
                break;
            }
        }

        setTypeForNode(node, SpecObjectOther);
        break;
    }

    case GetGlobalThis: {
        setTypeForNode(node, SpecObject);
        break;
    }

    case GetClosureVar:
        if (JSValue value = m_graph.tryGetConstantClosureVar(forNode(node->child1()), node->scopeOffset())) {
            setConstant(node, *m_graph.freeze(value));
            break;
        }
        makeBytecodeTopForNode(node);
        break;
            
    case PutClosureVar:
        break;

    case GetInternalField:
        makeBytecodeTopForNode(node);
        break;

    case PutInternalField:
        break;


    case GetRegExpObjectLastIndex:
        makeHeapTopForNode(node);
        break;

    case SetRegExpObjectLastIndex:
    case RecordRegExpCachedResult:
        break;
        
    case GetFromArguments:
        makeHeapTopForNode(node);
        break;
        
    case PutToArguments:
        break;

    case GetArgument:
        makeHeapTopForNode(node);
        break;

    case TryGetById:
        // FIXME: This should constant fold at least as well as the normal GetById case.
        // https://bugs.webkit.org/show_bug.cgi?id=156422
        makeHeapTopForNode(node);
        break;

    case GetByIdDirect:
    case GetByIdDirectFlush:
    case GetById:
    case GetByIdFlush: {
        AbstractValue& value = forNode(node->child1());
        if (value.m_structure.isFinite()
            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
            UniquedStringImpl* uid = node->cacheableIdentifier().uid();
            GetByStatus status = GetByStatus::computeFor(value.m_structure.toStructureSet(), uid);
            if (status.isSimple()) {
                // Figure out what the result is going to be - is it TOP, a constant, or maybe
                // something more subtle?
                AbstractValue result;
                for (unsigned i = status.numVariants(); i--;) {
                    // This thing won't give us a variant that involves prototypes. If it did, we'd
                    // have more work to do here.
                    DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());

                    result.merge(
                        m_graph.inferredValueForProperty(
                            value, status[i].offset(), m_state.structureClobberState()));
                }
            
                m_state.setShouldTryConstantFolding(true);
                didFoldClobberWorld();
                forNode(node) = result;
                break;
            }
        }

        clobberWorld();
        makeHeapTopForNode(node);
        break;
    }

    case GetByValWithThis:
    case GetByIdWithThis:
        clobberWorld();
        makeHeapTopForNode(node);
        break;
            
    case GetArrayLength: {
        JSArrayBufferView* view = m_graph.tryGetFoldableView(
            forNode(node->child1()).m_value, node->arrayMode());
        if (view) {
            setConstant(node, jsNumber(view->length()));
            break;
        }
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }

    case GetVectorLength: {
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }

    case DeleteById:
    case DeleteByVal: {
        // FIXME: This could decide if the delete will be successful based on the set of structures that
        // we get from our base value. https://bugs.webkit.org/show_bug.cgi?id=156611
        clobberWorld();
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }
        
    case CheckStructure: {
        AbstractValue& value = forNode(node->child1());

        const RegisteredStructureSet& set = node->structureSet();
        
        // It's interesting that we could have proven that the object has a larger structure set
        // that includes the set we're testing. In that case we could make the structure check
        // more efficient. We currently don't.
        
        if (value.m_structure.isSubsetOf(set))
            m_state.setShouldTryConstantFolding(true);

        SpeculatedType admittedTypes = SpecNone;
        switch (node->child1().useKind()) {
        case CellUse:
        case KnownCellUse:
            admittedTypes = SpecNone;
            break;
        case CellOrOtherUse:
            admittedTypes = SpecOther;
            break;
        default:
            DFG_CRASH(m_graph, node, "Bad use kind");
            break;
        }
        
        filter(value, set, admittedTypes);
        break;
    }

    case CheckStructureOrEmpty: {
        AbstractValue& value = forNode(node->child1());

        bool mayBeEmpty = value.m_type & SpecEmpty;
        if (!mayBeEmpty)
            m_state.setShouldTryConstantFolding(true);

        SpeculatedType admittedTypes = mayBeEmpty ? SpecEmpty : SpecNone;
        filter(value, node->structureSet(), admittedTypes);
        break;
    }
        
    case CheckStructureImmediate: {
        // FIXME: This currently can only reason about one structure at a time.
        // https://bugs.webkit.org/show_bug.cgi?id=136988
        
        AbstractValue& value = forNode(node->child1());
        const RegisteredStructureSet& set = node->structureSet();
        
        if (value.value()) {
            if (Structure* structure = jsDynamicCast<Structure*>(m_vm, value.value())) {
                if (set.contains(m_graph.registerStructure(structure))) {
                    m_state.setShouldTryConstantFolding(true);
                    break;
                }
            }
            m_state.setIsValid(false);
            break;
        }
        
        if (m_phiChildren) {
            bool allGood = true;
            m_phiChildren->forAllTransitiveIncomingValues(
                node,
                [&] (Node* incoming) {
                    if (Structure* structure = incoming->dynamicCastConstant<Structure*>(m_vm)) {
                        if (set.contains(m_graph.registerStructure(structure)))
                            return;
                    }
                    allGood = false;
                });
            if (allGood) {
                m_state.setShouldTryConstantFolding(true);
                break;
            }
        }
            
        if (RegisteredStructure structure = set.onlyStructure()) {
            filterByValue(node->child1(), *m_graph.freeze(structure.get()));
            break;
        }
        
        // Aw shucks, we can't do anything!
        break;
    }
        
    case PutStructure:
        if (!forNode(node->child1()).m_structure.isClear()) {
            if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next) {
                didFoldClobberStructures();
                m_state.setShouldTryConstantFolding(true);
            } else {
                observeTransition(
                    clobberLimit, node->transition()->previous, node->transition()->next);
                forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
            }
        } else {
            // We're going to exit before we get here, but for the sake of validation, we've folded our write to StructureID.
            didFoldClobberStructures();
        }
        break;
    case GetButterfly:
    case AllocatePropertyStorage:
    case ReallocatePropertyStorage:
    case NukeStructureAndSetButterfly:
        // FIXME: We don't model the fact that the structureID is nuked, simply because currently
        // nobody would currently benefit from having that information. But it's a bug nonetheless.
        if (node->op() == NukeStructureAndSetButterfly)
            didFoldClobberStructures();
        clearForNode(node); // The result is not a JS value.
        break;
    case CheckSubClass: {
        JSValue constant = forNode(node->child1()).value();
        if (constant) {
            if (constant.isCell() && constant.asCell()->inherits(m_vm, node->classInfo())) {
                m_state.setShouldTryConstantFolding(true);
                ASSERT(constant);
                break;
            }
        }

        AbstractValue& value = forNode(node->child1());

        if (value.m_structure.isSubClassOf(node->classInfo()))
            m_state.setShouldTryConstantFolding(true);

        filterClassInfo(value, node->classInfo());
        break;
    }
    case CallDOMGetter: {
        CallDOMGetterData* callDOMGetterData = node->callDOMGetterData();
        DOMJIT::CallDOMGetterSnippet* snippet = callDOMGetterData->snippet;
        if (!snippet || snippet->effect.writes)
            clobberWorld();
        if (callDOMGetterData->domJIT)
            setTypeForNode(node, callDOMGetterData->domJIT->resultType());
        else
            makeBytecodeTopForNode(node);
        break;
    }
    case CallDOM: {
        const DOMJIT::Signature* signature = node->signature();
        if (signature->effect.writes)
            clobberWorld();
        setTypeForNode(node, signature->result);
        break;
    }

    case CheckArrayOrEmpty:
    case CheckArray: {
        AbstractValue& value = forNode(node->child1());

        SpeculatedType admittedTypes = SpecNone;
        if (node->op() == CheckArrayOrEmpty) {
            bool mayBeEmpty = value.m_type & SpecEmpty;
            if (!mayBeEmpty)
                m_state.setShouldTryConstantFolding(true);
            else
                admittedTypes = SpecEmpty;
        }

        if (node->arrayMode().alreadyChecked(m_graph, node, value)) {
            m_state.setShouldTryConstantFolding(true);
            break;
        }

        switch (node->arrayMode().type()) {
        case Array::String:
            filter(node->child1(), SpecString | admittedTypes);
            break;
        case Array::Int32:
        case Array::Double:
        case Array::Contiguous:
        case Array::Undecided:
        case Array::ArrayStorage:
        case Array::SlowPutArrayStorage:
            break;
        case Array::DirectArguments:
            filter(node->child1(), SpecDirectArguments | admittedTypes);
            break;
        case Array::ScopedArguments:
            filter(node->child1(), SpecScopedArguments | admittedTypes);
            break;
        case Array::Int8Array:
            filter(node->child1(), SpecInt8Array | admittedTypes);
            break;
        case Array::Int16Array:
            filter(node->child1(), SpecInt16Array | admittedTypes);
            break;
        case Array::Int32Array:
            filter(node->child1(), SpecInt32Array | admittedTypes);
            break;
        case Array::Uint8Array:
            filter(node->child1(), SpecUint8Array | admittedTypes);
            break;
        case Array::Uint8ClampedArray:
            filter(node->child1(), SpecUint8ClampedArray | admittedTypes);
            break;
        case Array::Uint16Array:
            filter(node->child1(), SpecUint16Array | admittedTypes);
            break;
        case Array::Uint32Array:
            filter(node->child1(), SpecUint32Array | admittedTypes);
            break;
        case Array::Float32Array:
            filter(node->child1(), SpecFloat32Array | admittedTypes);
            break;
        case Array::Float64Array:
            filter(node->child1(), SpecFloat64Array | admittedTypes);
            break;
        case Array::AnyTypedArray:
            filter(node->child1(), SpecTypedArrayView | admittedTypes);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering(), admittedTypes);
        break;
    }

    case Arrayify: {
        if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
            didFoldClobberStructures();
            m_state.setShouldTryConstantFolding(true);
            break;
        }
        ASSERT(node->arrayMode().conversion() == Array::Convert);
        clobberStructures();
        filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
        break;
    }
    case ArrayifyToStructure: {
        AbstractValue& value = forNode(node->child1());
        if (value.m_structure.isSubsetOf(RegisteredStructureSet(node->structure())))
            m_state.setShouldTryConstantFolding(true);
        clobberStructures();
        
        // We have a bunch of options of how to express the abstract set at this point. Let set S
        // be the set of structures that the value had before clobbering and assume that all of
        // them are watchable. The new value should be the least expressible upper bound of the
        // intersection of "values that currently have structure = node->structure()" and "values
        // that have structure in S plus any structure transition-reachable from S". Assume that
        // node->structure() is not in S but it is transition-reachable from S. Then we would
        // like to say that the result is "values that have structure = node->structure() until
        // we invalidate", but there is no way to express this using the AbstractValue syntax. So
        // we must choose between:
        //
        // 1) "values that currently have structure = node->structure()". This is a valid
        //    superset of the value that we really want, and it's specific enough to satisfy the
        //    preconditions of the array access that this is guarding. It's also specific enough
        //    to allow relevant optimizations in the case that we didn't have a contradiction
        //    like in this example. Notice that in the abscence of any contradiction, this result
        //    is precise rather than being a conservative LUB.
        //
        // 2) "values that currently hava structure in S plus any structure transition-reachable
        //    from S". This is also a valid superset of the value that we really want, but it's
        //    not specific enough to satisfy the preconditions of the array access that this is
        //    guarding - so playing such shenanigans would preclude us from having assertions on
        //    the typing preconditions of any array accesses. This would also not be a desirable
        //    answer in the absence of a contradiction.
        //
        // Note that it's tempting to simply say that the resulting value is BOTTOM because of
        // the contradiction. That would be wrong, since we haven't hit an invalidation point,
        // yet.
        forNode(node->child1()).set(m_graph, node->structure());
        break;
    }
    case GetIndexedPropertyStorage: {
        JSArrayBufferView* view = m_graph.tryGetFoldableView(
            forNode(node->child1()).m_value, node->arrayMode());
        if (view)
            m_state.setShouldTryConstantFolding(true);
        clearForNode(node);
        break;
    }
    case ConstantStoragePointer: {
        clearForNode(node);
        break; 
    }
        
    case GetTypedArrayByteOffset: {
        JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
        if (view) {
            Optional<unsigned> byteOffset = view->byteOffsetConcurrently();
            if (byteOffset) {
                setConstant(node, jsNumber(*byteOffset));
                break;
            }
        }
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }

    case GetPrototypeOf: {
        AbstractValue& value = forNode(node->child1());
        if ((value.m_type && !(value.m_type & ~SpecObject)) && value.m_structure.isFinite()) {
            bool canFold = !value.m_structure.isClear();
            JSValue prototype;
            value.m_structure.forEach([&] (RegisteredStructure structure) {
                auto getPrototypeMethod = structure->classInfo()->methodTable.getPrototype;
                MethodTable::GetPrototypeFunctionPtr defaultGetPrototype = JSObject::getPrototype;
                if (getPrototypeMethod != defaultGetPrototype) {
                    canFold = false;
                    return;
                }

                if (structure->hasPolyProto()) {
                    canFold = false;
                    return;
                }
                if (!prototype)
                    prototype = structure->storedPrototype();
                else if (prototype != structure->storedPrototype())
                    canFold = false;
            });

            if (prototype && canFold) {
                switch (node->child1().useKind()) {
                case ArrayUse:
                case FunctionUse:
                case FinalObjectUse:
                    break;
                default:
                    didFoldClobberWorld();
                    break;
                }
                setConstant(node, *m_graph.freeze(prototype));
                break;
            }
        }

        switch (node->child1().useKind()) {
        case ArrayUse:
        case FunctionUse:
        case FinalObjectUse:
            break;
        default:
            clobberWorld();
            break;
        }
        setTypeForNode(node, SpecObject | SpecOther);
        break;
    }
        
    case GetByOffset: {
        StorageAccessData& data = node->storageAccessData();

        // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
        // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
        // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
        // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
        // on the type that ByteCodeParser was able to prove.
        AbstractValue value = m_graph.inferredValueForProperty(
            forNode(node->child2()), data.offset, m_state.structureClobberState());

        // If we decide that there does not exist any value that this can return, then it's probably
        // because the compilation was already invalidated.
        if (value.isClear())
            m_state.setIsValid(false);

        setForNode(node, value);
        if (value.m_value)
            m_state.setShouldTryConstantFolding(true);
        break;
    }
        
    case GetGetterSetterByOffset: {
        StorageAccessData& data = node->storageAccessData();
        AbstractValue base = forNode(node->child2());
        JSValue result = m_graph.tryGetConstantProperty(base, data.offset);
        if (result && jsDynamicCast<GetterSetter*>(m_vm, result)) {
            setConstant(node, *m_graph.freeze(result));
            break;
        }
        
        setForNode(node, m_vm.getterSetterStructure.get());
        break;
    }
        
    case MultiGetByOffset: {
        // This code will filter the base value in a manner that is possibly different (either more
        // or less precise) than the way it would be filtered if this was strength-reduced to a
        // CheckStructure. This is fine. It's legal for different passes over the code to prove
        // different things about the code, so long as all of them are sound. That even includes
        // one guy proving that code should never execute (due to a contradiction) and another guy
        // not finding that contradiction. If someone ever proved that there would be a
        // contradiction then there must always be a contradiction even if subsequent passes don't
        // realize it. This is the case here.
        
        // Ordinarily you have to be careful with calling setShouldTryConstantFolding()
        // because of the effect on compile times, but this node is FTL-only.
        m_state.setShouldTryConstantFolding(true);
        
        AbstractValue base = forNode(node->child1());
        RegisteredStructureSet baseSet;
        AbstractValue result;
        for (const MultiGetByOffsetCase& getCase : node->multiGetByOffsetData().cases) {
            RegisteredStructureSet set = getCase.set();
            set.filter(base);
            if (set.isEmpty())
                continue;
            baseSet.merge(set);

            switch (getCase.method().kind()) {
            case GetByOffsetMethod::Constant: {
                AbstractValue thisResult;
                thisResult.set(
                    m_graph,
                    *getCase.method().constant(),
                    m_state.structureClobberState());
                result.merge(thisResult);
                break;
            }

            default: {
                result.makeHeapTop();
                break;
            } }
        }
        
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
            m_state.setIsValid(false);
        
        setForNode(node, result);
        break;
    }
            
    case PutByOffset: {
        break;
    }
        
    case MultiPutByOffset: {
        RegisteredStructureSet newSet;
        TransitionVector transitions;
        
        // Ordinarily you have to be careful with calling setShouldTryConstantFolding()
        // because of the effect on compile times, but this node is FTL-only.
        m_state.setShouldTryConstantFolding(true);
        
        AbstractValue base = forNode(node->child1());
        AbstractValue originalValue = forNode(node->child2());
        AbstractValue resultingValue;
        
        if (node->multiPutByOffsetData().writesStructures())
            didFoldClobberStructures();
            
        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
            RegisteredStructureSet thisSet = *m_graph.addStructureSet(variant.oldStructure());
            thisSet.filter(base);
            if (thisSet.isEmpty())
                continue;

            AbstractValue thisValue = originalValue;
            resultingValue.merge(thisValue);
            
            if (variant.kind() == PutByIdVariant::Transition) {
                RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
                if (thisSet.onlyStructure() != newStructure) {
                    transitions.append(
                        Transition(m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
                } // else this is really a replace.
                newSet.add(newStructure);
            } else {
                ASSERT(variant.kind() == PutByIdVariant::Replace);
                newSet.merge(thisSet);
            }
        }
        
        // We need to order AI executing these effects in the same order as they're executed
        // at runtime. This is critical when you have JS code like `o.f = o;`. We first
        // filter types on o, then transition o. Not the other way around. If we got
        // this ordering wrong, we could end up with the wrong type representing o.
        setForNode(node->child2(), resultingValue);
        if (!!originalValue && !resultingValue)
            m_state.setIsValid(false);

        observeTransitions(clobberLimit, transitions);
        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
            m_state.setIsValid(false);
        break;
    }

    case MultiDeleteByOffset: {
        RegisteredStructureSet newSet;
        TransitionVector transitions;

        // Ordinarily you have to be careful with calling setShouldTryConstantFolding()
        // because of the effect on compile times, but this node is FTL-only.
        m_state.setShouldTryConstantFolding(true);

        AbstractValue base = forNode(node->child1());

        if (node->multiDeleteByOffsetData().writesStructures())
            didFoldClobberStructures();

        for (unsigned i = node->multiDeleteByOffsetData().variants.size(); i--;) {
            const DeleteByIdVariant& variant = node->multiDeleteByOffsetData().variants[i];
            RegisteredStructureSet thisSet = *m_graph.addStructureSet(variant.oldStructure());
            thisSet.filter(base);
            if (thisSet.isEmpty())
                continue;

            if (variant.newStructure()) {
                RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
                transitions.append(
                    Transition(m_graph.registerStructure(variant.oldStructure()), newStructure));
                newSet.add(newStructure);
            } else
                newSet.merge(thisSet);
        }

        observeTransitions(clobberLimit, transitions);
        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
            m_state.setIsValid(false);
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }
        
    case GetExecutable: {
        JSValue value = forNode(node->child1()).value();
        if (value) {
            JSFunction* function = jsDynamicCast<JSFunction*>(m_vm, value);
            if (function) {
                setConstant(node, *m_graph.freeze(function->executable()));
                break;
            }
        }
        setTypeForNode(node, SpecCellOther);
        break;
    }
    
    case CheckIsConstant: {
        AbstractValue& value = forNode(node->child1());
        if (value.value() == node->constant()->value() && (value.value() || value.m_type == SpecEmpty)) {
            m_state.setShouldTryConstantFolding(true);
            break;
        }
        filterByValue(node->child1(), *node->constant());
        break;
    }

    case AssertNotEmpty:
    case CheckNotEmpty: {
        AbstractValue& value = forNode(node->child1());
        if (!(value.m_type & SpecEmpty)) {
            m_state.setShouldTryConstantFolding(true);
            break;
        }
        
        filter(value, ~SpecEmpty);
        break;
    }

    case CheckIdent: {
        AbstractValue& value = forNode(node->child1());
        UniquedStringImpl* uid = node->uidOperand();

        JSValue childConstant = value.value();
        if (childConstant) {
            if (childConstant.isString()) {
                if (asString(childConstant)->tryGetValueImpl() == uid) {
                    m_state.setShouldTryConstantFolding(true);
                    break;
                }
            } else if (childConstant.isSymbol()) {
                if (&jsCast<Symbol*>(childConstant)->uid() == uid) {
                    m_state.setShouldTryConstantFolding(true);
                    break;
                }
            }
        }

        if (node->child1().useKind() == StringIdentUse)
            filter(value, SpecStringIdent);
        else
            filter(value, SpecSymbol);
        break;
    }

    case CheckInBounds: {
        JSValue left = forNode(node->child1()).value();
        JSValue right = forNode(node->child2()).value();
        if (left && right && left.isInt32() && right.isInt32() && static_cast<uint32_t>(left.asInt32()) < static_cast<uint32_t>(right.asInt32()))
            m_state.setShouldTryConstantFolding(true);

        // We claim we result in Int32. It's not really important what our result is (though we
        // don't want to claim we may result in the empty value), other nodes with data flow edges
        // to us just do that to maintain the invariant that they can't be hoisted higher than us.
        // So we just arbitrarily pick Int32. In some ways, StorageResult may be the more correct
        // thing to do here. We pick NodeResultJS because it makes converting this to an identity
        // easier.
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }
        
    case PutById:
    case PutByIdFlush:
    case PutByIdDirect: {
        AbstractValue& value = forNode(node->child1());
        if (value.m_structure.isFinite()) {
            PutByIdStatus status = PutByIdStatus::computeFor(
                m_graph.globalObjectFor(node->origin.semantic),
                value.m_structure.toStructureSet(),
                node->cacheableIdentifier().uid(),
                node->op() == PutByIdDirect);

            bool allGood = true;
            if (status.isSimple()) {
                RegisteredStructureSet newSet;
                TransitionVector transitions;
                
                for (const PutByIdVariant& variant : status.variants()) {
                    for (const ObjectPropertyCondition& condition : variant.conditionSet()) {
                        if (!m_graph.watchCondition(condition)) {
                            allGood = false;
                            break;
                        }
                    }

                    if (!allGood)
                        break;

                    if (variant.kind() == PutByIdVariant::Transition) {
                        RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
                        transitions.append(
                            Transition(
                                m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
                        newSet.add(newStructure);
                    } else {
                        ASSERT(variant.kind() == PutByIdVariant::Replace);
                        newSet.merge(*m_graph.addStructureSet(variant.oldStructure()));
                    }
                }

                if (status.numVariants() == 1 || m_graph.m_plan.isFTL())
                    m_state.setShouldTryConstantFolding(true);
                
                if (allGood) {
                    didFoldClobberWorld();
                    observeTransitions(clobberLimit, transitions);
                    if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
                        m_state.setIsValid(false);
                    break;
                }
            }
        }
        
        clobberWorld();
        break;
    }

    case PutByValWithThis:
    case PutByIdWithThis:
        clobberWorld();
        break;

    case PutGetterById:
    case PutSetterById:
    case PutGetterSetterById:
    case PutGetterByVal:
    case PutSetterByVal: {
        clobberWorld();
        break;
    }

    case DefineDataProperty:
    case DefineAccessorProperty:
        clobberWorld();
        break;
        
    case InById: {
        // FIXME: We can determine when the property definitely exists based on abstract
        // value information.
        clobberWorld();
        filter(node->child1(), SpecObject);
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }

    case InByVal: {
        AbstractValue& property = forNode(node->child2());
        if (JSValue constant = property.value()) {
            if (constant.isString()) {
                JSString* string = asString(constant);
                if (CacheableIdentifier::isCacheableIdentifierCell(string))
                    m_state.setShouldTryConstantFolding(true);
            }
        }

        // FIXME: We can determine when the property definitely exists based on abstract
        // value information.
        clobberWorld();
        filter(node->child1(), SpecObject);
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }

    case HasOwnProperty: {
        clobberWorld();
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }
            
    case GetEnumerableLength: {
        setNonCellTypeForNode(node, SpecInt32Only);
        break;
    }
    case HasGenericProperty: {
        setNonCellTypeForNode(node, SpecBoolean);
        clobberWorld();
        break;
    }
    case InStructureProperty:
    case HasStructureProperty: {
        setNonCellTypeForNode(node, SpecBoolean);
        clobberWorld();
        break;
    }
    case HasIndexedProperty: {
        ArrayMode mode = node->arrayMode();
        switch (mode.type()) {
        case Array::Int32:
        case Array::Double:
        case Array::Contiguous:
        case Array::ArrayStorage: {
            if (mode.isInBounds())
                break;
            FALLTHROUGH;
        }
        default: {
            clobberWorld();
            break;
        }
        }
        setNonCellTypeForNode(node, SpecBoolean);
        break;
    }
    case GetDirectPname: {
        clobberWorld();
        makeHeapTopForNode(node);
        break;
    }
    case GetPropertyEnumerator: {
        setTypeForNode(node, SpecCell);
        clobberWorld();
        break;
    }
    case GetEnumeratorStructurePname: {
        setTypeForNode(node, SpecString | SpecOther);
        break;
    }
    case GetEnumeratorGenericPname: {
        setTypeForNode(node, SpecString | SpecOther);
        break;
    }
    case ToIndexString: {
        setTypeForNode(node, SpecString);
        break;
    }

    case GetGlobalVar:
        makeHeapTopForNode(node);
        break;

    case GetGlobalLexicalVariable:
        makeBytecodeTopForNode(node);
        break;

    case GetDynamicVar:
        clobberWorld();
        makeBytecodeTopForNode(node);
        break;

    case PutDynamicVar:
        clobberWorld();
        break;

    case ResolveScope:
        clobberWorld();
        setTypeForNode(node, SpecObject);
        break;

    case ResolveScopeForHoistingFuncDeclInEval:
        clobberWorld();
        makeBytecodeTopForNode(node);
        break;

    case PutGlobalVariable:
    case NotifyWrite:
        break;

    case OverridesHasInstance:
        setNonCellTypeForNode(node, SpecBoolean);
        break;
            
    case InstanceOf:
        clobberWorld();
        setNonCellTypeForNode(node, SpecBoolean);
        break;

    case InstanceOfCustom:
        clobberWorld();
        setNonCellTypeForNode(node, SpecBoolean);
        break;
        
    case MatchStructure: {
        AbstractValue base = forNode(node->child1());
        RegisteredStructureSet baseSet;
        
        BooleanLattice result = BooleanLattice::Bottom;
        for (MatchStructureVariant& variant : node->matchStructureData().variants) {
            RegisteredStructure structure = variant.structure;
            if (!base.contains(structure)) {
                m_state.setShouldTryConstantFolding(true);
                continue;
            }
            
            baseSet.add(structure);
            result = leastUpperBoundOfBooleanLattices(
                result, variant.result ? BooleanLattice::True : BooleanLattice::False);
        }
        
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
            m_state.setIsValid(false);
        
        switch (result) {
        case BooleanLattice::False:
            setConstant(node, jsBoolean(false));
            break;
        case BooleanLattice::True:
            setConstant(node, jsBoolean(true));
            break;
        default:
            setNonCellTypeForNode(node, SpecBoolean);
            break;
        }
        break;
    }
            
    case Phi:
        RELEASE_ASSERT(m_graph.m_form == SSA);
        setForNode(node, forNode(NodeFlowProjection(node, NodeFlowProjection::Shadow)));
        // The state of this node would have already been decided, but it may have become a
        // constant, in which case we'd like to know.
        if (forNode(node).m_value)
            m_state.setShouldTryConstantFolding(true);
        break;
        
    case Upsilon: {
        NodeFlowProjection shadow(node->phi(), NodeFlowProjection::Shadow);
        if (shadow.isStillValid()) {
            m_state.createValueForNode(shadow);
            setForNode(shadow, forNode(node->child1()));
        }
        break;
    }
        
    case Flush:
    case PhantomLocal:
        break;
            
    case Call:
    case TailCallInlinedCaller:
    case Construct:
    case CallVarargs:
    case CallForwardVarargs:
    case TailCallVarargsInlinedCaller:
    case ConstructVarargs:
    case ConstructForwardVarargs:
    case TailCallForwardVarargsInlinedCaller:
    case CallEval:
    case DirectCall:
    case DirectConstruct:
    case DirectTailCallInlinedCaller:
        clobberWorld();
        makeHeapTopForNode(node);
        break;

    case ForceOSRExit:
    case CheckBadCell:
        m_state.setIsValid(false);
        break;
        
    case InvalidationPoint:
        m_state.setStructureClobberState(StructuresAreWatched);
        m_state.observeInvalidationPoint();
        break;

    case CPUIntrinsic: 
        if (node->intrinsic() == CPURdtscIntrinsic)
            setNonCellTypeForNode(node, SpecInt32Only);
        else
            setNonCellTypeForNode(node, SpecOther);
        break;

    case CheckTraps:
    case LogShadowChickenPrologue:
    case LogShadowChickenTail:
    case ProfileType:
    case ProfileControlFlow:
    case Phantom:
    case CountExecution:
    case CheckTierUpInLoop:
    case CheckTierUpAtReturn:
    case CheckNeutered:
    case SuperSamplerBegin:
    case SuperSamplerEnd:
    case CheckTierUpAndOSREnter:
    case LoopHint:
    case ZombieHint:
    case ExitOK:
    case FilterCallLinkStatus:
    case FilterGetByStatus:
    case FilterPutByIdStatus:
    case FilterInByIdStatus:
    case FilterDeleteByStatus:
    case ClearCatchLocals:
        break;

    case CheckTypeInfoFlags: {
        const AbstractValue& abstractValue = forNode(node->child1());
        unsigned bits = node->typeInfoOperand();
        ASSERT(bits);
        if (bits == ImplementsDefaultHasInstance) {
            if (abstractValue.m_type == SpecFunctionWithDefaultHasInstance) {
                m_state.setShouldTryConstantFolding(true);
                break;
            }
        }

        if (JSValue value = abstractValue.value()) {
            if (value.isCell()) {
                // This works because if we see a cell here, we know it's fully constructed
                // and we can read its inline type info flags. These flags don't change over the
                // object's lifetime.
                if ((value.asCell()->inlineTypeFlags() & bits) == bits) {
                    m_state.setShouldTryConstantFolding(true);
                    break;
                }
            }
        }

        if (abstractValue.m_structure.isFinite()) {
            bool ok = true;
            abstractValue.m_structure.forEach([&] (RegisteredStructure structure) {
                ok &= (structure->typeInfo().inlineTypeFlags() & bits) == bits;
            });
            if (ok) {
                m_state.setShouldTryConstantFolding(true);
                break;
            }
        }

        break;
    }

    case ParseInt: {
        AbstractValue value = forNode(node->child1());
        if (value.m_type && !(value.m_type & ~SpecInt32Only)) {
            JSValue radix;
            if (!node->child2())
                radix = jsNumber(0);
            else
                radix = forNode(node->child2()).m_value;

            if (radix.isNumber()
                && (radix.asNumber() == 0 || radix.asNumber() == 10)) {
                m_state.setShouldTryConstantFolding(true);
                if (node->child1().useKind() == UntypedUse)
                    didFoldClobberWorld();
                setNonCellTypeForNode(node, SpecInt32Only);
                break;
            }
        }

        if (node->child1().useKind() == UntypedUse)
            clobberWorld();
        setNonCellTypeForNode(node, SpecBytecodeNumber);
        break;
    }

    case CreateRest:
        if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
            // This means we're already having a bad time.
            clobberWorld();
            setTypeForNode(node, SpecArray);
            break;
        }
        setForNode(node,
            m_graph.globalObjectFor(node->origin.semantic)->restParameterStructure());
        break;
            
    case CheckVarargs:
    case Check: {
        // Simplify out checks that don't actually do checking.
        m_graph.doToChildren(node, [&] (Edge edge) {
            if (!edge)
                return;
            if (edge.isProved() || edge.willNotHaveCheck())
                m_state.setShouldTryConstantFolding(true);
        });
        break;
    }

    case SetFunctionName: {
        clobberWorld();
        break;
    }

    case StoreBarrier:
    case FencedStoreBarrier: {
        filter(node->child1(), SpecCell);
        break;
    }

    case DataViewGetInt: {
        DataViewData data = node->dataViewData();
        if (data.byteSize < 4)
            setNonCellTypeForNode(node, SpecInt32Only);
        else {
            ASSERT(data.byteSize == 4);
            if (data.isSigned)
                setNonCellTypeForNode(node, SpecInt32Only);
            else
                setNonCellTypeForNode(node, SpecInt52Any);
        }
        break;
    }

    case DataViewGetFloat: {
        setNonCellTypeForNode(node, SpecFullDouble);
        break;
    }

    case DateGetInt32OrNaN: {
        setNonCellTypeForNode(node, SpecInt32Only | SpecDoublePureNaN);
        break;
    }

    case DateGetTime: {
        setNonCellTypeForNode(node, SpecFullDouble);
        break;
    }

    case DataViewSet: {
        break;
    }
        
    case Unreachable:
        // It may be that during a previous run of AI we proved that something was unreachable, but
        // during this run of AI we forget that it's unreachable. AI's proofs don't have to get
        // monotonically stronger over time. So, we don't assert that AI doesn't reach the
        // Unreachable. We have no choice but to take our past proof at face value. Otherwise we'll
        // crash whenever AI fails to be as powerful on run K as it was on run K-1.
        m_state.setIsValid(false);
        break;
        
    case LastNodeType:
    case ArithIMul:
    case FiatInt52:
        DFG_CRASH(m_graph, node, "Unexpected node type");
        break;
    }
    
    return m_state.isValid();
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::filterICStatus(Node* node)
{
    switch (node->op()) {
    case FilterCallLinkStatus:
        if (JSValue value = forNode(node->child1()).m_value)
            node->callLinkStatus()->filter(m_vm, value);
        break;
        
    case FilterGetByStatus: {
        AbstractValue& value = forNode(node->child1());
        if (value.m_structure.isFinite())
            node->getByStatus()->filter(value.m_structure.toStructureSet());
        break;
    }
        
    case FilterInByIdStatus: {
        AbstractValue& value = forNode(node->child1());
        if (value.m_structure.isFinite())
            node->inByIdStatus()->filter(value.m_structure.toStructureSet());
        break;
    }
        
    case FilterPutByIdStatus: {
        AbstractValue& value = forNode(node->child1());
        if (value.m_structure.isFinite())
            node->putByIdStatus()->filter(value.m_structure.toStructureSet());
        break;
    }

    case FilterDeleteByStatus: {
        AbstractValue& value = forNode(node->child1());
        if (value.m_structure.isFinite())
            node->deleteByStatus()->filter(value.m_structure.toStructureSet());
        break;
    }

    default:
        RELEASE_ASSERT_NOT_REACHED();
        break;
    }
}

template<typename AbstractStateType>
bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned indexInBlock)
{
    return executeEffects(indexInBlock, m_state.block()->at(indexInBlock));
}

template<typename AbstractStateType>
bool AbstractInterpreter<AbstractStateType>::execute(unsigned indexInBlock)
{
    Node* node = m_state.block()->at(indexInBlock);

    startExecuting();
    executeEdges(node);
    return executeEffects(indexInBlock, node);
}

template<typename AbstractStateType>
bool AbstractInterpreter<AbstractStateType>::execute(Node* node)
{
    startExecuting();
    executeEdges(node);
    return executeEffects(UINT_MAX, node);
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::clobberWorld()
{
    clobberStructures();
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::didFoldClobberWorld()
{
    didFoldClobberStructures();
}

template<typename AbstractStateType>
template<typename Functor>
void AbstractInterpreter<AbstractStateType>::forAllValues(
    unsigned clobberLimit, Functor& functor)
{
    if (clobberLimit >= m_state.block()->size())
        clobberLimit = m_state.block()->size();
    else
        clobberLimit++;
    ASSERT(clobberLimit <= m_state.block()->size());
    for (size_t i = clobberLimit; i--;) {
        NodeFlowProjection::forEach(
            m_state.block()->at(i),
            [&] (NodeFlowProjection nodeProjection) {
                functor(forNode(nodeProjection));
            });
    }
    if (m_graph.m_form == SSA) {
        for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
            if (node.isStillValid())
                functor(forNode(node));
        }
    }
    for (size_t i = m_state.size(); i--;)
        functor(m_state.atIndex(i));
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::clobberStructures()
{
    m_state.clobberStructures();
    m_state.mergeClobberState(AbstractInterpreterClobberState::ClobberedStructures);
    m_state.setStructureClobberState(StructuresAreClobbered);
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::didFoldClobberStructures()
{
    m_state.mergeClobberState(AbstractInterpreterClobberState::FoldedClobber);
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::observeTransition(
    unsigned clobberLimit, RegisteredStructure from, RegisteredStructure to)
{
    // Stop performing precise structure transition tracking.
    // Precise structure transition tracking shows quadratic complexity for # of nodes in a basic block.
    // If it is too large, we conservatively clobber all the structures.
    if (m_state.block()->size() > Options::maxDFGNodesInBasicBlockForPreciseAnalysis()) {
        clobberStructures();
        return;
    }

    AbstractValue::TransitionObserver transitionObserver(from, to);
    forAllValues(clobberLimit, transitionObserver);
    
    ASSERT(!from->dfgShouldWatch()); // We don't need to claim to be in a clobbered state because 'from' was never watchable (during the time we were compiling), hence no constants ever introduced into the DFG IR that ever had a watchable structure would ever have the same structure as from.
    
    m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::observeTransitions(
    unsigned clobberLimit, const TransitionVector& vector)
{
    if (vector.isEmpty())
        return;
    
    // Stop performing precise structure transition tracking.
    // Precise structure transition tracking shows quadratic complexity for # of nodes in a basic block.
    // If it is too large, we conservatively clobber all the structures.
    if (m_state.block()->size() > Options::maxDFGNodesInBasicBlockForPreciseAnalysis()) {
        clobberStructures();
        return;
    }

    AbstractValue::TransitionsObserver transitionsObserver(vector);
    forAllValues(clobberLimit, transitionsObserver);
    
    if (ASSERT_ENABLED) {
        // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
        for (unsigned i = vector.size(); i--;)
            ASSERT(!vector[i].previous->dfgShouldWatch());
    }

    m_state.mergeClobberState(AbstractInterpreterClobberState::ObservedTransitions);
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out) const
{
    const_cast<AbstractInterpreter<AbstractStateType>*>(this)->dump(out);
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::dump(PrintStream& out)
{
    CommaPrinter comma(" ");
    HashSet<NodeFlowProjection> seen;
    if (m_graph.m_form == SSA) {
        for (NodeFlowProjection node : m_state.block()->ssa->liveAtHead) {
            seen.add(node);
            AbstractValue& value = forNode(node);
            if (value.isClear())
                continue;
            out.print(comma, node, ":", value);
        }
    }
    for (size_t i = 0; i < m_state.block()->size(); ++i) {
        NodeFlowProjection::forEach(
            m_state.block()->at(i), [&] (NodeFlowProjection nodeProjection) {
                seen.add(nodeProjection);
                AbstractValue& value = forNode(nodeProjection);
                if (value.isClear())
                    return;
                out.print(comma, nodeProjection, ":", value);
            });
    }
    if (m_graph.m_form == SSA) {
        for (NodeFlowProjection node : m_state.block()->ssa->liveAtTail) {
            if (seen.contains(node))
                continue;
            AbstractValue& value = forNode(node);
            if (value.isClear())
                continue;
            out.print(comma, node, ":", value);
        }
    }
}

template<typename AbstractStateType>
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
    AbstractValue& value, const RegisteredStructureSet& set, SpeculatedType admittedTypes)
{
    if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
        return FiltrationOK;
    m_state.setIsValid(false);
    return Contradiction;
}

template<typename AbstractStateType>
FiltrationResult AbstractInterpreter<AbstractStateType>::filterArrayModes(
    AbstractValue& value, ArrayModes arrayModes, SpeculatedType admittedTypes)
{
    if (value.filterArrayModes(arrayModes, admittedTypes) == FiltrationOK)
        return FiltrationOK;
    m_state.setIsValid(false);
    return Contradiction;
}

template<typename AbstractStateType>
FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
    AbstractValue& value, SpeculatedType type)
{
    if (value.filter(type) == FiltrationOK)
        return FiltrationOK;
    m_state.setIsValid(false);
    return Contradiction;
}

template<typename AbstractStateType>
FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
    AbstractValue& abstractValue, FrozenValue concreteValue)
{
    if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
        return FiltrationOK;
    m_state.setIsValid(false);
    return Contradiction;
}

template<typename AbstractStateType>
FiltrationResult AbstractInterpreter<AbstractStateType>::filterClassInfo(
    AbstractValue& value, const ClassInfo* classInfo)
{
    if (value.filterClassInfo(m_graph, classInfo) == FiltrationOK)
        return FiltrationOK;
    m_state.setIsValid(false);
    return Contradiction;
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects(Node* node, double(*equivalentFunction)(double))
{
    JSValue child = forNode(node->child1()).value();
    if (Optional<double> number = child.toNumberFromPrimitive()) {
        if (node->child1().useKind() != DoubleRepUse)
            didFoldClobberWorld();
        setConstant(node, jsDoubleNumber(equivalentFunction(*number)));
        return;
    }
    SpeculatedType type;
    if (node->child1().useKind() == DoubleRepUse)
        type = typeOfDoubleUnaryOp(forNode(node->child1()).m_type);
    else {
        clobberWorld();
        type = SpecBytecodeNumber;
    }
    setNonCellTypeForNode(node, type);
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)
