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