/*
 * Copyright (C) 2013-2018 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 "DFGAbstractInterpreter.h"
#include "DFGAbstractInterpreterClobberState.h"
#include "DOMJITGetterSetter.h"
#include "DOMJITSignature.h"
#include "GetByIdStatus.h"
#include "GetterSetter.h"
#include "HashMapImpl.h"
#include "JITOperations.h"
#include "MathCommon.h"
#include "NumberConstructor.h"
#include "Operations.h"
#include "PutByIdStatus.h"
#include "StringObject.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 = std::make_unique<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)->globalExec()))
            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>
void AbstractInterpreter<AbstractStateType>::executeEdges(Node* node)
{
    m_graph.doToChildren(
        node,
        [&] (Edge& edge) {
            filterEdgeByUse(edge);
        });
}

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>
void AbstractInterpreter<AbstractStateType>::verifyEdge(Node* node, Edge edge)
{
    if (!(forNode(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, bool isStrictMode, AbstractValue& valueForNode)
{
    // We look at the type first since that will cover most cases and does not require iterating all the structures.
    if (isStrictMode) {
        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 (isStrictMode)
                    return ToThisResult::Undefined;
                return ToThisResult::GlobalThis;
            }
        }
    }

    if ((isStrictMode || (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() == BigIntType);
            if (!isStrictMode)
                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 (isStrictMode)
                return ToThisResult::Undefined;
            return ToThisResult::GlobalThis;
        }
    }

    return ToThisResult::Dynamic;
}

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:
            forNode(node).setType(m_graph, SpecString);
            break;
        }
        break;
    }

    case IdentityWithProfile:
    case Identity: {
        forNode(node) = forNode(node->child1());
        if (forNode(node).value())
            m_state.setFoundConstants(true);
        break;
    }
        
    case ExtractCatchLocal:
    case ExtractOSREntryLocal: {
        forNode(node).makeBytecodeTop();
        break;
    }
            
    case GetLocal: {
        VariableAccessData* variableAccessData = node->variableAccessData();
        AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
        // The value in the local should already be checked.
        DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(variableAccessData->flushFormat())));
        if (value.value())
            m_state.setFoundConstants(true);
        forNode(node) = value;
        break;
    }
        
    case GetStack: {
        StackAccessData* data = node->stackAccessData();
        AbstractValue value = m_state.variables().operand(data->local);
        // The value in the local should already be checked.
        DFG_ASSERT(m_graph, node, value.isType(typeFilterFor(data->format)));
        if (value.value())
            m_state.setFoundConstants(true);
        forNode(node) = value;
        break;
    }
        
    case SetLocal: {
        m_state.variables().operand(node->local()) = forNode(node->child1());
        break;
    }
        
    case PutStack: {
        m_state.variables().operand(node->stackAccessData()->local) = 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 SetArgument:
        // Assert that the state of arguments has been set. SetArgument means that someone set
        // the argument values out-of-band, and currently this always means setting to a
        // non-clear value.
        ASSERT(!m_state.variables().operand(node->local()).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.variables().argument(argument);
            switch (argumentFormats[argument]) {
            case FlushedInt32:
                value.setType(SpecInt32Only);
                break;
            case FlushedBoolean:
                value.setType(SpecBoolean);
                break;
            case FlushedCell:
                value.setType(m_graph, SpecCell);
                break;
            case FlushedJSValue:
                value.makeBytecodeTop();
                break;
            default:
                DFG_CRASH(m_graph, node, "Bad flush format for argument");
                break;
            }
        }
        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(node->origin.semantic, clobberLimit);
            break;
        case ForwardVarargs:
            break;
        default:
            DFG_CRASH(m_graph, node, "Bad opcode");
            break;
        }
        LoadVarargsData* data = node->loadVarargsData();
        m_state.variables().operand(data->count).setType(SpecInt32Only);
        for (unsigned i = data->limit - 1; i--;)
            m_state.variables().operand(data->start.offset() + i).makeHeapTop();
        break;
    }
            
    case BitAnd:
    case BitOr:
    case BitXor:
    case BitRShift:
    case BitLShift:
    case BitURShift: {
        if (node->child1().useKind() == UntypedUse || node->child2().useKind() == UntypedUse) {
            clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).setType(m_graph, SpecInt32Only);
            break;
        }

        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();
            switch (node->op()) {
            case BitAnd:
                setConstant(node, JSValue(a & b));
                break;
            case BitOr:
                setConstant(node, JSValue(a | b));
                break;
            case BitXor:
                setConstant(node, JSValue(a ^ b));
                break;
            case BitRShift:
                setConstant(node, JSValue(a >> static_cast<uint32_t>(b)));
                break;
            case BitLShift:
                setConstant(node, JSValue(a << static_cast<uint32_t>(b)));
                break;
            case BitURShift:
                setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));
                break;
            default:
                RELEASE_ASSERT_NOT_REACHED();
                break;
            }
            break;
        }
        
        if (node->op() == BitAnd
            && (isBoolInt32Speculation(forNode(node->child1()).m_type) ||
                isBoolInt32Speculation(forNode(node->child2()).m_type))) {
            forNode(node).setType(SpecBoolInt32);
            break;
        }
        
        forNode(node).setType(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;
                }
                forNode(node).setType(SpecAnyInt);
                break;
            }
            if (child && child.isInt32()) {
                uint32_t value = child.asInt32();
                setConstant(node, jsNumber(value));
                break;
            }
            forNode(node).setType(SpecAnyIntAsDouble);
            break;
        }
        if (child && child.isInt32()) {
            int32_t value = child.asInt32();
            if (value >= 0) {
                setConstant(node, jsNumber(value));
                break;
            }
        }
        forNode(node).setType(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.setFoundConstants(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;
            }
        }
        forNode(node).setType(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)) {
            forNode(node).setType(SpecBoolInt32);
            break;
        }
        
        forNode(node).setType(SpecInt32Only);
        break;
    }
        
    case DoubleRep: {
        JSValue child = forNode(node->child1()).value();
        if (std::optional<double> number = child.toNumberFromPrimitive()) {
            setConstant(node, jsDoubleNumber(*number));
            break;
        }

        SpeculatedType type = forNode(node->child1()).m_type;
        switch (node->child1().useKind()) {
        case NotCellUse: {
            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();
        }
        forNode(node).setType(type);
        forNode(node).fixTypeForRepresentation(m_graph, node);
        break;
    }
        
    case Int52Rep: {
        JSValue child = forNode(node->child1()).value();
        if (child && child.isAnyInt()) {
            setConstant(node, child);
            break;
        }
        
        forNode(node).setType(SpecAnyInt);
        break;
    }
        
    case ValueRep: {
        JSValue value = forNode(node->child1()).value();
        if (value) {
            setConstant(node, value);
            break;
        }
        
        forNode(node).setType(m_graph, forNode(node->child1()).m_type & ~SpecDoubleImpureNaN);
        forNode(node).fixTypeForRepresentation(m_graph, node);
        break;
    }
        
    case ValueAdd: {
        ASSERT(node->binaryUseKind() == UntypedUse);
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(m_graph, SpecString | SpecBytecodeNumber);
        break;
    }

    case StrCat: {
        forNode(node).setType(m_graph, 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;
                }
            }
            forNode(node).setType(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;
                }
            }
            forNode(node).setType(SpecAnyInt);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                setConstant(node, jsDoubleNumber(left.asNumber() + right.asNumber()));
                break;
            }
            forNode(node).setType(
                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(node->origin.semantic, clobberLimit);
        forNode(node).setType(SpecBoolInt32);
        break;
    }

    case ArithClz32: {
        JSValue operand = forNode(node->child1()).value();
        if (std::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(clz32(value)));
            break;
        }
        switch (node->child1().useKind()) {
        case Int32Use:
        case KnownInt32Use:
            break;
        default:
            clobberWorld(node->origin.semantic, clobberLimit);
            break;
        }
        forNode(node).setType(SpecInt32Only);
        break;
    }

    case MakeRope: {
        unsigned numberOfChildren = 0;
        unsigned numberOfRemovedChildren = 0;
        std::optional<unsigned> nonEmptyIndex;
        for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
            Edge& edge = node->children.child(i);
            if (!edge)
                break;
            ++numberOfChildren;

            JSValue childConstant = m_state.forNode(edge).value();
            if (!childConstant) {
                nonEmptyIndex = i;
                continue;
            }
            if (!childConstant.isString()) {
                nonEmptyIndex = i;
                continue;
            }
            if (asString(childConstant)->length()) {
                nonEmptyIndex = i;
                continue;
            }

            ++numberOfRemovedChildren;
        }

        if (numberOfRemovedChildren) {
            m_state.setFoundConstants(true);
            if (numberOfRemovedChildren == numberOfChildren) {
                // Propagate the last child. This is the way taken in the constant folding phase.
                forNode(node) = forNode(node->children.child(numberOfChildren - 1));
                break;
            }
            if ((numberOfRemovedChildren + 1) == numberOfChildren) {
                ASSERT(nonEmptyIndex);
                forNode(node) = forNode(node->children.child(nonEmptyIndex.value()));
                break;
            }
        }
        forNode(node).set(m_graph, 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;
                }
            }
            forNode(node).setType(SpecInt32Only);
            break;
        case Int52RepUse:
            if (left && right && left.isAnyInt() && right.isAnyInt()) {
                JSValue result = jsNumber(left.asAnyInt() - right.asAnyInt());
                if (result.isAnyInt() || !shouldCheckOverflow(node->arithMode())) {
                    setConstant(node, result);
                    break;
                }
            }
            forNode(node).setType(SpecAnyInt);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                setConstant(node, jsDoubleNumber(left.asNumber() - right.asNumber()));
                break;
            }
            forNode(node).setType(
                typeOfDoubleDifference(
                    forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            break;
        case UntypedUse:
            clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).setType(m_graph, SpecBytecodeNumber);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        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;
                }
            }
            forNode(node).setType(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;
                }
            }
            forNode(node).setType(SpecAnyInt);
            break;
        case DoubleRepUse:
            if (child && child.isNumber()) {
                setConstant(node, jsDoubleNumber(-child.asNumber()));
                break;
            }
            forNode(node).setType(
                typeOfDoubleNegation(
                    forNode(node->child1()).m_type));
            break;
        default:
            DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
            clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).setType(SpecBytecodeNumber);
            break;
        }
        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;
                }
            }
            forNode(node).setType(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;
                }
            }
            forNode(node).setType(SpecAnyInt);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                setConstant(node, jsDoubleNumber(left.asNumber() * right.asNumber()));
                break;
            }
            forNode(node).setType(
                typeOfDoubleProduct(
                    forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            break;
        case UntypedUse:
            clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).setType(m_graph, SpecBytecodeNumber);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }
        
    case ArithDiv: {
        JSValue left = forNode(node->child1()).value();
        JSValue right = forNode(node->child2()).value();
        switch (node->binaryUseKind()) {
        case Int32Use:
            if (left && right && left.isInt32() && right.isInt32()) {
                double doubleResult = left.asNumber() / right.asNumber();
                if (!shouldCheckOverflow(node->arithMode()))
                    doubleResult = toInt32(doubleResult);
                else if (!shouldCheckNegativeZero(node->arithMode()))
                    doubleResult += 0; // Sanitizes zero.
                JSValue valueResult = jsNumber(doubleResult);
                if (valueResult.isInt32()) {
                    setConstant(node, valueResult);
                    break;
                }
            }
            forNode(node).setType(SpecInt32Only);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                setConstant(node, jsDoubleNumber(left.asNumber() / right.asNumber()));
                break;
            }
            forNode(node).setType(
                typeOfDoubleQuotient(
                    forNode(node->child1()).m_type, forNode(node->child2()).m_type));
            break;
        case UntypedUse:
            clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).setType(m_graph, SpecBytecodeNumber);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        break;
    }

    case ArithMod: {
        JSValue left = forNode(node->child1()).value();
        JSValue right = forNode(node->child2()).value();
        switch (node->binaryUseKind()) {
        case Int32Use:
            if (left && right && left.isInt32() && right.isInt32()) {
                double doubleResult = fmod(left.asNumber(), right.asNumber());
                if (!shouldCheckOverflow(node->arithMode()))
                    doubleResult = toInt32(doubleResult);
                else if (!shouldCheckNegativeZero(node->arithMode()))
                    doubleResult += 0; // Sanitizes zero.
                JSValue valueResult = jsNumber(doubleResult);
                if (valueResult.isInt32()) {
                    setConstant(node, valueResult);
                    break;
                }
            }
            forNode(node).setType(SpecInt32Only);
            break;
        case DoubleRepUse:
            if (left && right && left.isNumber() && right.isNumber()) {
                setConstant(node, jsDoubleNumber(fmod(left.asNumber(), right.asNumber())));
                break;
            }
            forNode(node).setType(
                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;
            }
            forNode(node).setType(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;
            }
            forNode(node).setType(
                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;
            }
            forNode(node).setType(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;
            }
            forNode(node).setType(
                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 (std::optional<double> number = child.toNumberFromPrimitive()) {
                JSValue result = jsNumber(fabs(*number));
                if (result.isInt32()) {
                    setConstant(node, result);
                    break;
                }
            }
            forNode(node).setType(SpecInt32Only);
            break;
        case DoubleRepUse:
            if (std::optional<double> number = child.toNumberFromPrimitive()) {
                setConstant(node, jsDoubleNumber(fabs(*number)));
                break;
            }
            forNode(node).setType(typeOfDoubleAbs(forNode(node->child1()).m_type));
            break;
        default:
            DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
            clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).setType(SpecFullNumber);
            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;
            }
        }
        forNode(node).setType(typeOfDoublePow(forNode(node->child1()).m_type, forNode(node->child2()).m_type));
        break;
    }

    case ArithRandom: {
        forNode(node).setType(m_graph, SpecDoubleReal);
        break;
    }

    case ArithRound:
    case ArithFloor:
    case ArithCeil:
    case ArithTrunc: {
        JSValue operand = forNode(node->child1()).value();
        if (std::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()))
                forNode(node).setType(SpecInt32Only);
            else if (node->child1().useKind() == DoubleRepUse)
                forNode(node).setType(typeOfDoubleRounding(forNode(node->child1()).m_type));
        } else {
            DFG_ASSERT(m_graph, node, node->child1().useKind() == UntypedUse, node->child1().useKind());
            clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).setType(SpecFullNumber);
        }
        break;
    }
            
    case ArithSqrt:
        executeDoubleUnaryOpEffects(node, clobberLimit, sqrt);
        break;

    case ArithFRound:
        executeDoubleUnaryOpEffects(node, clobberLimit, [](double value) -> double { return static_cast<float>(value); });
        break;
        
    case ArithUnary:
        executeDoubleUnaryOpEffects(node, clobberLimit, 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:
            forNode(node).setType(SpecBoolean);
            break;
        }
        break;
    }

    case MapHash: {
        if (JSValue key = forNode(node->child1()).value()) {
            if (std::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;
            }
        }
        forNode(node).setType(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.setFoundConstants(true);
            forNode(node) = forNode(node->child1());
            break;
        }

        forNode(node).makeHeapTop();
        break;
    }

    case StringSlice: {
        forNode(node).setType(m_graph, SpecString);
        break;
    }

    case ToLowerCase: {
        forNode(node).setType(m_graph, SpecString);
        break;
    }

    case LoadKeyFromMapBucket:
    case LoadValueFromMapBucket:
    case ExtractValueFromWeakMapGet:
        forNode(node).makeHeapTop();
        break;

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

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

    case SetAdd:
        forNode(node).set(m_graph, m_vm.hashMapBucketSetStructure.get());
        break;

    case MapSet:
        forNode(node).set(m_graph, m_vm.hashMapBucketMapStructure.get());
        break;

    case WeakSetAdd:
    case WeakMapSet:
        break;

    case WeakMapGet:
        forNode(node).makeBytecodeTop();
        break;

    case IsEmpty:
    case IsUndefined:
    case IsBoolean:
    case IsNumber:
    case NumberIsInteger:
    case IsObject:
    case IsObjectOrNull:
    case IsFunction:
    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()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->origin.semantic))
                    : child.value().isUndefined()));
                break;
            case IsBoolean:
                setConstant(node, jsBoolean(child.value().isBoolean()));
                break;
            case IsNumber:
                setConstant(node, jsBoolean(child.value().isNumber()));
                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() & TypeOfShouldCallGetCallData))
                        setConstant(node, jsBoolean(!child.value().asCell()->structure()->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() & TypeOfShouldCallGetCallData))
                        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 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;
        }
        
        // 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 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 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 IsCellWithType:
            if (!(child.m_type & ~node->speculatedTypeForQuery())) {
                setConstant(node, jsBoolean(true));
                constantWasSet = true;
                break;
            }
            if (!(child.m_type & node->speculatedTypeForQuery())) {
                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;
        
        forNode(node).setType(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;
        }

        forNode(node).setType(m_graph, 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;
        }
        forNode(node).setType(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()) {
                double a = leftConst.asNumber();
                double b = rightConst.asNumber();
                switch (node->op()) {
                case CompareLess:
                    setConstant(node, jsBoolean(a < b));
                    break;
                case CompareLessEq:
                    setConstant(node, jsBoolean(a <= b));
                    break;
                case CompareGreater:
                    setConstant(node, jsBoolean(a > b));
                    break;
                case CompareGreaterEq:
                    setConstant(node, jsBoolean(a >= b));
                    break;
                case CompareEq:
                    setConstant(node, jsBoolean(a == b));
                    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(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(node->origin.semantic, clobberLimit);
        forNode(node).setType(SpecBoolean);
        break;
    }
            
    case CompareStrictEq: {
        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 {
                setConstant(node, jsBoolean(JSValue::strictEqual(0, left, right)));
                break;
            }
        }

        if (node->isBinaryUseKind(UntypedUse)) {
            // FIXME: Revisit this condition when introducing BigInt to JSC.
            auto isNonStringCellConstant = [] (JSValue value) {
                return value && value.isCell() && !value.isString();
            };

            if (isNonStringCellConstant(left) || isNonStringCellConstant(right)) {
                m_state.setFoundConstants(true);
                forNode(node).setType(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()) {
            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)) {
                setConstant(node, jsBoolean(true));
                break;
            }
        }

        forNode(node).setType(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;
        }
        
        forNode(node).setType(SpecBoolean);
        break;
    }
        
    case StringCharCodeAt:
        forNode(node).setType(SpecInt32Only);
        break;
        
    case StringFromCharCode:
        switch (node->child1().useKind()) {
        case Int32Use:
            break;
        case UntypedUse:
            clobberWorld(node->origin.semantic, clobberLimit);
            break;
        default:
            DFG_CRASH(m_graph, node, "Bad use kind");
            break;
        }
        forNode(node).setType(m_graph, SpecString);
        break;

    case StringCharAt:
        forNode(node).set(m_graph, 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)
            clobberWorld(node->origin.semantic, clobberLimit);
        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;
            }
            forNode(node).setType(SpecOther);
            break;
        }
        case Array::Generic:
            clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).makeHeapTop();
            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(node->origin.semantic, clobberLimit);
                forNode(node).makeHeapTop();
            } else
                forNode(node).set(m_graph, m_vm.stringStructure.get());
            break;
        case Array::DirectArguments:
        case Array::ScopedArguments:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).makeHeapTop();
            break;
        case Array::Int32:
            if (node->arrayMode().isOutOfBounds()) {
                clobberWorld(node->origin.semantic, clobberLimit);
                forNode(node).makeHeapTop();
            } else
                forNode(node).setType(SpecInt32Only);
            break;
        case Array::Double:
            if (node->arrayMode().isOutOfBounds()) {
                clobberWorld(node->origin.semantic, clobberLimit);
                forNode(node).makeHeapTop();
            } else if (node->arrayMode().isSaneChain())
                forNode(node).setType(SpecBytecodeDouble);
            else
                forNode(node).setType(SpecDoubleReal);
            break;
        case Array::Contiguous:
        case Array::ArrayStorage:
        case Array::SlowPutArrayStorage:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).makeHeapTop();
            break;
        case Array::Int8Array:
            forNode(node).setType(SpecInt32Only);
            break;
        case Array::Int16Array:
            forNode(node).setType(SpecInt32Only);
            break;
        case Array::Int32Array:
            forNode(node).setType(SpecInt32Only);
            break;
        case Array::Uint8Array:
            forNode(node).setType(SpecInt32Only);
            break;
        case Array::Uint8ClampedArray:
            forNode(node).setType(SpecInt32Only);
            break;
        case Array::Uint16Array:
            forNode(node).setType(SpecInt32Only);
            break;
        case Array::Uint32Array:
            if (node->shouldSpeculateInt32())
                forNode(node).setType(SpecInt32Only);
            else if (enableInt52() && node->shouldSpeculateAnyInt())
                forNode(node).setType(SpecAnyInt);
            else
                forNode(node).setType(SpecAnyIntAsDouble);
            break;
        case Array::Float32Array:
            forNode(node).setType(SpecFullDouble);
            break;
        case Array::Float64Array:
            forNode(node).setType(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(node->origin.semantic, clobberLimit);
            break;
        case Array::Int32:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld(node->origin.semantic, clobberLimit);
            break;
        case Array::Double:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld(node->origin.semantic, clobberLimit);
            break;
        case Array::Contiguous:
        case Array::ArrayStorage:
            if (node->arrayMode().isOutOfBounds())
                clobberWorld(node->origin.semantic, clobberLimit);
            break;
        case Array::SlowPutArrayStorage:
            if (node->arrayMode().mayStoreToHole())
                clobberWorld(node->origin.semantic, clobberLimit);
            break;
        default:
            break;
        }
        break;
    }
            
    case ArrayPush:
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(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)));

        forNode(node).set(m_graph, structureSet);
        break;
    }

    case ArrayIndexOf: {
        forNode(node).setType(SpecInt32Only);
        break;
    }
            
    case ArrayPop:
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).makeHeapTop();
        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 < inlineCallFrame->argumentCountIncludingThis - 1) {
                        forNode(node) = m_state.variables().operand(
                            virtualRegisterForArgument(argumentIndex + 1) + inlineCallFrame->stackOffset);
                        m_state.setFoundConstants(true);
                        break;
                    }
                } else {
                    if (argumentIndex < m_state.variables().numberOfArguments() - 1) {
                        forNode(node) = m_state.variables().argument(argumentIndex + 1);
                        m_state.setFoundConstants(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.variables().operand(
                        virtualRegisterForArgument(i) + inlineCallFrame->stackOffset));
            }
            
            if (node->op() == GetMyArgumentByValOutOfBounds)
                result.merge(SpecOther);
            
            if (result.value())
                m_state.setFoundConstants(true);
            
            forNode(node) = result;
            break;
        }
        
        forNode(node).makeHeapTop();
        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(node->origin.semantic, clobberLimit);
        }

        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()));
                    structureSet.add(m_graph.registerStructure(globalObject->regExpMatchesArrayWithGroupsStructure()));
                    forNode(node).set(m_graph, structureSet);
                    forNode(node).merge(SpecOther);
                    break;
                }
            }
        }
        forNode(node).setType(m_graph, 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(node->origin.semantic, clobberLimit);
        forNode(node).setType(SpecBoolean);
        break;

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

    case RegExpMatchFastGlobal:
        ASSERT(node->child2().useKind() == StringUse);
        forNode(node).setType(m_graph, 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(node->origin.semantic, clobberLimit);
        forNode(node).set(m_graph, 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(node->origin.semantic, clobberLimit);
        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.setFoundConstants(true);
            didFoldClobberWorld();
            forNode(node) = forNode(node->child1());
            break;
        }
        
        clobberWorld(node->origin.semantic, clobberLimit);
        
        forNode(node).setType(m_graph, SpecHeapTop & ~SpecObject);
        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.setFoundConstants(true);
            didFoldClobberWorld();
            forNode(node) = forNode(node->child1());
            break;
        }

        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(m_graph, SpecBytecodeNumber);
        break;
    }
        
    case ToString:
    case CallStringConstructor: {
        switch (node->child1().useKind()) {
        case StringObjectUse:
            // This also filters that the StringObject has the primordial StringObject
            // structure.
            filter(
                node->child1(),
                m_graph.registerStructure(m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure()));
            break;
        case StringOrStringObjectUse:
        case Int32Use:
        case Int52RepUse:
        case DoubleRepUse:
        case NotCellUse:
            break;
        case CellUse:
        case UntypedUse:
            clobberWorld(node->origin.semantic, clobberLimit);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        forNode(node).set(m_graph, 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.setFoundConstants(true);
                didFoldClobberWorld();
                forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
                break;
            }
        }
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
        break;
    }

    case NumberToStringWithValidRadixConstant: {
        forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
        break;
    }
        
    case NewStringObject: {
        ASSERT(node->structure()->classInfo() == StringObject::info());
        forNode(node).set(m_graph, node->structure());
        break;
    }
            
    case NewArray:
        forNode(node).set(
            m_graph,
            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.
            forNode(node).set(
                m_graph,
                m_graph.globalObjectFor(node->origin.semantic)->originalArrayStructureForIndexingType(ArrayWithContiguous));
        } else {
            forNode(node).set(
                m_graph,
                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(node->origin.semantic, clobberLimit);
            else
                didFoldClobberWorld();
            break;
        }

        forNode(node).set(
            m_graph, m_vm.fixedArrayStructure.get());
        break;
        
    case NewArrayBuffer:
        forNode(node).set(
            m_graph,
            m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
        break;

    case NewArrayWithSize:
        forNode(node).setType(m_graph, SpecArray);
        break;
        
    case NewTypedArray:
        switch (node->child1().useKind()) {
        case Int32Use:
            break;
        case UntypedUse:
            clobberWorld(node->origin.semantic, clobberLimit);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        forNode(node).set(
            m_graph,
            m_graph.globalObjectFor(node->origin.semantic)->typedArrayStructureConcurrently(
                node->typedArrayType()));
        break;
        
    case NewRegexp:
        forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->regExpStructure());
        break;
            
    case ToThis: {
        AbstractValue& source = forNode(node->child1());
        AbstractValue& destination = forNode(node);
        bool strictMode = m_graph.executableFor(node->origin.semantic)->isStrictMode();

        ToThisResult result = isToThisAnIdentity(m_vm, strictMode, source);
        if (result != ToThisResult::Dynamic) {
            switch (result) {
            case ToThisResult::Identity:
                m_state.setFoundConstants(true);
                destination = source;
                break;
            case ToThisResult::Undefined:
                setConstant(node, jsUndefined());
                break;
            case ToThisResult::GlobalThis:
                m_state.setFoundConstants(true);
                destination.setType(m_graph, SpecObject);
                break;
            case ToThisResult::Dynamic:
                RELEASE_ASSERT_NOT_REACHED();
            }
            break;
        }

        if (strictMode)
            destination.makeHeapTop();
        else {
            destination = source;
            destination.merge(SpecObject);
        }
        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 (Structure* structure = rareData->objectAllocationStructure()) {
                        // FIXME: we should be able to allocate a poly proto object here:
                        // https://bugs.webkit.org/show_bug.cgi?id=177517
                        if (structure->hasMonoProto()) {
                            m_graph.freeze(rareData);
                            m_graph.watchpoints().addLazily(rareData->allocationProfileWatchpointSet());
                            m_state.setFoundConstants(true);
                            didFoldClobberWorld();
                            forNode(node).set(m_graph, structure);
                            break;
                        }
                    }
                }
            }
        }
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(m_graph, SpecFinalObject);
        break;
    }
        
    case NewObject:
        ASSERT(!!node->structure().get());
        forNode(node).set(m_graph, node->structure());
        break;

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

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

        if (node->op() == ToObject)
            clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(m_graph, 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 PhantomNewRegexp:
    case BottomValue:
        // This claims to return bottom.
        break;
        
    case PutHint:
        break;
        
    case MaterializeNewObject: {
        forNode(node).set(m_graph, 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.
        forNode(node).setType(m_graph, SpecObjectOther);
        break;

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

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

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

    case NewAsyncFunction:
        forNode(node).set(
            m_graph, 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*>());
        forNode(node).set(m_graph, structure);
        break;
    }
        
    case GetCallee:
        if (FunctionExecutable* executable = jsDynamicCast<FunctionExecutable*>(m_vm, m_codeBlock->ownerExecutable())) {
            InferredValue* singleton = executable->singletonFunction();
            if (JSValue value = singleton->inferredValue()) {
                m_graph.watchpoints().addLazily(singleton);
                JSFunction* function = jsCast<JSFunction*>(value);
                setConstant(node, *m_graph.freeze(function));
                break;
            }
        }
        forNode(node).setType(m_graph, SpecFunction);
        break;
        
    case GetArgumentCountIncludingThis:
        forNode(node).setType(SpecInt32Only);
        break;

    case SetArgumentCountIncludingThis:
        break;
        
    case GetRestLength:
        forNode(node).setType(SpecInt32Only);
        break;
        
    case GetGetter: {
        JSValue base = forNode(node->child1()).m_value;
        if (base) {
            GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
            if (!getterSetter->isGetterNull()) {
                setConstant(node, *m_graph.freeze(getterSetter->getterConcurrently()));
                break;
            }
        }
        
        forNode(node).setType(m_graph, SpecObject);
        break;
    }
        
    case GetSetter: {
        JSValue base = forNode(node->child1()).m_value;
        if (base) {
            GetterSetter* getterSetter = jsCast<GetterSetter*>(base);
            if (!getterSetter->isSetterNull()) {
                setConstant(node, *m_graph.freeze(getterSetter->setterConcurrently()));
                break;
            }
        }
        
        forNode(node).setType(m_graph, 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;
            }
        }
        forNode(node).setType(m_graph, SpecObjectOther);
        break;

    case SkipScope: {
        JSValue child = forNode(node->child1()).value();
        if (child) {
            setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
            break;
        }
        forNode(node).setType(m_graph, SpecObjectOther);
        break;
    }

    case GetGlobalObject: {
        JSValue child = forNode(node->child1()).value();
        if (child) {
            setConstant(node, *m_graph.freeze(JSValue(asObject(child)->globalObject())));
            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;
            }
        }

        forNode(node).setType(m_graph, SpecObjectOther);
        break;
    }

    case GetGlobalThis: {
        forNode(node).setType(m_graph, SpecObject);
        break;
    }

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

    case GetRegExpObjectLastIndex:
        forNode(node).makeHeapTop();
        break;

    case SetRegExpObjectLastIndex:
    case RecordRegExpCachedResult:
        break;
        
    case GetFromArguments:
        forNode(node).makeHeapTop();
        break;
        
    case PutToArguments:
        break;

    case GetArgument:
        forNode(node).makeHeapTop();
        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
        forNode(node).makeHeapTop();
        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 = m_graph.identifiers()[node->identifierNumber()];
            GetByIdStatus status = GetByIdStatus::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, uid, status[i].offset(), m_state.structureClobberState()));
                }
                m_state.setFoundConstants(true);
                didFoldClobberWorld();
                forNode(node) = result;
                break;
            }
        }

        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).makeHeapTop();
        break;
    }

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

    case GetVectorLength: {
        forNode(node).setType(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(node->origin.semantic, clobberLimit);
        forNode(node).setType(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.setFoundConstants(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.setFoundConstants(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.setFoundConstants(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.setFoundConstants(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.setFoundConstants(true);
            } else {
                observeTransition(
                    clobberLimit, node->transition()->previous, node->transition()->next);
                forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
            }
        }
        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();
        forNode(node).clear(); // 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.setFoundConstants(true);
                ASSERT(constant);
                break;
            }
        }

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

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

        filterClassInfo(value, node->classInfo());
        break;
    }
    case CallDOMGetter: {
        CallDOMGetterData* callDOMGetterData = node->callDOMGetterData();
        DOMJIT::CallDOMGetterSnippet* snippet = callDOMGetterData->snippet;
        if (!snippet || snippet->effect.writes)
            clobberWorld(node->origin.semantic, clobberLimit);
        if (callDOMGetterData->domJIT)
            forNode(node).setType(m_graph, callDOMGetterData->domJIT->resultType());
        else
            forNode(node).makeBytecodeTop();
        break;
    }
    case CallDOM: {
        const DOMJIT::Signature* signature = node->signature();
        if (signature->effect.writes)
            clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(m_graph, signature->result);
        break;
    }
    case CheckArray: {
        if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
            m_state.setFoundConstants(true);
            break;
        }
        switch (node->arrayMode().type()) {
        case Array::String:
            filter(node->child1(), SpecString);
            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);
            break;
        case Array::ScopedArguments:
            filter(node->child1(), SpecScopedArguments);
            break;
        case Array::Int8Array:
            filter(node->child1(), SpecInt8Array);
            break;
        case Array::Int16Array:
            filter(node->child1(), SpecInt16Array);
            break;
        case Array::Int32Array:
            filter(node->child1(), SpecInt32Array);
            break;
        case Array::Uint8Array:
            filter(node->child1(), SpecUint8Array);
            break;
        case Array::Uint8ClampedArray:
            filter(node->child1(), SpecUint8ClampedArray);
            break;
        case Array::Uint16Array:
            filter(node->child1(), SpecUint16Array);
            break;
        case Array::Uint32Array:
            filter(node->child1(), SpecUint32Array);
            break;
        case Array::Float32Array:
            filter(node->child1(), SpecFloat32Array);
            break;
        case Array::Float64Array:
            filter(node->child1(), SpecFloat64Array);
            break;
        case Array::AnyTypedArray:
            filter(node->child1(), SpecTypedArrayView);
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
        break;
    }
    case Arrayify: {
        if (node->arrayMode().alreadyChecked(m_graph, node, forNode(node->child1()))) {
            didFoldClobberStructures();
            m_state.setFoundConstants(true);
            break;
        }
        ASSERT(node->arrayMode().conversion() == Array::Convert);
        clobberStructures(clobberLimit);
        filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
        break;
    }
    case ArrayifyToStructure: {
        AbstractValue& value = forNode(node->child1());
        if (value.m_structure.isSubsetOf(RegisteredStructureSet(node->structure())))
            m_state.setFoundConstants(true);
        clobberStructures(clobberLimit);
        
        // 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.
        value.set(m_graph, node->structure());
        break;
    }
    case GetIndexedPropertyStorage: {
        JSArrayBufferView* view = m_graph.tryGetFoldableView(
            forNode(node->child1()).m_value, node->arrayMode());
        if (view)
            m_state.setFoundConstants(true);
        forNode(node).clear();
        break;
    }
    case ConstantStoragePointer: {
        forNode(node).clear();
        break; 
    }
        
    case GetTypedArrayByteOffset: {
        JSArrayBufferView* view = m_graph.tryGetFoldableView(forNode(node->child1()).m_value);
        if (view) {
            setConstant(node, jsNumber(view->byteOffset()));
            break;
        }
        forNode(node).setType(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(node->origin.semantic, clobberLimit);
            break;
        }
        forNode(node).setType(m_graph, SpecObject | SpecOther);
        break;
    }
        
    case GetByOffset: {
        StorageAccessData& data = node->storageAccessData();
        UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];

        // 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()), uid, data.offset, m_state.structureClobberState());

        // It's possible that the type that ByteCodeParser came up with is better.
        AbstractValue typeFromParsing;
        typeFromParsing.set(m_graph, data.inferredType, m_state.structureClobberState());
        value.filter(typeFromParsing);

        // 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);

        forNode(node) = value;
        if (value.m_value)
            m_state.setFoundConstants(true);
        break;
    }
        
    case GetGetterSetterByOffset: {
        StorageAccessData& data = node->storageAccessData();
        JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
        if (result && jsDynamicCast<GetterSetter*>(m_vm, result)) {
            setConstant(node, *m_graph.freeze(result));
            break;
        }
        
        forNode(node).set(m_graph, m_graph.globalObjectFor(node->origin.semantic)->getterSetterStructure());
        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 setFoundConstants()
        // because of the effect on compile times, but this node is FTL-only.
        m_state.setFoundConstants(true);
        
        UniquedStringImpl* uid = m_graph.identifiers()[node->multiGetByOffsetData().identifierNumber];

        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;
            }

            case GetByOffsetMethod::Load: {
                result.merge(
                    m_graph.inferredValueForProperty(
                        set, uid, m_state.structureClobberState()));
                break;
            }

            default: {
                result.makeHeapTop();
                break;
            } }
        }
        
        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
            m_state.setIsValid(false);
        
        forNode(node) = result;
        break;
    }
            
    case PutByOffset: {
        break;
    }
        
    case MultiPutByOffset: {
        RegisteredStructureSet newSet;
        TransitionVector transitions;
        
        // Ordinarily you have to be careful with calling setFoundConstants()
        // because of the effect on compile times, but this node is FTL-only.
        m_state.setFoundConstants(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;
            thisValue.filter(m_graph, variant.requiredType());
            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);
            }
        }
        
        observeTransitions(clobberLimit, transitions);
        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
            m_state.setIsValid(false);
        forNode(node->child2()) = resultingValue;
        if (!!originalValue && !resultingValue)
            m_state.setIsValid(false);
        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;
            }
        }
        forNode(node).setType(m_graph, SpecCellOther);
        break;
    }
    
    case CheckCell: {
        JSValue value = forNode(node->child1()).value();
        if (value == node->cellOperand()->value()) {
            m_state.setFoundConstants(true);
            ASSERT(value);
            break;
        }
        filterByValue(node->child1(), *node->cellOperand());
        break;
    }

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

    case CheckStringIdent: {
        AbstractValue& value = forNode(node->child1());
        UniquedStringImpl* uid = node->uidOperand();
        ASSERT(!(value.m_type & ~SpecStringIdent)); // Edge filtering should have already ensured this.

        JSValue childConstant = value.value();
        if (childConstant) {
            ASSERT(childConstant.isString());
            if (asString(childConstant)->tryGetValueImpl() == uid) {
                m_state.setFoundConstants(true);
                break;
            }
        }

        filter(value, SpecStringIdent);
        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.setFoundConstants(true);
            break;
        }
        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(),
                m_graph.identifiers()[node->identifierNumber()],
                node->op() == PutByIdDirect);

            if (status.isSimple()) {
                RegisteredStructureSet newSet;
                TransitionVector transitions;
                
                for (unsigned i = status.numVariants(); i--;) {
                    const PutByIdVariant& variant = status[i];
                    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 || isFTL(m_graph.m_plan.mode))
                    m_state.setFoundConstants(true);
                
                didFoldClobberWorld();
                observeTransitions(clobberLimit, transitions);
                if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
                    m_state.setIsValid(false);
                break;
            }
        }
        
        clobberWorld(node->origin.semantic, clobberLimit);
        break;
    }

    case PutByValWithThis:
    case PutByIdWithThis:
        clobberWorld(node->origin.semantic, clobberLimit);
        break;

    case PutGetterById:
    case PutSetterById:
    case PutGetterSetterById:
    case PutGetterByVal:
    case PutSetterByVal: {
        clobberWorld(node->origin.semantic, clobberLimit);
        break;
    }

    case DefineDataProperty:
    case DefineAccessorProperty:
        clobberWorld(node->origin.semantic, clobberLimit);
        break;
        
    case In: {
        // FIXME: We can determine when the property definitely exists based on abstract
        // value information.
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(SpecBoolean);
        break;
    }

    case HasOwnProperty: {
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(SpecBoolean);
        break;
    }
            
    case GetEnumerableLength: {
        forNode(node).setType(SpecInt32Only);
        break;
    }
    case HasGenericProperty: {
        forNode(node).setType(SpecBoolean);
        clobberWorld(node->origin.semantic, clobberLimit);
        break;
    }
    case HasStructureProperty: {
        forNode(node).setType(SpecBoolean);
        clobberWorld(node->origin.semantic, clobberLimit);
        break;
    }
    case HasIndexedProperty: {
        ArrayMode mode = node->arrayMode();
        switch (mode.type()) {
        case Array::Int32:
        case Array::Double:
        case Array::Contiguous:
        case Array::ArrayStorage: {
            break;
        }
        default: {
            clobberWorld(node->origin.semantic, clobberLimit);
            break;
        }
        }
        forNode(node).setType(SpecBoolean);
        break;
    }
    case GetDirectPname: {
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).makeHeapTop();
        break;
    }
    case GetPropertyEnumerator: {
        forNode(node).setType(m_graph, SpecCell);
        clobberWorld(node->origin.semantic, clobberLimit);
        break;
    }
    case GetEnumeratorStructurePname: {
        forNode(node).setType(m_graph, SpecString | SpecOther);
        break;
    }
    case GetEnumeratorGenericPname: {
        forNode(node).setType(m_graph, SpecString | SpecOther);
        break;
    }
    case ToIndexString: {
        forNode(node).setType(m_graph, SpecString);
        break;
    }

    case GetGlobalVar:
        forNode(node).makeHeapTop();
        break;

    case GetGlobalLexicalVariable:
        forNode(node).makeBytecodeTop();
        break;

    case GetDynamicVar:
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).makeBytecodeTop();
        break;

    case PutDynamicVar:
        clobberWorld(node->origin.semantic, clobberLimit);
        break;

    case ResolveScope:
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(m_graph, SpecObject);
        break;

    case ResolveScopeForHoistingFuncDeclInEval:
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).makeBytecodeTop();
        break;

    case PutGlobalVariable:
    case NotifyWrite:
        break;

    case OverridesHasInstance:
        forNode(node).setType(SpecBoolean);
        break;
            
    case InstanceOf:
        // Sadly, we don't propagate the fact that we've done InstanceOf
        forNode(node).setType(SpecBoolean);
        break;

    case InstanceOfCustom:
        clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(SpecBoolean);
        break;
            
    case Phi:
        RELEASE_ASSERT(m_graph.m_form == SSA);
        forNode(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.setFoundConstants(true);
        break;
        
    case Upsilon: {
        NodeFlowProjection shadow(node->phi(), NodeFlowProjection::Shadow);
        if (shadow.isStillValid()) {
            m_state.createValueForNode(shadow);
            forNode(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(node->origin.semantic, clobberLimit);
        forNode(node).makeHeapTop();
        break;

    case ForceOSRExit:
    case CheckBadCell:
        m_state.setIsValid(false);
        break;
        
    case InvalidationPoint:
        forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor);
        m_state.setStructureClobberState(StructuresAreWatched);
        break;

    case CPUIntrinsic: 
        if (node->intrinsic() == CPURdtscIntrinsic)
            forNode(node).setType(SpecInt32Only);
        else
            forNode(node).setType(SpecOther);
        break;

    case CheckTraps:
    case LogShadowChickenPrologue:
    case LogShadowChickenTail:
        break;

    case ProfileType:
    case ProfileControlFlow:
    case Phantom:
    case CountExecution:
    case CheckTierUpInLoop:
    case CheckTierUpAtReturn:
    case CheckTypeInfoFlags:
    case SuperSamplerBegin:
    case SuperSamplerEnd:
        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.setFoundConstants(true);
                if (node->child1().useKind() == UntypedUse)
                    didFoldClobberWorld();
                forNode(node).setType(SpecInt32Only);
                break;
            }
        }

        if (node->child1().useKind() == UntypedUse)
            clobberWorld(node->origin.semantic, clobberLimit);
        forNode(node).setType(m_graph, SpecBytecodeNumber);
        break;
    }

    case CreateRest:
        if (!m_graph.isWatchingHavingABadTimeWatchpoint(node)) {
            // This means we're already having a bad time.
            clobberWorld(node->origin.semantic, clobberLimit);
            forNode(node).setType(m_graph, SpecArray);
            break;
        }
        forNode(node).set(
            m_graph,
            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.setFoundConstants(true);
        });
        break;
    }

    case SetFunctionName: {
        clobberWorld(node->origin.semantic, clobberLimit);
        break;
    }

    case StoreBarrier:
    case FencedStoreBarrier: {
        filter(node->child1(), SpecCell);
        break;
    }
        
    case CheckTierUpAndOSREnter:
    case LoopHint:
    case ZombieHint:
    case ExitOK:
        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>
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(
    const CodeOrigin&, unsigned clobberLimit)
{
    clobberStructures(clobberLimit);
}

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.variables().numberOfArguments(); i--;)
        functor(m_state.variables().argument(i));
    for (size_t i = m_state.variables().numberOfLocals(); i--;)
        functor(m_state.variables().local(i));
}

template<typename AbstractStateType>
void AbstractInterpreter<AbstractStateType>::clobberStructures(unsigned clobberLimit)
{
    forAllValues(clobberLimit, AbstractValue::clobberStructuresFor);
    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)
{
    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;
    
    AbstractValue::TransitionsObserver transitionsObserver(vector);
    forAllValues(clobberLimit, transitionsObserver);
    
    if (!ASSERT_DISABLED) {
        // 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)
{
    if (value.filterArrayModes(arrayModes) == 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, unsigned clobberLimit, double(*equivalentFunction)(double))
{
    JSValue child = forNode(node->child1()).value();
    if (std::optional<double> number = child.toNumberFromPrimitive()) {
        if (node->child1().useKind() != DoubleRepUse)
            didFoldClobberWorld();
        setConstant(node, jsDoubleNumber(equivalentFunction(*number)));
        return;
    }
    SpeculatedType type = SpecFullNumber;
    if (node->child1().useKind() == DoubleRepUse)
        type = typeOfDoubleUnaryOp(forNode(node->child1()).m_type);
    else
        clobberWorld(node->origin.semantic, clobberLimit);
    forNode(node).setType(type);
}

} } // namespace JSC::DFG

#endif // ENABLE(DFG_JIT)
