Add a slice intrinsic to the DFG/FTL
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGNode.h
1 /*
2  * Copyright (C) 2011-2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #pragma once
27
28 #if ENABLE(DFG_JIT)
29
30 #include "BasicBlockLocation.h"
31 #include "CodeBlock.h"
32 #include "DFGAbstractValue.h"
33 #include "DFGAdjacencyList.h"
34 #include "DFGArithMode.h"
35 #include "DFGArrayMode.h"
36 #include "DFGCommon.h"
37 #include "DFGEpoch.h"
38 #include "DFGLazyJSValue.h"
39 #include "DFGMultiGetByOffsetData.h"
40 #include "DFGNodeFlags.h"
41 #include "DFGNodeOrigin.h"
42 #include "DFGNodeType.h"
43 #include "DFGObjectMaterializationData.h"
44 #include "DFGOpInfo.h"
45 #include "DFGTransition.h"
46 #include "DFGUseKind.h"
47 #include "DFGVariableAccessData.h"
48 #include "GetByIdVariant.h"
49 #include "JSCJSValue.h"
50 #include "Operands.h"
51 #include "PutByIdVariant.h"
52 #include "SpeculatedType.h"
53 #include "StructureSet.h"
54 #include "TypeLocation.h"
55 #include "ValueProfile.h"
56 #include <type_traits>
57 #include <wtf/ListDump.h>
58
59 namespace JSC {
60
61 namespace DOMJIT {
62 class GetterSetter;
63 class Patchpoint;
64 class CallDOMGetterPatchpoint;
65 class Signature;
66 }
67
68 namespace Profiler {
69 class ExecutionCounter;
70 }
71
72 namespace DFG {
73
74 class Graph;
75 class PromotedLocationDescriptor;
76 struct BasicBlock;
77
78 struct StorageAccessData {
79     PropertyOffset offset;
80     unsigned identifierNumber;
81
82     // This needs to know the inferred type. For puts, this is necessary because we need to remember
83     // what check is needed. For gets, this is necessary because otherwise AI might forget what type is
84     // guaranteed.
85     InferredType::Descriptor inferredType;
86 };
87
88 struct MultiPutByOffsetData {
89     unsigned identifierNumber;
90     Vector<PutByIdVariant, 2> variants;
91     
92     bool writesStructures() const;
93     bool reallocatesStorage() const;
94 };
95
96 struct NewArrayBufferData {
97     unsigned startConstant;
98     unsigned numConstants;
99     IndexingType indexingType;
100 };
101
102 struct BranchTarget {
103     BranchTarget()
104         : block(0)
105         , count(PNaN)
106     {
107     }
108     
109     explicit BranchTarget(BasicBlock* block)
110         : block(block)
111         , count(PNaN)
112     {
113     }
114     
115     void setBytecodeIndex(unsigned bytecodeIndex)
116     {
117         block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(bytecodeIndex));
118     }
119     unsigned bytecodeIndex() const { return bitwise_cast<uintptr_t>(block); }
120     
121     void dump(PrintStream&) const;
122     
123     BasicBlock* block;
124     float count;
125 };
126
127 struct BranchData {
128     static BranchData withBytecodeIndices(
129         unsigned takenBytecodeIndex, unsigned notTakenBytecodeIndex)
130     {
131         BranchData result;
132         result.taken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(takenBytecodeIndex));
133         result.notTaken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(notTakenBytecodeIndex));
134         return result;
135     }
136     
137     unsigned takenBytecodeIndex() const { return taken.bytecodeIndex(); }
138     unsigned notTakenBytecodeIndex() const { return notTaken.bytecodeIndex(); }
139     
140     BasicBlock*& forCondition(bool condition)
141     {
142         if (condition)
143             return taken.block;
144         return notTaken.block;
145     }
146     
147     BranchTarget taken;
148     BranchTarget notTaken;
149 };
150
151 // The SwitchData and associated data structures duplicate the information in
152 // JumpTable. The DFG may ultimately end up using the JumpTable, though it may
153 // instead decide to do something different - this is entirely up to the DFG.
154 // These data structures give the DFG a higher-level semantic description of
155 // what is going on, which will allow it to make the right decision.
156 //
157 // Note that there will never be multiple SwitchCases in SwitchData::cases that
158 // have the same SwitchCase::value, since the bytecode's JumpTables never have
159 // duplicates - since the JumpTable maps a value to a target. It's a
160 // one-to-many mapping. So we may have duplicate targets, but never duplicate
161 // values.
162 struct SwitchCase {
163     SwitchCase()
164     {
165     }
166     
167     SwitchCase(LazyJSValue value, BasicBlock* target)
168         : value(value)
169         , target(target)
170     {
171     }
172     
173     static SwitchCase withBytecodeIndex(LazyJSValue value, unsigned bytecodeIndex)
174     {
175         SwitchCase result;
176         result.value = value;
177         result.target.setBytecodeIndex(bytecodeIndex);
178         return result;
179     }
180     
181     LazyJSValue value;
182     BranchTarget target;
183 };
184
185 struct SwitchData {
186     // Initializes most fields to obviously invalid values. Anyone
187     // constructing this should make sure to initialize everything they
188     // care about manually.
189     SwitchData()
190         : kind(static_cast<SwitchKind>(-1))
191         , switchTableIndex(UINT_MAX)
192         , didUseJumpTable(false)
193     {
194     }
195     
196     Vector<SwitchCase> cases;
197     BranchTarget fallThrough;
198     SwitchKind kind;
199     unsigned switchTableIndex;
200     bool didUseJumpTable;
201 };
202
203 struct CallVarargsData {
204     int firstVarArgOffset;
205 };
206
207 struct LoadVarargsData {
208     VirtualRegister start; // Local for the first element. This is the first actual argument, not this.
209     VirtualRegister count; // Local for the count.
210     VirtualRegister machineStart;
211     VirtualRegister machineCount;
212     unsigned offset; // Which array element to start with. Usually this is 0.
213     unsigned mandatoryMinimum; // The number of elements on the stack that must be initialized; if the array is too short then the missing elements must get undefined. Does not include "this".
214     unsigned limit; // Maximum number of elements to load. Includes "this".
215 };
216
217 struct StackAccessData {
218     StackAccessData()
219         : format(DeadFlush)
220     {
221     }
222     
223     StackAccessData(VirtualRegister local, FlushFormat format)
224         : local(local)
225         , format(format)
226     {
227     }
228     
229     VirtualRegister local;
230     VirtualRegister machineLocal;
231     FlushFormat format;
232     
233     FlushedAt flushedAt() { return FlushedAt(format, machineLocal); }
234 };
235
236 struct CallDOMGetterData {
237     DOMJIT::GetterSetter* domJIT { nullptr };
238     DOMJIT::CallDOMGetterPatchpoint* patchpoint { nullptr };
239     unsigned identifierNumber { 0 };
240 };
241
242 // === Node ===
243 //
244 // Node represents a single operation in the data flow graph.
245 struct Node {
246 public:
247     enum VarArgTag { VarArg };
248     
249     Node() { }
250     
251     Node(NodeType op, NodeOrigin nodeOrigin, const AdjacencyList& children)
252         : origin(nodeOrigin)
253         , children(children)
254         , m_virtualRegister(VirtualRegister())
255         , m_refCount(1)
256         , m_prediction(SpecNone)
257         , owner(nullptr)
258     {
259         m_misc.replacement = nullptr;
260         setOpAndDefaultFlags(op);
261     }
262     
263     // Construct a node with up to 3 children, no immediate value.
264     Node(NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
265         : origin(nodeOrigin)
266         , children(AdjacencyList::Fixed, child1, child2, child3)
267         , m_virtualRegister(VirtualRegister())
268         , m_refCount(1)
269         , m_prediction(SpecNone)
270         , owner(nullptr)
271     {
272         m_misc.replacement = nullptr;
273         setOpAndDefaultFlags(op);
274         ASSERT(!(m_flags & NodeHasVarArgs));
275     }
276
277     // Construct a node with up to 3 children, no immediate value.
278     Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
279         : origin(nodeOrigin)
280         , children(AdjacencyList::Fixed, child1, child2, child3)
281         , m_virtualRegister(VirtualRegister())
282         , m_refCount(1)
283         , m_prediction(SpecNone)
284         , owner(nullptr)
285     {
286         m_misc.replacement = nullptr;
287         setOpAndDefaultFlags(op);
288         setResult(result);
289         ASSERT(!(m_flags & NodeHasVarArgs));
290     }
291
292     // Construct a node with up to 3 children and an immediate value.
293     Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
294         : origin(nodeOrigin)
295         , children(AdjacencyList::Fixed, child1, child2, child3)
296         , m_virtualRegister(VirtualRegister())
297         , m_refCount(1)
298         , m_prediction(SpecNone)
299         , m_opInfo(imm.m_value)
300         , owner(nullptr)
301     {
302         m_misc.replacement = nullptr;
303         setOpAndDefaultFlags(op);
304         ASSERT(!(m_flags & NodeHasVarArgs));
305     }
306
307     // Construct a node with up to 3 children and an immediate value.
308     Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
309         : origin(nodeOrigin)
310         , children(AdjacencyList::Fixed, child1, child2, child3)
311         , m_virtualRegister(VirtualRegister())
312         , m_refCount(1)
313         , m_prediction(SpecNone)
314         , m_opInfo(imm.m_value)
315         , owner(nullptr)
316     {
317         m_misc.replacement = nullptr;
318         setOpAndDefaultFlags(op);
319         setResult(result);
320         ASSERT(!(m_flags & NodeHasVarArgs));
321     }
322
323     // Construct a node with up to 3 children and two immediate values.
324     Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
325         : origin(nodeOrigin)
326         , children(AdjacencyList::Fixed, child1, child2, child3)
327         , m_virtualRegister(VirtualRegister())
328         , m_refCount(1)
329         , m_prediction(SpecNone)
330         , m_opInfo(imm1.m_value)
331         , m_opInfo2(imm2.m_value)
332         , owner(nullptr)
333     {
334         m_misc.replacement = nullptr;
335         setOpAndDefaultFlags(op);
336         ASSERT(!(m_flags & NodeHasVarArgs));
337     }
338     
339     // Construct a node with a variable number of children and two immediate values.
340     Node(VarArgTag, NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
341         : origin(nodeOrigin)
342         , children(AdjacencyList::Variable, firstChild, numChildren)
343         , m_virtualRegister(VirtualRegister())
344         , m_refCount(1)
345         , m_prediction(SpecNone)
346         , m_opInfo(imm1.m_value)
347         , m_opInfo2(imm2.m_value)
348         , owner(nullptr)
349     {
350         m_misc.replacement = nullptr;
351         setOpAndDefaultFlags(op);
352         ASSERT(m_flags & NodeHasVarArgs);
353     }
354     
355     NodeType op() const { return static_cast<NodeType>(m_op); }
356     NodeFlags flags() const { return m_flags; }
357
358     unsigned index() const { return m_index; }
359     
360     void setOp(NodeType op)
361     {
362         m_op = op;
363     }
364     
365     void setFlags(NodeFlags flags)
366     {
367         m_flags = flags;
368     }
369     
370     bool mergeFlags(NodeFlags flags)
371     {
372         NodeFlags newFlags = m_flags | flags;
373         if (newFlags == m_flags)
374             return false;
375         m_flags = newFlags;
376         return true;
377     }
378     
379     bool filterFlags(NodeFlags flags)
380     {
381         NodeFlags newFlags = m_flags & flags;
382         if (newFlags == m_flags)
383             return false;
384         m_flags = newFlags;
385         return true;
386     }
387     
388     bool clearFlags(NodeFlags flags)
389     {
390         return filterFlags(~flags);
391     }
392     
393     void setResult(NodeFlags result)
394     {
395         ASSERT(!(result & ~NodeResultMask));
396         clearFlags(NodeResultMask);
397         mergeFlags(result);
398     }
399     
400     NodeFlags result() const
401     {
402         return flags() & NodeResultMask;
403     }
404     
405     void setOpAndDefaultFlags(NodeType op)
406     {
407         m_op = op;
408         m_flags = defaultFlags(op);
409     }
410
411     void remove();
412
413     void convertToCheckStructure(StructureSet* set)
414     {
415         setOpAndDefaultFlags(CheckStructure);
416         m_opInfo = set; 
417     }
418
419     void convertToCheckStructureImmediate(Node* structure)
420     {
421         ASSERT(op() == CheckStructure);
422         m_op = CheckStructureImmediate;
423         children.setChild1(Edge(structure, CellUse));
424     }
425     
426     void replaceWith(Node* other)
427     {
428         remove();
429         setReplacement(other);
430     }
431
432     void convertToIdentity();
433     void convertToIdentityOn(Node*);
434
435     bool mustGenerate()
436     {
437         return m_flags & NodeMustGenerate;
438     }
439     
440     bool isConstant()
441     {
442         switch (op()) {
443         case JSConstant:
444         case DoubleConstant:
445         case Int52Constant:
446             return true;
447         default:
448             return false;
449         }
450     }
451     
452     bool hasConstant()
453     {
454         switch (op()) {
455         case JSConstant:
456         case DoubleConstant:
457         case Int52Constant:
458             return true;
459             
460         case PhantomDirectArguments:
461         case PhantomClonedArguments:
462             // These pretend to be the empty value constant for the benefit of the DFG backend, which
463             // otherwise wouldn't take kindly to a node that doesn't compute a value.
464             return true;
465             
466         default:
467             return false;
468         }
469     }
470
471     FrozenValue* constant()
472     {
473         ASSERT(hasConstant());
474         
475         if (op() == PhantomDirectArguments || op() == PhantomClonedArguments) {
476             // These pretend to be the empty value constant for the benefit of the DFG backend, which
477             // otherwise wouldn't take kindly to a node that doesn't compute a value.
478             return FrozenValue::emptySingleton();
479         }
480         
481         return m_opInfo.as<FrozenValue*>();
482     }
483     
484     // Don't call this directly - use Graph::convertToConstant() instead!
485     void convertToConstant(FrozenValue* value)
486     {
487         if (hasDoubleResult())
488             m_op = DoubleConstant;
489         else if (hasInt52Result())
490             m_op = Int52Constant;
491         else
492             m_op = JSConstant;
493         m_flags &= ~NodeMustGenerate;
494         m_opInfo = value;
495         children.reset();
496     }
497
498     void convertToLazyJSConstant(Graph&, LazyJSValue);
499     
500     void convertToConstantStoragePointer(void* pointer)
501     {
502         ASSERT(op() == GetIndexedPropertyStorage);
503         m_op = ConstantStoragePointer;
504         m_opInfo = pointer;
505         children.reset();
506     }
507     
508     void convertToGetLocalUnlinked(VirtualRegister local)
509     {
510         m_op = GetLocalUnlinked;
511         m_flags &= ~NodeMustGenerate;
512         m_opInfo = local.offset();
513         m_opInfo2 = VirtualRegister().offset();
514         children.reset();
515     }
516     
517     void convertToPutStack(StackAccessData* data)
518     {
519         m_op = PutStack;
520         m_flags |= NodeMustGenerate;
521         m_opInfo = data;
522         m_opInfo2 = OpInfoWrapper();
523     }
524     
525     void convertToGetStack(StackAccessData* data)
526     {
527         m_op = GetStack;
528         m_flags &= ~NodeMustGenerate;
529         m_opInfo = data;
530         m_opInfo2 = OpInfoWrapper();
531         children.reset();
532     }
533     
534     void convertToGetByOffset(StorageAccessData& data, Edge storage, Edge base)
535     {
536         ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
537         m_opInfo = &data;
538         children.setChild1(storage);
539         children.setChild2(base);
540         m_op = GetByOffset;
541         m_flags &= ~NodeMustGenerate;
542     }
543     
544     void convertToMultiGetByOffset(MultiGetByOffsetData* data)
545     {
546         ASSERT(m_op == GetById || m_op == GetByIdFlush);
547         m_opInfo = data;
548         child1().setUseKind(CellUse);
549         m_op = MultiGetByOffset;
550         ASSERT(m_flags & NodeMustGenerate);
551     }
552     
553     void convertToPutByOffset(StorageAccessData& data, Edge storage, Edge base)
554     {
555         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset);
556         m_opInfo = &data;
557         children.setChild3(children.child2());
558         children.setChild2(base);
559         children.setChild1(storage);
560         m_op = PutByOffset;
561     }
562     
563     void convertToMultiPutByOffset(MultiPutByOffsetData* data)
564     {
565         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
566         m_opInfo = data;
567         m_op = MultiPutByOffset;
568     }
569     
570     void convertToPutHint(const PromotedLocationDescriptor&, Node* base, Node* value);
571     
572     void convertToPutByOffsetHint();
573     void convertToPutStructureHint(Node* structure);
574     void convertToPutClosureVarHint();
575     
576     void convertToPhantomNewObject()
577     {
578         ASSERT(m_op == NewObject || m_op == MaterializeNewObject);
579         m_op = PhantomNewObject;
580         m_flags &= ~NodeHasVarArgs;
581         m_flags |= NodeMustGenerate;
582         m_opInfo = OpInfoWrapper();
583         m_opInfo2 = OpInfoWrapper();
584         children = AdjacencyList();
585     }
586
587     void convertToPhantomNewFunction()
588     {
589         ASSERT(m_op == NewFunction || m_op == NewGeneratorFunction || m_op == NewAsyncFunction);
590         m_op = PhantomNewFunction;
591         m_flags |= NodeMustGenerate;
592         m_opInfo = OpInfoWrapper();
593         m_opInfo2 = OpInfoWrapper();
594         children = AdjacencyList();
595     }
596
597     void convertToPhantomNewGeneratorFunction()
598     {
599         ASSERT(m_op == NewGeneratorFunction);
600         m_op = PhantomNewGeneratorFunction;
601         m_flags |= NodeMustGenerate;
602         m_opInfo = OpInfoWrapper();
603         m_opInfo2 = OpInfoWrapper();
604         children = AdjacencyList();
605     }
606
607     void convertToPhantomNewAsyncFunction()
608     {
609         ASSERT(m_op == NewAsyncFunction);
610         m_op = PhantomNewAsyncFunction;
611         m_flags |= NodeMustGenerate;
612         m_opInfo = OpInfoWrapper();
613         m_opInfo2 = OpInfoWrapper();
614         children = AdjacencyList();
615     }
616
617     void convertToPhantomCreateActivation()
618     {
619         ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
620         m_op = PhantomCreateActivation;
621         m_flags &= ~NodeHasVarArgs;
622         m_flags |= NodeMustGenerate;
623         m_opInfo = OpInfoWrapper();
624         m_opInfo2 = OpInfoWrapper();
625         children = AdjacencyList();
626     }
627
628     void convertPhantomToPhantomLocal()
629     {
630         ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
631         m_op = PhantomLocal;
632         m_opInfo = child1()->m_opInfo; // Copy the variableAccessData.
633         children.setChild1(Edge());
634     }
635     
636     void convertFlushToPhantomLocal()
637     {
638         ASSERT(m_op == Flush);
639         m_op = PhantomLocal;
640         children = AdjacencyList();
641     }
642     
643     void convertToGetLocal(VariableAccessData* variable, Node* phi)
644     {
645         ASSERT(m_op == GetLocalUnlinked);
646         m_op = GetLocal;
647         m_opInfo = variable;
648         m_opInfo2 = OpInfoWrapper();
649         children.setChild1(Edge(phi));
650     }
651     
652     void convertToToString()
653     {
654         ASSERT(m_op == ToPrimitive);
655         m_op = ToString;
656     }
657
658     void convertToArithNegate()
659     {
660         ASSERT(m_op == ArithAbs && child1().useKind() == Int32Use);
661         m_op = ArithNegate;
662     }
663     
664     void convertToDirectCall(FrozenValue*);
665
666     void convertToCallDOM(Graph&);
667     
668     JSValue asJSValue()
669     {
670         return constant()->value();
671     }
672      
673     bool isInt32Constant()
674     {
675         return isConstant() && constant()->value().isInt32();
676     }
677      
678     int32_t asInt32()
679     {
680         return asJSValue().asInt32();
681     }
682      
683     uint32_t asUInt32()
684     {
685         return asInt32();
686     }
687      
688     bool isDoubleConstant()
689     {
690         return isConstant() && constant()->value().isDouble();
691     }
692      
693     bool isNumberConstant()
694     {
695         return isConstant() && constant()->value().isNumber();
696     }
697     
698     double asNumber()
699     {
700         return asJSValue().asNumber();
701     }
702      
703     bool isAnyIntConstant()
704     {
705         return isConstant() && constant()->value().isAnyInt();
706     }
707      
708     int64_t asAnyInt()
709     {
710         return asJSValue().asAnyInt();
711     }
712      
713     bool isBooleanConstant()
714     {
715         return isConstant() && constant()->value().isBoolean();
716     }
717      
718     bool asBoolean()
719     {
720         return constant()->value().asBoolean();
721     }
722
723     bool isUndefinedOrNullConstant()
724     {
725         return isConstant() && constant()->value().isUndefinedOrNull();
726     }
727
728     bool isCellConstant()
729     {
730         return isConstant() && constant()->value() && constant()->value().isCell();
731     }
732      
733     JSCell* asCell()
734     {
735         return constant()->value().asCell();
736     }
737      
738     template<typename T>
739     T dynamicCastConstant()
740     {
741         if (!isCellConstant())
742             return nullptr;
743         return jsDynamicCast<T>(asCell());
744     }
745     
746     template<typename T>
747     T castConstant()
748     {
749         T result = dynamicCastConstant<T>();
750         RELEASE_ASSERT(result);
751         return result;
752     }
753
754     bool hasLazyJSValue()
755     {
756         return op() == LazyJSConstant;
757     }
758
759     LazyJSValue lazyJSValue()
760     {
761         ASSERT(hasLazyJSValue());
762         return *m_opInfo.as<LazyJSValue*>();
763     }
764
765     String tryGetString(Graph&);
766
767     JSValue initializationValueForActivation() const
768     {
769         ASSERT(op() == CreateActivation);
770         return m_opInfo2.as<FrozenValue*>()->value();
771     }
772
773     bool hasArgumentsChild()
774     {
775         switch (op()) {
776         case GetMyArgumentByVal:
777         case GetMyArgumentByValOutOfBounds:
778         case LoadVarargs:
779         case ForwardVarargs:
780         case CallVarargs:
781         case CallForwardVarargs:
782         case ConstructVarargs:
783         case ConstructForwardVarargs:
784         case TailCallVarargs:
785         case TailCallForwardVarargs:
786         case TailCallVarargsInlinedCaller:
787         case TailCallForwardVarargsInlinedCaller:
788             return true;
789         default:
790             return false;
791         }
792     }
793
794     Edge& argumentsChild()
795     {
796         switch (op()) {
797         case GetMyArgumentByVal:
798         case GetMyArgumentByValOutOfBounds:
799         case LoadVarargs:
800         case ForwardVarargs:
801             return child1();
802         case CallVarargs:
803         case CallForwardVarargs:
804         case ConstructVarargs:
805         case ConstructForwardVarargs:
806         case TailCallVarargs:
807         case TailCallForwardVarargs:
808         case TailCallVarargsInlinedCaller:
809         case TailCallForwardVarargsInlinedCaller:
810             return child3();
811         default:
812             RELEASE_ASSERT_NOT_REACHED();
813             return child1();
814         }
815     }
816
817     bool containsMovHint()
818     {
819         switch (op()) {
820         case MovHint:
821         case ZombieHint:
822             return true;
823         default:
824             return false;
825         }
826     }
827     
828     bool hasVariableAccessData(Graph&);
829     bool accessesStack(Graph& graph)
830     {
831         return hasVariableAccessData(graph);
832     }
833     
834     // This is useful for debugging code, where a node that should have a variable
835     // access data doesn't have one because it hasn't been initialized yet.
836     VariableAccessData* tryGetVariableAccessData()
837     {
838         VariableAccessData* result = m_opInfo.as<VariableAccessData*>();
839         if (!result)
840             return 0;
841         return result->find();
842     }
843     
844     VariableAccessData* variableAccessData()
845     {
846         return m_opInfo.as<VariableAccessData*>()->find();
847     }
848     
849     VirtualRegister local()
850     {
851         return variableAccessData()->local();
852     }
853     
854     VirtualRegister machineLocal()
855     {
856         return variableAccessData()->machineLocal();
857     }
858     
859     bool hasUnlinkedLocal()
860     {
861         switch (op()) {
862         case GetLocalUnlinked:
863         case ExtractOSREntryLocal:
864         case MovHint:
865         case ZombieHint:
866         case KillStack:
867             return true;
868         default:
869             return false;
870         }
871     }
872     
873     VirtualRegister unlinkedLocal()
874     {
875         ASSERT(hasUnlinkedLocal());
876         return VirtualRegister(m_opInfo.as<int32_t>());
877     }
878     
879     bool hasUnlinkedMachineLocal()
880     {
881         return op() == GetLocalUnlinked;
882     }
883     
884     void setUnlinkedMachineLocal(VirtualRegister reg)
885     {
886         ASSERT(hasUnlinkedMachineLocal());
887         m_opInfo2 = reg.offset();
888     }
889     
890     VirtualRegister unlinkedMachineLocal()
891     {
892         ASSERT(hasUnlinkedMachineLocal());
893         return VirtualRegister(m_opInfo2.as<int32_t>());
894     }
895     
896     bool hasStackAccessData()
897     {
898         switch (op()) {
899         case PutStack:
900         case GetStack:
901             return true;
902         default:
903             return false;
904         }
905     }
906     
907     StackAccessData* stackAccessData()
908     {
909         ASSERT(hasStackAccessData());
910         return m_opInfo.as<StackAccessData*>();
911     }
912     
913     bool hasPhi()
914     {
915         return op() == Upsilon;
916     }
917     
918     Node* phi()
919     {
920         ASSERT(hasPhi());
921         return m_opInfo.as<Node*>();
922     }
923
924     bool isStoreBarrier()
925     {
926         return op() == StoreBarrier || op() == FencedStoreBarrier;
927     }
928
929     bool hasIdentifier()
930     {
931         switch (op()) {
932         case TryGetById:
933         case GetById:
934         case GetByIdFlush:
935         case GetByIdWithThis:
936         case PutById:
937         case PutByIdFlush:
938         case PutByIdDirect:
939         case PutByIdWithThis:
940         case PutGetterById:
941         case PutSetterById:
942         case PutGetterSetterById:
943         case DeleteById:
944         case GetDynamicVar:
945         case PutDynamicVar:
946         case ResolveScope:
947             return true;
948         default:
949             return false;
950         }
951     }
952
953     unsigned identifierNumber()
954     {
955         ASSERT(hasIdentifier());
956         return m_opInfo.as<unsigned>();
957     }
958
959     bool hasGetPutInfo()
960     {
961         switch (op()) {
962         case GetDynamicVar:
963         case PutDynamicVar:
964             return true;
965         default:
966             return false;
967         }
968     }
969
970     unsigned getPutInfo()
971     {
972         ASSERT(hasGetPutInfo());
973         return m_opInfo2.as<unsigned>();
974     }
975
976     bool hasAccessorAttributes()
977     {
978         switch (op()) {
979         case PutGetterById:
980         case PutSetterById:
981         case PutGetterSetterById:
982         case PutGetterByVal:
983         case PutSetterByVal:
984             return true;
985         default:
986             return false;
987         }
988     }
989
990     int32_t accessorAttributes()
991     {
992         ASSERT(hasAccessorAttributes());
993         switch (op()) {
994         case PutGetterById:
995         case PutSetterById:
996         case PutGetterSetterById:
997             return m_opInfo2.as<int32_t>();
998         case PutGetterByVal:
999         case PutSetterByVal:
1000             return m_opInfo.as<int32_t>();
1001         default:
1002             RELEASE_ASSERT_NOT_REACHED();
1003             return 0;
1004         }
1005     }
1006     
1007     bool hasPromotedLocationDescriptor()
1008     {
1009         return op() == PutHint;
1010     }
1011     
1012     PromotedLocationDescriptor promotedLocationDescriptor();
1013     
1014     // This corrects the arithmetic node flags, so that irrelevant bits are
1015     // ignored. In particular, anything other than ArithMul does not need
1016     // to know if it can speculate on negative zero.
1017     NodeFlags arithNodeFlags()
1018     {
1019         NodeFlags result = m_flags & NodeArithFlagsMask;
1020         if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc || op() == DoubleAsInt32)
1021             return result;
1022         return result & ~NodeBytecodeNeedsNegZero;
1023     }
1024
1025     bool mayHaveNonIntResult()
1026     {
1027         return m_flags & NodeMayHaveNonIntResult;
1028     }
1029     
1030     bool mayHaveDoubleResult()
1031     {
1032         return m_flags & NodeMayHaveDoubleResult;
1033     }
1034     
1035     bool mayHaveNonNumberResult()
1036     {
1037         return m_flags & NodeMayHaveNonNumberResult;
1038     }
1039
1040     bool hasConstantBuffer()
1041     {
1042         return op() == NewArrayBuffer;
1043     }
1044     
1045     NewArrayBufferData* newArrayBufferData()
1046     {
1047         ASSERT(hasConstantBuffer());
1048         return m_opInfo.as<NewArrayBufferData*>();
1049     }
1050     
1051     unsigned startConstant()
1052     {
1053         return newArrayBufferData()->startConstant;
1054     }
1055     
1056     unsigned numConstants()
1057     {
1058         return newArrayBufferData()->numConstants;
1059     }
1060     
1061     bool hasIndexingType()
1062     {
1063         switch (op()) {
1064         case NewArray:
1065         case NewArrayWithSize:
1066         case NewArrayBuffer:
1067             return true;
1068         default:
1069             return false;
1070         }
1071     }
1072
1073     BitVector* bitVector()
1074     {
1075         ASSERT(op() == NewArrayWithSpread || op() == PhantomNewArrayWithSpread);
1076         return m_opInfo.as<BitVector*>();
1077     }
1078
1079     // Return the indexing type that an array allocation *wants* to use. It may end up using a different
1080     // type if we're having a bad time. You can determine the actual indexing type by asking the global
1081     // object:
1082     //
1083     //     m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())
1084     //
1085     // This will give you a Structure*, and that will have some indexing type that may be different from
1086     // the this one.
1087     IndexingType indexingType()
1088     {
1089         ASSERT(hasIndexingType());
1090         if (op() == NewArrayBuffer)
1091             return newArrayBufferData()->indexingType;
1092         return static_cast<IndexingType>(m_opInfo.as<uint32_t>());
1093     }
1094     
1095     bool hasTypedArrayType()
1096     {
1097         switch (op()) {
1098         case NewTypedArray:
1099             return true;
1100         default:
1101             return false;
1102         }
1103     }
1104     
1105     TypedArrayType typedArrayType()
1106     {
1107         ASSERT(hasTypedArrayType());
1108         TypedArrayType result = static_cast<TypedArrayType>(m_opInfo.as<uint32_t>());
1109         ASSERT(isTypedView(result));
1110         return result;
1111     }
1112     
1113     bool hasInlineCapacity()
1114     {
1115         return op() == CreateThis;
1116     }
1117
1118     unsigned inlineCapacity()
1119     {
1120         ASSERT(hasInlineCapacity());
1121         return m_opInfo.as<unsigned>();
1122     }
1123
1124     void setIndexingType(IndexingType indexingType)
1125     {
1126         ASSERT(hasIndexingType());
1127         m_opInfo = indexingType;
1128     }
1129     
1130     bool hasScopeOffset()
1131     {
1132         return op() == GetClosureVar || op() == PutClosureVar;
1133     }
1134
1135     ScopeOffset scopeOffset()
1136     {
1137         ASSERT(hasScopeOffset());
1138         return ScopeOffset(m_opInfo.as<uint32_t>());
1139     }
1140     
1141     bool hasDirectArgumentsOffset()
1142     {
1143         return op() == GetFromArguments || op() == PutToArguments;
1144     }
1145     
1146     DirectArgumentsOffset capturedArgumentsOffset()
1147     {
1148         ASSERT(hasDirectArgumentsOffset());
1149         return DirectArgumentsOffset(m_opInfo.as<uint32_t>());
1150     }
1151     
1152     bool hasRegisterPointer()
1153     {
1154         return op() == GetGlobalVar || op() == GetGlobalLexicalVariable || op() == PutGlobalVariable;
1155     }
1156     
1157     WriteBarrier<Unknown>* variablePointer()
1158     {
1159         return m_opInfo.as<WriteBarrier<Unknown>*>();
1160     }
1161     
1162     bool hasCallVarargsData()
1163     {
1164         switch (op()) {
1165         case CallVarargs:
1166         case CallForwardVarargs:
1167         case TailCallVarargs:
1168         case TailCallForwardVarargs:
1169         case TailCallVarargsInlinedCaller:
1170         case TailCallForwardVarargsInlinedCaller:
1171         case ConstructVarargs:
1172         case ConstructForwardVarargs:
1173             return true;
1174         default:
1175             return false;
1176         }
1177     }
1178     
1179     CallVarargsData* callVarargsData()
1180     {
1181         ASSERT(hasCallVarargsData());
1182         return m_opInfo.as<CallVarargsData*>();
1183     }
1184     
1185     bool hasLoadVarargsData()
1186     {
1187         return op() == LoadVarargs || op() == ForwardVarargs;
1188     }
1189     
1190     LoadVarargsData* loadVarargsData()
1191     {
1192         ASSERT(hasLoadVarargsData());
1193         return m_opInfo.as<LoadVarargsData*>();
1194     }
1195
1196     bool hasQueriedType()
1197     {
1198         return op() == IsCellWithType;
1199     }
1200
1201     JSType queriedType()
1202     {
1203         static_assert(std::is_same<uint8_t, std::underlying_type<JSType>::type>::value, "Ensure that uint8_t is the underlying type for JSType.");
1204         return static_cast<JSType>(m_opInfo.as<uint32_t>());
1205     }
1206
1207     bool hasSpeculatedTypeForQuery()
1208     {
1209         return op() == IsCellWithType;
1210     }
1211
1212     SpeculatedType speculatedTypeForQuery()
1213     {
1214         return speculationFromJSType(queriedType());
1215     }
1216     
1217     bool hasResult()
1218     {
1219         return !!result();
1220     }
1221     
1222     bool hasInt52Result()
1223     {
1224         return result() == NodeResultInt52;
1225     }
1226     
1227     bool hasNumberResult()
1228     {
1229         return result() == NodeResultNumber;
1230     }
1231     
1232     bool hasDoubleResult()
1233     {
1234         return result() == NodeResultDouble;
1235     }
1236     
1237     bool hasJSResult()
1238     {
1239         return result() == NodeResultJS;
1240     }
1241     
1242     bool hasBooleanResult()
1243     {
1244         return result() == NodeResultBoolean;
1245     }
1246
1247     bool hasStorageResult()
1248     {
1249         return result() == NodeResultStorage;
1250     }
1251     
1252     UseKind defaultUseKind()
1253     {
1254         return useKindForResult(result());
1255     }
1256     
1257     Edge defaultEdge()
1258     {
1259         return Edge(this, defaultUseKind());
1260     }
1261
1262     bool isJump()
1263     {
1264         return op() == Jump;
1265     }
1266
1267     bool isBranch()
1268     {
1269         return op() == Branch;
1270     }
1271     
1272     bool isSwitch()
1273     {
1274         return op() == Switch;
1275     }
1276
1277     bool isTerminal()
1278     {
1279         switch (op()) {
1280         case Jump:
1281         case Branch:
1282         case Switch:
1283         case Return:
1284         case TailCall:
1285         case DirectTailCall:
1286         case TailCallVarargs:
1287         case TailCallForwardVarargs:
1288         case Unreachable:
1289             return true;
1290         default:
1291             return false;
1292         }
1293     }
1294
1295     bool isFunctionTerminal()
1296     {
1297         if (isTerminal() && !numSuccessors())
1298             return true;
1299
1300         return false;
1301     }
1302
1303     unsigned targetBytecodeOffsetDuringParsing()
1304     {
1305         ASSERT(isJump());
1306         return m_opInfo.as<unsigned>();
1307     }
1308
1309     BasicBlock*& targetBlock()
1310     {
1311         ASSERT(isJump());
1312         return *bitwise_cast<BasicBlock**>(&m_opInfo.u.pointer);
1313     }
1314     
1315     BranchData* branchData()
1316     {
1317         ASSERT(isBranch());
1318         return m_opInfo.as<BranchData*>();
1319     }
1320     
1321     SwitchData* switchData()
1322     {
1323         ASSERT(isSwitch());
1324         return m_opInfo.as<SwitchData*>();
1325     }
1326     
1327     unsigned numSuccessors()
1328     {
1329         switch (op()) {
1330         case Jump:
1331             return 1;
1332         case Branch:
1333             return 2;
1334         case Switch:
1335             return switchData()->cases.size() + 1;
1336         default:
1337             return 0;
1338         }
1339     }
1340     
1341     BasicBlock*& successor(unsigned index)
1342     {
1343         if (isSwitch()) {
1344             if (index < switchData()->cases.size())
1345                 return switchData()->cases[index].target.block;
1346             RELEASE_ASSERT(index == switchData()->cases.size());
1347             return switchData()->fallThrough.block;
1348         }
1349         switch (index) {
1350         case 0:
1351             if (isJump())
1352                 return targetBlock();
1353             return branchData()->taken.block;
1354         case 1:
1355             return branchData()->notTaken.block;
1356         default:
1357             RELEASE_ASSERT_NOT_REACHED();
1358             return targetBlock();
1359         }
1360     }
1361     
1362     class SuccessorsIterable {
1363     public:
1364         SuccessorsIterable()
1365             : m_terminal(nullptr)
1366         {
1367         }
1368         
1369         SuccessorsIterable(Node* terminal)
1370             : m_terminal(terminal)
1371         {
1372         }
1373         
1374         class iterator {
1375         public:
1376             iterator()
1377                 : m_terminal(nullptr)
1378                 , m_index(UINT_MAX)
1379             {
1380             }
1381             
1382             iterator(Node* terminal, unsigned index)
1383                 : m_terminal(terminal)
1384                 , m_index(index)
1385             {
1386             }
1387             
1388             BasicBlock* operator*()
1389             {
1390                 return m_terminal->successor(m_index);
1391             }
1392             
1393             iterator& operator++()
1394             {
1395                 m_index++;
1396                 return *this;
1397             }
1398             
1399             bool operator==(const iterator& other) const
1400             {
1401                 return m_index == other.m_index;
1402             }
1403             
1404             bool operator!=(const iterator& other) const
1405             {
1406                 return !(*this == other);
1407             }
1408         private:
1409             Node* m_terminal;
1410             unsigned m_index;
1411         };
1412         
1413         iterator begin()
1414         {
1415             return iterator(m_terminal, 0);
1416         }
1417         
1418         iterator end()
1419         {
1420             return iterator(m_terminal, m_terminal->numSuccessors());
1421         }
1422
1423         size_t size() const { return m_terminal->numSuccessors(); }
1424         BasicBlock* at(size_t index) const { return m_terminal->successor(index); }
1425         BasicBlock* operator[](size_t index) const { return at(index); }
1426         
1427     private:
1428         Node* m_terminal;
1429     };
1430     
1431     SuccessorsIterable successors()
1432     {
1433         return SuccessorsIterable(this);
1434     }
1435     
1436     BasicBlock*& successorForCondition(bool condition)
1437     {
1438         return branchData()->forCondition(condition);
1439     }
1440     
1441     bool hasHeapPrediction()
1442     {
1443         switch (op()) {
1444         case ArithAbs:
1445         case ArithRound:
1446         case ArithFloor:
1447         case ArithCeil:
1448         case ArithTrunc:
1449         case GetDirectPname:
1450         case GetById:
1451         case GetByIdFlush:
1452         case GetByIdWithThis:
1453         case TryGetById:
1454         case GetByVal:
1455         case GetByValWithThis:
1456         case Call:
1457         case DirectCall:
1458         case TailCallInlinedCaller:
1459         case DirectTailCallInlinedCaller:
1460         case Construct:
1461         case DirectConstruct:
1462         case CallVarargs:
1463         case CallEval:
1464         case TailCallVarargsInlinedCaller:
1465         case ConstructVarargs:
1466         case CallForwardVarargs:
1467         case TailCallForwardVarargsInlinedCaller:
1468         case GetByOffset:
1469         case MultiGetByOffset:
1470         case GetClosureVar:
1471         case GetFromArguments:
1472         case GetArgument:
1473         case ArrayPop:
1474         case ArrayPush:
1475         case ArraySlice:
1476         case RegExpExec:
1477         case RegExpTest:
1478         case GetGlobalVar:
1479         case GetGlobalLexicalVariable:
1480         case StringReplace:
1481         case StringReplaceRegExp:
1482         case ToNumber:
1483         case LoadFromJSMapBucket:
1484         case CallDOMGetter:
1485         case CallDOM:
1486             return true;
1487         default:
1488             return false;
1489         }
1490     }
1491     
1492     SpeculatedType getHeapPrediction()
1493     {
1494         ASSERT(hasHeapPrediction());
1495         return m_opInfo2.as<SpeculatedType>();
1496     }
1497
1498     void setHeapPrediction(SpeculatedType prediction)
1499     {
1500         ASSERT(hasHeapPrediction());
1501         m_opInfo2 = prediction;
1502     }
1503     
1504     bool hasCellOperand()
1505     {
1506         switch (op()) {
1507         case CheckCell:
1508         case OverridesHasInstance:
1509         case NewFunction:
1510         case NewGeneratorFunction:
1511         case NewAsyncFunction:
1512         case CreateActivation:
1513         case MaterializeCreateActivation:
1514         case NewRegexp:
1515         case CompareEqPtr:
1516         case DirectCall:
1517         case DirectTailCall:
1518         case DirectConstruct:
1519         case DirectTailCallInlinedCaller:
1520             return true;
1521         default:
1522             return false;
1523         }
1524     }
1525
1526     FrozenValue* cellOperand()
1527     {
1528         ASSERT(hasCellOperand());
1529         return m_opInfo.as<FrozenValue*>();
1530     }
1531     
1532     template<typename T>
1533     T castOperand()
1534     {
1535         return cellOperand()->cast<T>();
1536     }
1537     
1538     void setCellOperand(FrozenValue* value)
1539     {
1540         ASSERT(hasCellOperand());
1541         m_opInfo = value;
1542     }
1543     
1544     bool hasWatchpointSet()
1545     {
1546         return op() == NotifyWrite;
1547     }
1548     
1549     WatchpointSet* watchpointSet()
1550     {
1551         ASSERT(hasWatchpointSet());
1552         return m_opInfo.as<WatchpointSet*>();
1553     }
1554     
1555     bool hasStoragePointer()
1556     {
1557         return op() == ConstantStoragePointer;
1558     }
1559     
1560     void* storagePointer()
1561     {
1562         ASSERT(hasStoragePointer());
1563         return m_opInfo.as<void*>();
1564     }
1565
1566     bool hasUidOperand()
1567     {
1568         return op() == CheckStringIdent;
1569     }
1570
1571     UniquedStringImpl* uidOperand()
1572     {
1573         ASSERT(hasUidOperand());
1574         return m_opInfo.as<UniquedStringImpl*>();
1575     }
1576
1577     bool hasTypeInfoOperand()
1578     {
1579         return op() == CheckTypeInfoFlags;
1580     }
1581
1582     unsigned typeInfoOperand()
1583     {
1584         ASSERT(hasTypeInfoOperand() && m_opInfo.as<uint32_t>() <= static_cast<uint32_t>(UCHAR_MAX));
1585         return m_opInfo.as<uint32_t>();
1586     }
1587
1588     bool hasTransition()
1589     {
1590         switch (op()) {
1591         case PutStructure:
1592         case AllocatePropertyStorage:
1593         case ReallocatePropertyStorage:
1594             return true;
1595         default:
1596             return false;
1597         }
1598     }
1599     
1600     Transition* transition()
1601     {
1602         ASSERT(hasTransition());
1603         return m_opInfo.as<Transition*>();
1604     }
1605     
1606     bool hasStructureSet()
1607     {
1608         switch (op()) {
1609         case CheckStructure:
1610         case CheckStructureImmediate:
1611         case MaterializeNewObject:
1612             return true;
1613         default:
1614             return false;
1615         }
1616     }
1617     
1618     StructureSet& structureSet()
1619     {
1620         ASSERT(hasStructureSet());
1621         return *m_opInfo.as<StructureSet*>();
1622     }
1623     
1624     bool hasStructure()
1625     {
1626         switch (op()) {
1627         case ArrayifyToStructure:
1628         case NewObject:
1629         case NewStringObject:
1630             return true;
1631         default:
1632             return false;
1633         }
1634     }
1635     
1636     Structure* structure()
1637     {
1638         ASSERT(hasStructure());
1639         return m_opInfo.as<Structure*>();
1640     }
1641     
1642     bool hasStorageAccessData()
1643     {
1644         switch (op()) {
1645         case GetByOffset:
1646         case PutByOffset:
1647         case GetGetterSetterByOffset:
1648             return true;
1649         default:
1650             return false;
1651         }
1652     }
1653     
1654     StorageAccessData& storageAccessData()
1655     {
1656         ASSERT(hasStorageAccessData());
1657         return *m_opInfo.as<StorageAccessData*>();
1658     }
1659     
1660     bool hasMultiGetByOffsetData()
1661     {
1662         return op() == MultiGetByOffset;
1663     }
1664     
1665     MultiGetByOffsetData& multiGetByOffsetData()
1666     {
1667         ASSERT(hasMultiGetByOffsetData());
1668         return *m_opInfo.as<MultiGetByOffsetData*>();
1669     }
1670     
1671     bool hasMultiPutByOffsetData()
1672     {
1673         return op() == MultiPutByOffset;
1674     }
1675     
1676     MultiPutByOffsetData& multiPutByOffsetData()
1677     {
1678         ASSERT(hasMultiPutByOffsetData());
1679         return *m_opInfo.as<MultiPutByOffsetData*>();
1680     }
1681     
1682     bool hasObjectMaterializationData()
1683     {
1684         switch (op()) {
1685         case MaterializeNewObject:
1686         case MaterializeCreateActivation:
1687             return true;
1688
1689         default:
1690             return false;
1691         }
1692     }
1693     
1694     ObjectMaterializationData& objectMaterializationData()
1695     {
1696         ASSERT(hasObjectMaterializationData());
1697         return *m_opInfo2.as<ObjectMaterializationData*>();
1698     }
1699
1700     bool isObjectAllocation()
1701     {
1702         switch (op()) {
1703         case NewObject:
1704         case MaterializeNewObject:
1705             return true;
1706         default:
1707             return false;
1708         }
1709     }
1710     
1711     bool isPhantomObjectAllocation()
1712     {
1713         switch (op()) {
1714         case PhantomNewObject:
1715             return true;
1716         default:
1717             return false;
1718         }
1719     }
1720     
1721     bool isActivationAllocation()
1722     {
1723         switch (op()) {
1724         case CreateActivation:
1725         case MaterializeCreateActivation:
1726             return true;
1727         default:
1728             return false;
1729         }
1730     }
1731
1732     bool isPhantomActivationAllocation()
1733     {
1734         switch (op()) {
1735         case PhantomCreateActivation:
1736             return true;
1737         default:
1738             return false;
1739         }
1740     }
1741
1742     bool isFunctionAllocation()
1743     {
1744         switch (op()) {
1745         case NewFunction:
1746         case NewGeneratorFunction:
1747         case NewAsyncFunction:
1748             return true;
1749         default:
1750             return false;
1751         }
1752     }
1753
1754     bool isPhantomFunctionAllocation()
1755     {
1756         switch (op()) {
1757         case PhantomNewFunction:
1758         case PhantomNewGeneratorFunction:
1759         case PhantomNewAsyncFunction:
1760             return true;
1761         default:
1762             return false;
1763         }
1764     }
1765
1766     bool isPhantomAllocation()
1767     {
1768         switch (op()) {
1769         case PhantomNewObject:
1770         case PhantomDirectArguments:
1771         case PhantomCreateRest:
1772         case PhantomSpread:
1773         case PhantomNewArrayWithSpread:
1774         case PhantomClonedArguments:
1775         case PhantomNewFunction:
1776         case PhantomNewGeneratorFunction:
1777         case PhantomNewAsyncFunction:
1778         case PhantomCreateActivation:
1779             return true;
1780         default:
1781             return false;
1782         }
1783     }
1784     
1785     bool hasArrayMode()
1786     {
1787         switch (op()) {
1788         case GetIndexedPropertyStorage:
1789         case GetArrayLength:
1790         case PutByValDirect:
1791         case PutByVal:
1792         case PutByValAlias:
1793         case GetByVal:
1794         case StringCharAt:
1795         case StringCharCodeAt:
1796         case CheckArray:
1797         case Arrayify:
1798         case ArrayifyToStructure:
1799         case ArrayPush:
1800         case ArraySlice:
1801         case ArrayPop:
1802         case HasIndexedProperty:
1803             return true;
1804         default:
1805             return false;
1806         }
1807     }
1808     
1809     ArrayMode arrayMode()
1810     {
1811         ASSERT(hasArrayMode());
1812         if (op() == ArrayifyToStructure)
1813             return ArrayMode::fromWord(m_opInfo2.as<uint32_t>());
1814         return ArrayMode::fromWord(m_opInfo.as<uint32_t>());
1815     }
1816     
1817     bool setArrayMode(ArrayMode arrayMode)
1818     {
1819         ASSERT(hasArrayMode());
1820         if (this->arrayMode() == arrayMode)
1821             return false;
1822         m_opInfo = arrayMode.asWord();
1823         return true;
1824     }
1825     
1826     bool hasArithMode()
1827     {
1828         switch (op()) {
1829         case ArithAbs:
1830         case ArithAdd:
1831         case ArithSub:
1832         case ArithNegate:
1833         case ArithMul:
1834         case ArithDiv:
1835         case ArithMod:
1836         case UInt32ToNumber:
1837         case DoubleAsInt32:
1838             return true;
1839         default:
1840             return false;
1841         }
1842     }
1843
1844     Arith::Mode arithMode()
1845     {
1846         ASSERT(hasArithMode());
1847         return static_cast<Arith::Mode>(m_opInfo.as<uint32_t>());
1848     }
1849     
1850     void setArithMode(Arith::Mode mode)
1851     {
1852         m_opInfo = mode;
1853     }
1854
1855     bool hasArithRoundingMode()
1856     {
1857         return op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc;
1858     }
1859
1860     Arith::RoundingMode arithRoundingMode()
1861     {
1862         ASSERT(hasArithRoundingMode());
1863         return static_cast<Arith::RoundingMode>(m_opInfo.as<uint32_t>());
1864     }
1865
1866     void setArithRoundingMode(Arith::RoundingMode mode)
1867     {
1868         ASSERT(hasArithRoundingMode());
1869         m_opInfo = static_cast<uint32_t>(mode);
1870     }
1871     
1872     bool hasVirtualRegister()
1873     {
1874         return m_virtualRegister.isValid();
1875     }
1876     
1877     VirtualRegister virtualRegister()
1878     {
1879         ASSERT(hasResult());
1880         ASSERT(m_virtualRegister.isValid());
1881         return m_virtualRegister;
1882     }
1883     
1884     void setVirtualRegister(VirtualRegister virtualRegister)
1885     {
1886         ASSERT(hasResult());
1887         ASSERT(!m_virtualRegister.isValid());
1888         m_virtualRegister = virtualRegister;
1889     }
1890     
1891     bool hasExecutionCounter()
1892     {
1893         return op() == CountExecution;
1894     }
1895     
1896     Profiler::ExecutionCounter* executionCounter()
1897     {
1898         return m_opInfo.as<Profiler::ExecutionCounter*>();
1899     }
1900
1901     bool shouldGenerate()
1902     {
1903         return m_refCount;
1904     }
1905     
1906     bool isSemanticallySkippable()
1907     {
1908         return op() == CountExecution;
1909     }
1910
1911     unsigned refCount()
1912     {
1913         return m_refCount;
1914     }
1915
1916     unsigned postfixRef()
1917     {
1918         return m_refCount++;
1919     }
1920
1921     unsigned adjustedRefCount()
1922     {
1923         return mustGenerate() ? m_refCount - 1 : m_refCount;
1924     }
1925     
1926     void setRefCount(unsigned refCount)
1927     {
1928         m_refCount = refCount;
1929     }
1930     
1931     Edge& child1()
1932     {
1933         ASSERT(!(m_flags & NodeHasVarArgs));
1934         return children.child1();
1935     }
1936     
1937     // This is useful if you want to do a fast check on the first child
1938     // before also doing a check on the opcode. Use this with care and
1939     // avoid it if possible.
1940     Edge child1Unchecked()
1941     {
1942         return children.child1Unchecked();
1943     }
1944
1945     Edge& child2()
1946     {
1947         ASSERT(!(m_flags & NodeHasVarArgs));
1948         return children.child2();
1949     }
1950
1951     Edge& child3()
1952     {
1953         ASSERT(!(m_flags & NodeHasVarArgs));
1954         return children.child3();
1955     }
1956     
1957     unsigned firstChild()
1958     {
1959         ASSERT(m_flags & NodeHasVarArgs);
1960         return children.firstChild();
1961     }
1962     
1963     unsigned numChildren()
1964     {
1965         ASSERT(m_flags & NodeHasVarArgs);
1966         return children.numChildren();
1967     }
1968     
1969     UseKind binaryUseKind()
1970     {
1971         ASSERT(child1().useKind() == child2().useKind());
1972         return child1().useKind();
1973     }
1974     
1975     bool isBinaryUseKind(UseKind left, UseKind right)
1976     {
1977         return child1().useKind() == left && child2().useKind() == right;
1978     }
1979     
1980     bool isBinaryUseKind(UseKind useKind)
1981     {
1982         return isBinaryUseKind(useKind, useKind);
1983     }
1984     
1985     Edge childFor(UseKind useKind)
1986     {
1987         if (child1().useKind() == useKind)
1988             return child1();
1989         if (child2().useKind() == useKind)
1990             return child2();
1991         if (child3().useKind() == useKind)
1992             return child3();
1993         return Edge();
1994     }
1995     
1996     SpeculatedType prediction()
1997     {
1998         return m_prediction;
1999     }
2000     
2001     bool predict(SpeculatedType prediction)
2002     {
2003         return mergeSpeculation(m_prediction, prediction);
2004     }
2005     
2006     bool shouldSpeculateInt32()
2007     {
2008         return isInt32Speculation(prediction());
2009     }
2010
2011     bool shouldSpeculateNotInt32()
2012     {
2013         return isNotInt32Speculation(prediction());
2014     }
2015     
2016     bool sawBooleans()
2017     {
2018         return !!(prediction() & SpecBoolean);
2019     }
2020     
2021     bool shouldSpeculateInt32OrBoolean()
2022     {
2023         return isInt32OrBooleanSpeculation(prediction());
2024     }
2025     
2026     bool shouldSpeculateInt32ForArithmetic()
2027     {
2028         return isInt32SpeculationForArithmetic(prediction());
2029     }
2030     
2031     bool shouldSpeculateInt32OrBooleanForArithmetic()
2032     {
2033         return isInt32OrBooleanSpeculationForArithmetic(prediction());
2034     }
2035     
2036     bool shouldSpeculateInt32OrBooleanExpectingDefined()
2037     {
2038         return isInt32OrBooleanSpeculationExpectingDefined(prediction());
2039     }
2040     
2041     bool shouldSpeculateAnyInt()
2042     {
2043         return isAnyIntSpeculation(prediction());
2044     }
2045     
2046     bool shouldSpeculateDouble()
2047     {
2048         return isDoubleSpeculation(prediction());
2049     }
2050     
2051     bool shouldSpeculateDoubleReal()
2052     {
2053         return isDoubleRealSpeculation(prediction());
2054     }
2055     
2056     bool shouldSpeculateNumber()
2057     {
2058         return isFullNumberSpeculation(prediction());
2059     }
2060     
2061     bool shouldSpeculateNumberOrBoolean()
2062     {
2063         return isFullNumberOrBooleanSpeculation(prediction());
2064     }
2065     
2066     bool shouldSpeculateNumberOrBooleanExpectingDefined()
2067     {
2068         return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
2069     }
2070     
2071     bool shouldSpeculateBoolean()
2072     {
2073         return isBooleanSpeculation(prediction());
2074     }
2075
2076     bool shouldSpeculateNotBoolean()
2077     {
2078         return isNotBooleanSpeculation(prediction());
2079     }
2080     
2081     bool shouldSpeculateOther()
2082     {
2083         return isOtherSpeculation(prediction());
2084     }
2085     
2086     bool shouldSpeculateMisc()
2087     {
2088         return isMiscSpeculation(prediction());
2089     }
2090    
2091     bool shouldSpeculateStringIdent()
2092     {
2093         return isStringIdentSpeculation(prediction());
2094     }
2095     
2096     bool shouldSpeculateNotStringVar()
2097     {
2098         return isNotStringVarSpeculation(prediction());
2099     }
2100  
2101     bool shouldSpeculateString()
2102     {
2103         return isStringSpeculation(prediction());
2104     }
2105
2106     bool shouldSpeculateNotString()
2107     {
2108         return isNotStringSpeculation(prediction());
2109     }
2110  
2111     bool shouldSpeculateStringOrOther()
2112     {
2113         return isStringOrOtherSpeculation(prediction());
2114     }
2115  
2116     bool shouldSpeculateStringObject()
2117     {
2118         return isStringObjectSpeculation(prediction());
2119     }
2120     
2121     bool shouldSpeculateStringOrStringObject()
2122     {
2123         return isStringOrStringObjectSpeculation(prediction());
2124     }
2125
2126     bool shouldSpeculateRegExpObject()
2127     {
2128         return isRegExpObjectSpeculation(prediction());
2129     }
2130     
2131     bool shouldSpeculateSymbol()
2132     {
2133         return isSymbolSpeculation(prediction());
2134     }
2135     
2136     bool shouldSpeculateFinalObject()
2137     {
2138         return isFinalObjectSpeculation(prediction());
2139     }
2140     
2141     bool shouldSpeculateFinalObjectOrOther()
2142     {
2143         return isFinalObjectOrOtherSpeculation(prediction());
2144     }
2145     
2146     bool shouldSpeculateArray()
2147     {
2148         return isArraySpeculation(prediction());
2149     }
2150
2151     bool shouldSpeculateProxyObject()
2152     {
2153         return isProxyObjectSpeculation(prediction());
2154     }
2155
2156     bool shouldSpeculateDerivedArray()
2157     {
2158         return isDerivedArraySpeculation(prediction());
2159     }
2160     
2161     bool shouldSpeculateDirectArguments()
2162     {
2163         return isDirectArgumentsSpeculation(prediction());
2164     }
2165     
2166     bool shouldSpeculateScopedArguments()
2167     {
2168         return isScopedArgumentsSpeculation(prediction());
2169     }
2170     
2171     bool shouldSpeculateInt8Array()
2172     {
2173         return isInt8ArraySpeculation(prediction());
2174     }
2175     
2176     bool shouldSpeculateInt16Array()
2177     {
2178         return isInt16ArraySpeculation(prediction());
2179     }
2180     
2181     bool shouldSpeculateInt32Array()
2182     {
2183         return isInt32ArraySpeculation(prediction());
2184     }
2185     
2186     bool shouldSpeculateUint8Array()
2187     {
2188         return isUint8ArraySpeculation(prediction());
2189     }
2190
2191     bool shouldSpeculateUint8ClampedArray()
2192     {
2193         return isUint8ClampedArraySpeculation(prediction());
2194     }
2195     
2196     bool shouldSpeculateUint16Array()
2197     {
2198         return isUint16ArraySpeculation(prediction());
2199     }
2200     
2201     bool shouldSpeculateUint32Array()
2202     {
2203         return isUint32ArraySpeculation(prediction());
2204     }
2205     
2206     bool shouldSpeculateFloat32Array()
2207     {
2208         return isFloat32ArraySpeculation(prediction());
2209     }
2210     
2211     bool shouldSpeculateFloat64Array()
2212     {
2213         return isFloat64ArraySpeculation(prediction());
2214     }
2215     
2216     bool shouldSpeculateArrayOrOther()
2217     {
2218         return isArrayOrOtherSpeculation(prediction());
2219     }
2220     
2221     bool shouldSpeculateObject()
2222     {
2223         return isObjectSpeculation(prediction());
2224     }
2225     
2226     bool shouldSpeculateObjectOrOther()
2227     {
2228         return isObjectOrOtherSpeculation(prediction());
2229     }
2230
2231     bool shouldSpeculateCell()
2232     {
2233         return isCellSpeculation(prediction());
2234     }
2235     
2236     bool shouldSpeculateCellOrOther()
2237     {
2238         return isCellOrOtherSpeculation(prediction());
2239     }
2240     
2241     bool shouldSpeculateNotCell()
2242     {
2243         return isNotCellSpeculation(prediction());
2244     }
2245     
2246     bool shouldSpeculateUntypedForArithmetic()
2247     {
2248         return isUntypedSpeculationForArithmetic(prediction());
2249     }
2250
2251     static bool shouldSpeculateUntypedForArithmetic(Node* op1, Node* op2)
2252     {
2253         return op1->shouldSpeculateUntypedForArithmetic() || op2->shouldSpeculateUntypedForArithmetic();
2254     }
2255     
2256     bool shouldSpeculateUntypedForBitOps()
2257     {
2258         return isUntypedSpeculationForBitOps(prediction());
2259     }
2260     
2261     static bool shouldSpeculateUntypedForBitOps(Node* op1, Node* op2)
2262     {
2263         return op1->shouldSpeculateUntypedForBitOps() || op2->shouldSpeculateUntypedForBitOps();
2264     }
2265     
2266     static bool shouldSpeculateBoolean(Node* op1, Node* op2)
2267     {
2268         return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
2269     }
2270     
2271     static bool shouldSpeculateInt32(Node* op1, Node* op2)
2272     {
2273         return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
2274     }
2275     
2276     static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
2277     {
2278         return op1->shouldSpeculateInt32OrBoolean()
2279             && op2->shouldSpeculateInt32OrBoolean();
2280     }
2281     
2282     static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
2283     {
2284         return op1->shouldSpeculateInt32OrBooleanForArithmetic()
2285             && op2->shouldSpeculateInt32OrBooleanForArithmetic();
2286     }
2287     
2288     static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
2289     {
2290         return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
2291             && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
2292     }
2293     
2294     static bool shouldSpeculateAnyInt(Node* op1, Node* op2)
2295     {
2296         return op1->shouldSpeculateAnyInt() && op2->shouldSpeculateAnyInt();
2297     }
2298     
2299     static bool shouldSpeculateNumber(Node* op1, Node* op2)
2300     {
2301         return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
2302     }
2303     
2304     static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2)
2305     {
2306         return op1->shouldSpeculateNumberOrBoolean()
2307             && op2->shouldSpeculateNumberOrBoolean();
2308     }
2309     
2310     static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2)
2311     {
2312         return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
2313             && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
2314     }
2315
2316     static bool shouldSpeculateSymbol(Node* op1, Node* op2)
2317     {
2318         return op1->shouldSpeculateSymbol() && op2->shouldSpeculateSymbol();
2319     }
2320     
2321     static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
2322     {
2323         return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
2324     }
2325
2326     static bool shouldSpeculateArray(Node* op1, Node* op2)
2327     {
2328         return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
2329     }
2330     
2331     bool canSpeculateInt32(RareCaseProfilingSource source)
2332     {
2333         return nodeCanSpeculateInt32(arithNodeFlags(), source);
2334     }
2335     
2336     bool canSpeculateInt52(RareCaseProfilingSource source)
2337     {
2338         return nodeCanSpeculateInt52(arithNodeFlags(), source);
2339     }
2340     
2341     RareCaseProfilingSource sourceFor(PredictionPass pass)
2342     {
2343         if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
2344             return DFGRareCase;
2345         return AllRareCases;
2346     }
2347     
2348     bool canSpeculateInt32(PredictionPass pass)
2349     {
2350         return canSpeculateInt32(sourceFor(pass));
2351     }
2352     
2353     bool canSpeculateInt52(PredictionPass pass)
2354     {
2355         return canSpeculateInt52(sourceFor(pass));
2356     }
2357
2358     bool hasTypeLocation()
2359     {
2360         return op() == ProfileType;
2361     }
2362
2363     TypeLocation* typeLocation()
2364     {
2365         ASSERT(hasTypeLocation());
2366         return m_opInfo.as<TypeLocation*>();
2367     }
2368
2369     bool hasBasicBlockLocation()
2370     {
2371         return op() == ProfileControlFlow;
2372     }
2373
2374     BasicBlockLocation* basicBlockLocation()
2375     {
2376         ASSERT(hasBasicBlockLocation());
2377         return m_opInfo.as<BasicBlockLocation*>();
2378     }
2379
2380     bool hasCheckDOMPatchpoint() const
2381     {
2382         return op() == CheckDOM;
2383     }
2384
2385     DOMJIT::Patchpoint* checkDOMPatchpoint()
2386     {
2387         ASSERT(hasCheckDOMPatchpoint());
2388         return m_opInfo.as<DOMJIT::Patchpoint*>();
2389     }
2390
2391     bool hasCallDOMGetterData() const
2392     {
2393         return op() == CallDOMGetter;
2394     }
2395
2396     CallDOMGetterData* callDOMGetterData()
2397     {
2398         ASSERT(hasCallDOMGetterData());
2399         return m_opInfo.as<CallDOMGetterData*>();
2400     }
2401
2402     bool hasClassInfo() const
2403     {
2404         return op() == CheckDOM;
2405     }
2406
2407     const ClassInfo* classInfo()
2408     {
2409         return m_opInfo2.as<const ClassInfo*>();
2410     }
2411
2412     bool hasSignature() const
2413     {
2414         // Note that this does not include TailCall node types intentionally.
2415         // CallDOM node types are always converted from Call.
2416         return op() == Call || op() == CallDOM;
2417     }
2418
2419     const DOMJIT::Signature* signature()
2420     {
2421         return m_opInfo.as<const DOMJIT::Signature*>();
2422     }
2423
2424     Node* replacement() const
2425     {
2426         return m_misc.replacement;
2427     }
2428     
2429     void setReplacement(Node* replacement)
2430     {
2431         m_misc.replacement = replacement;
2432     }
2433     
2434     Epoch epoch() const
2435     {
2436         return Epoch::fromUnsigned(m_misc.epoch);
2437     }
2438     
2439     void setEpoch(Epoch epoch)
2440     {
2441         m_misc.epoch = epoch.toUnsigned();
2442     }
2443
2444     unsigned numberOfArgumentsToSkip()
2445     {
2446         ASSERT(op() == CreateRest || op() == PhantomCreateRest || op() == GetRestLength || op() == GetMyArgumentByVal || op() == GetMyArgumentByValOutOfBounds);
2447         return m_opInfo.as<unsigned>();
2448     }
2449
2450     bool hasArgumentIndex()
2451     {
2452         return op() == GetArgument;
2453     }
2454
2455     unsigned argumentIndex()
2456     {
2457         ASSERT(hasArgumentIndex());
2458         return m_opInfo.as<unsigned>();
2459     }
2460
2461     void dumpChildren(PrintStream& out)
2462     {
2463         if (!child1())
2464             return;
2465         out.printf("@%u", child1()->index());
2466         if (!child2())
2467             return;
2468         out.printf(", @%u", child2()->index());
2469         if (!child3())
2470             return;
2471         out.printf(", @%u", child3()->index());
2472     }
2473     
2474     // NB. This class must have a trivial destructor.
2475
2476     NodeOrigin origin;
2477
2478     // References to up to 3 children, or links to a variable length set of children.
2479     AdjacencyList children;
2480
2481 private:
2482     friend class Graph;
2483
2484     unsigned m_index { std::numeric_limits<unsigned>::max() };
2485     unsigned m_op : 10; // real type is NodeType
2486     unsigned m_flags : 20;
2487     // The virtual register number (spill location) associated with this .
2488     VirtualRegister m_virtualRegister;
2489     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
2490     unsigned m_refCount;
2491     // The prediction ascribed to this node after propagation.
2492     SpeculatedType m_prediction { SpecNone };
2493     // Immediate values, accesses type-checked via accessors above.
2494     struct OpInfoWrapper {
2495         OpInfoWrapper()
2496         {
2497             u.int64 = 0;
2498         }
2499         OpInfoWrapper(uint32_t intValue)
2500         {
2501             u.int64 = 0;
2502             u.int32 = intValue;
2503         }
2504         OpInfoWrapper(uint64_t intValue)
2505         {
2506             u.int64 = intValue;
2507         }
2508         OpInfoWrapper(void* pointer)
2509         {
2510             u.int64 = 0;
2511             u.pointer = pointer;
2512         }
2513         OpInfoWrapper(const void* constPointer)
2514         {
2515             u.int64 = 0;
2516             u.constPointer = constPointer;
2517         }
2518         OpInfoWrapper& operator=(uint32_t int32)
2519         {
2520             u.int64 = 0;
2521             u.int32 = int32;
2522             return *this;
2523         }
2524         OpInfoWrapper& operator=(int32_t int32)
2525         {
2526             u.int64 = 0;
2527             u.int32 = int32;
2528             return *this;
2529         }
2530         OpInfoWrapper& operator=(uint64_t int64)
2531         {
2532             u.int64 = int64;
2533             return *this;
2534         }
2535         OpInfoWrapper& operator=(void* pointer)
2536         {
2537             u.int64 = 0;
2538             u.pointer = pointer;
2539             return *this;
2540         }
2541         OpInfoWrapper& operator=(const void* constPointer)
2542         {
2543             u.int64 = 0;
2544             u.constPointer = constPointer;
2545             return *this;
2546         }
2547         template <typename T>
2548         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
2549         {
2550             return static_cast<T>(u.pointer);
2551         }
2552         template <typename T>
2553         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
2554         {
2555             return static_cast<T>(u.constPointer);
2556         }
2557         template <typename T>
2558         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 4, T>::type
2559         {
2560             return u.int32;
2561         }
2562         template <typename T>
2563         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 8, T>::type
2564         {
2565             return u.int64;
2566         }
2567         union {
2568             uint32_t int32;
2569             uint64_t int64;
2570             void* pointer;
2571             const void* constPointer;
2572         } u;
2573     };
2574     OpInfoWrapper m_opInfo;
2575     OpInfoWrapper m_opInfo2;
2576
2577     // Miscellaneous data that is usually meaningless, but can hold some analysis results
2578     // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
2579     // will tell you which basic block a node belongs to. You cannot rely on this persisting
2580     // across transformations unless you do the maintenance work yourself. Other phases use
2581     // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
2582     // and then you set, and use, replacement's yourself. Same thing for epoch.
2583     //
2584     // Bottom line: don't use these fields unless you initialize them yourself, or by
2585     // calling some appropriate methods that initialize them the way you want. Otherwise,
2586     // these fields are meaningless.
2587 private:
2588     union {
2589         Node* replacement;
2590         unsigned epoch;
2591     } m_misc;
2592 public:
2593     BasicBlock* owner;
2594 };
2595
2596 struct NodeComparator {
2597     template<typename NodePtrType>
2598     bool operator()(NodePtrType a, NodePtrType b) const
2599     {
2600         return a->index() < b->index();
2601     }
2602 };
2603
2604 template<typename T>
2605 CString nodeListDump(const T& nodeList)
2606 {
2607     return sortedListDump(nodeList, NodeComparator());
2608 }
2609
2610 template<typename T>
2611 CString nodeMapDump(const T& nodeMap, DumpContext* context = 0)
2612 {
2613     Vector<typename T::KeyType> keys;
2614     for (
2615         typename T::const_iterator iter = nodeMap.begin();
2616         iter != nodeMap.end(); ++iter)
2617         keys.append(iter->key);
2618     std::sort(keys.begin(), keys.end(), NodeComparator());
2619     StringPrintStream out;
2620     CommaPrinter comma;
2621     for(unsigned i = 0; i < keys.size(); ++i)
2622         out.print(comma, keys[i], "=>", inContext(nodeMap.get(keys[i]), context));
2623     return out.toCString();
2624 }
2625
2626 template<typename T>
2627 CString nodeValuePairListDump(const T& nodeValuePairList, DumpContext* context = 0)
2628 {
2629     using V = typename T::ValueType;
2630     T sortedList = nodeValuePairList;
2631     std::sort(sortedList.begin(), sortedList.end(), [](const V& a, const V& b) {
2632         return NodeComparator()(a.node, b.node);
2633     });
2634
2635     StringPrintStream out;
2636     CommaPrinter comma;
2637     for (const auto& pair : sortedList)
2638         out.print(comma, pair.node, "=>", inContext(pair.value, context));
2639     return out.toCString();
2640 }
2641
2642 } } // namespace JSC::DFG
2643
2644 namespace WTF {
2645
2646 void printInternal(PrintStream&, JSC::DFG::SwitchKind);
2647 void printInternal(PrintStream&, JSC::DFG::Node*);
2648
2649 inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
2650
2651 } // namespace WTF
2652
2653 using WTF::inContext;
2654
2655 #endif