Unreviewed, rolling out r215476.
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGNode.h
index 0007115..0d98caf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
+ * 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
@@ -23,8 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-#ifndef DFGNode_h
-#define DFGNode_h
+#pragma once
 
 #if ENABLE(DFG_JIT)
 
@@ -43,6 +42,8 @@
 #include "DFGNodeType.h"
 #include "DFGObjectMaterializationData.h"
 #include "DFGOpInfo.h"
+#include "DFGRegisteredStructure.h"
+#include "DFGRegisteredStructureSet.h"
 #include "DFGTransition.h"
 #include "DFGUseKind.h"
 #include "DFGVariableAccessData.h"
 #include "StructureSet.h"
 #include "TypeLocation.h"
 #include "ValueProfile.h"
+#include <type_traits>
 #include <wtf/ListDump.h>
+#include <wtf/LoggingHashSet.h>
 
 namespace JSC {
 
+namespace DOMJIT {
+class GetterSetter;
+class Patchpoint;
+class CallDOMGetterPatchpoint;
+class Signature;
+}
+
 namespace Profiler {
 class ExecutionCounter;
 }
@@ -226,11 +236,19 @@ struct StackAccessData {
     FlushedAt flushedAt() { return FlushedAt(format, machineLocal); }
 };
 
+struct CallDOMGetterData {
+    DOMJIT::GetterSetter* domJIT { nullptr };
+    DOMJIT::CallDOMGetterPatchpoint* patchpoint { nullptr };
+    unsigned identifierNumber { 0 };
+};
+
 // === Node ===
 //
 // Node represents a single operation in the data flow graph.
 struct Node {
 public:
+    static const char HashSetTemplateInstantiationString[];
+    
     enum VarArgTag { VarArg };
     
     Node() { }
@@ -254,8 +272,6 @@ public:
         , m_virtualRegister(VirtualRegister())
         , m_refCount(1)
         , m_prediction(SpecNone)
-        , m_opInfo(0)
-        , m_opInfo2(0)
         , owner(nullptr)
     {
         m_misc.replacement = nullptr;
@@ -270,8 +286,6 @@ public:
         , m_virtualRegister(VirtualRegister())
         , m_refCount(1)
         , m_prediction(SpecNone)
-        , m_opInfo(0)
-        , m_opInfo2(0)
         , owner(nullptr)
     {
         m_misc.replacement = nullptr;
@@ -288,7 +302,6 @@ public:
         , m_refCount(1)
         , m_prediction(SpecNone)
         , m_opInfo(imm.m_value)
-        , m_opInfo2(0)
         , owner(nullptr)
     {
         m_misc.replacement = nullptr;
@@ -304,7 +317,6 @@ public:
         , m_refCount(1)
         , m_prediction(SpecNone)
         , m_opInfo(imm.m_value)
-        , m_opInfo2(0)
         , owner(nullptr)
     {
         m_misc.replacement = nullptr;
@@ -403,10 +415,10 @@ public:
 
     void remove();
 
-    void convertToCheckStructure(StructureSet* set)
+    void convertToCheckStructure(RegisteredStructureSet* set)
     {
         setOpAndDefaultFlags(CheckStructure);
-        m_opInfo = bitwise_cast<uintptr_t>(set); 
+        m_opInfo = set;
     }
 
     void convertToCheckStructureImmediate(Node* structure)
@@ -471,7 +483,7 @@ public:
             return FrozenValue::emptySingleton();
         }
         
-        return bitwise_cast<FrozenValue*>(m_opInfo);
+        return m_opInfo.as<FrozenValue*>();
     }
     
     // Don't call this directly - use Graph::convertToConstant() instead!
@@ -484,7 +496,7 @@ public:
         else
             m_op = JSConstant;
         m_flags &= ~NodeMustGenerate;
-        m_opInfo = bitwise_cast<uintptr_t>(value);
+        m_opInfo = value;
         children.reset();
     }
 
@@ -494,7 +506,7 @@ public:
     {
         ASSERT(op() == GetIndexedPropertyStorage);
         m_op = ConstantStoragePointer;
-        m_opInfo = bitwise_cast<uintptr_t>(pointer);
+        m_opInfo = pointer;
         children.reset();
     }
     
@@ -511,23 +523,23 @@ public:
     {
         m_op = PutStack;
         m_flags |= NodeMustGenerate;
-        m_opInfo = bitwise_cast<uintptr_t>(data);
-        m_opInfo2 = 0;
+        m_opInfo = data;
+        m_opInfo2 = OpInfoWrapper();
     }
     
     void convertToGetStack(StackAccessData* data)
     {
         m_op = GetStack;
         m_flags &= ~NodeMustGenerate;
-        m_opInfo = bitwise_cast<uintptr_t>(data);
-        m_opInfo2 = 0;
+        m_opInfo = data;
+        m_opInfo2 = OpInfoWrapper();
         children.reset();
     }
     
     void convertToGetByOffset(StorageAccessData& data, Edge storage, Edge base)
     {
         ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
-        m_opInfo = bitwise_cast<uintptr_t>(&data);
+        m_opInfo = &data;
         children.setChild1(storage);
         children.setChild2(base);
         m_op = GetByOffset;
@@ -537,7 +549,7 @@ public:
     void convertToMultiGetByOffset(MultiGetByOffsetData* data)
     {
         ASSERT(m_op == GetById || m_op == GetByIdFlush);
-        m_opInfo = bitwise_cast<intptr_t>(data);
+        m_opInfo = data;
         child1().setUseKind(CellUse);
         m_op = MultiGetByOffset;
         ASSERT(m_flags & NodeMustGenerate);
@@ -546,7 +558,7 @@ public:
     void convertToPutByOffset(StorageAccessData& data, Edge storage, Edge base)
     {
         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset);
-        m_opInfo = bitwise_cast<uintptr_t>(&data);
+        m_opInfo = &data;
         children.setChild3(children.child2());
         children.setChild2(base);
         children.setChild1(storage);
@@ -556,7 +568,7 @@ public:
     void convertToMultiPutByOffset(MultiPutByOffsetData* data)
     {
         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
-        m_opInfo = bitwise_cast<intptr_t>(data);
+        m_opInfo = data;
         m_op = MultiPutByOffset;
     }
     
@@ -572,18 +584,18 @@ public:
         m_op = PhantomNewObject;
         m_flags &= ~NodeHasVarArgs;
         m_flags |= NodeMustGenerate;
-        m_opInfo = 0;
-        m_opInfo2 = 0;
+        m_opInfo = OpInfoWrapper();
+        m_opInfo2 = OpInfoWrapper();
         children = AdjacencyList();
     }
 
     void convertToPhantomNewFunction()
     {
-        ASSERT(m_op == NewFunction || m_op == NewGeneratorFunction);
+        ASSERT(m_op == NewFunction || m_op == NewGeneratorFunction || m_op == NewAsyncFunction);
         m_op = PhantomNewFunction;
         m_flags |= NodeMustGenerate;
-        m_opInfo = 0;
-        m_opInfo2 = 0;
+        m_opInfo = OpInfoWrapper();
+        m_opInfo2 = OpInfoWrapper();
         children = AdjacencyList();
     }
 
@@ -592,8 +604,18 @@ public:
         ASSERT(m_op == NewGeneratorFunction);
         m_op = PhantomNewGeneratorFunction;
         m_flags |= NodeMustGenerate;
-        m_opInfo = 0;
-        m_opInfo2 = 0;
+        m_opInfo = OpInfoWrapper();
+        m_opInfo2 = OpInfoWrapper();
+        children = AdjacencyList();
+    }
+
+    void convertToPhantomNewAsyncFunction()
+    {
+        ASSERT(m_op == NewAsyncFunction);
+        m_op = PhantomNewAsyncFunction;
+        m_flags |= NodeMustGenerate;
+        m_opInfo = OpInfoWrapper();
+        m_opInfo2 = OpInfoWrapper();
         children = AdjacencyList();
     }
 
@@ -603,8 +625,8 @@ public:
         m_op = PhantomCreateActivation;
         m_flags &= ~NodeHasVarArgs;
         m_flags |= NodeMustGenerate;
-        m_opInfo = 0;
-        m_opInfo2 = 0;
+        m_opInfo = OpInfoWrapper();
+        m_opInfo2 = OpInfoWrapper();
         children = AdjacencyList();
     }
 
@@ -627,8 +649,8 @@ public:
     {
         ASSERT(m_op == GetLocalUnlinked);
         m_op = GetLocal;
-        m_opInfo = bitwise_cast<uintptr_t>(variable);
-        m_opInfo2 = 0;
+        m_opInfo = variable;
+        m_opInfo2 = OpInfoWrapper();
         children.setChild1(Edge(phi));
     }
     
@@ -644,6 +666,10 @@ public:
         m_op = ArithNegate;
     }
     
+    void convertToDirectCall(FrozenValue*);
+
+    void convertToCallDOM(Graph&);
+    
     JSValue asJSValue()
     {
         return constant()->value();
@@ -715,17 +741,17 @@ public:
     }
      
     template<typename T>
-    T dynamicCastConstant()
+    T dynamicCastConstant(VM& vm)
     {
         if (!isCellConstant())
             return nullptr;
-        return jsDynamicCast<T>(asCell());
+        return jsDynamicCast<T>(vm, asCell());
     }
     
     template<typename T>
-    T castConstant()
+    T castConstant(VM& vm)
     {
-        T result = dynamicCastConstant<T>();
+        T result = dynamicCastConstant<T>(vm);
         RELEASE_ASSERT(result);
         return result;
     }
@@ -738,7 +764,7 @@ public:
     LazyJSValue lazyJSValue()
     {
         ASSERT(hasLazyJSValue());
-        return *bitwise_cast<LazyJSValue*>(m_opInfo);
+        return *m_opInfo.as<LazyJSValue*>();
     }
 
     String tryGetString(Graph&);
@@ -746,7 +772,7 @@ public:
     JSValue initializationValueForActivation() const
     {
         ASSERT(op() == CreateActivation);
-        return bitwise_cast<FrozenValue*>(m_opInfo2)->value();
+        return m_opInfo2.as<FrozenValue*>()->value();
     }
 
     bool hasArgumentsChild()
@@ -814,7 +840,7 @@ public:
     // access data doesn't have one because it hasn't been initialized yet.
     VariableAccessData* tryGetVariableAccessData()
     {
-        VariableAccessData* result = reinterpret_cast<VariableAccessData*>(m_opInfo);
+        VariableAccessData* result = m_opInfo.as<VariableAccessData*>();
         if (!result)
             return 0;
         return result->find();
@@ -822,7 +848,7 @@ public:
     
     VariableAccessData* variableAccessData()
     {
-        return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
+        return m_opInfo.as<VariableAccessData*>()->find();
     }
     
     VirtualRegister local()
@@ -852,7 +878,7 @@ public:
     VirtualRegister unlinkedLocal()
     {
         ASSERT(hasUnlinkedLocal());
-        return static_cast<VirtualRegister>(m_opInfo);
+        return VirtualRegister(m_opInfo.as<int32_t>());
     }
     
     bool hasUnlinkedMachineLocal()
@@ -869,7 +895,7 @@ public:
     VirtualRegister unlinkedMachineLocal()
     {
         ASSERT(hasUnlinkedMachineLocal());
-        return VirtualRegister(m_opInfo2);
+        return VirtualRegister(m_opInfo2.as<int32_t>());
     }
     
     bool hasStackAccessData()
@@ -886,7 +912,7 @@ public:
     StackAccessData* stackAccessData()
     {
         ASSERT(hasStackAccessData());
-        return bitwise_cast<StackAccessData*>(m_opInfo);
+        return m_opInfo.as<StackAccessData*>();
     }
     
     bool hasPhi()
@@ -897,12 +923,12 @@ public:
     Node* phi()
     {
         ASSERT(hasPhi());
-        return bitwise_cast<Node*>(m_opInfo);
+        return m_opInfo.as<Node*>();
     }
 
     bool isStoreBarrier()
     {
-        return op() == StoreBarrier;
+        return op() == StoreBarrier || op() == FencedStoreBarrier;
     }
 
     bool hasIdentifier()
@@ -932,7 +958,7 @@ public:
     unsigned identifierNumber()
     {
         ASSERT(hasIdentifier());
-        return m_opInfo;
+        return m_opInfo.as<unsigned>();
     }
 
     bool hasGetPutInfo()
@@ -949,7 +975,7 @@ public:
     unsigned getPutInfo()
     {
         ASSERT(hasGetPutInfo());
-        return m_opInfo2;
+        return m_opInfo2.as<unsigned>();
     }
 
     bool hasAccessorAttributes()
@@ -973,10 +999,10 @@ public:
         case PutGetterById:
         case PutSetterById:
         case PutGetterSetterById:
-            return m_opInfo2;
+            return m_opInfo2.as<int32_t>();
         case PutGetterByVal:
         case PutSetterByVal:
-            return m_opInfo;
+            return m_opInfo.as<int32_t>();
         default:
             RELEASE_ASSERT_NOT_REACHED();
             return 0;
@@ -1024,7 +1050,7 @@ public:
     NewArrayBufferData* newArrayBufferData()
     {
         ASSERT(hasConstantBuffer());
-        return reinterpret_cast<NewArrayBufferData*>(m_opInfo);
+        return m_opInfo.as<NewArrayBufferData*>();
     }
     
     unsigned startConstant()
@@ -1049,6 +1075,12 @@ public:
         }
     }
 
