DFG should not speculate array even when predictions say that the base is not an...
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGNode.h
1 /*
2  * Copyright (C) 2011 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 #ifndef DFGNode_h
27 #define DFGNode_h
28
29 #include <wtf/Platform.h>
30
31 #if ENABLE(DFG_JIT)
32
33 #include "CodeBlock.h"
34 #include "CodeOrigin.h"
35 #include "DFGCommon.h"
36 #include "DFGOperands.h"
37 #include "DFGVariableAccessData.h"
38 #include "JSValue.h"
39 #include "PredictedType.h"
40 #include "ValueProfile.h"
41 #include <wtf/BoundsCheckedPointer.h>
42 #include <wtf/Vector.h>
43
44 namespace JSC { namespace DFG {
45
46 struct StructureTransitionData {
47     Structure* previousStructure;
48     Structure* newStructure;
49     
50     StructureTransitionData() { }
51     
52     StructureTransitionData(Structure* previousStructure, Structure* newStructure)
53         : previousStructure(previousStructure)
54         , newStructure(newStructure)
55     {
56     }
57 };
58
59 typedef unsigned ArithNodeFlags;
60 #define NodeUseBottom      0x00
61 #define NodeUsedAsNumber   0x01
62 #define NodeNeedsNegZero   0x02
63 #define NodeUsedAsMask     0x03
64 #define NodeMayOverflow    0x04
65 #define NodeMayNegZero     0x08
66 #define NodeBehaviorMask   0x0c
67
68 static inline bool nodeUsedAsNumber(ArithNodeFlags flags)
69 {
70     return !!(flags & NodeUsedAsNumber);
71 }
72
73 static inline bool nodeCanTruncateInteger(ArithNodeFlags flags)
74 {
75     return !nodeUsedAsNumber(flags);
76 }
77
78 static inline bool nodeCanIgnoreNegativeZero(ArithNodeFlags flags)
79 {
80     return !(flags & NodeNeedsNegZero);
81 }
82
83 static inline bool nodeMayOverflow(ArithNodeFlags flags)
84 {
85     return !!(flags & NodeMayOverflow);
86 }
87
88 static inline bool nodeCanSpeculateInteger(ArithNodeFlags flags)
89 {
90     if (flags & NodeMayOverflow)
91         return !nodeUsedAsNumber(flags);
92     
93     if (flags & NodeMayNegZero)
94         return nodeCanIgnoreNegativeZero(flags);
95     
96     return true;
97 }
98
99 #ifndef NDEBUG
100 static inline const char* arithNodeFlagsAsString(ArithNodeFlags flags)
101 {
102     if (!flags)
103         return "<empty>";
104
105     static const int size = 64;
106     static char description[size];
107     BoundsCheckedPointer<char> ptr(description, size);
108     
109     bool hasPrinted = false;
110     
111     if (flags & NodeUsedAsNumber) {
112         ptr.strcat("UsedAsNum");
113         hasPrinted = true;
114     }
115     
116     if (flags & NodeNeedsNegZero) {
117         if (hasPrinted)
118             ptr.strcat("|");
119         ptr.strcat("NeedsNegZero");
120         hasPrinted = true;
121     }
122     
123     if (flags & NodeMayOverflow) {
124         if (hasPrinted)
125             ptr.strcat("|");
126         ptr.strcat("MayOverflow");
127         hasPrinted = true;
128     }
129     
130     if (flags & NodeMayNegZero) {
131         if (hasPrinted)
132             ptr.strcat("|");
133         ptr.strcat("MayNegZero");
134         hasPrinted = true;
135     }
136     
137     *ptr++ = 0;
138     
139     return description;
140 }
141 #endif
142
143 // Entries in the NodeType enum (below) are composed of an id, a result type (possibly none)
144 // and some additional informative flags (must generate, is constant, etc).
145 #define NodeIdMask           0xFFF
146 #define NodeResultMask      0xF000
147 #define NodeMustGenerate   0x10000 // set on nodes that have side effects, and may not trivially be removed by DCE.
148 #define NodeIsConstant     0x20000
149 #define NodeIsJump         0x40000
150 #define NodeIsBranch       0x80000
151 #define NodeIsTerminal    0x100000
152 #define NodeHasVarArgs    0x200000
153 #define NodeClobbersWorld 0x400000
154 #define NodeMightClobber  0x800000
155
156 // These values record the result type of the node (as checked by NodeResultMask, above), 0 for no result.
157 #define NodeResultJS        0x1000
158 #define NodeResultNumber    0x2000
159 #define NodeResultInt32     0x3000
160 #define NodeResultBoolean   0x4000
161 #define NodeResultStorage   0x5000
162
163 // This macro defines a set of information about all known node types, used to populate NodeId, NodeType below.
164 #define FOR_EACH_DFG_OP(macro) \
165     /* A constant in the CodeBlock's constant pool. */\
166     macro(JSConstant, NodeResultJS) \
167     \
168     /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\
169     /* code block. */\
170     macro(WeakJSConstant, NodeResultJS) \
171     \
172     /* Nodes for handling functions (both as call and as construct). */\
173     macro(ConvertThis, NodeResultJS) \
174     macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \
175     macro(GetCallee, NodeResultJS) \
176     \
177     /* Nodes for local variable access. */\
178     macro(GetLocal, NodeResultJS) \
179     macro(SetLocal, 0) \
180     macro(Phantom, NodeMustGenerate) \
181     macro(Nop, 0) \
182     macro(Phi, 0) \
183     macro(Flush, NodeMustGenerate) \
184     \
185     /* Marker for arguments being set. */\
186     macro(SetArgument, 0) \
187     \
188     /* Hint that inlining begins here. No code is generated for this node. It's only */\
189     /* used for copying OSR data into inline frame data, to support reification of */\
190     /* call frames of inlined functions. */\
191     macro(InlineStart, 0) \
192     \
193     /* Nodes for bitwise operations. */\
194     macro(BitAnd, NodeResultInt32) \
195     macro(BitOr, NodeResultInt32) \
196     macro(BitXor, NodeResultInt32) \
197     macro(BitLShift, NodeResultInt32) \
198     macro(BitRShift, NodeResultInt32) \
199     macro(BitURShift, NodeResultInt32) \
200     /* Bitwise operators call ToInt32 on their operands. */\
201     macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
202     /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
203     macro(UInt32ToNumber, NodeResultNumber) \
204     \
205     /* Nodes for arithmetic operations. */\
206     macro(ArithAdd, NodeResultNumber) \
207     macro(ArithSub, NodeResultNumber) \
208     macro(ArithMul, NodeResultNumber) \
209     macro(ArithDiv, NodeResultNumber) \
210     macro(ArithMod, NodeResultNumber) \
211     macro(ArithAbs, NodeResultNumber) \
212     macro(ArithMin, NodeResultNumber) \
213     macro(ArithMax, NodeResultNumber) \
214     macro(ArithSqrt, NodeResultNumber) \
215     /* Arithmetic operators call ToNumber on their operands. */\
216     macro(ValueToNumber, NodeResultNumber | NodeMustGenerate) \
217     \
218     /* A variant of ValueToNumber, which a hint that the parents will always use this as a double. */\
219     macro(ValueToDouble, NodeResultNumber | NodeMustGenerate) \
220     \
221     /* Add of values may either be arithmetic, or result in string concatenation. */\
222     macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
223     \
224     /* Property access. */\
225     /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
226     /* Since a put to 'length' may invalidate optimizations here, */\
227     /* this must be the directly subsequent property put. */\
228     macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
229     macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \
230     macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \
231     macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
232     macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
233     macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
234     macro(CheckStructure, NodeMustGenerate) \
235     macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \
236     macro(GetPropertyStorage, NodeResultStorage) \
237     macro(GetIndexedPropertyStorage, NodeMustGenerate | NodeResultStorage) \
238     macro(GetByOffset, NodeResultJS) \
239     macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \
240     macro(GetArrayLength, NodeResultInt32) \
241     macro(GetStringLength, NodeResultInt32) \
242     macro(GetByteArrayLength, NodeResultInt32) \
243     macro(GetInt8ArrayLength, NodeResultInt32) \
244     macro(GetInt16ArrayLength, NodeResultInt32) \
245     macro(GetInt32ArrayLength, NodeResultInt32) \
246     macro(GetUint8ArrayLength, NodeResultInt32) \
247     macro(GetUint16ArrayLength, NodeResultInt32) \
248     macro(GetUint32ArrayLength, NodeResultInt32) \
249     macro(GetFloat32ArrayLength, NodeResultInt32) \
250     macro(GetFloat64ArrayLength, NodeResultInt32) \
251     macro(GetScopeChain, NodeResultJS) \
252     macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \
253     macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
254     macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
255     macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
256     macro(CheckFunction, NodeMustGenerate) \
257     \
258     /* Optimizations for array mutation. */\
259     macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
260     macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
261     \
262     /* Optimizations for string access */ \
263     macro(StringCharCodeAt, NodeResultInt32) \
264     macro(StringCharAt, NodeResultJS) \
265     \
266     /* Nodes for comparison operations. */\
267     macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
268     macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
269     macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
270     macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
271     macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
272     macro(CompareStrictEq, NodeResultBoolean) \
273     \
274     /* Calls. */\
275     macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
276     macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
277     \
278     /* Allocations. */\
279     macro(NewObject, NodeResultJS) \
280     macro(NewArray, NodeResultJS | NodeHasVarArgs) \
281     macro(NewArrayBuffer, NodeResultJS) \
282     macro(NewRegexp, NodeResultJS) \
283     \
284     /* Resolve nodes. */\
285     macro(Resolve, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
286     macro(ResolveBase, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
287     macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
288     macro(ResolveGlobal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
289     \
290     /* Nodes for misc operations. */\
291     macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
292     macro(CheckHasInstance, NodeMustGenerate) \
293     macro(InstanceOf, NodeResultBoolean) \
294     macro(LogicalNot, NodeResultBoolean | NodeMightClobber) \
295     macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
296     macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
297     \
298     /* Block terminals. */\
299     macro(Jump, NodeMustGenerate | NodeIsTerminal | NodeIsJump) \
300     macro(Branch, NodeMustGenerate | NodeIsTerminal | NodeIsBranch) \
301     macro(Return, NodeMustGenerate | NodeIsTerminal) \
302     macro(Throw, NodeMustGenerate | NodeIsTerminal) \
303     macro(ThrowReferenceError, NodeMustGenerate | NodeIsTerminal) \
304     \
305     /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
306     /* this point, but execution does continue in the basic block - just in a */\
307     /* different compiler. */\
308     macro(ForceOSRExit, NodeMustGenerate)
309
310 // This enum generates a monotonically increasing id for all Node types,
311 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
312 enum NodeId {
313 #define DFG_OP_ENUM(opcode, flags) opcode##_id,
314     FOR_EACH_DFG_OP(DFG_OP_ENUM)
315 #undef DFG_OP_ENUM
316     LastNodeId
317 };
318
319 // Entries in this enum describe all Node types.
320 // The enum value contains a monotonically increasing id, a result type, and additional flags.
321 enum NodeType {
322 #define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags),
323     FOR_EACH_DFG_OP(DFG_OP_ENUM)
324 #undef DFG_OP_ENUM
325 };
326
327 // This type used in passing an immediate argument to Node constructor;
328 // distinguishes an immediate value (typically an index into a CodeBlock data structure - 
329 // a constant index, argument, or identifier) from a NodeIndex.
330 struct OpInfo {
331     explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
332     explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
333 #if OS(DARWIN) || USE(JSVALUE64)
334     explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
335 #endif
336     explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
337     uintptr_t m_value;
338 };
339
340 // === Node ===
341 //
342 // Node represents a single operation in the data flow graph.
343 struct Node {
344     enum VarArgTag { VarArg };
345
346     // Construct a node with up to 3 children, no immediate value.
347     Node(NodeType op, CodeOrigin codeOrigin, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
348         : op(op)
349         , codeOrigin(codeOrigin)
350         , m_virtualRegister(InvalidVirtualRegister)
351         , m_refCount(0)
352         , m_prediction(PredictNone)
353     {
354         ASSERT(!(op & NodeHasVarArgs));
355         ASSERT(!hasArithNodeFlags());
356         children.fixed.child1 = child1;
357         children.fixed.child2 = child2;
358         children.fixed.child3 = child3;
359     }
360
361     // Construct a node with up to 3 children and an immediate value.
362     Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
363         : op(op)
364         , codeOrigin(codeOrigin)
365         , m_virtualRegister(InvalidVirtualRegister)
366         , m_refCount(0)
367         , m_opInfo(imm.m_value)
368         , m_prediction(PredictNone)
369     {
370         ASSERT(!(op & NodeHasVarArgs));
371         children.fixed.child1 = child1;
372         children.fixed.child2 = child2;
373         children.fixed.child3 = child3;
374     }
375
376     // Construct a node with up to 3 children and two immediate values.
377     Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
378         : op(op)
379         , codeOrigin(codeOrigin)
380         , m_virtualRegister(InvalidVirtualRegister)
381         , m_refCount(0)
382         , m_opInfo(imm1.m_value)
383         , m_opInfo2(safeCast<unsigned>(imm2.m_value))
384         , m_prediction(PredictNone)
385     {
386         ASSERT(!(op & NodeHasVarArgs));
387         children.fixed.child1 = child1;
388         children.fixed.child2 = child2;
389         children.fixed.child3 = child3;
390     }
391     
392     // Construct a node with a variable number of children and two immediate values.
393     Node(VarArgTag, NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
394         : op(op)
395         , codeOrigin(codeOrigin)
396         , m_virtualRegister(InvalidVirtualRegister)
397         , m_refCount(0)
398         , m_opInfo(imm1.m_value)
399         , m_opInfo2(safeCast<unsigned>(imm2.m_value))
400         , m_prediction(PredictNone)
401     {
402         ASSERT(op & NodeHasVarArgs);
403         children.variable.firstChild = firstChild;
404         children.variable.numChildren = numChildren;
405     }
406
407     bool mustGenerate()
408     {
409         return op & NodeMustGenerate;
410     }
411
412     bool isConstant()
413     {
414         return op == JSConstant;
415     }
416     
417     bool isWeakConstant()
418     {
419         return op == WeakJSConstant;
420     }
421     
422     bool hasConstant()
423     {
424         return isConstant() || isWeakConstant();
425     }
426
427     unsigned constantNumber()
428     {
429         ASSERT(isConstant());
430         return m_opInfo;
431     }
432     
433     JSCell* weakConstant()
434     {
435         return bitwise_cast<JSCell*>(m_opInfo);
436     }
437     
438     JSValue valueOfJSConstant(CodeBlock* codeBlock)
439     {
440         if (op == WeakJSConstant)
441             return JSValue(weakConstant());
442         return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
443     }
444
445     bool isInt32Constant(CodeBlock* codeBlock)
446     {
447         return isConstant() && valueOfJSConstant(codeBlock).isInt32();
448     }
449     
450     bool isDoubleConstant(CodeBlock* codeBlock)
451     {
452         bool result = isConstant() && valueOfJSConstant(codeBlock).isDouble();
453         if (result)
454             ASSERT(!isInt32Constant(codeBlock));
455         return result;
456     }
457     
458     bool isNumberConstant(CodeBlock* codeBlock)
459     {
460         bool result = isConstant() && valueOfJSConstant(codeBlock).isNumber();
461         ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock)));
462         return result;
463     }
464     
465     bool isBooleanConstant(CodeBlock* codeBlock)
466     {
467         return isConstant() && valueOfJSConstant(codeBlock).isBoolean();
468     }
469     
470     bool hasVariableAccessData()
471     {
472         switch (op) {
473         case GetLocal:
474         case SetLocal:
475         case Phi:
476         case SetArgument:
477         case Flush:
478             return true;
479         default:
480             return false;
481         }
482     }
483     
484     bool hasLocal()
485     {
486         return hasVariableAccessData();
487     }
488     
489     VariableAccessData* variableAccessData()
490     {
491         ASSERT(hasVariableAccessData());
492         return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
493     }
494     
495     VirtualRegister local()
496     {
497         return variableAccessData()->local();
498     }
499
500 #ifndef NDEBUG
501     bool hasIdentifier()
502     {
503         switch (op) {
504         case GetById:
505         case PutById:
506         case PutByIdDirect:
507         case Resolve:
508         case ResolveBase:
509         case ResolveBaseStrictPut:
510             return true;
511         default:
512             return false;
513         }
514     }
515 #endif
516
517     unsigned identifierNumber()
518     {
519         ASSERT(hasIdentifier());
520         return m_opInfo;
521     }
522     
523     unsigned resolveGlobalDataIndex()
524     {
525         ASSERT(op == ResolveGlobal);
526         return m_opInfo;
527     }
528
529     bool hasArithNodeFlags()
530     {
531         switch (op) {
532         case ValueToNumber:
533         case ValueToDouble:
534         case UInt32ToNumber:
535         case ArithAdd:
536         case ArithSub:
537         case ArithMul:
538         case ArithAbs:
539         case ArithMin:
540         case ArithMax:
541         case ArithMod:
542         case ArithDiv:
543         case ValueAdd:
544             return true;
545         default:
546             return false;
547         }
548     }
549     
550     ArithNodeFlags rawArithNodeFlags()
551     {
552         ASSERT(hasArithNodeFlags());
553         return m_opInfo;
554     }
555     
556     // This corrects the arithmetic node flags, so that irrelevant bits are
557     // ignored. In particular, anything other than ArithMul does not need
558     // to know if it can speculate on negative zero.
559     ArithNodeFlags arithNodeFlags()
560     {
561         ArithNodeFlags result = rawArithNodeFlags();
562         if (op == ArithMul)
563             return result;
564         return result & ~NodeNeedsNegZero;
565     }
566     
567     ArithNodeFlags arithNodeFlagsForCompare()
568     {
569         if (hasArithNodeFlags())
570             return arithNodeFlags();
571         return 0;
572     }
573     
574     void setArithNodeFlag(ArithNodeFlags flags)
575     {
576         ASSERT(hasArithNodeFlags());
577         m_opInfo = flags;
578     }
579     
580     bool mergeArithNodeFlags(ArithNodeFlags flags)
581     {
582         if (!hasArithNodeFlags())
583             return false;
584         ArithNodeFlags newFlags = m_opInfo | flags;
585         if (newFlags == m_opInfo)
586             return false;
587         m_opInfo = newFlags;
588         return true;
589     }
590     
591     bool hasConstantBuffer()
592     {
593         return op == NewArrayBuffer;
594     }
595     
596     unsigned startConstant()
597     {
598         ASSERT(hasConstantBuffer());
599         return m_opInfo;
600     }
601     
602     unsigned numConstants()
603     {
604         ASSERT(hasConstantBuffer());
605         return m_opInfo2;
606     }
607     
608     bool hasRegexpIndex()
609     {
610         return op == NewRegexp;
611     }
612     
613     unsigned regexpIndex()
614     {
615         ASSERT(hasRegexpIndex());
616         return m_opInfo;
617     }
618     
619     bool hasVarNumber()
620     {
621         return op == GetGlobalVar || op == PutGlobalVar || op == GetScopedVar || op == PutScopedVar;
622     }
623
624     unsigned varNumber()
625     {
626         ASSERT(hasVarNumber());
627         return m_opInfo;
628     }
629
630     bool hasScopeChainDepth()
631     {
632         return op == GetScopeChain;
633     }
634     
635     unsigned scopeChainDepth()
636     {
637         ASSERT(hasScopeChainDepth());
638         return m_opInfo;
639     }
640
641     bool hasResult()
642     {
643         return op & NodeResultMask;
644     }
645
646     bool hasInt32Result()
647     {
648         return (op & NodeResultMask) == NodeResultInt32;
649     }
650     
651     bool hasNumberResult()
652     {
653         return (op & NodeResultMask) == NodeResultNumber;
654     }
655     
656     bool hasJSResult()
657     {
658         return (op & NodeResultMask) == NodeResultJS;
659     }
660     
661     bool hasBooleanResult()
662     {
663         return (op & NodeResultMask) == NodeResultBoolean;
664     }
665
666     bool isJump()
667     {
668         return op & NodeIsJump;
669     }
670
671     bool isBranch()
672     {
673         return op & NodeIsBranch;
674     }
675
676     bool isTerminal()
677     {
678         return op & NodeIsTerminal;
679     }
680
681     unsigned takenBytecodeOffsetDuringParsing()
682     {
683         ASSERT(isBranch() || isJump());
684         return m_opInfo;
685     }
686
687     unsigned notTakenBytecodeOffsetDuringParsing()
688     {
689         ASSERT(isBranch());
690         return m_opInfo2;
691     }
692     
693     void setTakenBlockIndex(BlockIndex blockIndex)
694     {
695         ASSERT(isBranch() || isJump());
696         m_opInfo = blockIndex;
697     }
698     
699     void setNotTakenBlockIndex(BlockIndex blockIndex)
700     {
701         ASSERT(isBranch());
702         m_opInfo2 = blockIndex;
703     }
704     
705     BlockIndex takenBlockIndex()
706     {
707         ASSERT(isBranch() || isJump());
708         return m_opInfo;
709     }
710     
711     BlockIndex notTakenBlockIndex()
712     {
713         ASSERT(isBranch());
714         return m_opInfo2;
715     }
716     
717     bool hasHeapPrediction()
718     {
719         switch (op) {
720         case GetById:
721         case GetByVal:
722         case Call:
723         case Construct:
724         case GetByOffset:
725         case GetScopedVar:
726         case Resolve:
727         case ResolveBase:
728         case ResolveBaseStrictPut:
729         case ResolveGlobal:
730         case ArrayPop:
731         case ArrayPush:
732             return true;
733         default:
734             return false;
735         }
736     }
737     
738     PredictedType getHeapPrediction()
739     {
740         ASSERT(hasHeapPrediction());
741         return static_cast<PredictedType>(m_opInfo2);
742     }
743     
744     bool predictHeap(PredictedType prediction)
745     {
746         ASSERT(hasHeapPrediction());
747         
748         return mergePrediction(m_opInfo2, prediction);
749     }
750     
751     bool hasFunctionCheckData()
752     {
753         return op == CheckFunction;
754     }
755
756     JSFunction* function()
757     {
758         ASSERT(hasFunctionCheckData());
759         return reinterpret_cast<JSFunction*>(m_opInfo);
760     }
761
762     bool hasStructureTransitionData()
763     {
764         return op == PutStructure;
765     }
766     
767     StructureTransitionData& structureTransitionData()
768     {
769         ASSERT(hasStructureTransitionData());
770         return *reinterpret_cast<StructureTransitionData*>(m_opInfo);
771     }
772     
773     bool hasStructureSet()
774     {
775         return op == CheckStructure;
776     }
777     
778     StructureSet& structureSet()
779     {
780         ASSERT(hasStructureSet());
781         return *reinterpret_cast<StructureSet*>(m_opInfo);
782     }
783     
784     bool hasStorageAccessData()
785     {
786         return op == GetByOffset || op == PutByOffset;
787     }
788     
789     unsigned storageAccessDataIndex()
790     {
791         return m_opInfo;
792     }
793     
794     bool hasVirtualRegister()
795     {
796         return m_virtualRegister != InvalidVirtualRegister;
797     }
798     
799     VirtualRegister virtualRegister()
800     {
801         ASSERT(hasResult());
802         ASSERT(m_virtualRegister != InvalidVirtualRegister);
803         return m_virtualRegister;
804     }
805
806     void setVirtualRegister(VirtualRegister virtualRegister)
807     {
808         ASSERT(hasResult());
809         ASSERT(m_virtualRegister == InvalidVirtualRegister);
810         m_virtualRegister = virtualRegister;
811     }
812
813     bool shouldGenerate()
814     {
815         return m_refCount && op != Phi && op != Flush;
816     }
817
818     unsigned refCount()
819     {
820         return m_refCount;
821     }
822
823     // returns true when ref count passes from 0 to 1.
824     bool ref()
825     {
826         return !m_refCount++;
827     }
828
829     unsigned adjustedRefCount()
830     {
831         return mustGenerate() ? m_refCount - 1 : m_refCount;
832     }
833     
834     void setRefCount(unsigned refCount)
835     {
836         m_refCount = refCount;
837     }
838     
839     void deref()
840     {
841         m_refCount--;
842     }
843     
844     NodeIndex child1()
845     {
846         ASSERT(!(op & NodeHasVarArgs));
847         return children.fixed.child1;
848     }
849     
850     // This is useful if you want to do a fast check on the first child
851     // before also doing a check on the opcode. Use this with care and
852     // avoid it if possible.
853     NodeIndex child1Unchecked()
854     {
855         return children.fixed.child1;
856     }
857
858     NodeIndex child2()
859     {
860         ASSERT(!(op & NodeHasVarArgs));
861         return children.fixed.child2;
862     }
863
864     NodeIndex child3()
865     {
866         ASSERT(!(op & NodeHasVarArgs));
867         return children.fixed.child3;
868     }
869     
870     unsigned firstChild()
871     {
872         ASSERT(op & NodeHasVarArgs);
873         return children.variable.firstChild;
874     }
875     
876     unsigned numChildren()
877     {
878         ASSERT(op & NodeHasVarArgs);
879         return children.variable.numChildren;
880     }
881     
882     PredictedType prediction()
883     {
884         return m_prediction;
885     }
886     
887     bool predict(PredictedType prediction)
888     {
889         return mergePrediction(m_prediction, prediction);
890     }
891     
892     bool shouldSpeculateInteger()
893     {
894         return isInt32Prediction(prediction());
895     }
896     
897     bool shouldSpeculateDouble()
898     {
899         return isDoublePrediction(prediction());
900     }
901     
902     bool shouldSpeculateNumber()
903     {
904         return isNumberPrediction(prediction()) || prediction() == PredictNone;
905     }
906     
907     bool shouldNotSpeculateInteger()
908     {
909         return !!(prediction() & PredictDouble);
910     }
911     
912     bool shouldSpeculateFinalObject()
913     {
914         return isFinalObjectPrediction(prediction());
915     }
916     
917     bool shouldSpeculateFinalObjectOrOther()
918     {
919         return isFinalObjectOrOtherPrediction(prediction());
920     }
921     
922     bool shouldSpeculateArray()
923     {
924         return isArrayPrediction(prediction());
925     }
926     
927     bool shouldSpeculateByteArray()
928     {
929         return !!(prediction() & PredictByteArray);
930     }
931     
932     bool shouldSpeculateInt8Array()
933     {
934         return isInt8ArrayPrediction(prediction());
935     }
936     
937     bool shouldSpeculateInt16Array()
938     {
939         return isInt16ArrayPrediction(prediction());
940     }
941     
942     bool shouldSpeculateInt32Array()
943     {
944         return isInt32ArrayPrediction(prediction());
945     }
946     
947     bool shouldSpeculateUint8Array()
948     {
949         return isUint8ArrayPrediction(prediction());
950     }
951     
952     bool shouldSpeculateUint16Array()
953     {
954         return isUint16ArrayPrediction(prediction());
955     }
956     
957     bool shouldSpeculateUint32Array()
958     {
959         return isUint32ArrayPrediction(prediction());
960     }
961     
962     bool shouldSpeculateFloat32Array()
963     {
964 #if CPU(X86) || CPU(X86_64)
965         return isFloat32ArrayPrediction(prediction());
966 #else
967         return false;
968 #endif
969     }
970     
971     bool shouldSpeculateFloat64Array()
972     {
973         return isFloat64ArrayPrediction(prediction());
974     }
975     
976     bool shouldSpeculateArrayOrOther()
977     {
978         return isArrayOrOtherPrediction(prediction());
979     }
980     
981     bool shouldSpeculateObject()
982     {
983         return isObjectPrediction(prediction());
984     }
985     
986     bool shouldSpeculateCell()
987     {
988         return isCellPrediction(prediction());
989     }
990     
991     static bool shouldSpeculateInteger(Node& op1, Node& op2)
992     {
993         return op1.shouldSpeculateInteger() && op2.shouldSpeculateInteger();
994     }
995     
996     static bool shouldSpeculateNumber(Node& op1, Node& op2)
997     {
998         return op1.shouldSpeculateNumber() && op2.shouldSpeculateNumber();
999     }
1000     
1001     static bool shouldSpeculateFinalObject(Node& op1, Node& op2)
1002     {
1003         return (op1.shouldSpeculateFinalObject() && op2.shouldSpeculateObject())
1004             || (op1.shouldSpeculateObject() && op2.shouldSpeculateFinalObject());
1005     }
1006
1007     static bool shouldSpeculateArray(Node& op1, Node& op2)
1008     {
1009         return (op1.shouldSpeculateArray() && op2.shouldSpeculateObject())
1010             || (op1.shouldSpeculateObject() && op2.shouldSpeculateArray());
1011     }
1012     
1013     bool canSpeculateInteger()
1014     {
1015         return nodeCanSpeculateInteger(arithNodeFlags());
1016     }
1017     
1018 #ifndef NDEBUG
1019     void dumpChildren(FILE* out)
1020     {
1021         if (child1() == NoNode)
1022             return;
1023         fprintf(out, "@%u", child1());
1024         if (child2() == NoNode)
1025             return;
1026         fprintf(out, ", @%u", child2());
1027         if (child3() == NoNode)
1028             return;
1029         fprintf(out, ", @%u", child3());
1030     }
1031 #endif
1032     
1033     // This enum value describes the type of the node.
1034     NodeType op;
1035     // Used to look up exception handling information (currently implemented as a bytecode index).
1036     CodeOrigin codeOrigin;
1037     // References to up to 3 children (0 for no child).
1038     union {
1039         struct {
1040             NodeIndex child1, child2, child3;
1041         } fixed;
1042         struct {
1043             unsigned firstChild;
1044             unsigned numChildren;
1045         } variable;
1046     } children;
1047
1048 private:
1049     // The virtual register number (spill location) associated with this .
1050     VirtualRegister m_virtualRegister;
1051     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
1052     unsigned m_refCount;
1053     // Immediate values, accesses type-checked via accessors above. The first one is
1054     // big enough to store a pointer.
1055     uintptr_t m_opInfo;
1056     unsigned m_opInfo2;
1057     // The prediction ascribed to this node after propagation.
1058     PredictedType m_prediction;
1059 };
1060
1061 } } // namespace JSC::DFG
1062
1063 #endif
1064 #endif