JSTests:
[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 || m_op == NewAsyncGeneratorFunction);
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 convertToPhantomNewAsyncGeneratorFunction()
625     {
626         ASSERT(m_op == NewAsyncGeneratorFunction);
627         m_op = PhantomNewAsyncGeneratorFunction;
628         m_flags |= NodeMustGenerate;
629         m_opInfo = OpInfoWrapper();
630         m_opInfo2 = OpInfoWrapper();
631         children = AdjacencyList();
632     }
633     
634     void convertToPhantomCreateActivation()
635     {
636         ASSERT(m_op == CreateActivation || m_op == MaterializeCreateActivation);
637         m_op = PhantomCreateActivation;
638         m_flags &= ~NodeHasVarArgs;
639         m_flags |= NodeMustGenerate;
640         m_opInfo = OpInfoWrapper();
641         m_opInfo2 = OpInfoWrapper();
642         children = AdjacencyList();
643     }
644
645     void convertPhantomToPhantomLocal()
646     {
647         ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
648         m_op = PhantomLocal;
649         m_opInfo = child1()->m_opInfo; // Copy the variableAccessData.
650         children.setChild1(Edge());
651     }
652     
653     void convertFlushToPhantomLocal()
654     {
655         ASSERT(m_op == Flush);
656         m_op = PhantomLocal;
657         children = AdjacencyList();
658     }
659     
660     void convertToGetLocal(VariableAccessData* variable, Node* phi)
661     {
662         ASSERT(m_op == GetLocalUnlinked);
663         m_op = GetLocal;
664         m_opInfo = variable;
665         m_opInfo2 = OpInfoWrapper();
666         children.setChild1(Edge(phi));
667     }
668     
669     void convertToToString()
670     {
671         ASSERT(m_op == ToPrimitive);
672         m_op = ToString;
673     }
674
675     void convertToArithNegate()
676     {
677         ASSERT(m_op == ArithAbs && child1().useKind() == Int32Use);
678         m_op = ArithNegate;
679     }
680     
681     void convertToDirectCall(FrozenValue*);
682
683     void convertToCallDOM(Graph&);
684     
685     JSValue asJSValue()
686     {
687         return constant()->value();
688     }
689      
690     bool isInt32Constant()
691     {
692         return isConstant() && constant()->value().isInt32();
693     }
694      
695     int32_t asInt32()
696     {
697         return asJSValue().asInt32();
698     }
699      
700     uint32_t asUInt32()
701     {
702         return asInt32();
703     }
704      
705     bool isDoubleConstant()
706     {
707         return isConstant() && constant()->value().isDouble();
708     }
709      
710     bool isNumberConstant()
711     {
712         return isConstant() && constant()->value().isNumber();
713     }
714     
715     double asNumber()
716     {
717         return asJSValue().asNumber();
718     }
719      
720     bool isAnyIntConstant()
721     {
722         return isConstant() && constant()->value().isAnyInt();
723     }
724      
725     int64_t asAnyInt()
726     {
727         return asJSValue().asAnyInt();
728     }
729      
730     bool isBooleanConstant()
731     {
732         return isConstant() && constant()->value().isBoolean();
733     }
734      
735     bool asBoolean()
736     {
737         return constant()->value().asBoolean();
738     }
739
740     bool isUndefinedOrNullConstant()
741     {
742         return isConstant() && constant()->value().isUndefinedOrNull();
743     }
744
745     bool isCellConstant()
746     {
747         return isConstant() && constant()->value() && constant()->value().isCell();
748     }
749      
750     JSCell* asCell()
751     {
752         return constant()->value().asCell();
753     }
754      
755     template<typename T>
756     T dynamicCastConstant(VM& vm)
757     {
758         if (!isCellConstant())
759             return nullptr;
760         return jsDynamicCast<T>(vm, asCell());
761     }
762     
763     template<typename T>
764     T castConstant(VM& vm)
765     {
766         T result = dynamicCastConstant<T>(vm);
767         RELEASE_ASSERT(result);
768         return result;
769     }
770
771     bool hasLazyJSValue()
772     {
773         return op() == LazyJSConstant;
774     }
775
776     LazyJSValue lazyJSValue()
777     {
778         ASSERT(hasLazyJSValue());
779         return *m_opInfo.as<LazyJSValue*>();
780     }
781
782     String tryGetString(Graph&);
783
784     JSValue initializationValueForActivation() const
785     {
786         ASSERT(op() == CreateActivation);
787         return m_opInfo2.as<FrozenValue*>()->value();
788     }
789
790     bool hasArgumentsChild()
791     {
792         switch (op()) {
793         case GetMyArgumentByVal:
794         case GetMyArgumentByValOutOfBounds:
795         case LoadVarargs:
796         case ForwardVarargs:
797         case CallVarargs:
798         case CallForwardVarargs:
799         case ConstructVarargs:
800         case ConstructForwardVarargs:
801         case TailCallVarargs:
802         case TailCallForwardVarargs:
803         case TailCallVarargsInlinedCaller:
804         case TailCallForwardVarargsInlinedCaller:
805             return true;
806         default:
807             return false;
808         }
809     }
810
811     Edge& argumentsChild()
812     {
813         switch (op()) {
814         case GetMyArgumentByVal:
815         case GetMyArgumentByValOutOfBounds:
816         case LoadVarargs:
817         case ForwardVarargs:
818             return child1();
819         case CallVarargs:
820         case CallForwardVarargs:
821         case ConstructVarargs:
822         case ConstructForwardVarargs:
823         case TailCallVarargs:
824         case TailCallForwardVarargs:
825         case TailCallVarargsInlinedCaller:
826         case TailCallForwardVarargsInlinedCaller:
827             return child3();
828         default:
829             RELEASE_ASSERT_NOT_REACHED();
830             return child1();
831         }
832     }
833
834     bool containsMovHint()
835     {
836         switch (op()) {
837         case MovHint:
838         case ZombieHint:
839             return true;
840         default:
841             return false;
842         }
843     }
844     
845     bool hasVariableAccessData(Graph&);
846     bool accessesStack(Graph& graph)
847     {
848         return hasVariableAccessData(graph);
849     }
850     
851     // This is useful for debugging code, where a node that should have a variable
852     // access data doesn't have one because it hasn't been initialized yet.
853     VariableAccessData* tryGetVariableAccessData()
854     {
855         VariableAccessData* result = m_opInfo.as<VariableAccessData*>();
856         if (!result)
857             return 0;
858         return result->find();
859     }
860     
861     VariableAccessData* variableAccessData()
862     {
863         return m_opInfo.as<VariableAccessData*>()->find();
864     }
865     
866     VirtualRegister local()
867     {
868         return variableAccessData()->local();
869     }
870     
871     VirtualRegister machineLocal()
872     {
873         return variableAccessData()->machineLocal();
874     }
875     
876     bool hasUnlinkedLocal()
877     {
878         switch (op()) {
879         case GetLocalUnlinked:
880         case ExtractOSREntryLocal:
881         case MovHint:
882         case ZombieHint:
883         case KillStack:
884             return true;
885         default:
886             return false;
887         }
888     }
889     
890     VirtualRegister unlinkedLocal()
891     {
892         ASSERT(hasUnlinkedLocal());
893         return VirtualRegister(m_opInfo.as<int32_t>());
894     }
895     
896     bool hasUnlinkedMachineLocal()
897     {
898         return op() == GetLocalUnlinked;
899     }
900     
901     void setUnlinkedMachineLocal(VirtualRegister reg)
902     {
903         ASSERT(hasUnlinkedMachineLocal());
904         m_opInfo2 = reg.offset();
905     }
906     
907     VirtualRegister unlinkedMachineLocal()
908     {
909         ASSERT(hasUnlinkedMachineLocal());
910         return VirtualRegister(m_opInfo2.as<int32_t>());
911     }
912     
913     bool hasStackAccessData()
914     {
915         switch (op()) {
916         case PutStack:
917         case GetStack:
918             return true;
919         default:
920             return false;
921         }
922     }
923     
924     StackAccessData* stackAccessData()
925     {
926         ASSERT(hasStackAccessData());
927         return m_opInfo.as<StackAccessData*>();
928     }
929     
930     bool hasPhi()
931     {
932         return op() == Upsilon;
933     }
934     
935     Node* phi()
936     {
937         ASSERT(hasPhi());
938         return m_opInfo.as<Node*>();
939     }
940
941     bool isStoreBarrier()
942     {
943         return op() == StoreBarrier || op() == FencedStoreBarrier;
944     }
945
946     bool hasIdentifier()
947     {
948         switch (op()) {
949         case TryGetById:
950         case GetById:
951         case GetByIdFlush:
952         case GetByIdWithThis:
953         case PutById:
954         case PutByIdFlush:
955         case PutByIdDirect:
956         case PutByIdWithThis:
957         case PutGetterById:
958         case PutSetterById:
959         case PutGetterSetterById:
960         case DeleteById:
961         case GetDynamicVar:
962         case PutDynamicVar:
963         case ResolveScopeForHoistingFuncDeclInEval:
964         case ResolveScope:
965             return true;
966         default:
967             return false;
968         }
969     }
970
971     unsigned identifierNumber()
972     {
973         ASSERT(hasIdentifier());
974         return m_opInfo.as<unsigned>();
975     }
976
977     bool hasGetPutInfo()
978     {
979         switch (op()) {
980         case GetDynamicVar:
981         case PutDynamicVar:
982             return true;
983         default:
984             return false;
985         }
986     }
987
988     unsigned getPutInfo()
989     {
990         ASSERT(hasGetPutInfo());
991         return static_cast<unsigned>(m_opInfo.as<uint64_t>() >> 32);
992     }
993
994     bool hasAccessorAttributes()
995     {
996         switch (op()) {
997         case PutGetterById:
998         case PutSetterById:
999         case PutGetterSetterById:
1000         case PutGetterByVal:
1001         case PutSetterByVal:
1002             return true;
1003         default:
1004             return false;
1005         }
1006     }
1007
1008     int32_t accessorAttributes()
1009     {
1010         ASSERT(hasAccessorAttributes());
1011         switch (op()) {
1012         case PutGetterById:
1013         case PutSetterById:
1014         case PutGetterSetterById:
1015             return m_opInfo2.as<int32_t>();
1016         case PutGetterByVal:
1017         case PutSetterByVal:
1018             return m_opInfo.as<int32_t>();
1019         default:
1020             RELEASE_ASSERT_NOT_REACHED();
1021             return 0;
1022         }
1023     }
1024     
1025     bool hasPromotedLocationDescriptor()
1026     {
1027         return op() == PutHint;
1028     }
1029     
1030     PromotedLocationDescriptor promotedLocationDescriptor();
1031     
1032     // This corrects the arithmetic node flags, so that irrelevant bits are
1033     // ignored. In particular, anything other than ArithMul does not need
1034     // to know if it can speculate on negative zero.
1035     NodeFlags arithNodeFlags()
1036     {
1037         NodeFlags result = m_flags & NodeArithFlagsMask;
1038         if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == ArithPow || op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc || op() == DoubleAsInt32)
1039             return result;
1040         return result & ~NodeBytecodeNeedsNegZero;
1041     }
1042
1043     bool mayHaveNonIntResult()
1044     {
1045         return m_flags & NodeMayHaveNonIntResult;
1046     }
1047     
1048     bool mayHaveDoubleResult()
1049     {
1050         return m_flags & NodeMayHaveDoubleResult;
1051     }
1052     
1053     bool mayHaveNonNumberResult()
1054     {
1055         return m_flags & NodeMayHaveNonNumberResult;
1056     }
1057
1058     bool hasConstantBuffer()
1059     {
1060         return op() == NewArrayBuffer;
1061     }
1062     
1063     NewArrayBufferData* newArrayBufferData()
1064     {
1065         ASSERT(hasConstantBuffer());
1066         return m_opInfo.as<NewArrayBufferData*>();
1067     }
1068     
1069     unsigned startConstant()
1070     {
1071         return newArrayBufferData()->startConstant;
1072     }
1073     
1074     unsigned numConstants()
1075     {
1076         return newArrayBufferData()->numConstants;
1077     }
1078     
1079     bool hasIndexingType()
1080     {
1081         switch (op()) {
1082         case NewArray:
1083         case NewArrayWithSize:
1084         case NewArrayBuffer:
1085             return true;
1086         default:
1087             return false;
1088         }
1089     }
1090
1091     BitVector* bitVector()
1092     {
1093         ASSERT(op() == NewArrayWithSpread || op() == PhantomNewArrayWithSpread);
1094         return m_opInfo.as<BitVector*>();
1095     }
1096
1097     // Return the indexing type that an array allocation *wants* to use. It may end up using a different
1098     // type if we're having a bad time. You can determine the actual indexing type by asking the global
1099     // object:
1100     //
1101     //     m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType())
1102     //
1103     // This will give you a Structure*, and that will have some indexing type that may be different from
1104     // the this one.
1105     IndexingType indexingType()
1106     {
1107         ASSERT(hasIndexingType());
1108         if (op() == NewArrayBuffer)
1109             return newArrayBufferData()->indexingType;
1110         return static_cast<IndexingType>(m_opInfo.as<uint32_t>());
1111     }
1112     
1113     bool hasTypedArrayType()
1114     {
1115         switch (op()) {
1116         case NewTypedArray:
1117             return true;
1118         default:
1119             return false;
1120         }
1121     }
1122     
1123     TypedArrayType typedArrayType()
1124     {
1125         ASSERT(hasTypedArrayType());
1126         TypedArrayType result = static_cast<TypedArrayType>(m_opInfo.as<uint32_t>());
1127         ASSERT(isTypedView(result));
1128         return result;
1129     }
1130     
1131     bool hasInlineCapacity()
1132     {
1133         return op() == CreateThis;
1134     }
1135
1136     unsigned inlineCapacity()
1137     {
1138         ASSERT(hasInlineCapacity());
1139         return m_opInfo.as<unsigned>();
1140     }
1141
1142     void setIndexingType(IndexingType indexingType)
1143     {
1144         ASSERT(hasIndexingType());
1145         m_opInfo = indexingType;
1146     }
1147     
1148     bool hasScopeOffset()
1149     {
1150         return op() == GetClosureVar || op() == PutClosureVar;
1151     }
1152
1153     ScopeOffset scopeOffset()
1154     {
1155         ASSERT(hasScopeOffset());
1156         return ScopeOffset(m_opInfo.as<uint32_t>());
1157     }
1158     
1159     bool hasDirectArgumentsOffset()
1160     {
1161         return op() == GetFromArguments || op() == PutToArguments;
1162     }
1163     
1164     DirectArgumentsOffset capturedArgumentsOffset()
1165     {
1166         ASSERT(hasDirectArgumentsOffset());
1167         return DirectArgumentsOffset(m_opInfo.as<uint32_t>());
1168     }
1169     
1170     bool hasRegisterPointer()
1171     {
1172         return op() == GetGlobalVar || op() == GetGlobalLexicalVariable || op() == PutGlobalVariable;
1173     }
1174     
1175     WriteBarrier<Unknown>* variablePointer()
1176     {
1177         return m_opInfo.as<WriteBarrier<Unknown>*>();
1178     }
1179     
1180     bool hasCallVarargsData()
1181     {
1182         switch (op()) {
1183         case CallVarargs:
1184         case CallForwardVarargs:
1185         case TailCallVarargs:
1186         case TailCallForwardVarargs:
1187         case TailCallVarargsInlinedCaller:
1188         case TailCallForwardVarargsInlinedCaller:
1189         case ConstructVarargs:
1190         case ConstructForwardVarargs:
1191             return true;
1192         default:
1193             return false;
1194         }
1195     }
1196     
1197     CallVarargsData* callVarargsData()
1198     {
1199         ASSERT(hasCallVarargsData());
1200         return m_opInfo.as<CallVarargsData*>();
1201     }
1202     
1203     bool hasLoadVarargsData()
1204     {
1205         return op() == LoadVarargs || op() == ForwardVarargs;
1206     }
1207     
1208     LoadVarargsData* loadVarargsData()
1209     {
1210         ASSERT(hasLoadVarargsData());
1211         return m_opInfo.as<LoadVarargsData*>();
1212     }
1213
1214     bool hasQueriedType()
1215     {
1216         return op() == IsCellWithType;
1217     }
1218
1219     JSType queriedType()
1220     {
1221         static_assert(std::is_same<uint8_t, std::underlying_type<JSType>::type>::value, "Ensure that uint8_t is the underlying type for JSType.");
1222         return static_cast<JSType>(m_opInfo.as<uint32_t>());
1223     }
1224
1225     bool hasSpeculatedTypeForQuery()
1226     {
1227         return op() == IsCellWithType;
1228     }
1229
1230     SpeculatedType speculatedTypeForQuery()
1231     {
1232         return speculationFromJSType(queriedType());
1233     }
1234     
1235     bool hasResult()
1236     {
1237         return !!result();
1238     }
1239     
1240     bool hasInt52Result()
1241     {
1242         return result() == NodeResultInt52;
1243     }
1244     
1245     bool hasNumberResult()
1246     {
1247         return result() == NodeResultNumber;
1248     }
1249     
1250     bool hasDoubleResult()
1251     {
1252         return result() == NodeResultDouble;
1253     }
1254     
1255     bool hasJSResult()
1256     {
1257         return result() == NodeResultJS;
1258     }
1259     
1260     bool hasBooleanResult()
1261     {
1262         return result() == NodeResultBoolean;
1263     }
1264
1265     bool hasStorageResult()
1266     {
1267         return result() == NodeResultStorage;
1268     }
1269     
1270     UseKind defaultUseKind()
1271     {
1272         return useKindForResult(result());
1273     }
1274     
1275     Edge defaultEdge()
1276     {
1277         return Edge(this, defaultUseKind());
1278     }
1279
1280     bool isJump()
1281     {
1282         return op() == Jump;
1283     }
1284
1285     bool isBranch()
1286     {
1287         return op() == Branch;
1288     }
1289     
1290     bool isSwitch()
1291     {
1292         return op() == Switch;
1293     }
1294
1295     bool isTerminal()
1296     {
1297         switch (op()) {
1298         case Jump:
1299         case Branch:
1300         case Switch:
1301         case Return:
1302         case TailCall:
1303         case DirectTailCall:
1304         case TailCallVarargs:
1305         case TailCallForwardVarargs:
1306         case Unreachable:
1307             return true;
1308         default:
1309             return false;
1310         }
1311     }
1312
1313     bool isFunctionTerminal()
1314     {
1315         if (isTerminal() && !numSuccessors())
1316             return true;
1317
1318         return false;
1319     }
1320
1321     // As is described in DFGNodeType.h's ForceOSRExit, this is a pseudo-terminal.
1322     // It means that execution should fall out of DFG at this point, but execution
1323     // does continue in the basic block - just in a different compiler.
1324     // FIXME: This is used for lightweight reachability decision. But this should
1325     // be replaced with AI-based reachability ideally.
1326     bool isPseudoTerminal()
1327     {
1328         switch (op()) {
1329         case ForceOSRExit:
1330         case CheckBadCell:
1331         case Throw:
1332         case ThrowStaticError:
1333             return true;
1334         default:
1335             return false;
1336         }
1337     }
1338
1339     unsigned targetBytecodeOffsetDuringParsing()
1340     {
1341         ASSERT(isJump());
1342         return m_opInfo.as<unsigned>();
1343     }
1344
1345     BasicBlock*& targetBlock()
1346     {
1347         ASSERT(isJump());
1348         return *bitwise_cast<BasicBlock**>(&m_opInfo.u.pointer);
1349     }
1350     
1351     BranchData* branchData()
1352     {
1353         ASSERT(isBranch());
1354         return m_opInfo.as<BranchData*>();
1355     }
1356     
1357     SwitchData* switchData()
1358     {
1359         ASSERT(isSwitch());
1360         return m_opInfo.as<SwitchData*>();
1361     }
1362     
1363     unsigned numSuccessors()
1364     {
1365         switch (op()) {
1366         case Jump:
1367             return 1;
1368         case Branch:
1369             return 2;
1370         case Switch:
1371             return switchData()->cases.size() + 1;
1372         default:
1373             return 0;
1374         }
1375     }
1376     
1377     BasicBlock*& successor(unsigned index)
1378     {
1379         if (isSwitch()) {
1380             if (index < switchData()->cases.size())
1381                 return switchData()->cases[index].target.block;
1382             RELEASE_ASSERT(index == switchData()->cases.size());
1383             return switchData()->fallThrough.block;
1384         }
1385         switch (index) {
1386         case 0:
1387             if (isJump())
1388                 return targetBlock();
1389             return branchData()->taken.block;
1390         case 1:
1391             return branchData()->notTaken.block;
1392         default:
1393             RELEASE_ASSERT_NOT_REACHED();
1394             return targetBlock();
1395         }
1396     }
1397     
1398     class SuccessorsIterable {
1399     public:
1400         SuccessorsIterable()
1401             : m_terminal(nullptr)
1402         {
1403         }
1404         
1405         SuccessorsIterable(Node* terminal)
1406             : m_terminal(terminal)
1407         {
1408         }
1409         
1410         class iterator {
1411         public:
1412             iterator()
1413                 : m_terminal(nullptr)
1414                 , m_index(UINT_MAX)
1415             {
1416             }
1417             
1418             iterator(Node* terminal, unsigned index)
1419                 : m_terminal(terminal)
1420                 , m_index(index)
1421             {
1422             }
1423             
1424             BasicBlock* operator*()
1425             {
1426                 return m_terminal->successor(m_index);
1427             }
1428             
1429             iterator& operator++()
1430             {
1431                 m_index++;
1432                 return *this;
1433             }
1434             
1435             bool operator==(const iterator& other) const
1436             {
1437                 return m_index == other.m_index;
1438             }
1439             
1440             bool operator!=(const iterator& other) const
1441             {
1442                 return !(*this == other);
1443             }
1444         private:
1445             Node* m_terminal;
1446             unsigned m_index;
1447         };
1448         
1449         iterator begin()
1450         {
1451             return iterator(m_terminal, 0);
1452         }
1453         
1454         iterator end()
1455         {
1456             return iterator(m_terminal, m_terminal->numSuccessors());
1457         }
1458
1459         size_t size() const { return m_terminal->numSuccessors(); }
1460         BasicBlock* at(size_t index) const { return m_terminal->successor(index); }
1461         BasicBlock* operator[](size_t index) const { return at(index); }
1462         
1463     private:
1464         Node* m_terminal;
1465     };
1466     
1467     SuccessorsIterable successors()
1468     {
1469         return SuccessorsIterable(this);
1470     }
1471     
1472     BasicBlock*& successorForCondition(bool condition)
1473     {
1474         return branchData()->forCondition(condition);
1475     }
1476     
1477     bool hasHeapPrediction()
1478     {
1479         switch (op()) {
1480         case ArithAbs:
1481         case ArithRound:
1482         case ArithFloor:
1483         case ArithCeil:
1484         case ArithTrunc:
1485         case GetDirectPname:
1486         case GetById:
1487         case GetByIdFlush:
1488         case GetByIdWithThis:
1489         case TryGetById:
1490         case GetByVal:
1491         case GetByValWithThis:
1492         case Call:
1493         case DirectCall:
1494         case TailCallInlinedCaller:
1495         case DirectTailCallInlinedCaller:
1496         case Construct:
1497         case DirectConstruct:
1498         case CallVarargs:
1499         case CallEval:
1500         case TailCallVarargsInlinedCaller:
1501         case ConstructVarargs:
1502         case CallForwardVarargs:
1503         case TailCallForwardVarargsInlinedCaller:
1504         case GetByOffset:
1505         case MultiGetByOffset:
1506         case GetClosureVar:
1507         case GetFromArguments:
1508         case GetArgument:
1509         case ArrayPop:
1510         case ArrayPush:
1511         case RegExpExec:
1512         case RegExpTest:
1513         case GetGlobalVar:
1514         case GetGlobalLexicalVariable:
1515         case StringReplace:
1516         case StringReplaceRegExp:
1517         case ToNumber:
1518         case LoadFromJSMapBucket:
1519         case CallDOMGetter:
1520         case CallDOM:
1521         case ParseInt:
1522         case AtomicsAdd:
1523         case AtomicsAnd:
1524         case AtomicsCompareExchange:
1525         case AtomicsExchange:
1526         case AtomicsLoad:
1527         case AtomicsOr:
1528         case AtomicsStore:
1529         case AtomicsSub:
1530         case AtomicsXor:
1531         case GetDynamicVar:
1532             return true;
1533         default:
1534             return false;
1535         }
1536     }
1537     
1538     SpeculatedType getHeapPrediction()
1539     {
1540         ASSERT(hasHeapPrediction());
1541         return m_opInfo2.as<SpeculatedType>();
1542     }
1543
1544     void setHeapPrediction(SpeculatedType prediction)
1545     {
1546         ASSERT(hasHeapPrediction());
1547         m_opInfo2 = prediction;
1548     }
1549
1550     SpeculatedType getForcedPrediction()
1551     {
1552         ASSERT(op() == IdentityWithProfile);
1553         return m_opInfo.as<SpeculatedType>();
1554     }
1555     
1556     bool hasCellOperand()
1557     {
1558         switch (op()) {
1559         case CheckCell:
1560         case OverridesHasInstance:
1561         case NewFunction:
1562         case NewGeneratorFunction:
1563         case NewAsyncFunction:
1564         case NewAsyncGeneratorFunction:
1565         case CreateActivation:
1566         case MaterializeCreateActivation:
1567         case NewRegexp:
1568         case CompareEqPtr:
1569         case DirectCall:
1570         case DirectTailCall:
1571         case DirectConstruct:
1572         case DirectTailCallInlinedCaller:
1573             return true;
1574         default:
1575             return false;
1576         }
1577     }
1578
1579     FrozenValue* cellOperand()
1580     {
1581         ASSERT(hasCellOperand());
1582         return m_opInfo.as<FrozenValue*>();
1583     }
1584     
1585     template<typename T>
1586     T castOperand()
1587     {
1588         return cellOperand()->cast<T>();
1589     }
1590     
1591     void setCellOperand(FrozenValue* value)
1592     {
1593         ASSERT(hasCellOperand());
1594         m_opInfo = value;
1595     }
1596     
1597     bool hasWatchpointSet()
1598     {
1599         return op() == NotifyWrite;
1600     }
1601     
1602     WatchpointSet* watchpointSet()
1603     {
1604         ASSERT(hasWatchpointSet());
1605         return m_opInfo.as<WatchpointSet*>();
1606     }
1607     
1608     bool hasStoragePointer()
1609     {
1610         return op() == ConstantStoragePointer;
1611     }
1612     
1613     void* storagePointer()
1614     {
1615         ASSERT(hasStoragePointer());
1616         return m_opInfo.as<void*>();
1617     }
1618
1619     bool hasUidOperand()
1620     {
1621         return op() == CheckStringIdent;
1622     }
1623
1624     UniquedStringImpl* uidOperand()
1625     {
1626         ASSERT(hasUidOperand());
1627         return m_opInfo.as<UniquedStringImpl*>();
1628     }
1629
1630     bool hasTypeInfoOperand()
1631     {
1632         return op() == CheckTypeInfoFlags;
1633     }
1634
1635     unsigned typeInfoOperand()
1636     {
1637         ASSERT(hasTypeInfoOperand() && m_opInfo.as<uint32_t>() <= static_cast<uint32_t>(UCHAR_MAX));
1638         return m_opInfo.as<uint32_t>();
1639     }
1640
1641     bool hasTransition()
1642     {
1643         switch (op()) {
1644         case PutStructure:
1645         case AllocatePropertyStorage:
1646         case ReallocatePropertyStorage:
1647             return true;
1648         default:
1649             return false;
1650         }
1651     }
1652     
1653     Transition* transition()
1654     {
1655         ASSERT(hasTransition());
1656         return m_opInfo.as<Transition*>();
1657     }
1658     
1659     bool hasStructureSet()
1660     {
1661         switch (op()) {
1662         case CheckStructure:
1663         case CheckStructureImmediate:
1664         case MaterializeNewObject:
1665             return true;
1666         default:
1667             return false;
1668         }
1669     }
1670     
1671     const RegisteredStructureSet& structureSet()
1672     {
1673         ASSERT(hasStructureSet());
1674         return *m_opInfo.as<RegisteredStructureSet*>();
1675     }
1676     
1677     bool hasStructure()
1678     {
1679         switch (op()) {
1680         case ArrayifyToStructure:
1681         case NewObject:
1682         case NewStringObject:
1683             return true;
1684         default:
1685             return false;
1686         }
1687     }
1688     
1689     RegisteredStructure structure()
1690     {
1691         ASSERT(hasStructure());
1692         return m_opInfo.asRegisteredStructure();
1693     }
1694     
1695     bool hasStorageAccessData()
1696     {
1697         switch (op()) {
1698         case GetByOffset:
1699         case PutByOffset:
1700         case GetGetterSetterByOffset:
1701             return true;
1702         default:
1703             return false;
1704         }
1705     }
1706     
1707     StorageAccessData& storageAccessData()
1708     {
1709         ASSERT(hasStorageAccessData());
1710         return *m_opInfo.as<StorageAccessData*>();
1711     }
1712     
1713     bool hasMultiGetByOffsetData()
1714     {
1715         return op() == MultiGetByOffset;
1716     }
1717     
1718     MultiGetByOffsetData& multiGetByOffsetData()
1719     {
1720         ASSERT(hasMultiGetByOffsetData());
1721         return *m_opInfo.as<MultiGetByOffsetData*>();
1722     }
1723     
1724     bool hasMultiPutByOffsetData()
1725     {
1726         return op() == MultiPutByOffset;
1727     }
1728     
1729     MultiPutByOffsetData& multiPutByOffsetData()
1730     {
1731         ASSERT(hasMultiPutByOffsetData());
1732         return *m_opInfo.as<MultiPutByOffsetData*>();
1733     }
1734     
1735     bool hasObjectMaterializationData()
1736     {
1737         switch (op()) {
1738         case MaterializeNewObject:
1739         case MaterializeCreateActivation:
1740             return true;
1741
1742         default:
1743             return false;
1744         }
1745     }
1746     
1747     ObjectMaterializationData& objectMaterializationData()
1748     {
1749         ASSERT(hasObjectMaterializationData());
1750         return *m_opInfo2.as<ObjectMaterializationData*>();
1751     }
1752
1753     bool isObjectAllocation()
1754     {
1755         switch (op()) {
1756         case NewObject:
1757         case MaterializeNewObject:
1758             return true;
1759         default:
1760             return false;
1761         }
1762     }
1763     
1764     bool isPhantomObjectAllocation()
1765     {
1766         switch (op()) {
1767         case PhantomNewObject:
1768             return true;
1769         default:
1770             return false;
1771         }
1772     }
1773     
1774     bool isActivationAllocation()
1775     {
1776         switch (op()) {
1777         case CreateActivation:
1778         case MaterializeCreateActivation:
1779             return true;
1780         default:
1781             return false;
1782         }
1783     }
1784
1785     bool isPhantomActivationAllocation()
1786     {
1787         switch (op()) {
1788         case PhantomCreateActivation:
1789             return true;
1790         default:
1791             return false;
1792         }
1793     }
1794
1795     bool isFunctionAllocation()
1796     {
1797         switch (op()) {
1798         case NewFunction:
1799         case NewGeneratorFunction:
1800         case NewAsyncGeneratorFunction:
1801         case NewAsyncFunction:
1802             return true;
1803         default:
1804             return false;
1805         }
1806     }
1807
1808     bool isPhantomFunctionAllocation()
1809     {
1810         switch (op()) {
1811         case PhantomNewFunction:
1812         case PhantomNewGeneratorFunction:
1813         case PhantomNewAsyncFunction:
1814         case PhantomNewAsyncGeneratorFunction:
1815             return true;
1816         default:
1817             return false;
1818         }
1819     }
1820
1821     bool isPhantomAllocation()
1822     {
1823         switch (op()) {
1824         case PhantomNewObject:
1825         case PhantomDirectArguments:
1826         case PhantomCreateRest:
1827         case PhantomSpread:
1828         case PhantomNewArrayWithSpread:
1829         case PhantomClonedArguments:
1830         case PhantomNewFunction:
1831         case PhantomNewGeneratorFunction:
1832         case PhantomNewAsyncFunction:
1833         case PhantomNewAsyncGeneratorFunction:
1834         case PhantomCreateActivation:
1835             return true;
1836         default:
1837             return false;
1838         }
1839     }
1840     
1841     bool hasArrayMode()
1842     {
1843         switch (op()) {
1844         case GetIndexedPropertyStorage:
1845         case GetArrayLength:
1846         case GetVectorLength:
1847         case In:
1848         case PutByValDirect:
1849         case PutByVal:
1850         case PutByValAlias:
1851         case GetByVal:
1852         case StringCharAt:
1853         case StringCharCodeAt:
1854         case CheckArray:
1855         case Arrayify:
1856         case ArrayifyToStructure:
1857         case ArrayPush:
1858         case ArrayPop:
1859         case ArrayIndexOf:
1860         case HasIndexedProperty:
1861         case AtomicsAdd:
1862         case AtomicsAnd:
1863         case AtomicsCompareExchange:
1864         case AtomicsExchange:
1865         case AtomicsLoad:
1866         case AtomicsOr:
1867         case AtomicsStore:
1868         case AtomicsSub:
1869         case AtomicsXor:
1870             return true;
1871         default:
1872             return false;
1873         }
1874     }
1875     
1876     ArrayMode arrayMode()
1877     {
1878         ASSERT(hasArrayMode());
1879         if (op() == ArrayifyToStructure)
1880             return ArrayMode::fromWord(m_opInfo2.as<uint32_t>());
1881         return ArrayMode::fromWord(m_opInfo.as<uint32_t>());
1882     }
1883     
1884     bool setArrayMode(ArrayMode arrayMode)
1885     {
1886         ASSERT(hasArrayMode());
1887         if (this->arrayMode() == arrayMode)
1888             return false;
1889         m_opInfo = arrayMode.asWord();
1890         return true;
1891     }
1892     
1893     bool hasArithMode()
1894     {
1895         switch (op()) {
1896         case ArithAbs:
1897         case ArithAdd:
1898         case ArithSub:
1899         case ArithNegate:
1900         case ArithMul:
1901         case ArithDiv:
1902         case ArithMod:
1903         case UInt32ToNumber:
1904         case DoubleAsInt32:
1905             return true;
1906         default:
1907             return false;
1908         }
1909     }
1910
1911     Arith::Mode arithMode()
1912     {
1913         ASSERT(hasArithMode());
1914         return static_cast<Arith::Mode>(m_opInfo.as<uint32_t>());
1915     }
1916     
1917     void setArithMode(Arith::Mode mode)
1918     {
1919         m_opInfo = mode;
1920     }
1921
1922     bool hasArithRoundingMode()
1923     {
1924         return op() == ArithRound || op() == ArithFloor || op() == ArithCeil || op() == ArithTrunc;
1925     }
1926
1927     Arith::RoundingMode arithRoundingMode()
1928     {
1929         ASSERT(hasArithRoundingMode());
1930         return static_cast<Arith::RoundingMode>(m_opInfo.as<uint32_t>());
1931     }
1932
1933     void setArithRoundingMode(Arith::RoundingMode mode)
1934     {
1935         ASSERT(hasArithRoundingMode());
1936         m_opInfo = static_cast<uint32_t>(mode);
1937     }
1938
1939     bool hasArithUnaryType()
1940     {
1941         return op() == ArithUnary;
1942     }
1943
1944     Arith::UnaryType arithUnaryType()
1945     {
1946         ASSERT(hasArithUnaryType());
1947         return static_cast<Arith::UnaryType>(m_opInfo.as<uint32_t>());
1948     }
1949     
1950     bool hasVirtualRegister()
1951     {
1952         return m_virtualRegister.isValid();
1953     }
1954     
1955     VirtualRegister virtualRegister()
1956     {
1957         ASSERT(hasResult());
1958         ASSERT(m_virtualRegister.isValid());
1959         return m_virtualRegister;
1960     }
1961     
1962     void setVirtualRegister(VirtualRegister virtualRegister)
1963     {
1964         ASSERT(hasResult());
1965         ASSERT(!m_virtualRegister.isValid());
1966         m_virtualRegister = virtualRegister;
1967     }
1968     
1969     bool hasExecutionCounter()
1970     {
1971         return op() == CountExecution;
1972     }
1973     
1974     Profiler::ExecutionCounter* executionCounter()
1975     {
1976         return m_opInfo.as<Profiler::ExecutionCounter*>();
1977     }
1978
1979     bool shouldGenerate()
1980     {
1981         return m_refCount;
1982     }
1983     
1984     // Return true if the execution of this Node does not affect our ability to OSR to the FTL.
1985     // FIXME: Isn't this just like checking if the node has effects?
1986     bool isSemanticallySkippable()
1987     {
1988         return op() == CountExecution || op() == InvalidationPoint;
1989     }
1990
1991     unsigned refCount()
1992     {
1993         return m_refCount;
1994     }
1995
1996     unsigned postfixRef()
1997     {
1998         return m_refCount++;
1999     }
2000
2001     unsigned adjustedRefCount()
2002     {
2003         return mustGenerate() ? m_refCount - 1 : m_refCount;
2004     }
2005     
2006     void setRefCount(unsigned refCount)
2007     {
2008         m_refCount = refCount;
2009     }
2010     
2011     Edge& child1()
2012     {
2013         ASSERT(!(m_flags & NodeHasVarArgs));
2014         return children.child1();
2015     }
2016     
2017     // This is useful if you want to do a fast check on the first child
2018     // before also doing a check on the opcode. Use this with care and
2019     // avoid it if possible.
2020     Edge child1Unchecked()
2021     {
2022         return children.child1Unchecked();
2023     }
2024
2025     Edge& child2()
2026     {
2027         ASSERT(!(m_flags & NodeHasVarArgs));
2028         return children.child2();
2029     }
2030
2031     Edge& child3()
2032     {
2033         ASSERT(!(m_flags & NodeHasVarArgs));
2034         return children.child3();
2035     }
2036     
2037     unsigned firstChild()
2038     {
2039         ASSERT(m_flags & NodeHasVarArgs);
2040         return children.firstChild();
2041     }
2042     
2043     unsigned numChildren()
2044     {
2045         ASSERT(m_flags & NodeHasVarArgs);
2046         return children.numChildren();
2047     }
2048     
2049     UseKind binaryUseKind()
2050     {
2051         ASSERT(child1().useKind() == child2().useKind());
2052         return child1().useKind();
2053     }
2054     
2055     bool isBinaryUseKind(UseKind left, UseKind right)
2056     {
2057         return child1().useKind() == left && child2().useKind() == right;
2058     }
2059     
2060     bool isBinaryUseKind(UseKind useKind)
2061     {
2062         return isBinaryUseKind(useKind, useKind);
2063     }
2064     
2065     Edge childFor(UseKind useKind)
2066     {
2067         if (child1().useKind() == useKind)
2068             return child1();
2069         if (child2().useKind() == useKind)
2070             return child2();
2071         if (child3().useKind() == useKind)
2072             return child3();
2073         return Edge();
2074     }
2075     
2076     SpeculatedType prediction()
2077     {
2078         return m_prediction;
2079     }
2080     
2081     bool predict(SpeculatedType prediction)
2082     {
2083         return mergeSpeculation(m_prediction, prediction);
2084     }
2085     
2086     bool shouldSpeculateInt32()
2087     {
2088         return isInt32Speculation(prediction());
2089     }
2090
2091     bool shouldSpeculateNotInt32()
2092     {
2093         return isNotInt32Speculation(prediction());
2094     }
2095     
2096     bool sawBooleans()
2097     {
2098         return !!(prediction() & SpecBoolean);
2099     }
2100     
2101     bool shouldSpeculateInt32OrBoolean()
2102     {
2103         return isInt32OrBooleanSpeculation(prediction());
2104     }
2105     
2106     bool shouldSpeculateInt32ForArithmetic()
2107     {
2108         return isInt32SpeculationForArithmetic(prediction());
2109     }
2110     
2111     bool shouldSpeculateInt32OrBooleanForArithmetic()
2112     {
2113         return isInt32OrBooleanSpeculationForArithmetic(prediction());
2114     }
2115     
2116     bool shouldSpeculateInt32OrBooleanExpectingDefined()
2117     {
2118         return isInt32OrBooleanSpeculationExpectingDefined(prediction());
2119     }
2120     
2121     bool shouldSpeculateAnyInt()
2122     {
2123         return isAnyIntSpeculation(prediction());
2124     }
2125     
2126     bool shouldSpeculateDouble()
2127     {
2128         return isDoubleSpeculation(prediction());
2129     }
2130     
2131     bool shouldSpeculateDoubleReal()
2132     {
2133         return isDoubleRealSpeculation(prediction());
2134     }
2135     
2136     bool shouldSpeculateNumber()
2137     {
2138         return isFullNumberSpeculation(prediction());
2139     }
2140     
2141     bool shouldSpeculateNumberOrBoolean()
2142     {
2143         return isFullNumberOrBooleanSpeculation(prediction());
2144     }
2145     
2146     bool shouldSpeculateNumberOrBooleanExpectingDefined()
2147     {
2148         return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
2149     }
2150     
2151     bool shouldSpeculateBoolean()
2152     {
2153         return isBooleanSpeculation(prediction());
2154     }
2155
2156     bool shouldSpeculateNotBoolean()
2157     {
2158         return isNotBooleanSpeculation(prediction());
2159     }
2160     
2161     bool shouldSpeculateOther()
2162     {
2163         return isOtherSpeculation(prediction());
2164     }
2165     
2166     bool shouldSpeculateMisc()
2167     {
2168         return isMiscSpeculation(prediction());
2169     }
2170    
2171     bool shouldSpeculateStringIdent()
2172     {
2173         return isStringIdentSpeculation(prediction());
2174     }
2175     
2176     bool shouldSpeculateNotStringVar()
2177     {
2178         return isNotStringVarSpeculation(prediction());
2179     }
2180  
2181     bool shouldSpeculateString()
2182     {
2183         return isStringSpeculation(prediction());
2184     }
2185
2186     bool shouldSpeculateNotString()
2187     {
2188         return isNotStringSpeculation(prediction());
2189     }
2190  
2191     bool shouldSpeculateStringOrOther()
2192     {
2193         return isStringOrOtherSpeculation(prediction());
2194     }
2195  
2196     bool shouldSpeculateStringObject()
2197     {
2198         return isStringObjectSpeculation(prediction());
2199     }
2200     
2201     bool shouldSpeculateStringOrStringObject()
2202     {
2203         return isStringOrStringObjectSpeculation(prediction());
2204     }
2205
2206     bool shouldSpeculateRegExpObject()
2207     {
2208         return isRegExpObjectSpeculation(prediction());
2209     }
2210     
2211     bool shouldSpeculateSymbol()
2212     {
2213         return isSymbolSpeculation(prediction());
2214     }
2215     
2216     bool shouldSpeculateFinalObject()
2217     {
2218         return isFinalObjectSpeculation(prediction());
2219     }
2220     
2221     bool shouldSpeculateFinalObjectOrOther()
2222     {
2223         return isFinalObjectOrOtherSpeculation(prediction());
2224     }
2225     
2226     bool shouldSpeculateArray()
2227     {
2228         return isArraySpeculation(prediction());
2229     }
2230
2231     bool shouldSpeculateProxyObject()
2232     {
2233         return isProxyObjectSpeculation(prediction());
2234     }
2235
2236     bool shouldSpeculateDerivedArray()
2237     {
2238         return isDerivedArraySpeculation(prediction());
2239     }
2240     
2241     bool shouldSpeculateDirectArguments()
2242     {
2243         return isDirectArgumentsSpeculation(prediction());
2244     }
2245     
2246     bool shouldSpeculateScopedArguments()
2247     {
2248         return isScopedArgumentsSpeculation(prediction());
2249     }
2250     
2251     bool shouldSpeculateInt8Array()
2252     {
2253         return isInt8ArraySpeculation(prediction());
2254     }
2255     
2256     bool shouldSpeculateInt16Array()
2257     {
2258         return isInt16ArraySpeculation(prediction());
2259     }
2260     
2261     bool shouldSpeculateInt32Array()
2262     {
2263         return isInt32ArraySpeculation(prediction());
2264     }
2265     
2266     bool shouldSpeculateUint8Array()
2267     {
2268         return isUint8ArraySpeculation(prediction());
2269     }
2270
2271     bool shouldSpeculateUint8ClampedArray()
2272     {
2273         return isUint8ClampedArraySpeculation(prediction());
2274     }
2275     
2276     bool shouldSpeculateUint16Array()
2277     {
2278         return isUint16ArraySpeculation(prediction());
2279     }
2280     
2281     bool shouldSpeculateUint32Array()
2282     {
2283         return isUint32ArraySpeculation(prediction());
2284     }
2285     
2286     bool shouldSpeculateFloat32Array()
2287     {
2288         return isFloat32ArraySpeculation(prediction());
2289     }
2290     
2291     bool shouldSpeculateFloat64Array()
2292     {
2293         return isFloat64ArraySpeculation(prediction());
2294     }
2295     
2296     bool shouldSpeculateArrayOrOther()
2297     {
2298         return isArrayOrOtherSpeculation(prediction());
2299     }
2300     
2301     bool shouldSpeculateObject()
2302     {
2303         return isObjectSpeculation(prediction());
2304     }
2305     
2306     bool shouldSpeculateObjectOrOther()
2307     {
2308         return isObjectOrOtherSpeculation(prediction());
2309     }
2310
2311     bool shouldSpeculateCell()
2312     {
2313         return isCellSpeculation(prediction());
2314     }
2315     
2316     bool shouldSpeculateCellOrOther()
2317     {
2318         return isCellOrOtherSpeculation(prediction());
2319     }
2320     
2321     bool shouldSpeculateNotCell()
2322     {
2323         return isNotCellSpeculation(prediction());
2324     }
2325     
2326     bool shouldSpeculateUntypedForArithmetic()
2327     {
2328         return isUntypedSpeculationForArithmetic(prediction());
2329     }
2330
2331     static bool shouldSpeculateUntypedForArithmetic(Node* op1, Node* op2)
2332     {
2333         return op1->shouldSpeculateUntypedForArithmetic() || op2->shouldSpeculateUntypedForArithmetic();
2334     }
2335     
2336     bool shouldSpeculateUntypedForBitOps()
2337     {
2338         return isUntypedSpeculationForBitOps(prediction());
2339     }
2340     
2341     static bool shouldSpeculateUntypedForBitOps(Node* op1, Node* op2)
2342     {
2343         return op1->shouldSpeculateUntypedForBitOps() || op2->shouldSpeculateUntypedForBitOps();
2344     }
2345     
2346     static bool shouldSpeculateBoolean(Node* op1, Node* op2)
2347     {
2348         return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
2349     }
2350     
2351     static bool shouldSpeculateInt32(Node* op1, Node* op2)
2352     {
2353         return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
2354     }
2355     
2356     static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
2357     {
2358         return op1->shouldSpeculateInt32OrBoolean()
2359             && op2->shouldSpeculateInt32OrBoolean();
2360     }
2361     
2362     static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
2363     {
2364         return op1->shouldSpeculateInt32OrBooleanForArithmetic()
2365             && op2->shouldSpeculateInt32OrBooleanForArithmetic();
2366     }
2367     
2368     static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
2369     {
2370         return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
2371             && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
2372     }
2373     
2374     static bool shouldSpeculateAnyInt(Node* op1, Node* op2)
2375     {
2376         return op1->shouldSpeculateAnyInt() && op2->shouldSpeculateAnyInt();
2377     }
2378     
2379     static bool shouldSpeculateNumber(Node* op1, Node* op2)
2380     {
2381         return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
2382     }
2383     
2384     static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2)
2385     {
2386         return op1->shouldSpeculateNumberOrBoolean()
2387             && op2->shouldSpeculateNumberOrBoolean();
2388     }
2389     
2390     static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2)
2391     {
2392         return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
2393             && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
2394     }
2395
2396     static bool shouldSpeculateSymbol(Node* op1, Node* op2)
2397     {
2398         return op1->shouldSpeculateSymbol() && op2->shouldSpeculateSymbol();
2399     }
2400     
2401     static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
2402     {
2403         return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
2404     }
2405
2406     static bool shouldSpeculateArray(Node* op1, Node* op2)
2407     {
2408         return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
2409     }
2410     
2411     bool canSpeculateInt32(RareCaseProfilingSource source)
2412     {
2413         return nodeCanSpeculateInt32(arithNodeFlags(), source);
2414     }
2415     
2416     bool canSpeculateInt52(RareCaseProfilingSource source)
2417     {
2418         return nodeCanSpeculateInt52(arithNodeFlags(), source);
2419     }
2420     
2421     RareCaseProfilingSource sourceFor(PredictionPass pass)
2422     {
2423         if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
2424             return DFGRareCase;
2425         return AllRareCases;
2426     }
2427     
2428     bool canSpeculateInt32(PredictionPass pass)
2429     {
2430         return canSpeculateInt32(sourceFor(pass));
2431     }
2432     
2433     bool canSpeculateInt52(PredictionPass pass)
2434     {
2435         return canSpeculateInt52(sourceFor(pass));
2436     }
2437
2438     bool hasTypeLocation()
2439     {
2440         return op() == ProfileType;
2441     }
2442
2443     TypeLocation* typeLocation()
2444     {
2445         ASSERT(hasTypeLocation());
2446         return m_opInfo.as<TypeLocation*>();
2447     }
2448
2449     bool hasBasicBlockLocation()
2450     {
2451         return op() == ProfileControlFlow;
2452     }
2453
2454     BasicBlockLocation* basicBlockLocation()
2455     {
2456         ASSERT(hasBasicBlockLocation());
2457         return m_opInfo.as<BasicBlockLocation*>();
2458     }
2459
2460     bool hasCallDOMGetterData() const
2461     {
2462         return op() == CallDOMGetter;
2463     }
2464
2465     CallDOMGetterData* callDOMGetterData()
2466     {
2467         ASSERT(hasCallDOMGetterData());
2468         return m_opInfo.as<CallDOMGetterData*>();
2469     }
2470
2471     bool hasClassInfo() const
2472     {
2473         return op() == CheckSubClass;
2474     }
2475
2476     const ClassInfo* classInfo()
2477     {
2478         return m_opInfo.as<const ClassInfo*>();
2479     }
2480
2481     bool hasSignature() const
2482     {
2483         // Note that this does not include TailCall node types intentionally.
2484         // CallDOM node types are always converted from Call.
2485         return op() == Call || op() == CallDOM;
2486     }
2487
2488     const DOMJIT::Signature* signature()
2489     {
2490         return m_opInfo.as<const DOMJIT::Signature*>();
2491     }
2492
2493     bool hasInternalMethodType() const
2494     {
2495         return op() == HasIndexedProperty;
2496     }
2497
2498     PropertySlot::InternalMethodType internalMethodType() const
2499     {
2500         ASSERT(hasInternalMethodType());
2501         return static_cast<PropertySlot::InternalMethodType>(m_opInfo2.as<uint32_t>());
2502     }
2503
2504     void setInternalMethodType(PropertySlot::InternalMethodType type)
2505     {
2506         ASSERT(hasInternalMethodType());
2507         m_opInfo2 = static_cast<uint32_t>(type);
2508     }
2509
2510     Node* replacement() const
2511     {
2512         return m_misc.replacement;
2513     }
2514     
2515     void setReplacement(Node* replacement)
2516     {
2517         m_misc.replacement = replacement;
2518     }
2519     
2520     Epoch epoch() const
2521     {
2522         return Epoch::fromUnsigned(m_misc.epoch);
2523     }
2524     
2525     void setEpoch(Epoch epoch)
2526     {
2527         m_misc.epoch = epoch.toUnsigned();
2528     }
2529
2530     unsigned numberOfArgumentsToSkip()
2531     {
2532         ASSERT(op() == CreateRest || op() == PhantomCreateRest || op() == GetRestLength || op() == GetMyArgumentByVal || op() == GetMyArgumentByValOutOfBounds);
2533         return m_opInfo.as<unsigned>();
2534     }
2535
2536     bool hasArgumentIndex()
2537     {
2538         return op() == GetArgument;
2539     }
2540
2541     unsigned argumentIndex()
2542     {
2543         ASSERT(hasArgumentIndex());
2544         return m_opInfo.as<unsigned>();
2545     }
2546
2547     void dumpChildren(PrintStream& out)
2548     {
2549         if (!child1())
2550             return;
2551         out.printf("@%u", child1()->index());
2552         if (!child2())
2553             return;
2554         out.printf(", @%u", child2()->index());
2555         if (!child3())
2556             return;
2557         out.printf(", @%u", child3()->index());
2558     }
2559     
2560     // NB. This class must have a trivial destructor.
2561
2562     NodeOrigin origin;
2563
2564     // References to up to 3 children, or links to a variable length set of children.
2565     AdjacencyList children;
2566
2567 private:
2568     friend class B3::SparseCollection<Node>;
2569
2570     unsigned m_index { std::numeric_limits<unsigned>::max() };
2571     unsigned m_op : 10; // real type is NodeType
2572     unsigned m_flags : 20;
2573     // The virtual register number (spill location) associated with this .
2574     VirtualRegister m_virtualRegister;
2575     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
2576     unsigned m_refCount;
2577     // The prediction ascribed to this node after propagation.
2578     SpeculatedType m_prediction { SpecNone };
2579     // Immediate values, accesses type-checked via accessors above.
2580     struct OpInfoWrapper {
2581         OpInfoWrapper()
2582         {
2583             u.int64 = 0;
2584         }
2585         OpInfoWrapper(uint32_t intValue)
2586         {
2587             u.int64 = 0;
2588             u.int32 = intValue;
2589         }
2590         OpInfoWrapper(uint64_t intValue)
2591         {
2592             u.int64 = intValue;
2593         }
2594         OpInfoWrapper(void* pointer)
2595         {
2596             u.int64 = 0;
2597             u.pointer = pointer;
2598         }
2599         OpInfoWrapper(const void* constPointer)
2600         {
2601             u.int64 = 0;
2602             u.constPointer = constPointer;
2603         }
2604         OpInfoWrapper(RegisteredStructure structure)
2605         {
2606             u.int64 = 0;
2607             u.pointer = bitwise_cast<void*>(structure);
2608         }
2609         OpInfoWrapper& operator=(uint32_t int32)
2610         {
2611             u.int64 = 0;
2612             u.int32 = int32;
2613             return *this;
2614         }
2615         OpInfoWrapper& operator=(int32_t int32)
2616         {
2617             u.int64 = 0;
2618             u.int32 = int32;
2619             return *this;
2620         }
2621         OpInfoWrapper& operator=(uint64_t int64)
2622         {
2623             u.int64 = int64;
2624             return *this;
2625         }
2626         OpInfoWrapper& operator=(void* pointer)
2627         {
2628             u.int64 = 0;
2629             u.pointer = pointer;
2630             return *this;
2631         }
2632         OpInfoWrapper& operator=(const void* constPointer)
2633         {
2634             u.int64 = 0;
2635             u.constPointer = constPointer;
2636             return *this;
2637         }
2638         OpInfoWrapper& operator=(RegisteredStructure structure)
2639         {
2640             u.int64 = 0;
2641             u.pointer = bitwise_cast<void*>(structure);
2642             return *this;
2643         }
2644         template <typename T>
2645         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
2646         {
2647             return static_cast<T>(u.pointer);
2648         }
2649         template <typename T>
2650         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
2651         {
2652             return static_cast<T>(u.constPointer);
2653         }
2654         template <typename T>
2655         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 4, T>::type
2656         {
2657             return u.int32;
2658         }
2659         template <typename T>
2660         ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_integral<T>::value && sizeof(T) == 8, T>::type
2661         {
2662             return u.int64;
2663         }
2664         ALWAYS_INLINE RegisteredStructure asRegisteredStructure() const
2665         {
2666             return bitwise_cast<RegisteredStructure>(u.pointer);
2667         }
2668
2669         union {
2670             uint32_t int32;
2671             uint64_t int64;
2672             void* pointer;
2673             const void* constPointer;
2674         } u;
2675     };
2676     OpInfoWrapper m_opInfo;
2677     OpInfoWrapper m_opInfo2;
2678
2679     // Miscellaneous data that is usually meaningless, but can hold some analysis results
2680     // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
2681     // will tell you which basic block a node belongs to. You cannot rely on this persisting
2682     // across transformations unless you do the maintenance work yourself. Other phases use
2683     // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
2684     // and then you set, and use, replacement's yourself. Same thing for epoch.
2685     //
2686     // Bottom line: don't use these fields unless you initialize them yourself, or by
2687     // calling some appropriate methods that initialize them the way you want. Otherwise,
2688     // these fields are meaningless.
2689 private:
2690     union {
2691         Node* replacement;
2692         unsigned epoch;
2693     } m_misc;
2694 public:
2695     BasicBlock* owner;
2696 };
2697
2698 // Uncomment this to log NodeSet operations.
2699 // typedef LoggingHashSet<Node::HashSetTemplateInstantiationString, Node*> NodeSet;
2700 typedef HashSet<Node*> NodeSet;
2701
2702 struct NodeComparator {
2703     template<typename NodePtrType>
2704     bool operator()(NodePtrType a, NodePtrType b) const
2705     {
2706         return a->index() < b->index();
2707     }
2708 };
2709
2710 template<typename T>
2711 CString nodeListDump(const T& nodeList)
2712 {
2713     return sortedListDump(nodeList, NodeComparator());
2714 }
2715
2716 template<typename T>
2717 CString nodeMapDump(const T& nodeMap, DumpContext* context = 0)
2718 {
2719     Vector<typename T::KeyType> keys;
2720     for (
2721         typename T::const_iterator iter = nodeMap.begin();
2722         iter != nodeMap.end(); ++iter)
2723         keys.append(iter->key);
2724     std::sort(keys.begin(), keys.end(), NodeComparator());
2725     StringPrintStream out;
2726     CommaPrinter comma;
2727     for(unsigned i = 0; i < keys.size(); ++i)
2728         out.print(comma, keys[i], "=>", inContext(nodeMap.get(keys[i]), context));
2729     return out.toCString();
2730 }
2731
2732 template<typename T>
2733 CString nodeValuePairListDump(const T& nodeValuePairList, DumpContext* context = 0)
2734 {
2735     using V = typename T::ValueType;
2736     T sortedList = nodeValuePairList;
2737     std::sort(sortedList.begin(), sortedList.end(), [](const V& a, const V& b) {
2738         return NodeComparator()(a.node, b.node);
2739     });
2740
2741     StringPrintStream out;
2742     CommaPrinter comma;
2743     for (const auto& pair : sortedList)
2744         out.print(comma, pair.node, "=>", inContext(pair.value, context));
2745     return out.toCString();
2746 }
2747
2748 } } // namespace JSC::DFG
2749
2750 namespace WTF {
2751
2752 void printInternal(PrintStream&, JSC::DFG::SwitchKind);
2753 void printInternal(PrintStream&, JSC::DFG::Node*);
2754
2755 inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
2756
2757 template<>
2758 struct LoggingHashKeyTraits<JSC::DFG::Node*> {
2759     static void print(PrintStream& out, JSC::DFG::Node* key)
2760     {
2761         out.print("bitwise_cast<::JSC::DFG::Node*>(", RawPointer(key), "lu)");
2762     }
2763 };
2764
2765 } // namespace WTF
2766
2767 using WTF::inContext;
2768
2769 #endif