+    BitVector* bitVector()
+    {
+        ASSERT(op() == NewArrayWithSpread || op() == PhantomNewArrayWithSpread);
+        return m_opInfo.as<BitVector*>();
+    }
+
     // Return the indexing type that an array allocation *wants* to use. It may end up using a different
     // type if we're having a bad time. You can determine the actual indexing type by asking the global
     // object:
@@ -1062,7 +1094,7 @@ public:
         ASSERT(hasIndexingType());
         if (op() == NewArrayBuffer)
             return newArrayBufferData()->indexingType;
-        return m_opInfo;
+        return static_cast<IndexingType>(m_opInfo.as<uint32_t>());
     }
     
     bool hasTypedArrayType()
@@ -1078,7 +1110,7 @@ public:
     TypedArrayType typedArrayType()
     {
         ASSERT(hasTypedArrayType());
-        TypedArrayType result = static_cast<TypedArrayType>(m_opInfo);
+        TypedArrayType result = static_cast<TypedArrayType>(m_opInfo.as<uint32_t>());
         ASSERT(isTypedView(result));
         return result;
     }
@@ -1091,7 +1123,7 @@ public:
     unsigned inlineCapacity()
     {
         ASSERT(hasInlineCapacity());
-        return m_opInfo;
+        return m_opInfo.as<unsigned>();
     }
 
     void setIndexingType(IndexingType indexingType)
