DFG should inline InstanceOf ICs
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGNode.h
index 8f61021..6236309 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-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
@@ -30,7 +30,6 @@
 #include "B3SparseCollection.h"
 #include "BasicBlockLocation.h"
 #include "CodeBlock.h"
-#include "DFGAbstractValue.h"
 #include "DFGAdjacencyList.h"
 #include "DFGArithMode.h"
 #include "DFGArrayMode.h"
@@ -53,7 +52,6 @@
 #include "Operands.h"
 #include "PutByIdVariant.h"
 #include "SpeculatedType.h"
-#include "StructureSet.h"
 #include "TypeLocation.h"
 #include "ValueProfile.h"
 #include <type_traits>
@@ -64,8 +62,7 @@ namespace JSC {
 
 namespace DOMJIT {
 class GetterSetter;
-class Patchpoint;
-class CallDOMGetterPatchpoint;
+class CallDOMGetterSnippet;
 class Signature;
 }
 
@@ -73,6 +70,8 @@ namespace Profiler {
 class ExecutionCounter;
 }
 
+class Snippet;
+
 namespace DFG {
 
 class Graph;
@@ -97,11 +96,26 @@ struct MultiPutByOffsetData {
     bool reallocatesStorage() const;
 };
 
+struct MatchStructureVariant {
+    RegisteredStructure structure;
+    bool result;
+};
+
+struct MatchStructureData {
+    Vector<MatchStructureVariant, 2> variants;
+};
+
 struct NewArrayBufferData {
-    unsigned startConstant;
-    unsigned numConstants;
-    IndexingType indexingType;
+    union {
+        struct {
+            unsigned vectorLengthHint;
+            unsigned indexingType;
+        };
+        uint64_t asQuadWord;
+    };
 };
+static_assert(sizeof(IndexingType) <= sizeof(unsigned), "");
+static_assert(sizeof(NewArrayBufferData) == sizeof(uint64_t), "");
 
 struct BranchTarget {
     BranchTarget()
@@ -200,10 +214,14 @@ struct SwitchData {
     Vector<SwitchCase> cases;
     BranchTarget fallThrough;
     SwitchKind kind;
-    unsigned switchTableIndex;
+    size_t switchTableIndex;
     bool didUseJumpTable;
 };
 
+struct EntrySwitchData {
+    Vector<BasicBlock*> cases;
+};
+
 struct CallVarargsData {
     int firstVarArgOffset;
 };
@@ -238,11 +256,17 @@ struct StackAccessData {
 };
 
 struct CallDOMGetterData {
-    DOMJIT::GetterSetter* domJIT { nullptr };
-    DOMJIT::CallDOMGetterPatchpoint* patchpoint { nullptr };
+    FunctionPtr<OperationPtrTag> customAccessorGetter;
+    const DOMJIT::GetterSetter* domJIT { nullptr };
+    DOMJIT::CallDOMGetterSnippet* snippet { nullptr };
     unsigned identifierNumber { 0 };
 };
 
+enum class BucketOwnerType : uint32_t {
+    Map,
+    Set
+};
+
 // === Node ===
 //
 // Node represents a single operation in the data flow graph.
@@ -415,7 +439,8 @@ public:
         m_flags = defaultFlags(op);
     }
 
-    void remove();
+    void remove(Graph&);
+    void removeWithoutChecks();
 
     void convertToCheckStructure(RegisteredStructureSet* set)
     {
@@ -423,18 +448,21 @@ public:
         m_opInfo = set;
     }
 
+    void convertCheckStructureOrEmptyToCheckStructure()
+    {
+        ASSERT(op() == CheckStructureOrEmpty);
+        setOpAndDefaultFlags(CheckStructure);
+    }
+
     void convertToCheckStructureImmediate(Node* structure)
     {
-        ASSERT(op() == CheckStructure);
+        ASSERT(op() == CheckStructure || op() == CheckStructureOrEmpty);
         m_op = CheckStructureImmediate;
         children.setChild1(Edge(structure, CellUse));
     }
     
-    void replaceWith(Node* other)
-    {
-        remove();
-        setReplacement(other);
-    }
+    void replaceWith(Graph&, Node* other);
+    void replaceWithWithoutChecks(Node* other);
 
     void convertToIdentity();
     void convertToIdentityOn(Node*);
@@ -497,7 +525,7 @@ public:
             m_op = Int52Constant;
         else
             m_op = JSConstant;
-        m_flags &= ~NodeMustGenerate;
+        m_flags &= ~(NodeMustGenerate | NodeHasVarArgs);
         m_opInfo = value;
         children.reset();
     }
@@ -512,15 +540,6 @@ public:
         children.reset();
     }
     
