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