@@ -1100,20 +1132,6 @@ public:
         m_opInfo = indexingType;
     }
     
-    // FIXME: We really should be able to inline code that uses NewRegexp. That means
-    // using something other than the index into the CodeBlock here.
-    // https://bugs.webkit.org/show_bug.cgi?id=154808
-    bool hasRegexpIndex()
-    {
-        return op() == NewRegexp;
-    }
-    
-    unsigned regexpIndex()
-    {
-        ASSERT(hasRegexpIndex());
-        return m_opInfo;
-    }
-    
     bool hasScopeOffset()
     {
         return op() == GetClosureVar || op() == PutClosureVar;
@@ -1122,7 +1140,7 @@ public:
     ScopeOffset scopeOffset()
     {
         ASSERT(hasScopeOffset());
-        return ScopeOffset(m_opInfo);
+        return ScopeOffset(m_opInfo.as<uint32_t>());
     }
     
     bool hasDirectArgumentsOffset()
@@ -1133,7 +1151,7 @@ public:
     DirectArgumentsOffset capturedArgumentsOffset()
     {
         ASSERT(hasDirectArgumentsOffset());
-        return DirectArgumentsOffset(m_opInfo);
+        return DirectArgumentsOffset(m_opInfo.as<uint32_t>());
     }
     
     bool hasRegisterPointer()
@@ -1143,7 +1161,7 @@ public:
     
     WriteBarrier<Unknown>* variablePointer()
     {
-        return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo);
+        return m_opInfo.as<WriteBarrier<Unknown>*>();
     }
     
     bool hasCallVarargsData()