-    void convertToGetLocalUnlinked(VirtualRegister local)
-    {
-        m_op = GetLocalUnlinked;
-        m_flags &= ~NodeMustGenerate;
-        m_opInfo = local.offset();
-        m_opInfo2 = VirtualRegister().offset();
-        children.reset();
-    }
-    
     void convertToPutStack(StackAccessData* data)
     {
         m_op = PutStack;
@@ -540,7 +559,7 @@ public:
     
     void convertToGetByOffset(StorageAccessData& data, Edge storage, Edge base)
     {
-        ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
+        ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == GetByIdDirect || m_op == GetByIdDirectFlush || m_op == MultiGetByOffset);
         m_opInfo = &data;
         children.setChild1(storage);
         children.setChild2(base);
@@ -550,11 +569,11 @@ public:
     
     void convertToMultiGetByOffset(MultiGetByOffsetData* data)
     {
-        ASSERT(m_op == GetById || m_op == GetByIdFlush);
+        RELEASE_ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == GetByIdDirect || m_op == GetByIdDirectFlush);
         m_opInfo = data;
         child1().setUseKind(CellUse);
         m_op = MultiGetByOffset;
-        ASSERT(m_flags & NodeMustGenerate);
+        RELEASE_ASSERT(m_flags & NodeMustGenerate);
     }
     
     void convertToPutByOffset(StorageAccessData& data, Edge storage, Edge base)
@@ -574,12 +593,6 @@ public:
         m_op = MultiPutByOffset;
     }
     
