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