@@ -1166,7 +1184,7 @@ public:
     CallVarargsData* callVarargsData()
     {
         ASSERT(hasCallVarargsData());
-        return bitwise_cast<CallVarargsData*>(m_opInfo);
+        return m_opInfo.as<CallVarargsData*>();
     }
     
     bool hasLoadVarargsData()
@@ -1177,17 +1195,33 @@ public:
     LoadVarargsData* loadVarargsData()
     {
         ASSERT(hasLoadVarargsData());
-        return bitwise_cast<LoadVarargsData*>(m_opInfo);
+        return m_opInfo.as<LoadVarargsData*>();
     }
-    
-    bool hasResult()
+
+    bool hasQueriedType()
     {
-        return !!result();
+        return op() == IsCellWithType;
+    }
+
+    JSType queriedType()
+    {
+        static_assert(std::is_same<uint8_t, std::underlying_type<JSType>::type>::value, "Ensure that uint8_t is the underlying type for JSType.");
+        return static_cast<JSType>(m_opInfo.as<uint32_t>());
     }
 
-    bool hasInt32Result()
+    bool hasSpeculatedTypeForQuery()
     {
-        return result() == NodeResultInt32;
+        return op() == IsCellWithType;
+    }
+
+    SpeculatedType speculatedTypeForQuery()
+    {
+        return speculationFromJSType(queriedType());
+    }
+    
+    bool hasResult()
+    {
+        return !!result();
     }
     
     bool hasInt52Result()
@@ -1253,6 +1287,7 @@ public:
         case Switch:
         case Return:
         case TailCall:
+        case DirectTailCall:
         case TailCallVarargs:
         case TailCallForwardVarargs:
         case Unreachable:
@@ -1273,25 +1308,25 @@ public:
     unsigned targetBytecodeOffsetDuringParsing()
     {
         ASSERT(isJump());
-        return m_opInfo;
+        return m_opInfo.as<unsigned>();
     }
 
     BasicBlock*& targetBlock()
     {
         ASSERT(isJump());
-        return *bitwise_cast<BasicBlock**>(&m_opInfo);
+        return *bitwise_cast<BasicBlock**>(&m_opInfo.u.pointer);
     }
     
     BranchData* branchData()
     {
         ASSERT(isBranch());
-        return bitwise_cast<BranchData*>(m_opInfo);
+        return m_opInfo.as<BranchData*>();
     }
     
     SwitchData* switchData()
     {
         ASSERT(isSwitch());
-        return bitwise_cast<SwitchData*>(m_opInfo);
+        return m_opInfo.as<SwitchData*>();
     }
     
     unsigned numSuccessors()