-    void convertToPutHint(const PromotedLocationDescriptor&, Node* base, Node* value);
-    
-    void convertToPutByOffsetHint();
-    void convertToPutStructureHint(Node* structure);
-    void convertToPutClosureVarHint();
-    
     void convertToPhantomNewObject()
     {
         ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
@@ -593,7 +606,7 @@ public:
 
     void convertToPhantomNewFunction()
     {
-        ASSERT(m_op == NewFunction || m_op == NewGeneratorFunction || m_op == NewAsyncFunction);
+        ASSERT(m_op == NewFunction || m_op == NewGeneratorFunction || m_op == NewAsyncFunction || m_op == NewAsyncGeneratorFunction);
         m_op = PhantomNewFunction;
         m_flags |= NodeMustGenerate;
         m_opInfo = OpInfoWrapper();
@@ -621,6 +634,16 @@ public:
         children = AdjacencyList();
     }
 
+    void convertToPhantomNewAsyncGeneratorFunction()
+    {
+        ASSERT(m_op == NewAsyncGeneratorFunction);
+        m_op = PhantomNewAsyncGeneratorFunction;
+        m_flags |= NodeMustGenerate;
+        m_opInfo = OpInfoWrapper();
+        m_opInfo2 = OpInfoWrapper();
+        children = AdjacencyList();
+    }
+    
     void convertToPhantomCreateActivation()
     {
         ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
@@ -632,6 +655,15 @@ public:
         children = AdjacencyList();
     }
 
+    void convertToPhantomNewRegexp()
+    {
+        ASSERT(m_op == NewRegexp);
+        setOpAndDefaultFlags(PhantomNewRegexp);
+        m_opInfo = OpInfoWrapper();
+        m_opInfo2 = OpInfoWrapper();
+        children = AdjacencyList();
+    }
+
     void convertPhantomToPhantomLocal()
     {
         ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
@@ -647,15 +679,6 @@ public:
         children = AdjacencyList();
     }
     
-    void convertToGetLocal(VariableAccessData* variable, Node* phi)
-    {
-        ASSERT(m_op == GetLocalUnlinked);
-        m_op = GetLocal;
-        m_opInfo = variable;
-        m_opInfo2 = OpInfoWrapper();
-        children.setChild1(Edge(phi));
-    }
-    
     void convertToToString()
     {
         ASSERT(m_op == ToPrimitive);
@@ -667,10 +690,77 @@ public:
         ASSERT(m_op == ArithAbs && child1().useKind() == Int32Use);
         m_op = ArithNegate;
     }
+
+    void convertToCompareEqPtr(FrozenValue* cell, Edge node)
+    {
+        ASSERT(m_op == CompareStrictEq);
+        setOpAndDefaultFlags(CompareEqPtr);
+        children.setChild1(node);
+        children.setChild2(Edge());
+        m_opInfo = cell;
+    }
+
+    void convertToNumberToStringWithValidRadixConstant(int32_t radix)
+    {
+        ASSERT(m_op == NumberToStringWithRadix);
+        ASSERT(2 <= radix && radix <= 36);
+        setOpAndDefaultFlags(NumberToStringWithValidRadixConstant);
+        children.setChild2(Edge());
+        m_opInfo = radix;
+    }
+
+    void convertToGetGlobalThis()
+    {
+        ASSERT(m_op == ToThis);
+        setOpAndDefaultFlags(GetGlobalThis);
+        children.setChild1(Edge());
+    }
+
+    void convertToCallObjectConstructor(FrozenValue* globalObject)
+    {
+        ASSERT(m_op == ToObject);
+        setOpAndDefaultFlags(CallObjectConstructor);
+        m_opInfo = globalObject;
+    }
+
+    void convertToNewStringObject(RegisteredStructure structure)
+    {
+        ASSERT(m_op == CallObjectConstructor || m_op == ToObject);
+        setOpAndDefaultFlags(NewStringObject);
+        m_opInfo = structure;
+        m_opInfo2 = OpInfoWrapper();
+    }
+
+    void convertToNewObject(RegisteredStructure structure)
+    {
+        ASSERT(m_op == CallObjectConstructor || m_op == CreateThis);
+        setOpAndDefaultFlags(NewObject);
+        children.reset();
+        m_opInfo = structure;
+        m_opInfo2 = OpInfoWrapper();
+    }
     
     void convertToDirectCall(FrozenValue*);
 
     void convertToCallDOM(Graph&);
+
+    void convertToRegExpExecNonGlobalOrSticky(FrozenValue* regExp);
+    void convertToRegExpMatchFastGlobal(FrozenValue* regExp);
+
+    void convertToSetRegExpObjectLastIndex()
+    {
+        setOp(SetRegExpObjectLastIndex);
+        m_opInfo = false;
+    }
+
+    void convertToInById(unsigned identifierNumber)
+    {
+        ASSERT(m_op == InByVal);
+        setOpAndDefaultFlags(InById);
+        children.setChild2(Edge());
+        m_opInfo = identifierNumber;
+        m_opInfo2 = OpInfoWrapper();
+    }
     
     JSValue asJSValue()
     {
@@ -866,7 +956,6 @@ public:
     bool hasUnlinkedLocal()
     {
         switch (op()) {
-        case GetLocalUnlinked:
         case ExtractOSREntryLocal:
         case MovHint:
         case ZombieHint:
@@ -883,23 +972,6 @@ public:
         return VirtualRegister(m_opInfo.as<int32_t>());
     }
     
-    bool hasUnlinkedMachineLocal()
-    {
-        return op() == GetLocalUnlinked;
-    }
-    
-    void setUnlinkedMachineLocal(VirtualRegister reg)
-    {
-        ASSERT(hasUnlinkedMachineLocal());
-        m_opInfo2 = reg.offset();
-    }
-    
-    VirtualRegister unlinkedMachineLocal()
-    {
-        ASSERT(hasUnlinkedMachineLocal());
-        return VirtualRegister(m_opInfo2.as<int32_t>());
-    }
-    
     bool hasStackAccessData()
     {
         switch (op()) {
@@ -916,6 +988,12 @@ public:
         ASSERT(hasStackAccessData());
         return m_opInfo.as<StackAccessData*>();
     }
+
+    unsigned argumentCountIncludingThis()
+    {
+        ASSERT(op() == SetArgumentCountIncludingThis);
+        return m_opInfo.as<unsigned>();
+    }
     
     bool hasPhi()
     {
@@ -940,6 +1018,8 @@ public:
         case GetById:
         case GetByIdFlush:
         case GetByIdWithThis:
+        case GetByIdDirect:
+        case GetByIdDirectFlush:
         case PutById:
         case PutByIdFlush:
         case PutByIdDirect:
@@ -948,10 +1028,12 @@ public:
         case PutSetterById:
         case PutGetterSetterById:
         case DeleteById:
+        case InById:
         case GetDynamicVar:
         case PutDynamicVar:
         case ResolveScopeForHoistingFuncDeclInEval:
         case ResolveScope:
+        case ToObject:
             return true;
         default:
             return false;
@@ -978,7 +1060,7 @@ public:
     unsigned getPutInfo()
     {
         ASSERT(hasGetPutInfo());
-        return m_opInfo2.as<unsigned>();
+        return static_cast<unsigned>(m_opInfo.as<uint64_t>() >> 32);
     }
 
     bool hasAccessorAttributes()
@@ -1045,25 +1127,35 @@ public:
         return m_flags & NodeMayHaveNonNumberResult;
     }
 
-    bool hasConstantBuffer()
+    bool hasNewArrayBufferData()
     {
-        return op() == NewArrayBuffer;
+        return op() == NewArrayBuffer || op() == PhantomNewArrayBuffer;
     }
     
-    NewArrayBufferData* newArrayBufferData()
+    NewArrayBufferData newArrayBufferData()
     {
-        ASSERT(hasConstantBuffer());
-        return m_opInfo.as<NewArrayBufferData*>();
+        ASSERT(hasNewArrayBufferData());
+        return m_opInfo2.asNewArrayBufferData();
     }
-    
-    unsigned startConstant()
+
+    unsigned hasVectorLengthHint()
     {
-        return newArrayBufferData()->startConstant;
+        switch (op()) {
+        case NewArray:
+        case NewArrayBuffer:
+        case PhantomNewArrayBuffer:
+            return true;
+        default:
+            return false;
+        }
     }
     
-    unsigned numConstants()
+    unsigned vectorLengthHint()
     {
-        return newArrayBufferData()->numConstants;
+        ASSERT(hasVectorLengthHint());
+        if (op() == NewArray)
+            return m_opInfo2.as<unsigned>();
+        return newArrayBufferData().vectorLengthHint;
     }
     
     bool hasIndexingType()
@@ -1072,6 +1164,7 @@ public:
         case NewArray:
         case NewArrayWithSize:
         case NewArrayBuffer:
+        case PhantomNewArrayBuffer:
             return true;
         default:
             return false;
@@ -1095,8 +1188,8 @@ public:
     IndexingType indexingType()
     {
         ASSERT(hasIndexingType());
-        if (op() == NewArrayBuffer)
-            return newArrayBufferData()->indexingType;
+        if (op() == NewArrayBuffer || op() == PhantomNewArrayBuffer)
+            return static_cast<IndexingType>(newArrayBufferData().indexingType);
         return static_cast<IndexingType>(m_opInfo.as<uint32_t>());
     }
     
@@ -1201,6 +1294,12 @@ public:
         return m_opInfo.as<LoadVarargsData*>();
     }
 
+    InlineCallFrame* argumentsInlineCallFrame()
+    {
+        ASSERT(op() == GetArgumentCountIncludingThis);
+        return m_opInfo.as<InlineCallFrame*>();
+    }
+
     bool hasQueriedType()
     {
         return op() == IsCellWithType;
@@ -1277,23 +1376,31 @@ public:
         return op() == Branch;
     }
     
-    bool isSwitch()
+    bool isSwitch() const
     {
         return op() == Switch;
     }
 
+    bool isEntrySwitch() const
+    {
+        return op() == EntrySwitch;
+    }
+
     bool isTerminal()
     {
         switch (op()) {
         case Jump:
         case Branch:
         case Switch:
+        case EntrySwitch:
         case Return:
         case TailCall:
         case DirectTailCall:
         case TailCallVarargs:
         case TailCallForwardVarargs:
         case Unreachable:
+        case Throw:
+        case ThrowStaticError:
             return true;
         default:
             return false;
@@ -1308,6 +1415,22 @@ public:
         return false;
     }
 
+    // As is described in DFGNodeType.h's ForceOSRExit, this is a pseudo-terminal.
+    // It means that execution should fall out of DFG at this point, but execution
+    // does continue in the basic block - just in a different compiler.
+    // FIXME: This is used for lightweight reachability decision. But this should
+    // be replaced with AI-based reachability ideally.
+    bool isPseudoTerminal()
+    {
+        switch (op()) {
+        case ForceOSRExit:
+        case CheckBadCell:
+            return true;
+        default:
+            return false;
+        }
+    }
+
     unsigned targetBytecodeOffsetDuringParsing()
     {
         ASSERT(isJump());
@@ -1331,6 +1454,18 @@ public:
         ASSERT(isSwitch());
         return m_opInfo.as<SwitchData*>();
     }
+
+    EntrySwitchData* entrySwitchData()
+    {
+        ASSERT(isEntrySwitch());
+        return m_opInfo.as<EntrySwitchData*>();
+    }
+
+    Intrinsic intrinsic()
+    {
+        RELEASE_ASSERT(op() == CPUIntrinsic);
+        return m_opInfo.as<Intrinsic>();
+    }
     
     unsigned numSuccessors()
     {
@@ -1341,6 +1476,8 @@ public:
             return 2;
         case Switch:
             return switchData()->cases.size() + 1;
+        case EntrySwitch:
+            return entrySwitchData()->cases.size();
         default:
             return 0;
         }
@@ -1353,7 +1490,9 @@ public:
                 return switchData()->cases[index].target.block;
             RELEASE_ASSERT(index == switchData()->cases.size());
             return switchData()->fallThrough.block;
-        }
+        } else if (isEntrySwitch())
+            return entrySwitchData()->cases[index];
+
         switch (index) {
         case 0:
             if (isJump())
@@ -1458,6 +1597,9 @@ public:
         case GetById:
         case GetByIdFlush:
         case GetByIdWithThis:
+        case GetByIdDirect:
+        case GetByIdDirectFlush:
+        case GetPrototypeOf:
         case TryGetById:
         case GetByVal:
         case GetByValWithThis:
@@ -1481,13 +1623,19 @@ public:
         case ArrayPop:
         case ArrayPush:
         case RegExpExec:
+        case RegExpExecNonGlobalOrSticky:
         case RegExpTest:
+        case RegExpMatchFast:
+        case RegExpMatchFastGlobal:
         case GetGlobalVar:
         case GetGlobalLexicalVariable:
         case StringReplace:
         case StringReplaceRegExp:
         case ToNumber:
-        case LoadFromJSMapBucket:
+        case ToObject:
+        case CallObjectConstructor:
+        case LoadKeyFromMapBucket:
+        case LoadValueFromMapBucket:
         case CallDOMGetter:
         case CallDOM:
         case ParseInt:
@@ -1500,6 +1648,9 @@ public:
         case AtomicsStore:
         case AtomicsSub:
         case AtomicsXor:
+        case GetDynamicVar:
+        case ExtractValueFromWeakMapGet:
+        case ToThis:
             return true;
         default:
             return false;
@@ -1517,6 +1668,24 @@ public:
         ASSERT(hasHeapPrediction());
         m_opInfo2 = prediction;
     }
+
+    SpeculatedType getForcedPrediction()
+    {
+        ASSERT(op() == IdentityWithProfile);
+        return m_opInfo.as<SpeculatedType>();
+    }
+
+    uint32_t catchOSREntryIndex() const
+    {
+        ASSERT(op() == ExtractCatchLocal);
+        return m_opInfo.as<uint32_t>();
+    }
+
+    SpeculatedType catchLocalPrediction()
+    {
+        ASSERT(op() == ExtractCatchLocal);
+        return m_opInfo2.as<SpeculatedType>();
+    }
     
     bool hasCellOperand()
     {
@@ -1526,14 +1695,20 @@ public:
         case NewFunction:
         case NewGeneratorFunction:
         case NewAsyncFunction:
+        case NewAsyncGeneratorFunction:
         case CreateActivation:
         case MaterializeCreateActivation:
         case NewRegexp:
+        case NewArrayBuffer:
+        case PhantomNewArrayBuffer:
         case CompareEqPtr:
+        case CallObjectConstructor:
         case DirectCall:
         case DirectTailCall:
         case DirectConstruct:
         case DirectTailCallInlinedCaller:
+        case RegExpExecNonGlobalOrSticky:
+        case RegExpMatchFastGlobal:
             return true;
         default:
             return false;
@@ -1624,6 +1799,7 @@ public:
     {
         switch (op()) {
         case CheckStructure:
+        case CheckStructureOrEmpty:
         case CheckStructureImmediate:
         case MaterializeNewObject:
             return true;
@@ -1696,6 +1872,17 @@ public:
         return *m_opInfo.as<MultiPutByOffsetData*>();
     }
     
+    bool hasMatchStructureData()
+    {
+        return op() == MatchStructure;
+    }
+    
+    MatchStructureData& matchStructureData()
+    {
+        ASSERT(hasMatchStructureData());
+        return *m_opInfo.as<MatchStructureData*>();
+    }
+    
     bool hasObjectMaterializationData()
     {
         switch (op()) {
@@ -1761,6 +1948,7 @@ public:
         switch (op()) {
         case NewFunction:
         case NewGeneratorFunction:
+        case NewAsyncGeneratorFunction:
         case NewAsyncFunction:
             return true;
         default:
@@ -1774,6 +1962,7 @@ public:
         case PhantomNewFunction:
         case PhantomNewGeneratorFunction:
         case PhantomNewAsyncFunction:
+        case PhantomNewAsyncGeneratorFunction:
             return true;
         default:
             return false;
@@ -1788,11 +1977,14 @@ public:
         case PhantomCreateRest:
         case PhantomSpread:
         case PhantomNewArrayWithSpread:
+        case PhantomNewArrayBuffer:
         case PhantomClonedArguments:
         case PhantomNewFunction:
         case PhantomNewGeneratorFunction:
         case PhantomNewAsyncFunction:
+        case PhantomNewAsyncGeneratorFunction:
         case PhantomCreateActivation:
+        case PhantomNewRegexp:
             return true;
         default:
             return false;
@@ -1804,7 +1996,8 @@ public:
         switch (op()) {
         case GetIndexedPropertyStorage:
         case GetArrayLength:
-        case In:
+        case GetVectorLength:
+        case InByVal:
         case PutByValDirect:
         case PutByVal:
         case PutByValAlias:
@@ -1816,6 +2009,7 @@ public:
         case ArrayifyToStructure:
         case ArrayPush:
         case ArrayPop:
+        case ArrayIndexOf:
         case HasIndexedProperty:
         case AtomicsAdd:
         case AtomicsAnd:
@@ -1910,7 +2104,7 @@ public:
     {
         return m_virtualRegister.isValid();
     }
-    
+
     VirtualRegister virtualRegister()
     {
         ASSERT(hasResult());
@@ -1935,6 +2129,12 @@ public:
         return m_opInfo.as<Profiler::ExecutionCounter*>();
     }
 
+    unsigned entrypointIndex()
+    {
+        ASSERT(op() == InitializeEntrypointArguments);
+        return m_opInfo.as<unsigned>();
+    }
+
     bool shouldGenerate()
     {
         return m_refCount;
@@ -2172,6 +2372,11 @@ public:
         return isSymbolSpeculation(prediction());
     }
     
+    bool shouldSpeculateBigInt()
+    {
+        return isBigIntSpeculation(prediction());
+    }
+    
     bool shouldSpeculateFinalObject()
     {
         return isFinalObjectSpeculation(prediction());
@@ -2187,6 +2392,11 @@ public:
         return isArraySpeculation(prediction());
     }
 
+    bool shouldSpeculateFunction()
+    {
+        return isFunctionSpeculation(prediction());
+    }
+
     bool shouldSpeculateProxyObject()
     {
         return isProxyObjectSpeculation(prediction());
@@ -2357,6 +2567,11 @@ public:
         return op1->shouldSpeculateSymbol() && op2->shouldSpeculateSymbol();
     }
     
+    static bool shouldSpeculateBigInt(Node* op1, Node* op2)
+    {
+        return op1->shouldSpeculateBigInt() && op2->shouldSpeculateBigInt();
+    }
+    
     static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
     {
         return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
@@ -2485,10 +2700,15 @@ public:
     {
         m_misc.epoch = epoch.toUnsigned();
     }
+    
+    bool hasNumberOfArgumentsToSkip()
+    {
+        return op() == CreateRest || op() == PhantomCreateRest || op() == GetRestLength || op() == GetMyArgumentByVal || op() == GetMyArgumentByValOutOfBounds;
+    }
 
     unsigned numberOfArgumentsToSkip()
     {
-        ASSERT(op() == CreateRest || op() == PhantomCreateRest || op() == GetRestLength || op() == GetMyArgumentByVal || op() == GetMyArgumentByValOutOfBounds);
+        ASSERT(hasNumberOfArgumentsToSkip());
         return m_opInfo.as<unsigned>();
     }
 
@@ -2503,6 +2723,45 @@ public:
         return m_opInfo.as<unsigned>();
     }
 
+    bool hasBucketOwnerType()
+    {
+        return op() == GetMapBucketNext || op() == LoadKeyFromMapBucket || op() == LoadValueFromMapBucket;
+    }
+
+    BucketOwnerType bucketOwnerType()
+    {
+        ASSERT(hasBucketOwnerType());
+        return m_opInfo.as<BucketOwnerType>();
+    }
+
+    bool hasValidRadixConstant()
+    {
+        return op() == NumberToStringWithValidRadixConstant;
+    }
+
+    int32_t validRadixConstant()
+    {
+        ASSERT(hasValidRadixConstant());
+        return m_opInfo.as<int32_t>();
+    }
+
+    bool hasIgnoreLastIndexIsWritable()
+    {
+        return op() == SetRegExpObjectLastIndex;
+    }
+
+    bool ignoreLastIndexIsWritable()
+    {
+        ASSERT(hasIgnoreLastIndexIsWritable());
+        return m_opInfo.as<uint32_t>();
+    }
+
+    uint32_t errorType()
+    {
+        ASSERT(op() == ThrowStaticError);
+        return m_opInfo.as<uint32_t>();
+    }
+
     void dumpChildren(PrintStream& out)
     {
         if (!child1())
@@ -2600,6 +2859,11 @@ private:
             u.pointer = bitwise_cast<void*>(structure);
             return *this;
         }
+        OpInfoWrapper& operator=(NewArrayBufferData newArrayBufferData)
+        {
+            u.int64 = bitwise_cast<uint64_t>(newArrayBufferData);
+            return *this;
+        }
         template <typename T>
         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_pointer<T>::value && !std::is_const<typename std::remove_pointer<T>::type>::value, T>::type
         {
@@ -2611,19 +2875,23 @@ private:
             return static_cast<T>(u.constPointer);
         }
         template <typename T>
-        ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 4, T>::type
+        ALWAYS_INLINE auto as() const -> typename std::enable_if<(std::is_integral<T>::value || std::is_enum<T>::value) && sizeof(T) == 4, T>::type
         {
-            return u.int32;
+            return static_cast<T>(u.int32);
         }
         template <typename T>
-        ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 8, T>::type
+        ALWAYS_INLINE auto as() const -> typename std::enable_if<(std::is_integral<T>::value || std::is_enum<T>::value) && sizeof(T) == 8, T>::type
         {
-            return u.int64;
+            return static_cast<T>(u.int64);
         }
         ALWAYS_INLINE RegisteredStructure asRegisteredStructure() const
         {
             return bitwise_cast<RegisteredStructure>(u.pointer);
         }
+        ALWAYS_INLINE NewArrayBufferData asNewArrayBufferData() const
+        {
+            return bitwise_cast<NewArrayBufferData>(u.int64);
+        }
 
         union {
             uint32_t int32;