tizen beta release
[profile/ivi/webkit-efl.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(Phi, 0) \
182     macro(Flush, NodeMustGenerate) \
183     \
184     /* Marker for arguments being set. */\
185     macro(SetArgument, 0) \
186     \
187     /* Hint that inlining begins here. No code is generated for this node. It's only */\
188     /* used for copying OSR data into inline frame data, to support reification of */\
189     /* call frames of inlined functions. */\
190     macro(InlineStart, 0) \
191     \
192     /* Nodes for bitwise operations. */\
193     macro(BitAnd, NodeResultInt32) \
194     macro(BitOr, NodeResultInt32) \
195     macro(BitXor, NodeResultInt32) \
196     macro(BitLShift, NodeResultInt32) \
197     macro(BitRShift, NodeResultInt32) \
198     macro(BitURShift, NodeResultInt32) \
199     /* Bitwise operators call ToInt32 on their operands. */\
200     macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \
201     /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
202     macro(UInt32ToNumber, NodeResultNumber) \
203     \
204     /* Nodes for arithmetic operations. */\
205     macro(ArithAdd, NodeResultNumber) \
206     macro(ArithSub, NodeResultNumber) \
207     macro(ArithMul, NodeResultNumber) \
208     macro(ArithDiv, NodeResultNumber) \
209     macro(ArithMod, NodeResultNumber) \
210     macro(ArithAbs, NodeResultNumber) \
211     macro(ArithMin, NodeResultNumber) \
212     macro(ArithMax, NodeResultNumber) \
213     macro(ArithSqrt, NodeResultNumber) \
214     /* Arithmetic operators call ToNumber on their operands. */\
215     macro(ValueToNumber, NodeResultNumber | NodeMustGenerate) \
216     \
217     /* A variant of ValueToNumber, which a hint that the parents will always use this as a double. */\
218     macro(ValueToDouble, NodeResultNumber | NodeMustGenerate) \
219     \
220     /* Add of values may either be arithmetic, or result in string concatenation. */\
221     macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
222     \
223     /* Property access. */\
224     /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\
225     /* Since a put to 'length' may invalidate optimizations here, */\
226     /* this must be the directly subsequent property put. */\
227     macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \
228     macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \
229     macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \
230     macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
231     macro(PutById, NodeMustGenerate | NodeClobbersWorld) \
232     macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \
233     macro(CheckStructure, NodeMustGenerate) \
234     macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \
235     macro(GetPropertyStorage, NodeResultStorage) \
236     macro(GetByOffset, NodeResultJS) \
237     macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \
238     macro(GetArrayLength, NodeResultInt32) \
239     macro(GetStringLength, NodeResultInt32) \
240     macro(GetByteArrayLength, NodeResultInt32) \
241     macro(GetScopeChain, NodeResultJS) \
242     macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \
243     macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \
244     macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \
245     macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \
246     macro(CheckFunction, NodeMustGenerate) \
247     \
248     /* Optimizations for array mutation. */\
249     macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
250     macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
251     \
252     /* Optimizations for string access */ \
253     macro(StringCharCodeAt, NodeResultInt32) \
254     macro(StringCharAt, NodeResultJS) \
255     \
256     /* Nodes for comparison operations. */\
257     macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
258     macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
259     macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
260     macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
261     macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \
262     macro(CompareStrictEq, NodeResultBoolean) \
263     \
264     /* Calls. */\
265     macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
266     macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
267     \
268     /* Allocations. */\
269     macro(NewObject, NodeResultJS) \
270     macro(NewArray, NodeResultJS | NodeHasVarArgs) \
271     macro(NewArrayBuffer, NodeResultJS) \
272     macro(NewRegexp, NodeResultJS) \
273     \
274     /* Resolve nodes. */\
275     macro(Resolve, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
276     macro(ResolveBase, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
277     macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
278     macro(ResolveGlobal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
279     \
280     /* Nodes for misc operations. */\
281     macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \
282     macro(CheckHasInstance, NodeMustGenerate) \
283     macro(InstanceOf, NodeResultBoolean) \
284     macro(LogicalNot, NodeResultBoolean | NodeMightClobber) \
285     macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \
286     macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \
287     \
288     /* Block terminals. */\
289     macro(Jump, NodeMustGenerate | NodeIsTerminal | NodeIsJump) \
290     macro(Branch, NodeMustGenerate | NodeIsTerminal | NodeIsBranch) \
291     macro(Return, NodeMustGenerate | NodeIsTerminal) \
292     macro(Throw, NodeMustGenerate | NodeIsTerminal) \
293     macro(ThrowReferenceError, NodeMustGenerate | NodeIsTerminal) \
294     \
295     /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\
296     /* this point, but execution does continue in the basic block - just in a */\
297     /* different compiler. */\
298     macro(ForceOSRExit, NodeMustGenerate)
299
300 // This enum generates a monotonically increasing id for all Node types,
301 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
302 enum NodeId {
303 #define DFG_OP_ENUM(opcode, flags) opcode##_id,
304     FOR_EACH_DFG_OP(DFG_OP_ENUM)
305 #undef DFG_OP_ENUM
306     LastNodeId
307 };
308
309 // Entries in this enum describe all Node types.
310 // The enum value contains a monotonically increasing id, a result type, and additional flags.
311 enum NodeType {
312 #define DFG_OP_ENUM(opcode, flags) opcode = opcode##_id | (flags),
313     FOR_EACH_DFG_OP(DFG_OP_ENUM)
314 #undef DFG_OP_ENUM
315 };
316
317 // This type used in passing an immediate argument to Node constructor;
318 // distinguishes an immediate value (typically an index into a CodeBlock data structure - 
319 // a constant index, argument, or identifier) from a NodeIndex.
320 struct OpInfo {
321     explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
322     explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
323 #if OS(DARWIN) || USE(JSVALUE64)
324     explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
325 #endif
326     explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
327     uintptr_t m_value;
328 };
329
330 // === Node ===
331 //
332 // Node represents a single operation in the data flow graph.
333 struct Node {
334     enum VarArgTag { VarArg };
335
336     // Construct a node with up to 3 children, no immediate value.
337     Node(NodeType op, CodeOrigin codeOrigin, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
338         : op(op)
339         , codeOrigin(codeOrigin)
340         , m_virtualRegister(InvalidVirtualRegister)
341         , m_refCount(0)
342         , m_prediction(PredictNone)
343     {
344         ASSERT(!(op & NodeHasVarArgs));
345         ASSERT(!hasArithNodeFlags());
346         children.fixed.child1 = child1;
347         children.fixed.child2 = child2;
348         children.fixed.child3 = child3;
349     }
350
351     // Construct a node with up to 3 children and an immediate value.
352     Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
353         : op(op)
354         , codeOrigin(codeOrigin)
355         , m_virtualRegister(InvalidVirtualRegister)
356         , m_refCount(0)
357         , m_opInfo(imm.m_value)
358         , m_prediction(PredictNone)
359     {
360         ASSERT(!(op & NodeHasVarArgs));
361         children.fixed.child1 = child1;
362         children.fixed.child2 = child2;
363         children.fixed.child3 = child3;
364     }
365
366     // Construct a node with up to 3 children and two immediate values.
367     Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode)
368         : op(op)
369         , codeOrigin(codeOrigin)
370         , m_virtualRegister(InvalidVirtualRegister)
371         , m_refCount(0)
372         , m_opInfo(imm1.m_value)
373         , m_opInfo2(safeCast<unsigned>(imm2.m_value))
374         , m_prediction(PredictNone)
375     {
376         ASSERT(!(op & NodeHasVarArgs));
377         children.fixed.child1 = child1;
378         children.fixed.child2 = child2;
379         children.fixed.child3 = child3;
380     }
381     
382     // Construct a node with a variable number of children and two immediate values.
383     Node(VarArgTag, NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
384         : op(op)
385         , codeOrigin(codeOrigin)
386         , m_virtualRegister(InvalidVirtualRegister)
387         , m_refCount(0)
388         , m_opInfo(imm1.m_value)
389         , m_opInfo2(safeCast<unsigned>(imm2.m_value))
390         , m_prediction(PredictNone)
391     {
392         ASSERT(op & NodeHasVarArgs);
393         children.variable.firstChild = firstChild;
394         children.variable.numChildren = numChildren;
395     }
396
397     bool mustGenerate()
398     {
399         return op & NodeMustGenerate;
400     }
401
402     bool isConstant()
403     {
404         return op == JSConstant;
405     }
406     
407     bool isWeakConstant()
408     {
409         return op == WeakJSConstant;
410     }
411     
412     bool hasConstant()
413     {
414         return isConstant() || isWeakConstant();
415     }
416
417     unsigned constantNumber()
418     {
419         ASSERT(isConstant());
420         return m_opInfo;
421     }
422     
423     JSCell* weakConstant()
424     {
425         return bitwise_cast<JSCell*>(m_opInfo);
426     }
427     
428     JSValue valueOfJSConstant(CodeBlock* codeBlock)
429     {
430         if (op == WeakJSConstant)
431             return JSValue(weakConstant());
432         return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
433     }
434
435     bool isInt32Constant(CodeBlock* codeBlock)
436     {
437         return isConstant() && valueOfJSConstant(codeBlock).isInt32();
438     }
439     
440     bool isDoubleConstant(CodeBlock* codeBlock)
441     {
442         bool result = isConstant() && valueOfJSConstant(codeBlock).isDouble();
443         if (result)
444             ASSERT(!isInt32Constant(codeBlock));
445         return result;
446     }
447     
448     bool isNumberConstant(CodeBlock* codeBlock)
449     {
450         bool result = isConstant() && valueOfJSConstant(codeBlock).isNumber();
451         ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock)));
452         return result;
453     }
454     
455     bool isBooleanConstant(CodeBlock* codeBlock)
456     {
457         return isConstant() && valueOfJSConstant(codeBlock).isBoolean();
458     }
459     
460     bool hasVariableAccessData()
461     {
462         switch (op) {
463         case GetLocal:
464         case SetLocal:
465         case Phi:
466         case SetArgument:
467         case Flush:
468             return true;
469         default:
470             return false;
471         }
472     }
473     
474     bool hasLocal()
475     {
476         return hasVariableAccessData();
477     }
478     
479     VariableAccessData* variableAccessData()
480     {
481         ASSERT(hasVariableAccessData());
482         return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
483     }
484     
485     VirtualRegister local()
486     {
487         return variableAccessData()->local();
488     }
489
490 #ifndef NDEBUG
491     bool hasIdentifier()
492     {
493         switch (op) {
494         case GetById:
495         case PutById:
496         case PutByIdDirect:
497         case Resolve:
498         case ResolveBase:
499         case ResolveBaseStrictPut:
500             return true;
501         default:
502             return false;
503         }
504     }
505 #endif
506
507     unsigned identifierNumber()
508     {
509         ASSERT(hasIdentifier());
510         return m_opInfo;
511     }
512     
513     unsigned resolveGlobalDataIndex()
514     {
515         ASSERT(op == ResolveGlobal);
516         return m_opInfo;
517     }
518
519     bool hasArithNodeFlags()
520     {
521         switch (op) {
522         case ValueToNumber:
523         case ValueToDouble:
524         case UInt32ToNumber:
525         case ArithAdd:
526         case ArithSub:
527         case ArithMul:
528         case ArithAbs:
529         case ArithMin:
530         case ArithMax:
531         case ArithMod:
532         case ArithDiv:
533         case ValueAdd:
534             return true;
535         default:
536             return false;
537         }
538     }
539     
540     ArithNodeFlags rawArithNodeFlags()
541     {
542         ASSERT(hasArithNodeFlags());
543         return m_opInfo;
544     }
545     
546     // This corrects the arithmetic node flags, so that irrelevant bits are
547     // ignored. In particular, anything other than ArithMul does not need
548     // to know if it can speculate on negative zero.
549     ArithNodeFlags arithNodeFlags()
550     {
551         ArithNodeFlags result = rawArithNodeFlags();
552         if (op == ArithMul)
553             return result;
554         return result & ~NodeNeedsNegZero;
555     }
556     
557     ArithNodeFlags arithNodeFlagsForCompare()
558     {
559         if (hasArithNodeFlags())
560             return arithNodeFlags();
561         return 0;
562     }
563     
564     void setArithNodeFlag(ArithNodeFlags flags)
565     {
566         ASSERT(hasArithNodeFlags());
567         m_opInfo = flags;
568     }
569     
570     bool mergeArithNodeFlags(ArithNodeFlags flags)
571     {
572         if (!hasArithNodeFlags())
573             return false;
574         ArithNodeFlags newFlags = m_opInfo | flags;
575         if (newFlags == m_opInfo)
576             return false;
577         m_opInfo = newFlags;
578         return true;
579     }
580     
581     bool hasConstantBuffer()
582     {
583         return op == NewArrayBuffer;
584     }
585     
586     unsigned startConstant()
587     {
588         ASSERT(hasConstantBuffer());
589         return m_opInfo;
590     }
591     
592     unsigned numConstants()
593     {
594         ASSERT(hasConstantBuffer());
595         return m_opInfo2;
596     }
597     
598     bool hasRegexpIndex()
599     {
600         return op == NewRegexp;
601     }
602     
603     unsigned regexpIndex()
604     {
605         ASSERT(hasRegexpIndex());
606         return m_opInfo;
607     }
608     
609     bool hasVarNumber()
610     {
611         return op == GetGlobalVar || op == PutGlobalVar || op == GetScopedVar || op == PutScopedVar;
612     }
613
614     unsigned varNumber()
615     {
616         ASSERT(hasVarNumber());
617         return m_opInfo;
618     }
619
620     bool hasScopeChainDepth()
621     {
622         return op == GetScopeChain;
623     }
624     
625     unsigned scopeChainDepth()
626     {
627         ASSERT(hasScopeChainDepth());
628         return m_opInfo;
629     }
630
631     bool hasResult()
632     {
633         return op & NodeResultMask;
634     }
635
636     bool hasInt32Result()
637     {
638         return (op & NodeResultMask) == NodeResultInt32;
639     }
640     
641     bool hasNumberResult()
642     {
643         return (op & NodeResultMask) == NodeResultNumber;
644     }
645     
646     bool hasJSResult()
647     {
648         return (op & NodeResultMask) == NodeResultJS;
649     }
650     
651     bool hasBooleanResult()
652     {
653         return (op & NodeResultMask) == NodeResultBoolean;
654     }
655
656     bool isJump()
657     {
658         return op & NodeIsJump;
659     }
660
661     bool isBranch()
662     {
663         return op & NodeIsBranch;
664     }
665
666     bool isTerminal()
667     {
668         return op & NodeIsTerminal;
669     }
670
671     unsigned takenBytecodeOffsetDuringParsing()
672     {
673         ASSERT(isBranch() || isJump());
674         return m_opInfo;
675     }
676
677     unsigned notTakenBytecodeOffsetDuringParsing()
678     {
679         ASSERT(isBranch());
680         return m_opInfo2;
681     }
682     
683     void setTakenBlockIndex(BlockIndex blockIndex)
684     {
685         ASSERT(isBranch() || isJump());
686         m_opInfo = blockIndex;
687     }
688     
689     void setNotTakenBlockIndex(BlockIndex blockIndex)
690     {
691         ASSERT(isBranch());
692         m_opInfo2 = blockIndex;
693     }
694     
695     BlockIndex takenBlockIndex()
696     {
697         ASSERT(isBranch() || isJump());
698         return m_opInfo;
699     }
700     
701     BlockIndex notTakenBlockIndex()
702     {
703         ASSERT(isBranch());
704         return m_opInfo2;
705     }
706     
707     bool hasHeapPrediction()
708     {
709         switch (op) {
710         case GetById:
711         case GetByVal:
712         case Call:
713         case Construct:
714         case GetByOffset:
715         case GetScopedVar:
716         case Resolve:
717         case ResolveBase:
718         case ResolveBaseStrictPut:
719         case ResolveGlobal:
720         case ArrayPop:
721         case ArrayPush:
722             return true;
723         default:
724             return false;
725         }
726     }
727     
728     PredictedType getHeapPrediction()
729     {
730         ASSERT(hasHeapPrediction());
731         return static_cast<PredictedType>(m_opInfo2);
732     }
733     
734     bool predictHeap(PredictedType prediction)
735     {
736         ASSERT(hasHeapPrediction());
737         
738         return mergePrediction(m_opInfo2, prediction);
739     }
740     
741     bool hasFunctionCheckData()
742     {
743         return op == CheckFunction;
744     }
745
746     JSFunction* function()
747     {
748         ASSERT(hasFunctionCheckData());
749         return reinterpret_cast<JSFunction*>(m_opInfo);
750     }
751
752     bool hasStructureTransitionData()
753     {
754         return op == PutStructure;
755     }
756     
757     StructureTransitionData& structureTransitionData()
758     {
759         ASSERT(hasStructureTransitionData());
760         return *reinterpret_cast<StructureTransitionData*>(m_opInfo);
761     }
762     
763     bool hasStructureSet()
764     {
765         return op == CheckStructure;
766     }
767     
768     StructureSet& structureSet()
769     {
770         ASSERT(hasStructureSet());
771         return *reinterpret_cast<StructureSet*>(m_opInfo);
772     }
773     
774     bool hasStorageAccessData()
775     {
776         return op == GetByOffset || op == PutByOffset;
777     }
778     
779     unsigned storageAccessDataIndex()
780     {
781         return m_opInfo;
782     }
783     
784     bool hasVirtualRegister()
785     {
786         return m_virtualRegister != InvalidVirtualRegister;
787     }
788     
789     VirtualRegister virtualRegister()
790     {
791         ASSERT(hasResult());
792         ASSERT(m_virtualRegister != InvalidVirtualRegister);
793         return m_virtualRegister;
794     }
795
796     void setVirtualRegister(VirtualRegister virtualRegister)
797     {
798         ASSERT(hasResult());
799         ASSERT(m_virtualRegister == InvalidVirtualRegister);
800         m_virtualRegister = virtualRegister;
801     }
802
803     bool shouldGenerate()
804     {
805         return m_refCount && op != Phi && op != Flush;
806     }
807
808     unsigned refCount()
809     {
810         return m_refCount;
811     }
812
813     // returns true when ref count passes from 0 to 1.
814     bool ref()
815     {
816         return !m_refCount++;
817     }
818
819     unsigned adjustedRefCount()
820     {
821         return mustGenerate() ? m_refCount - 1 : m_refCount;
822     }
823     
824     void setRefCount(unsigned refCount)
825     {
826         m_refCount = refCount;
827     }
828     
829     NodeIndex child1()
830     {
831         ASSERT(!(op & NodeHasVarArgs));
832         return children.fixed.child1;
833     }
834     
835     // This is useful if you want to do a fast check on the first child
836     // before also doing a check on the opcode. Use this with care and
837     // avoid it if possible.
838     NodeIndex child1Unchecked()
839     {
840         return children.fixed.child1;
841     }
842
843     NodeIndex child2()
844     {
845         ASSERT(!(op & NodeHasVarArgs));
846         return children.fixed.child2;
847     }
848
849     NodeIndex child3()
850     {
851         ASSERT(!(op & NodeHasVarArgs));
852         return children.fixed.child3;
853     }
854     
855     unsigned firstChild()
856     {
857         ASSERT(op & NodeHasVarArgs);
858         return children.variable.firstChild;
859     }
860     
861     unsigned numChildren()
862     {
863         ASSERT(op & NodeHasVarArgs);
864         return children.variable.numChildren;
865     }
866     
867     PredictedType prediction()
868     {
869         return m_prediction;
870     }
871     
872     bool predict(PredictedType prediction)
873     {
874         return mergePrediction(m_prediction, prediction);
875     }
876     
877     bool shouldSpeculateInteger()
878     {
879         return isInt32Prediction(prediction());
880     }
881     
882     bool shouldSpeculateDouble()
883     {
884         return isDoublePrediction(prediction());
885     }
886     
887     bool shouldSpeculateNumber()
888     {
889         return isNumberPrediction(prediction()) || prediction() == PredictNone;
890     }
891     
892     bool shouldNotSpeculateInteger()
893     {
894         return !!(prediction() & PredictDouble);
895     }
896     
897     bool shouldSpeculateFinalObject()
898     {
899         return isFinalObjectPrediction(prediction());
900     }
901     
902     bool shouldSpeculateFinalObjectOrOther()
903     {
904         return isFinalObjectOrOtherPrediction(prediction());
905     }
906     
907     bool shouldSpeculateArray()
908     {
909         return isArrayPrediction(prediction());
910     }
911     
912     bool shouldSpeculateByteArray()
913     {
914         return !!(prediction() & PredictByteArray);
915     }
916     
917     bool shouldSpeculateArrayOrOther()
918     {
919         return isArrayOrOtherPrediction(prediction());
920     }
921     
922     bool shouldSpeculateObject()
923     {
924         return isObjectPrediction(prediction());
925     }
926     
927     bool shouldSpeculateCell()
928     {
929         return isCellPrediction(prediction());
930     }
931     
932     static bool shouldSpeculateInteger(Node& op1, Node& op2)
933     {
934         return op1.shouldSpeculateInteger() && op2.shouldSpeculateInteger();
935     }
936     
937     static bool shouldSpeculateNumber(Node& op1, Node& op2)
938     {
939         return op1.shouldSpeculateNumber() && op2.shouldSpeculateNumber();
940     }
941     
942     static bool shouldSpeculateFinalObject(Node& op1, Node& op2)
943     {
944         return (op1.shouldSpeculateFinalObject() && op2.shouldSpeculateObject())
945             || (op1.shouldSpeculateObject() && op2.shouldSpeculateFinalObject());
946     }
947
948     static bool shouldSpeculateArray(Node& op1, Node& op2)
949     {
950         return (op1.shouldSpeculateArray() && op2.shouldSpeculateObject())
951             || (op1.shouldSpeculateObject() && op2.shouldSpeculateArray());
952     }
953     
954     bool canSpeculateInteger()
955     {
956         return nodeCanSpeculateInteger(arithNodeFlags());
957     }
958     
959 #ifndef NDEBUG
960     void dumpChildren(FILE* out)
961     {
962         if (child1() == NoNode)
963             return;
964         fprintf(out, "@%u", child1());
965         if (child2() == NoNode)
966             return;
967         fprintf(out, ", @%u", child2());
968         if (child3() == NoNode)
969             return;
970         fprintf(out, ", @%u", child3());
971     }
972 #endif
973     
974     // This enum value describes the type of the node.
975     NodeType op;
976     // Used to look up exception handling information (currently implemented as a bytecode index).
977     CodeOrigin codeOrigin;
978     // References to up to 3 children (0 for no child).
979     union {
980         struct {
981             NodeIndex child1, child2, child3;
982         } fixed;
983         struct {
984             unsigned firstChild;
985             unsigned numChildren;
986         } variable;
987     } children;
988
989 private:
990     // The virtual register number (spill location) associated with this .
991     VirtualRegister m_virtualRegister;
992     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
993     unsigned m_refCount;
994     // Immediate values, accesses type-checked via accessors above. The first one is
995     // big enough to store a pointer.
996     uintptr_t m_opInfo;
997     unsigned m_opInfo2;
998     // The prediction ascribed to this node after propagation.
999     PredictedType m_prediction;
1000 };
1001
1002 } } // namespace JSC::DFG
1003
1004 #endif
1005 #endif