@@ -1411,6 +1446,7 @@ public:
     bool hasHeapPrediction()
     {
         switch (op()) {
+        case ArithAbs:
         case ArithRound:
         case ArithFloor:
         case ArithCeil:
@@ -1418,10 +1454,16 @@ public:
         case GetDirectPname:
         case GetById:
         case GetByIdFlush:
+        case GetByIdWithThis:
+        case TryGetById:
         case GetByVal:
+        case GetByValWithThis:
         case Call:
+        case DirectCall:
         case TailCallInlinedCaller:
+        case DirectTailCallInlinedCaller:
         case Construct:
+        case DirectConstruct:
         case CallVarargs:
         case CallEval:
         case TailCallVarargsInlinedCaller:
@@ -1432,6 +1474,7 @@ public:
         case MultiGetByOffset:
         case GetClosureVar:
         case GetFromArguments:
+        case GetArgument:
         case ArrayPop:
         case ArrayPush:
         case RegExpExec:
@@ -1441,6 +1484,19 @@ public:
         case StringReplace:
         case StringReplaceRegExp:
         case ToNumber:
+        case LoadFromJSMapBucket:
+        case CallDOMGetter:
+        case CallDOM:
+        case ParseInt:
+        case AtomicsAdd:
+        case AtomicsAnd:
+        case AtomicsCompareExchange:
+        case AtomicsExchange:
+        case AtomicsLoad:
+        case AtomicsOr:
+        case AtomicsStore:
+        case AtomicsSub:
+        case AtomicsXor:
             return true;
         default:
             return false;
@@ -1450,7 +1506,7 @@ public:
     SpeculatedType getHeapPrediction()
     {
         ASSERT(hasHeapPrediction());
-        return static_cast<SpeculatedType>(m_opInfo2);
+        return m_opInfo2.as<SpeculatedType>();
     }
 
     void setHeapPrediction(SpeculatedType prediction)
@@ -1466,9 +1522,15 @@ public:
         case OverridesHasInstance:
         case NewFunction:
         case NewGeneratorFunction:
+        case NewAsyncFunction:
         case CreateActivation:
         case MaterializeCreateActivation:
+        case NewRegexp:
         case CompareEqPtr:
+        case DirectCall:
+        case DirectTailCall:
+        case DirectConstruct:
+        case DirectTailCallInlinedCaller:
             return true;
         default:
             return false;
@@ -1478,7 +1540,7 @@ public:
     FrozenValue* cellOperand()
     {
         ASSERT(hasCellOperand());
-        return reinterpret_cast<FrozenValue*>(m_opInfo);
+        return m_opInfo.as<FrozenValue*>();
     }
     
     template<typename T>
@@ -1490,7 +1552,7 @@ public:
     void setCellOperand(FrozenValue* value)
     {
         ASSERT(hasCellOperand());
-        m_opInfo = bitwise_cast<uintptr_t>(value);
+        m_opInfo = value;
     }
     
     bool hasWatchpointSet()
@@ -1501,7 +1563,7 @@ public:
     WatchpointSet* watchpointSet()
     {
         ASSERT(hasWatchpointSet());
-        return reinterpret_cast<WatchpointSet*>(m_opInfo);
+        return m_opInfo.as<WatchpointSet*>();
     }
     
     bool hasStoragePointer()
@@ -1512,7 +1574,7 @@ public:
     void* storagePointer()
     {
         ASSERT(hasStoragePointer());
-        return reinterpret_cast<void*>(m_opInfo);
+        return m_opInfo.as<void*>();
     }
 
     bool hasUidOperand()
@@ -1523,7 +1585,7 @@ public:
     UniquedStringImpl* uidOperand()
     {
         ASSERT(hasUidOperand());
-        return reinterpret_cast<UniquedStringImpl*>(m_opInfo);
+        return m_opInfo.as<UniquedStringImpl*>();
     }
 
     bool hasTypeInfoOperand()
@@ -1533,8 +1595,8 @@ public:
 
     unsigned typeInfoOperand()
     {
-        ASSERT(hasTypeInfoOperand() && m_opInfo <= UCHAR_MAX);
-        return static_cast<unsigned>(m_opInfo);
+        ASSERT(hasTypeInfoOperand() && m_opInfo.as<uint32_t>() <= static_cast<uint32_t>(UCHAR_MAX));
+        return m_opInfo.as<uint32_t>();
     }
 
     bool hasTransition()
@@ -1552,7 +1614,7 @@ public:
     Transition* transition()
     {
         ASSERT(hasTransition());
-        return reinterpret_cast<Transition*>(m_opInfo);
+        return m_opInfo.as<Transition*>();
     }
     
     bool hasStructureSet()
@@ -1567,10 +1629,10 @@ public:
         }
     }
     
-    StructureSet& structureSet()
+    const RegisteredStructureSet& structureSet()
     {
         ASSERT(hasStructureSet());
-        return *reinterpret_cast<StructureSet*>(m_opInfo);
+        return *m_opInfo.as<RegisteredStructureSet*>();
     }
     
     bool hasStructure()
@@ -1585,10 +1647,10 @@ public:
         }
     }
     
-    Structure* structure()
+    RegisteredStructure structure()
     {
         ASSERT(hasStructure());
-        return reinterpret_cast<Structure*>(m_opInfo);
+        return m_opInfo.asRegisteredStructure();
     }
     
     bool hasStorageAccessData()
