SpeculatedType.cpp   [plain text]


/*
 * Copyright (C) 2011-2017 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.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "SpeculatedType.h"

#include "DirectArguments.h"
#include "JSArray.h"
#include "JSBigInt.h"
#include "JSBoundFunction.h"
#include "JSCInlines.h"
#include "JSFunction.h"
#include "JSMap.h"
#include "JSSet.h"
#include "JSWeakMap.h"
#include "JSWeakSet.h"
#include "ProxyObject.h"
#include "RegExpObject.h"
#include "ScopedArguments.h"
#include "StringObject.h"
#include "ValueProfile.h"
#include <wtf/CommaPrinter.h>
#include <wtf/StringPrintStream.h>

namespace JSC {

struct PrettyPrinter {
    PrettyPrinter(PrintStream& out)
        : out(out)
        , separator("|")
    { }
    
    template<typename T>
    void print(const T& value)
    {
        out.print(separator, value);
    }
    
    PrintStream& out;
    CommaPrinter separator;
};
    
void dumpSpeculation(PrintStream& outStream, SpeculatedType value)
{
    StringPrintStream strStream;
    PrettyPrinter out(outStream);
    PrettyPrinter strOut(strStream);
    
    if (value == SpecNone) {
        out.print("None");
        return;
    }
    
    bool isTop = true;
    
    if ((value & SpecCell) == SpecCell)
        strOut.print("Cell");
    else {
        if ((value & SpecObject) == SpecObject)
            strOut.print("Object");
        else {
            if (value & SpecCellOther)
                strOut.print("OtherCell");
            else
                isTop = false;
    
            if (value & SpecObjectOther)
                strOut.print("OtherObj");
            else
                isTop = false;
    
            if (value & SpecFinalObject)
                strOut.print("Final");
            else
                isTop = false;

            if (value & SpecArray)
                strOut.print("Array");
            else
                isTop = false;
    
            if (value & SpecInt8Array)
                strOut.print("Int8Array");
            else
                isTop = false;
    
            if (value & SpecInt16Array)
                strOut.print("Int16Array");
            else
                isTop = false;
    
            if (value & SpecInt32Array)
                strOut.print("Int32Array");
            else
                isTop = false;
    
            if (value & SpecUint8Array)
                strOut.print("Uint8Array");
            else
                isTop = false;

            if (value & SpecUint8ClampedArray)
                strOut.print("Uint8ClampedArray");
            else
                isTop = false;
    
            if (value & SpecUint16Array)
                strOut.print("Uint16Array");
            else
                isTop = false;
    
            if (value & SpecUint32Array)
                strOut.print("Uint32Array");
            else
                isTop = false;
    
            if (value & SpecFloat32Array)
                strOut.print("Float32array");
            else
                isTop = false;
    
            if (value & SpecFloat64Array)
                strOut.print("Float64Array");
            else
                isTop = false;
    
            if (value & SpecFunction)
                strOut.print("Function");
            else
                isTop = false;
    
            if (value & SpecDirectArguments)
                strOut.print("DirectArguments");
            else
                isTop = false;
    
            if (value & SpecScopedArguments)
                strOut.print("ScopedArguments");
            else
                isTop = false;
    
            if (value & SpecStringObject)
                strOut.print("StringObject");
            else
                isTop = false;
    
            if (value & SpecRegExpObject)
                strOut.print("RegExpObject");
            else
                isTop = false;

            if (value & SpecMapObject)
                strOut.print("MapObject");
            else
                isTop = false;

            if (value & SpecSetObject)
                strOut.print("SetObject");
            else
                isTop = false;

            if (value & SpecWeakMapObject)
                strOut.print("WeakMapObject");
            else
                isTop = false;

            if (value & SpecWeakSetObject)
                strOut.print("WeakSetObject");
            else
                isTop = false;

            if (value & SpecProxyObject)
                strOut.print("ProxyObject");
            else
                isTop = false;

            if (value & SpecDerivedArray)
                strOut.print("DerivedArray");
            else
                isTop = false;
        }

        if ((value & SpecString) == SpecString)
            strOut.print("String");
        else {
            if (value & SpecStringIdent)
                strOut.print("StringIdent");
            else
                isTop = false;
            
            if (value & SpecStringVar)
                strOut.print("StringVar");
            else
                isTop = false;
        }

        if (value & SpecSymbol)
            strOut.print("Symbol");
        else
            isTop = false;

        if (value & SpecBigInt)
            strOut.print("BigInt");
        else
            isTop = false;
    }
    
    if (value == SpecInt32Only)
        strOut.print("Int32");
    else {
        if (value & SpecBoolInt32)
            strOut.print("BoolInt32");
        else
            isTop = false;
        
        if (value & SpecNonBoolInt32)
            strOut.print("NonBoolInt32");
        else
            isTop = false;
    }
    
    if (value & SpecInt52Only)
        strOut.print("Int52");
        
    if ((value & SpecBytecodeDouble) == SpecBytecodeDouble)
        strOut.print("BytecodeDouble");
    else {
        if (value & SpecAnyIntAsDouble)
            strOut.print("AnyIntAsDouble");
        else
            isTop = false;
        
        if (value & SpecNonIntAsDouble)
            strOut.print("NonIntAsdouble");
        else
            isTop = false;
        
        if (value & SpecDoublePureNaN)
            strOut.print("DoublePureNan");
        else
            isTop = false;
    }
    
    if (value & SpecDoubleImpureNaN)
        out.print("DoubleImpureNan");
    
    if (value & SpecBoolean)
        strOut.print("Bool");
    else
        isTop = false;
    
    if (value & SpecOther)
        strOut.print("Other");
    else
        isTop = false;
    
    if (isTop)
        out.print("Top");
    else
        out.print(strStream.toCString());
    
    if (value & SpecEmpty)
        out.print("Empty");
}

// We don't expose this because we don't want anyone relying on the fact that this method currently
// just returns string constants.
static const char* speculationToAbbreviatedString(SpeculatedType prediction)
{
    if (isFinalObjectSpeculation(prediction))
        return "<Final>";
    if (isArraySpeculation(prediction))
        return "<Array>";
    if (isStringIdentSpeculation(prediction))
        return "<StringIdent>";
    if (isStringSpeculation(prediction))
        return "<String>";
    if (isFunctionSpeculation(prediction))
        return "<Function>";
    if (isInt8ArraySpeculation(prediction))
        return "<Int8array>";
    if (isInt16ArraySpeculation(prediction))
        return "<Int16array>";
    if (isInt32ArraySpeculation(prediction))
        return "<Int32array>";
    if (isUint8ArraySpeculation(prediction))
        return "<Uint8array>";
    if (isUint16ArraySpeculation(prediction))
        return "<Uint16array>";
    if (isUint32ArraySpeculation(prediction))
        return "<Uint32array>";
    if (isFloat32ArraySpeculation(prediction))
        return "<Float32array>";
    if (isFloat64ArraySpeculation(prediction))
        return "<Float64array>";
    if (isDirectArgumentsSpeculation(prediction))
        return "<DirectArguments>";
    if (isScopedArgumentsSpeculation(prediction))
        return "<ScopedArguments>";
    if (isStringObjectSpeculation(prediction))
        return "<StringObject>";
    if (isRegExpObjectSpeculation(prediction))
        return "<RegExpObject>";
    if (isStringOrStringObjectSpeculation(prediction))
        return "<StringOrStringObject>";
    if (isObjectSpeculation(prediction))
        return "<Object>";
    if (isCellSpeculation(prediction))
        return "<Cell>";
    if (isBoolInt32Speculation(prediction))
        return "<BoolInt32>";
    if (isInt32Speculation(prediction))
        return "<Int32>";
    if (isAnyIntAsDoubleSpeculation(prediction))
        return "<AnyIntAsDouble>";
    if (isInt52Speculation(prediction))
        return "<Int52>";
    if (isAnyIntSpeculation(prediction))
        return "<AnyInt>";
    if (isDoubleSpeculation(prediction))
        return "<Double>";
    if (isFullNumberSpeculation(prediction))
        return "<Number>";
    if (isBooleanSpeculation(prediction))
        return "<Boolean>";
    if (isOtherSpeculation(prediction))
        return "<Other>";
    if (isMiscSpeculation(prediction))
        return "<Misc>";
    return "";
}

void dumpSpeculationAbbreviated(PrintStream& out, SpeculatedType value)
{
    out.print(speculationToAbbreviatedString(value));
}

SpeculatedType speculationFromTypedArrayType(TypedArrayType type)
{
    switch (type) {
    case TypeInt8:
        return SpecInt8Array;
    case TypeInt16:
        return SpecInt16Array;
    case TypeInt32:
        return SpecInt32Array;
    case TypeUint8:
        return SpecUint8Array;
    case TypeUint8Clamped:
        return SpecUint8ClampedArray;
    case TypeUint16:
        return SpecUint16Array;
    case TypeUint32:
        return SpecUint32Array;
    case TypeFloat32:
        return SpecFloat32Array;
    case TypeFloat64:
        return SpecFloat64Array;
    case NotTypedArray:
    case TypeDataView:
        break;
    }
    RELEASE_ASSERT_NOT_REACHED();
    return SpecNone;
}

SpeculatedType speculationFromClassInfo(const ClassInfo* classInfo)
{
    if (classInfo == JSString::info())
        return SpecString;

    if (classInfo == Symbol::info())
        return SpecSymbol;
    
    if (classInfo == JSBigInt::info())
        return SpecBigInt;

    if (classInfo == JSFinalObject::info())
        return SpecFinalObject;
    
    if (classInfo == JSArray::info())
        return SpecArray;
    
    if (classInfo == DirectArguments::info())
        return SpecDirectArguments;
    
    if (classInfo == ScopedArguments::info())
        return SpecScopedArguments;
    
    if (classInfo == StringObject::info())
        return SpecStringObject;

    if (classInfo == RegExpObject::info())
        return SpecRegExpObject;

    if (classInfo == JSMap::info())
        return SpecMapObject;

    if (classInfo == JSSet::info())
        return SpecSetObject;

    if (classInfo == JSWeakMap::info())
        return SpecWeakMapObject;

    if (classInfo == JSWeakSet::info())
        return SpecWeakSetObject;

    if (classInfo == ProxyObject::info())
        return SpecProxyObject;
    
    if (classInfo->isSubClassOf(JSFunction::info())) {
        if (classInfo == JSBoundFunction::info())
            return SpecFunctionWithNonDefaultHasInstance;
        return SpecFunctionWithDefaultHasInstance;
    }
    
    if (isTypedView(classInfo->typedArrayStorageType))
        return speculationFromTypedArrayType(classInfo->typedArrayStorageType);

    if (classInfo->isSubClassOf(JSArray::info()))
        return SpecDerivedArray;
    
    if (classInfo->isSubClassOf(JSObject::info()))
        return SpecObjectOther;
    
    return SpecCellOther;
}

SpeculatedType speculationFromStructure(Structure* structure)
{
    if (structure->typeInfo().type() == StringType)
        return SpecString;
    if (structure->typeInfo().type() == SymbolType)
        return SpecSymbol;
    if (structure->typeInfo().type() == BigIntType)
        return SpecBigInt;
    if (structure->typeInfo().type() == DerivedArrayType)
        return SpecDerivedArray;
    return speculationFromClassInfo(structure->classInfo());
}

SpeculatedType speculationFromCell(JSCell* cell)
{
    if (cell->isString()) {
        JSString* string = jsCast<JSString*>(cell);
        if (const StringImpl* impl = string->tryGetValueImpl()) {
            if (impl->isAtomic())
                return SpecStringIdent;
        }
        return SpecStringVar;
    }
    return speculationFromStructure(cell->structure());
}

SpeculatedType speculationFromValue(JSValue value)
{
    if (value.isEmpty())
        return SpecEmpty;
    if (value.isInt32()) {
        if (value.asInt32() & ~1)
            return SpecNonBoolInt32;
        return SpecBoolInt32;
    }
    if (value.isDouble()) {
        double number = value.asNumber();
        if (number != number)
            return SpecDoublePureNaN;
        if (value.isAnyInt())
            return SpecAnyIntAsDouble;
        return SpecNonIntAsDouble;
    }
    if (value.isCell())
        return speculationFromCell(value.asCell());
    if (value.isBoolean())
        return SpecBoolean;
    ASSERT(value.isUndefinedOrNull());
    return SpecOther;
}

TypedArrayType typedArrayTypeFromSpeculation(SpeculatedType type)
{
    if (isInt8ArraySpeculation(type))
        return TypeInt8;
        
    if (isInt16ArraySpeculation(type))
        return TypeInt16;
        
    if (isInt32ArraySpeculation(type))
        return TypeInt32;
        
    if (isUint8ArraySpeculation(type))
        return TypeUint8;
        
    if (isUint8ClampedArraySpeculation(type))
        return TypeUint8Clamped;
        
    if (isUint16ArraySpeculation(type))
        return TypeUint16;
        
    if (isUint32ArraySpeculation(type))
        return TypeUint32;
        
    if (isFloat32ArraySpeculation(type))
        return TypeFloat32;
        
    if (isFloat64ArraySpeculation(type))
        return TypeFloat64;
    
    return NotTypedArray;
}

SpeculatedType speculationFromJSType(JSType type)
{
    switch (type) {
    case StringType:
        return SpecString;
    case SymbolType:
        return SpecSymbol;
    case BigIntType:
        return SpecBigInt;
    case ArrayType:
        return SpecArray;
    case DerivedArrayType:
        return SpecDerivedArray;
    case RegExpObjectType:
        return SpecRegExpObject;
    case ProxyObjectType:
        return SpecProxyObject;
    case JSMapType:
        return SpecMapObject;
    case JSSetType:
        return SpecSetObject;
    case JSWeakMapType:
        return SpecWeakMapObject;
    case JSWeakSetType:
        return SpecWeakSetObject;
    default:
        ASSERT_NOT_REACHED();
    }
    return SpecNone;
}

SpeculatedType leastUpperBoundOfStrictlyEquivalentSpeculations(SpeculatedType type)
{
    // SpecNonIntAsDouble includes negative zero (-0.0), which can be equal to 0 and 0.0 in the context of == and ===.
    if (type & (SpecAnyInt | SpecAnyIntAsDouble | SpecNonIntAsDouble))
        type |= (SpecAnyInt | SpecAnyIntAsDouble | SpecNonIntAsDouble);

    if (type & SpecString)
        type |= SpecString;
    return type;
}

bool valuesCouldBeEqual(SpeculatedType a, SpeculatedType b)
{
    a = leastUpperBoundOfStrictlyEquivalentSpeculations(a);
    b = leastUpperBoundOfStrictlyEquivalentSpeculations(b);
    
    // Anything could be equal to a string.
    if (a & SpecString)
        return true;
    if (b & SpecString)
        return true;
    
    // If both sides are definitely only objects, then equality is fairly sane.
    if (isObjectSpeculation(a) && isObjectSpeculation(b))
        return !!(a & b);
    
    // If either side could be an object or not, then we could call toString or
    // valueOf, which could return anything.
    if (a & SpecObject)
        return true;
    if (b & SpecObject)
        return true;
    
    // Neither side is an object or string, so the world is relatively sane.
    return !!(a & b);
}

SpeculatedType typeOfDoubleSum(SpeculatedType a, SpeculatedType b)
{
    SpeculatedType result = a | b;
    // Impure NaN could become pure NaN during addition because addition may clear bits.
    if (result & SpecDoubleImpureNaN)
        result |= SpecDoublePureNaN;
    // Values could overflow, or fractions could become integers.
    if (result & SpecDoubleReal)
        result |= SpecDoubleReal;
    return result;
}

SpeculatedType typeOfDoubleDifference(SpeculatedType a, SpeculatedType b)
{
    return typeOfDoubleSum(a, b);
}

SpeculatedType typeOfDoubleProduct(SpeculatedType a, SpeculatedType b)
{
    return typeOfDoubleSum(a, b);
}

static SpeculatedType polluteDouble(SpeculatedType value)
{
    // Impure NaN could become pure NaN because the operation could clear some bits.
    if (value & SpecDoubleImpureNaN)
        value |= SpecDoubleNaN;
    // Values could overflow, fractions could become integers, or an error could produce
    // PureNaN.
    if (value & SpecDoubleReal)
        value |= SpecDoubleReal | SpecDoublePureNaN;
    return value;
}

SpeculatedType typeOfDoubleQuotient(SpeculatedType a, SpeculatedType b)
{
    return polluteDouble(a | b);
}

SpeculatedType typeOfDoubleMinMax(SpeculatedType a, SpeculatedType b)
{
    SpeculatedType result = a | b;
    // Impure NaN could become pure NaN during addition because addition may clear bits.
    if (result & SpecDoubleImpureNaN)
        result |= SpecDoublePureNaN;
    return result;
}

SpeculatedType typeOfDoubleNegation(SpeculatedType value)
{
    // Changing bits can make pure NaN impure and vice versa:
    // 0xefff000000000000 (pure) - 0xffff000000000000 (impure)
    if (value & SpecDoubleNaN)
        value |= SpecDoubleNaN;
    // We could get negative zero, which mixes SpecAnyIntAsDouble and SpecNotIntAsDouble.
    // We could also overflow a large negative int into something that is no longer
    // representable as an int.
    if (value & SpecDoubleReal)
        value |= SpecDoubleReal;
    return value;
}

SpeculatedType typeOfDoubleAbs(SpeculatedType value)
{
    return typeOfDoubleNegation(value);
}

SpeculatedType typeOfDoubleRounding(SpeculatedType value)
{
    // Double Pure NaN can becomes impure when converted back from Float.
    // and vice versa.
    if (value & SpecDoubleNaN)
        value |= SpecDoubleNaN;
    // We might lose bits, which leads to a value becoming integer-representable.
    if (value & SpecNonIntAsDouble)
        value |= SpecAnyIntAsDouble;
    return value;
}

SpeculatedType typeOfDoublePow(SpeculatedType xValue, SpeculatedType yValue)
{
    // Math.pow() always return NaN if the exponent is NaN, unlike std::pow().
    // We always set a pure NaN in that case.
    if (yValue & SpecDoubleNaN)
        xValue |= SpecDoublePureNaN;
    return polluteDouble(xValue);
}

SpeculatedType typeOfDoubleBinaryOp(SpeculatedType a, SpeculatedType b)
{
    return polluteDouble(a | b);
}

SpeculatedType typeOfDoubleUnaryOp(SpeculatedType value)
{
    return polluteDouble(value);
}

SpeculatedType speculationFromString(const char* speculation)
{
    if (!strncmp(speculation, "SpecNone", strlen("SpecNone")))
        return SpecNone;
    if (!strncmp(speculation, "SpecFinalObject", strlen("SpecFinalObject")))
        return SpecFinalObject;
    if (!strncmp(speculation, "SpecArray", strlen("SpecArray")))
        return SpecArray;
    if (!strncmp(speculation, "SpecFunction", strlen("SpecFunction")))
        return SpecFunction;
    if (!strncmp(speculation, "SpecInt8Array", strlen("SpecInt8Array")))
        return SpecInt8Array;
    if (!strncmp(speculation, "SpecInt16Array", strlen("SpecInt16Array")))
        return SpecInt16Array;
    if (!strncmp(speculation, "SpecInt32Array", strlen("SpecInt32Array")))
        return SpecInt32Array;
    if (!strncmp(speculation, "SpecUint8Array", strlen("SpecUint8Array")))
        return SpecUint8Array;
    if (!strncmp(speculation, "SpecUint8ClampedArray", strlen("SpecUint8ClampedArray")))
        return SpecUint8ClampedArray;
    if (!strncmp(speculation, "SpecUint16Array", strlen("SpecUint16Array")))
        return SpecUint16Array;
    if (!strncmp(speculation, "SpecUint32Array", strlen("SpecUint32Array")))
        return SpecUint32Array;
    if (!strncmp(speculation, "SpecFloat32Array", strlen("SpecFloat32Array")))
        return SpecFloat32Array;
    if (!strncmp(speculation, "SpecFloat64Array", strlen("SpecFloat64Array")))
        return SpecFloat64Array;
    if (!strncmp(speculation, "SpecTypedArrayView", strlen("SpecTypedArrayView")))
        return SpecTypedArrayView;
    if (!strncmp(speculation, "SpecDirectArguments", strlen("SpecDirectArguments")))
        return SpecDirectArguments;
    if (!strncmp(speculation, "SpecScopedArguments", strlen("SpecScopedArguments")))
        return SpecScopedArguments;
    if (!strncmp(speculation, "SpecStringObject", strlen("SpecStringObject")))
        return SpecStringObject;
    if (!strncmp(speculation, "SpecRegExpObject", strlen("SpecRegExpObject")))
        return SpecRegExpObject;
    if (!strncmp(speculation, "SpecMapObject", strlen("SpecMapObject")))
        return SpecMapObject;
    if (!strncmp(speculation, "SpecSetObject", strlen("SpecSetObject")))
        return SpecSetObject;
    if (!strncmp(speculation, "SpecWeakMapObject", strlen("SpecWeakMapObject")))
        return SpecWeakMapObject;
    if (!strncmp(speculation, "SpecWeakSetObject", strlen("SpecWeakSetObject")))
        return SpecWeakSetObject;
    if (!strncmp(speculation, "SpecProxyObject", strlen("SpecProxyObject")))
        return SpecProxyObject;
    if (!strncmp(speculation, "SpecDerivedArray", strlen("SpecDerivedArray")))
        return SpecDerivedArray;
    if (!strncmp(speculation, "SpecObjectOther", strlen("SpecObjectOther")))
        return SpecObjectOther;
    if (!strncmp(speculation, "SpecObject", strlen("SpecObject")))
        return SpecObject;
    if (!strncmp(speculation, "SpecStringIdent", strlen("SpecStringIdent")))
        return SpecStringIdent;
    if (!strncmp(speculation, "SpecStringVar", strlen("SpecStringVar")))
        return SpecStringVar;
    if (!strncmp(speculation, "SpecString", strlen("SpecString")))
        return SpecString;
    if (!strncmp(speculation, "SpecSymbol", strlen("SpecSymbol")))
        return SpecSymbol;
    if (!strncmp(speculation, "SpecBigInt", strlen("SpecBigInt")))
        return SpecBigInt;
    if (!strncmp(speculation, "SpecCellOther", strlen("SpecCellOther")))
        return SpecCellOther;
    if (!strncmp(speculation, "SpecCell", strlen("SpecCell")))
        return SpecCell;
    if (!strncmp(speculation, "SpecBoolInt32", strlen("SpecBoolInt32")))
        return SpecBoolInt32;
    if (!strncmp(speculation, "SpecNonBoolInt32", strlen("SpecNonBoolInt32")))
        return SpecNonBoolInt32;
    if (!strncmp(speculation, "SpecInt32Only", strlen("SpecInt32Only")))
        return SpecInt32Only;
    if (!strncmp(speculation, "SpecInt52Only", strlen("SpecInt52Only")))
        return SpecInt52Only;
    if (!strncmp(speculation, "SpecAnyInt", strlen("SpecAnyInt")))
        return SpecAnyInt;
    if (!strncmp(speculation, "SpecAnyIntAsDouble", strlen("SpecAnyIntAsDouble")))
        return SpecAnyIntAsDouble;
    if (!strncmp(speculation, "SpecNonIntAsDouble", strlen("SpecNonIntAsDouble")))
        return SpecNonIntAsDouble;
    if (!strncmp(speculation, "SpecDoubleReal", strlen("SpecDoubleReal")))
        return SpecDoubleReal;
    if (!strncmp(speculation, "SpecDoublePureNaN", strlen("SpecDoublePureNaN")))
        return SpecDoublePureNaN;
    if (!strncmp(speculation, "SpecDoubleImpureNaN", strlen("SpecDoubleImpureNaN")))
        return SpecDoubleImpureNaN;
    if (!strncmp(speculation, "SpecDoubleNaN", strlen("SpecDoubleNaN")))
        return SpecDoubleNaN;
    if (!strncmp(speculation, "SpecBytecodeDouble", strlen("SpecBytecodeDouble")))
        return SpecBytecodeDouble;
    if (!strncmp(speculation, "SpecFullDouble", strlen("SpecFullDouble")))
        return SpecFullDouble;
    if (!strncmp(speculation, "SpecBytecodeRealNumber", strlen("SpecBytecodeRealNumber")))
        return SpecBytecodeRealNumber;
    if (!strncmp(speculation, "SpecFullRealNumber", strlen("SpecFullRealNumber")))
        return SpecFullRealNumber;
    if (!strncmp(speculation, "SpecBytecodeNumber", strlen("SpecBytecodeNumber")))
        return SpecBytecodeNumber;
    if (!strncmp(speculation, "SpecFullNumber", strlen("SpecFullNumber")))
        return SpecFullNumber;
    if (!strncmp(speculation, "SpecBoolean", strlen("SpecBoolean")))
        return SpecBoolean;
    if (!strncmp(speculation, "SpecOther", strlen("SpecOther")))
        return SpecOther;
    if (!strncmp(speculation, "SpecMisc", strlen("SpecMisc")))
        return SpecMisc;
    if (!strncmp(speculation, "SpecHeapTop", strlen("SpecHeapTop")))
        return SpecHeapTop;
    if (!strncmp(speculation, "SpecPrimitive", strlen("SpecPrimitive")))
        return SpecPrimitive;
    if (!strncmp(speculation, "SpecEmpty", strlen("SpecEmpty")))
        return SpecEmpty;
    if (!strncmp(speculation, "SpecBytecodeTop", strlen("SpecBytecodeTop")))
        return SpecBytecodeTop;
    if (!strncmp(speculation, "SpecFullTop", strlen("SpecFullTop")))
        return SpecFullTop;
    if (!strncmp(speculation, "SpecCellCheck", strlen("SpecCellCheck")))
        return SpecCellCheck;
    RELEASE_ASSERT_NOT_REACHED();
}

} // namespace JSC