@@ -1606,7 +1668,7 @@ public:
     StorageAccessData& storageAccessData()
     {
         ASSERT(hasStorageAccessData());
-        return *bitwise_cast<StorageAccessData*>(m_opInfo);
+        return *m_opInfo.as<StorageAccessData*>();
     }
     
     bool hasMultiGetByOffsetData()
@@ -1617,7 +1679,7 @@ public:
     MultiGetByOffsetData& multiGetByOffsetData()
     {
         ASSERT(hasMultiGetByOffsetData());
-        return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo);
+        return *m_opInfo.as<MultiGetByOffsetData*>();
     }
     
     bool hasMultiPutByOffsetData()
@@ -1628,7 +1690,7 @@ public:
     MultiPutByOffsetData& multiPutByOffsetData()
     {
         ASSERT(hasMultiPutByOffsetData());
-        return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
+        return *m_opInfo.as<MultiPutByOffsetData*>();
     }
     
     bool hasObjectMaterializationData()
@@ -1646,7 +1708,7 @@ public:
     ObjectMaterializationData& objectMaterializationData()
     {
         ASSERT(hasObjectMaterializationData());
-        return *reinterpret_cast<ObjectMaterializationData*>(m_opInfo2);
+        return *m_opInfo2.as<ObjectMaterializationData*>();
     }
 
     bool isObjectAllocation()
@@ -1696,6 +1758,7 @@ public:
         switch (op()) {
         case NewFunction:
         case NewGeneratorFunction:
+        case NewAsyncFunction:
             return true;
         default:
             return false;
@@ -1707,6 +1770,7 @@ public:
         switch (op()) {
         case PhantomNewFunction:
         case PhantomNewGeneratorFunction:
+        case PhantomNewAsyncFunction:
             return true;
         default:
             return false;
@@ -1718,9 +1782,13 @@ public:
         switch (op()) {
         case PhantomNewObject:
         case PhantomDirectArguments:
+        case PhantomCreateRest:
+        case PhantomSpread:
+        case PhantomNewArrayWithSpread:
         case PhantomClonedArguments:
         case PhantomNewFunction:
         case PhantomNewGeneratorFunction:
+        case PhantomNewAsyncFunction:
         case PhantomCreateActivation:
             return true;
         default:
@@ -1733,6 +1801,7 @@ public:
         switch (op()) {
         case GetIndexedPropertyStorage:
         case GetArrayLength:
+        case In:
         case PutByValDirect:
         case PutByVal:
         case PutByValAlias:
@@ -1745,6 +1814,15 @@ public:
         case ArrayPush:
         case ArrayPop:
         case HasIndexedProperty:
+        case AtomicsAdd:
+        case AtomicsAnd:
+        case AtomicsCompareExchange:
+        case AtomicsExchange:
+        case AtomicsLoad:
+        case AtomicsOr:
+        case AtomicsStore:
+        case AtomicsSub:
+        case AtomicsXor:
             return true;
         default:
             return false;
@@ -1755,8 +1833,8 @@ public:
     {
         ASSERT(hasArrayMode());
         if (op() == ArrayifyToStructure)
-            return ArrayMode::fromWord(m_opInfo2);
-        return ArrayMode::fromWord(m_opInfo);
+            return ArrayMode::fromWord(m_opInfo2.as<uint32_t>());
+        return ArrayMode::fromWord(m_opInfo.as<uint32_t>());
     }
     
     bool setArrayMode(ArrayMode arrayMode)
@@ -1789,7 +1867,7 @@ public:
     Arith::Mode arithMode()
     {
         ASSERT(hasArithMode());
-        return static_cast<Arith::Mode>(m_opInfo);
+        return static_cast<Arith::Mode>(m_opInfo.as<uint32_t>());
     }
     
     void setArithMode(Arith::Mode mode)
@@ -1805,13 +1883,13 @@ public:
     Arith::RoundingMode arithRoundingMode()
     {
         ASSERT(hasArithRoundingMode());
-        return static_cast<Arith::RoundingMode>(m_opInfo);
+        return static_cast<Arith::RoundingMode>(m_opInfo.as<uint32_t>());
     }
 
     void setArithRoundingMode(Arith::RoundingMode mode)
     {
         ASSERT(hasArithRoundingMode());
-        m_opInfo = static_cast<uintptr_t>(mode);
+        m_opInfo = static_cast<uint32_t>(mode);
     }
     
     bool hasVirtualRegister()
@@ -1840,7 +1918,7 @@ public:
     
     Profiler::ExecutionCounter* executionCounter()
     {
-        return bitwise_cast<Profiler::ExecutionCounter*>(m_opInfo);
+        return m_opInfo.as<Profiler::ExecutionCounter*>();
     }
 
     bool shouldGenerate()
@@ -1848,9 +1926,11 @@ public:
         return m_refCount;
     }
     
+    // Return true if the execution of this Node does not affect our ability to OSR to the FTL.
+    // FIXME: Isn't this just like checking if the node has effects?
     bool isSemanticallySkippable()
     {
-        return op() == CountExecution;
+        return op() == CountExecution || op() == InvalidationPoint;
     }
 
     unsigned refCount()
@@ -1952,6 +2032,11 @@ public:
     {
         return isInt32Speculation(prediction());
     }
+
+    bool shouldSpeculateNotInt32()
+    {
+        return isNotInt32Speculation(prediction());
+    }
     
     bool sawBooleans()
     {
@@ -2012,6 +2097,11 @@ public:
     {
         return isBooleanSpeculation(prediction());
     }
+
+    bool shouldSpeculateNotBoolean()
+    {
+        return isNotBooleanSpeculation(prediction());
+    }
     
     bool shouldSpeculateOther()
     {
@@ -2037,6 +2127,11 @@ public:
     {
         return isStringSpeculation(prediction());
     }
+
+    bool shouldSpeculateNotString()
+    {
+        return isNotStringSpeculation(prediction());
+    }
  
     bool shouldSpeculateStringOrOther()
     {
@@ -2077,6 +2172,16 @@ public:
     {
         return isArraySpeculation(prediction());
     }
+
+    bool shouldSpeculateProxyObject()
+    {
+        return isProxyObjectSpeculation(prediction());
+    }
+
+    bool shouldSpeculateDerivedArray()
+    {
+        return isDerivedArraySpeculation(prediction());
+    }
     
     bool shouldSpeculateDirectArguments()
     {
@@ -2283,7 +2388,7 @@ public:
     TypeLocation* typeLocation()
     {
         ASSERT(hasTypeLocation());
-        return reinterpret_cast<TypeLocation*>(m_opInfo);
+        return m_opInfo.as<TypeLocation*>();
     }
 
     bool hasBasicBlockLocation()
@@ -2294,9 +2399,70 @@ public:
     BasicBlockLocation* basicBlockLocation()
     {
         ASSERT(hasBasicBlockLocation());
-        return reinterpret_cast<BasicBlockLocation*>(m_opInfo);
+        return m_opInfo.as<BasicBlockLocation*>();
     }
-    
+
+    bool hasCheckDOMPatchpoint() const
+    {
+        return op() == CheckDOM;
+    }
+
+    DOMJIT::Patchpoint* checkDOMPatchpoint()
+    {
+        ASSERT(hasCheckDOMPatchpoint());
+        return m_opInfo.as<DOMJIT::Patchpoint*>();
+    }
+
+    bool hasCallDOMGetterData() const
+    {
+        return op() == CallDOMGetter;
+    }
+
+    CallDOMGetterData* callDOMGetterData()
+    {
+        ASSERT(hasCallDOMGetterData());
+        return m_opInfo.as<CallDOMGetterData*>();
+    }
+
+    bool hasClassInfo() const
+    {
+        return op() == CheckDOM;
+    }
+
+    const ClassInfo* classInfo()
+    {
+        return m_opInfo2.as<const ClassInfo*>();
+    }
+
+    bool hasSignature() const
+    {
+        // Note that this does not include TailCall node types intentionally.
+        // CallDOM node types are always converted from Call.
+        return op() == Call || op() == CallDOM;
+    }
+
+    const DOMJIT::Signature* signature()
+    {
+        return m_opInfo.as<const DOMJIT::Signature*>();
+    }
+
+    bool hasInternalMethodType() const
+    {
+        return op() == HasIndexedProperty;
+    }
+
+    PropertySlot::InternalMethodType internalMethodType() const
+    {
+        ASSERT(hasInternalMethodType());
+        return static_cast<PropertySlot::InternalMethodType>(m_opInfo2.as<uint32_t>());
+    }
+
+    void setInternalMethodType(PropertySlot::InternalMethodType type)
+    {
+        ASSERT(hasInternalMethodType());
+        m_opInfo2 = static_cast<uint32_t>(type);
+    }
+
     Node* replacement() const
     {
         return m_misc.replacement;
@@ -2319,8 +2485,19 @@ public:
 
     unsigned numberOfArgumentsToSkip()
     {
-        ASSERT(op() == CreateRest || op() == GetRestLength);
-        return static_cast<unsigned>(m_opInfo);
+        ASSERT(op() == CreateRest || op() == PhantomCreateRest || op() == GetRestLength || op() == GetMyArgumentByVal || op() == GetMyArgumentByValOutOfBounds);
+        return m_opInfo.as<unsigned>();
+    }
+
+    bool hasArgumentIndex()
+    {
+        return op() == GetArgument;
+    }
+
+    unsigned argumentIndex()
+    {
+        ASSERT(hasArgumentIndex());
+        return m_opInfo.as<unsigned>();
     }
 
     void dumpChildren(PrintStream& out)
@@ -2355,10 +2532,105 @@ private:
     unsigned m_refCount;
     // The prediction ascribed to this node after propagation.
     SpeculatedType m_prediction { SpecNone };
-    // Immediate values, accesses type-checked via accessors above. The first one is
-    // big enough to store a pointer.
-    uintptr_t m_opInfo;
-    uintptr_t m_opInfo2;
+    // Immediate values, accesses type-checked via accessors above.
+    struct OpInfoWrapper {
+        OpInfoWrapper()
+        {
+            u.int64 = 0;
+        }
+        OpInfoWrapper(uint32_t intValue)
+        {
+            u.int64 = 0;
+            u.int32 = intValue;
+        }
+        OpInfoWrapper(uint64_t intValue)
+        {
+            u.int64 = intValue;
+        }
+        OpInfoWrapper(void* pointer)
+        {
+            u.int64 = 0;
+            u.pointer = pointer;
+        }
+        OpInfoWrapper(const void* constPointer)
+        {
+            u.int64 = 0;
+            u.constPointer = constPointer;
+        }
+        OpInfoWrapper(RegisteredStructure structure)
+        {
+            u.int64 = 0;
+            u.pointer = bitwise_cast<void*>(structure);
+        }
+        OpInfoWrapper& operator=(uint32_t int32)
+        {
+            u.int64 = 0;
+            u.int32 = int32;
+            return *this;
+        }
+        OpInfoWrapper& operator=(int32_t int32)
+        {
+            u.int64 = 0;
+            u.int32 = int32;
+            return *this;
+        }
+        OpInfoWrapper& operator=(uint64_t int64)
+        {
+            u.int64 = int64;
+            return *this;
+        }
+        OpInfoWrapper& operator=(void* pointer)
+        {
+            u.int64 = 0;
+            u.pointer = pointer;
+            return *this;
+        }
+        OpInfoWrapper& operator=(const void* constPointer)
+        {
+            u.int64 = 0;
+            u.constPointer = constPointer;
+            return *this;
+        }
+        OpInfoWrapper& operator=(RegisteredStructure structure)
+        {
+            u.int64 = 0;
+            u.pointer = bitwise_cast<void*>(structure);
+            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
+        {
+            return static_cast<T>(u.pointer);
+        }
+        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
+        {
+            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
+        {
+            return u.int32;
+        }
+        template <typename T>
+        ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 8, T>::type
+        {
+            return u.int64;
+        }
+        ALWAYS_INLINE RegisteredStructure asRegisteredStructure() const
+        {
+            return bitwise_cast<RegisteredStructure>(u.pointer);
+        }
+
+        union {
+            uint32_t int32;
+            uint64_t int64;
+            void* pointer;
+            const void* constPointer;
+        } u;
+    };
+    OpInfoWrapper m_opInfo;
+    OpInfoWrapper m_opInfo2;
 
     // Miscellaneous data that is usually meaningless, but can hold some analysis results
     // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
@@ -2379,15 +2651,22 @@ public:
     BasicBlock* owner;
 };
 
-inline bool nodeComparator(Node* a, Node* b)
-{
-    return a->index() < b->index();
-}
+// Uncomment this to log NodeSet operations.
+// typedef LoggingHashSet<Node::HashSetTemplateInstantiationString, Node*> NodeSet;
+typedef HashSet<Node*> NodeSet;
+
+struct NodeComparator {
+    template<typename NodePtrType>
+    bool operator()(NodePtrType a, NodePtrType b) const
+    {
+        return a->index() < b->index();
+    }
+};
 
 template<typename T>
 CString nodeListDump(const T& nodeList)
 {
-    return sortedListDump(nodeList, nodeComparator);
+    return sortedListDump(nodeList, NodeComparator());
 }
 
 template<typename T>
@@ -2398,7 +2677,7 @@ CString nodeMapDump(const T& nodeMap, DumpContext* context = 0)
         typename T::const_iterator iter = nodeMap.begin();
         iter != nodeMap.end(); ++iter)
         keys.append(iter->key);
-    std::sort(keys.begin(), keys.end(), nodeComparator);
+    std::sort(keys.begin(), keys.end(), NodeComparator());
     StringPrintStream out;
     CommaPrinter comma;
     for(unsigned i = 0; i < keys.size(); ++i)
@@ -2412,7 +2691,7 @@ CString nodeValuePairListDump(const T& nodeValuePairList, DumpContext* context =
     using V = typename T::ValueType;
     T sortedList = nodeValuePairList;
     std::sort(sortedList.begin(), sortedList.end(), [](const V& a, const V& b) {
-        return nodeComparator(a.node, b.node);
+        return NodeComparator()(a.node, b.node);
     });
 
     StringPrintStream out;
@@ -2431,9 +2710,16 @@ void printInternal(PrintStream&, JSC::DFG::Node*);
 
 inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
 
+template<>
+struct LoggingHashKeyTraits<JSC::DFG::Node*> {
+    static void print(PrintStream& out, JSC::DFG::Node* key)
+    {
+        out.print("bitwise_cast<::JSC::DFG::Node*>(", RawPointer(key), "lu)");
+    }
+};
+
 } // namespace WTF
 
 using WTF::inContext;
 
 #endif
-#endif