]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - dfg/DFGNode.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / dfg / DFGNode.h
... / ...
CommitLineData
1/*
2 * Copyright (C) 2011, 2012, 2013, 2014 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#if ENABLE(DFG_JIT)
30
31#include "CodeBlock.h"
32#include "DFGAbstractValue.h"
33#include "DFGAdjacencyList.h"
34#include "DFGArithMode.h"
35#include "DFGArrayMode.h"
36#include "DFGCommon.h"
37#include "DFGLazyJSValue.h"
38#include "DFGNodeFlags.h"
39#include "DFGNodeOrigin.h"
40#include "DFGNodeType.h"
41#include "DFGUseKind.h"
42#include "DFGVariableAccessData.h"
43#include "GetByIdVariant.h"
44#include "JSCJSValue.h"
45#include "Operands.h"
46#include "PutByIdVariant.h"
47#include "SpeculatedType.h"
48#include "StructureSet.h"
49#include "ValueProfile.h"
50#include <wtf/ListDump.h>
51
52namespace JSC { namespace DFG {
53
54class Graph;
55struct BasicBlock;
56
57struct MultiGetByOffsetData {
58 unsigned identifierNumber;
59 Vector<GetByIdVariant, 2> variants;
60};
61
62struct MultiPutByOffsetData {
63 unsigned identifierNumber;
64 Vector<PutByIdVariant, 2> variants;
65
66 bool writesStructures() const;
67 bool reallocatesStorage() const;
68};
69
70struct StructureTransitionData {
71 Structure* previousStructure;
72 Structure* newStructure;
73
74 StructureTransitionData() { }
75
76 StructureTransitionData(Structure* previousStructure, Structure* newStructure)
77 : previousStructure(previousStructure)
78 , newStructure(newStructure)
79 {
80 }
81};
82
83struct NewArrayBufferData {
84 unsigned startConstant;
85 unsigned numConstants;
86 IndexingType indexingType;
87};
88
89struct BranchTarget {
90 BranchTarget()
91 : block(0)
92 , count(PNaN)
93 {
94 }
95
96 explicit BranchTarget(BasicBlock* block)
97 : block(block)
98 , count(PNaN)
99 {
100 }
101
102 void setBytecodeIndex(unsigned bytecodeIndex)
103 {
104 block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(bytecodeIndex));
105 }
106 unsigned bytecodeIndex() const { return bitwise_cast<uintptr_t>(block); }
107
108 void dump(PrintStream&) const;
109
110 BasicBlock* block;
111 float count;
112};
113
114struct BranchData {
115 static BranchData withBytecodeIndices(
116 unsigned takenBytecodeIndex, unsigned notTakenBytecodeIndex)
117 {
118 BranchData result;
119 result.taken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(takenBytecodeIndex));
120 result.notTaken.block = bitwise_cast<BasicBlock*>(static_cast<uintptr_t>(notTakenBytecodeIndex));
121 return result;
122 }
123
124 unsigned takenBytecodeIndex() const { return taken.bytecodeIndex(); }
125 unsigned notTakenBytecodeIndex() const { return notTaken.bytecodeIndex(); }
126
127 BasicBlock*& forCondition(bool condition)
128 {
129 if (condition)
130 return taken.block;
131 return notTaken.block;
132 }
133
134 BranchTarget taken;
135 BranchTarget notTaken;
136};
137
138// The SwitchData and associated data structures duplicate the information in
139// JumpTable. The DFG may ultimately end up using the JumpTable, though it may
140// instead decide to do something different - this is entirely up to the DFG.
141// These data structures give the DFG a higher-level semantic description of
142// what is going on, which will allow it to make the right decision.
143//
144// Note that there will never be multiple SwitchCases in SwitchData::cases that
145// have the same SwitchCase::value, since the bytecode's JumpTables never have
146// duplicates - since the JumpTable maps a value to a target. It's a
147// one-to-many mapping. So we may have duplicate targets, but never duplicate
148// values.
149struct SwitchCase {
150 SwitchCase()
151 {
152 }
153
154 SwitchCase(LazyJSValue value, BasicBlock* target)
155 : value(value)
156 , target(target)
157 {
158 }
159
160 static SwitchCase withBytecodeIndex(LazyJSValue value, unsigned bytecodeIndex)
161 {
162 SwitchCase result;
163 result.value = value;
164 result.target.setBytecodeIndex(bytecodeIndex);
165 return result;
166 }
167
168 LazyJSValue value;
169 BranchTarget target;
170};
171
172enum SwitchKind {
173 SwitchImm,
174 SwitchChar,
175 SwitchString
176};
177
178struct SwitchData {
179 // Initializes most fields to obviously invalid values. Anyone
180 // constructing this should make sure to initialize everything they
181 // care about manually.
182 SwitchData()
183 : kind(static_cast<SwitchKind>(-1))
184 , switchTableIndex(UINT_MAX)
185 , didUseJumpTable(false)
186 {
187 }
188
189 Vector<SwitchCase> cases;
190 BranchTarget fallThrough;
191 SwitchKind kind;
192 unsigned switchTableIndex;
193 bool didUseJumpTable;
194};
195
196// This type used in passing an immediate argument to Node constructor;
197// distinguishes an immediate value (typically an index into a CodeBlock data structure -
198// a constant index, argument, or identifier) from a Node*.
199struct OpInfo {
200 explicit OpInfo(int32_t value) : m_value(static_cast<uintptr_t>(value)) { }
201 explicit OpInfo(uint32_t value) : m_value(static_cast<uintptr_t>(value)) { }
202#if OS(DARWIN) || USE(JSVALUE64)
203 explicit OpInfo(size_t value) : m_value(static_cast<uintptr_t>(value)) { }
204#endif
205 explicit OpInfo(void* value) : m_value(reinterpret_cast<uintptr_t>(value)) { }
206 uintptr_t m_value;
207};
208
209// === Node ===
210//
211// Node represents a single operation in the data flow graph.
212struct Node {
213 enum VarArgTag { VarArg };
214
215 Node() { }
216
217 Node(NodeType op, NodeOrigin nodeOrigin, const AdjacencyList& children)
218 : origin(nodeOrigin)
219 , children(children)
220 , m_virtualRegister(VirtualRegister())
221 , m_refCount(1)
222 , m_prediction(SpecNone)
223 {
224 misc.replacement = 0;
225 setOpAndDefaultFlags(op);
226 }
227
228 // Construct a node with up to 3 children, no immediate value.
229 Node(NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
230 : origin(nodeOrigin)
231 , children(AdjacencyList::Fixed, child1, child2, child3)
232 , m_virtualRegister(VirtualRegister())
233 , m_refCount(1)
234 , m_prediction(SpecNone)
235 , m_opInfo(0)
236 , m_opInfo2(0)
237 {
238 misc.replacement = 0;
239 setOpAndDefaultFlags(op);
240 ASSERT(!(m_flags & NodeHasVarArgs));
241 }
242
243 // Construct a node with up to 3 children, no immediate value.
244 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
245 : origin(nodeOrigin)
246 , children(AdjacencyList::Fixed, child1, child2, child3)
247 , m_virtualRegister(VirtualRegister())
248 , m_refCount(1)
249 , m_prediction(SpecNone)
250 , m_opInfo(0)
251 , m_opInfo2(0)
252 {
253 misc.replacement = 0;
254 setOpAndDefaultFlags(op);
255 setResult(result);
256 ASSERT(!(m_flags & NodeHasVarArgs));
257 }
258
259 // Construct a node with up to 3 children and an immediate value.
260 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
261 : origin(nodeOrigin)
262 , children(AdjacencyList::Fixed, child1, child2, child3)
263 , m_virtualRegister(VirtualRegister())
264 , m_refCount(1)
265 , m_prediction(SpecNone)
266 , m_opInfo(imm.m_value)
267 , m_opInfo2(0)
268 {
269 misc.replacement = 0;
270 setOpAndDefaultFlags(op);
271 ASSERT(!(m_flags & NodeHasVarArgs));
272 }
273
274 // Construct a node with up to 3 children and an immediate value.
275 Node(NodeFlags result, NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
276 : origin(nodeOrigin)
277 , children(AdjacencyList::Fixed, child1, child2, child3)
278 , m_virtualRegister(VirtualRegister())
279 , m_refCount(1)
280 , m_prediction(SpecNone)
281 , m_opInfo(imm.m_value)
282 , m_opInfo2(0)
283 {
284 misc.replacement = 0;
285 setOpAndDefaultFlags(op);
286 setResult(result);
287 ASSERT(!(m_flags & NodeHasVarArgs));
288 }
289
290 // Construct a node with up to 3 children and two immediate values.
291 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
292 : origin(nodeOrigin)
293 , children(AdjacencyList::Fixed, child1, child2, child3)
294 , m_virtualRegister(VirtualRegister())
295 , m_refCount(1)
296 , m_prediction(SpecNone)
297 , m_opInfo(imm1.m_value)
298 , m_opInfo2(imm2.m_value)
299 {
300 misc.replacement = 0;
301 setOpAndDefaultFlags(op);
302 ASSERT(!(m_flags & NodeHasVarArgs));
303 }
304
305 // Construct a node with a variable number of children and two immediate values.
306 Node(VarArgTag, NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
307 : origin(nodeOrigin)
308 , children(AdjacencyList::Variable, firstChild, numChildren)
309 , m_virtualRegister(VirtualRegister())
310 , m_refCount(1)
311 , m_prediction(SpecNone)
312 , m_opInfo(imm1.m_value)
313 , m_opInfo2(imm2.m_value)
314 {
315 misc.replacement = 0;
316 setOpAndDefaultFlags(op);
317 ASSERT(m_flags & NodeHasVarArgs);
318 }
319
320 NodeType op() const { return static_cast<NodeType>(m_op); }
321 NodeFlags flags() const { return m_flags; }
322
323 // This is not a fast method.
324 unsigned index() const;
325
326 void setOp(NodeType op)
327 {
328 m_op = op;
329 }
330
331 void setFlags(NodeFlags flags)
332 {
333 m_flags = flags;
334 }
335
336 bool mergeFlags(NodeFlags flags)
337 {
338 ASSERT(!(flags & NodeDoesNotExit));
339 NodeFlags newFlags = m_flags | flags;
340 if (newFlags == m_flags)
341 return false;
342 m_flags = newFlags;
343 return true;
344 }
345
346 bool filterFlags(NodeFlags flags)
347 {
348 ASSERT(flags & NodeDoesNotExit);
349 NodeFlags newFlags = m_flags & flags;
350 if (newFlags == m_flags)
351 return false;
352 m_flags = newFlags;
353 return true;
354 }
355
356 bool clearFlags(NodeFlags flags)
357 {
358 return filterFlags(~flags);
359 }
360
361 void setResult(NodeFlags result)
362 {
363 ASSERT(!(result & ~NodeResultMask));
364 clearFlags(NodeResultMask);
365 mergeFlags(result);
366 }
367
368 NodeFlags result() const
369 {
370 return flags() & NodeResultMask;
371 }
372
373 void setOpAndDefaultFlags(NodeType op)
374 {
375 m_op = op;
376 m_flags = defaultFlags(op);
377 }
378
379 void convertToPhantom()
380 {
381 setOpAndDefaultFlags(Phantom);
382 }
383
384 void convertToPhantomUnchecked()
385 {
386 setOpAndDefaultFlags(Phantom);
387 }
388
389 void convertToIdentity();
390
391 bool mustGenerate()
392 {
393 return m_flags & NodeMustGenerate;
394 }
395
396 void setCanExit(bool exits)
397 {
398 if (exits)
399 m_flags &= ~NodeDoesNotExit;
400 else
401 m_flags |= NodeDoesNotExit;
402 }
403
404 bool canExit()
405 {
406 return !(m_flags & NodeDoesNotExit);
407 }
408
409 bool isConstant()
410 {
411 switch (op()) {
412 case JSConstant:
413 case DoubleConstant:
414 case Int52Constant:
415 return true;
416 default:
417 return false;
418 }
419 }
420
421 bool isWeakConstant()
422 {
423 return op() == WeakJSConstant;
424 }
425
426 bool isPhantomArguments()
427 {
428 return op() == PhantomArguments;
429 }
430
431 bool hasConstant()
432 {
433 switch (op()) {
434 case JSConstant:
435 case DoubleConstant:
436 case Int52Constant:
437 case WeakJSConstant:
438 case PhantomArguments:
439 return true;
440 default:
441 return false;
442 }
443 }
444
445 unsigned constantNumber()
446 {
447 ASSERT(isConstant());
448 return m_opInfo;
449 }
450
451 void convertToConstant(unsigned constantNumber)
452 {
453 if (hasDoubleResult())
454 m_op = DoubleConstant;
455 else if (hasInt52Result())
456 m_op = Int52Constant;
457 else
458 m_op = JSConstant;
459 m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld);
460 m_opInfo = constantNumber;
461 children.reset();
462 }
463
464 void convertToWeakConstant(JSCell* cell)
465 {
466 m_op = WeakJSConstant;
467 m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld);
468 m_opInfo = bitwise_cast<uintptr_t>(cell);
469 children.reset();
470 }
471
472 void convertToConstantStoragePointer(void* pointer)
473 {
474 ASSERT(op() == GetIndexedPropertyStorage);
475 m_op = ConstantStoragePointer;
476 m_opInfo = bitwise_cast<uintptr_t>(pointer);
477 }
478
479 void convertToGetLocalUnlinked(VirtualRegister local)
480 {
481 m_op = GetLocalUnlinked;
482 m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld);
483 m_opInfo = local.offset();
484 m_opInfo2 = VirtualRegister().offset();
485 children.reset();
486 }
487
488 void convertToStructureTransitionWatchpoint(Structure* structure)
489 {
490 ASSERT(m_op == CheckStructure || m_op == ArrayifyToStructure);
491 ASSERT(!child2());
492 ASSERT(!child3());
493 m_opInfo = bitwise_cast<uintptr_t>(structure);
494 m_op = StructureTransitionWatchpoint;
495 }
496
497 void convertToStructureTransitionWatchpoint()
498 {
499 convertToStructureTransitionWatchpoint(structureSet().singletonStructure());
500 }
501
502 void convertToGetByOffset(unsigned storageAccessDataIndex, Edge storage)
503 {
504 ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
505 m_opInfo = storageAccessDataIndex;
506 children.setChild2(children.child1());
507 children.child2().setUseKind(KnownCellUse);
508 children.setChild1(storage);
509 m_op = GetByOffset;
510 m_flags &= ~NodeClobbersWorld;
511 }
512
513 void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage)
514 {
515 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == MultiPutByOffset);
516 m_opInfo = storageAccessDataIndex;
517 children.setChild3(children.child2());
518 children.setChild2(children.child1());
519 children.setChild1(storage);
520 m_op = PutByOffset;
521 m_flags &= ~NodeClobbersWorld;
522 }
523
524 void convertToPhantomLocal()
525 {
526 ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
527 m_op = PhantomLocal;
528 m_opInfo = child1()->m_opInfo; // Copy the variableAccessData.
529 children.setChild1(Edge());
530 }
531
532 void convertToGetLocal(VariableAccessData* variable, Node* phi)
533 {
534 ASSERT(m_op == GetLocalUnlinked);
535 m_op = GetLocal;
536 m_opInfo = bitwise_cast<uintptr_t>(variable);
537 m_opInfo2 = 0;
538 children.setChild1(Edge(phi));
539 }
540
541 void convertToToString()
542 {
543 ASSERT(m_op == ToPrimitive);
544 m_op = ToString;
545 }
546
547 JSCell* weakConstant()
548 {
549 ASSERT(op() == WeakJSConstant);
550 return bitwise_cast<JSCell*>(m_opInfo);
551 }
552
553 JSValue valueOfJSConstant(CodeBlock* codeBlock)
554 {
555 switch (op()) {
556 case WeakJSConstant:
557 return JSValue(weakConstant());
558 case JSConstant:
559 case DoubleConstant:
560 case Int52Constant:
561 return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get();
562 case PhantomArguments:
563 return JSValue();
564 default:
565 RELEASE_ASSERT_NOT_REACHED();
566 return JSValue(); // Have to return something in release mode.
567 }
568 }
569
570 bool isInt32Constant(CodeBlock* codeBlock)
571 {
572 return isConstant() && valueOfJSConstant(codeBlock).isInt32();
573 }
574
575 bool isDoubleConstant(CodeBlock* codeBlock)
576 {
577 bool result = isConstant() && valueOfJSConstant(codeBlock).isDouble();
578 if (result)
579 ASSERT(!isInt32Constant(codeBlock));
580 return result;
581 }
582
583 bool isNumberConstant(CodeBlock* codeBlock)
584 {
585 bool result = isConstant() && valueOfJSConstant(codeBlock).isNumber();
586 ASSERT(result == (isInt32Constant(codeBlock) || isDoubleConstant(codeBlock)));
587 return result;
588 }
589
590 bool isMachineIntConstant(CodeBlock* codeBlock)
591 {
592 return isConstant() && valueOfJSConstant(codeBlock).isMachineInt();
593 }
594
595 bool isBooleanConstant(CodeBlock* codeBlock)
596 {
597 return isConstant() && valueOfJSConstant(codeBlock).isBoolean();
598 }
599
600 bool containsMovHint()
601 {
602 switch (op()) {
603 case MovHint:
604 case ZombieHint:
605 return true;
606 default:
607 return false;
608 }
609 }
610
611 bool hasVariableAccessData(Graph&);
612 bool hasLocal(Graph& graph)
613 {
614 return hasVariableAccessData(graph);
615 }
616
617 // This is useful for debugging code, where a node that should have a variable
618 // access data doesn't have one because it hasn't been initialized yet.
619 VariableAccessData* tryGetVariableAccessData()
620 {
621 VariableAccessData* result = reinterpret_cast<VariableAccessData*>(m_opInfo);
622 if (!result)
623 return 0;
624 return result->find();
625 }
626
627 VariableAccessData* variableAccessData()
628 {
629 return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
630 }
631
632 VirtualRegister local()
633 {
634 return variableAccessData()->local();
635 }
636
637 VirtualRegister machineLocal()
638 {
639 return variableAccessData()->machineLocal();
640 }
641
642 bool hasUnlinkedLocal()
643 {
644 switch (op()) {
645 case GetLocalUnlinked:
646 case ExtractOSREntryLocal:
647 case MovHint:
648 case ZombieHint:
649 return true;
650 default:
651 return false;
652 }
653 }
654
655 VirtualRegister unlinkedLocal()
656 {
657 ASSERT(hasUnlinkedLocal());
658 return static_cast<VirtualRegister>(m_opInfo);
659 }
660
661 bool hasUnlinkedMachineLocal()
662 {
663 return op() == GetLocalUnlinked;
664 }
665
666 void setUnlinkedMachineLocal(VirtualRegister reg)
667 {
668 ASSERT(hasUnlinkedMachineLocal());
669 m_opInfo2 = reg.offset();
670 }
671
672 VirtualRegister unlinkedMachineLocal()
673 {
674 ASSERT(hasUnlinkedMachineLocal());
675 return VirtualRegister(m_opInfo2);
676 }
677
678 bool hasPhi()
679 {
680 return op() == Upsilon;
681 }
682
683 Node* phi()
684 {
685 ASSERT(hasPhi());
686 return bitwise_cast<Node*>(m_opInfo);
687 }
688
689 bool isStoreBarrier()
690 {
691 switch (op()) {
692 case StoreBarrier:
693 case StoreBarrierWithNullCheck:
694 return true;
695 default:
696 return false;
697 }
698 }
699
700 bool hasIdentifier()
701 {
702 switch (op()) {
703 case GetById:
704 case GetByIdFlush:
705 case PutById:
706 case PutByIdFlush:
707 case PutByIdDirect:
708 return true;
709 default:
710 return false;
711 }
712 }
713
714 unsigned identifierNumber()
715 {
716 ASSERT(hasIdentifier());
717 return m_opInfo;
718 }
719
720 bool hasArithNodeFlags()
721 {
722 switch (op()) {
723 case UInt32ToNumber:
724 case ArithAdd:
725 case ArithSub:
726 case ArithNegate:
727 case ArithMul:
728 case ArithAbs:
729 case ArithMin:
730 case ArithMax:
731 case ArithMod:
732 case ArithDiv:
733 case ValueAdd:
734 return true;
735 default:
736 return false;
737 }
738 }
739
740 // This corrects the arithmetic node flags, so that irrelevant bits are
741 // ignored. In particular, anything other than ArithMul does not need
742 // to know if it can speculate on negative zero.
743 NodeFlags arithNodeFlags()
744 {
745 NodeFlags result = m_flags & NodeArithFlagsMask;
746 if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == DoubleAsInt32)
747 return result;
748 return result & ~NodeBytecodeNeedsNegZero;
749 }
750
751 bool hasConstantBuffer()
752 {
753 return op() == NewArrayBuffer;
754 }
755
756 NewArrayBufferData* newArrayBufferData()
757 {
758 ASSERT(hasConstantBuffer());
759 return reinterpret_cast<NewArrayBufferData*>(m_opInfo);
760 }
761
762 unsigned startConstant()
763 {
764 return newArrayBufferData()->startConstant;
765 }
766
767 unsigned numConstants()
768 {
769 return newArrayBufferData()->numConstants;
770 }
771
772 bool hasIndexingType()
773 {
774 switch (op()) {
775 case NewArray:
776 case NewArrayWithSize:
777 case NewArrayBuffer:
778 return true;
779 default:
780 return false;
781 }
782 }
783
784 IndexingType indexingType()
785 {
786 ASSERT(hasIndexingType());
787 if (op() == NewArrayBuffer)
788 return newArrayBufferData()->indexingType;
789 return m_opInfo;
790 }
791
792 bool hasTypedArrayType()
793 {
794 switch (op()) {
795 case NewTypedArray:
796 return true;
797 default:
798 return false;
799 }
800 }
801
802 TypedArrayType typedArrayType()
803 {
804 ASSERT(hasTypedArrayType());
805 TypedArrayType result = static_cast<TypedArrayType>(m_opInfo);
806 ASSERT(isTypedView(result));
807 return result;
808 }
809
810 bool hasInlineCapacity()
811 {
812 return op() == CreateThis;
813 }
814
815 unsigned inlineCapacity()
816 {
817 ASSERT(hasInlineCapacity());
818 return m_opInfo;
819 }
820
821 void setIndexingType(IndexingType indexingType)
822 {
823 ASSERT(hasIndexingType());
824 m_opInfo = indexingType;
825 }
826
827 bool hasRegexpIndex()
828 {
829 return op() == NewRegexp;
830 }
831
832 unsigned regexpIndex()
833 {
834 ASSERT(hasRegexpIndex());
835 return m_opInfo;
836 }
837
838 bool hasVarNumber()
839 {
840 return op() == GetClosureVar || op() == PutClosureVar;
841 }
842
843 int varNumber()
844 {
845 ASSERT(hasVarNumber());
846 return m_opInfo;
847 }
848
849 bool hasRegisterPointer()
850 {
851 return op() == GetGlobalVar || op() == PutGlobalVar;
852 }
853
854 WriteBarrier<Unknown>* registerPointer()
855 {
856 return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo);
857 }
858
859 bool hasResult()
860 {
861 return !!result();
862 }
863
864 bool hasInt32Result()
865 {
866 return result() == NodeResultInt32;
867 }
868
869 bool hasInt52Result()
870 {
871 return result() == NodeResultInt52;
872 }
873
874 bool hasNumberResult()
875 {
876 return result() == NodeResultNumber;
877 }
878
879 bool hasDoubleResult()
880 {
881 return result() == NodeResultDouble;
882 }
883
884 bool hasJSResult()
885 {
886 return result() == NodeResultJS;
887 }
888
889 bool hasBooleanResult()
890 {
891 return result() == NodeResultBoolean;
892 }
893
894 bool hasStorageResult()
895 {
896 return result() == NodeResultStorage;
897 }
898
899 UseKind defaultUseKind()
900 {
901 return useKindForResult(result());
902 }
903
904 Edge defaultEdge()
905 {
906 return Edge(this, defaultUseKind());
907 }
908
909 bool isJump()
910 {
911 return op() == Jump;
912 }
913
914 bool isBranch()
915 {
916 return op() == Branch;
917 }
918
919 bool isSwitch()
920 {
921 return op() == Switch;
922 }
923
924 bool isTerminal()
925 {
926 switch (op()) {
927 case Jump:
928 case Branch:
929 case Switch:
930 case Return:
931 case Unreachable:
932 return true;
933 default:
934 return false;
935 }
936 }
937
938 unsigned targetBytecodeOffsetDuringParsing()
939 {
940 ASSERT(isJump());
941 return m_opInfo;
942 }
943
944 BasicBlock*& targetBlock()
945 {
946 ASSERT(isJump());
947 return *bitwise_cast<BasicBlock**>(&m_opInfo);
948 }
949
950 BranchData* branchData()
951 {
952 ASSERT(isBranch());
953 return bitwise_cast<BranchData*>(m_opInfo);
954 }
955
956 SwitchData* switchData()
957 {
958 ASSERT(isSwitch());
959 return bitwise_cast<SwitchData*>(m_opInfo);
960 }
961
962 unsigned numSuccessors()
963 {
964 switch (op()) {
965 case Jump:
966 return 1;
967 case Branch:
968 return 2;
969 case Switch:
970 return switchData()->cases.size() + 1;
971 default:
972 return 0;
973 }
974 }
975
976 BasicBlock*& successor(unsigned index)
977 {
978 if (isSwitch()) {
979 if (index < switchData()->cases.size())
980 return switchData()->cases[index].target.block;
981 RELEASE_ASSERT(index == switchData()->cases.size());
982 return switchData()->fallThrough.block;
983 }
984 switch (index) {
985 case 0:
986 if (isJump())
987 return targetBlock();
988 return branchData()->taken.block;
989 case 1:
990 return branchData()->notTaken.block;
991 default:
992 RELEASE_ASSERT_NOT_REACHED();
993 return targetBlock();
994 }
995 }
996
997 BasicBlock*& successorForCondition(bool condition)
998 {
999 return branchData()->forCondition(condition);
1000 }
1001
1002 bool hasHeapPrediction()
1003 {
1004 switch (op()) {
1005 case GetById:
1006 case GetByIdFlush:
1007 case GetByVal:
1008 case GetMyArgumentByVal:
1009 case GetMyArgumentByValSafe:
1010 case Call:
1011 case Construct:
1012 case GetByOffset:
1013 case MultiGetByOffset:
1014 case GetClosureVar:
1015 case ArrayPop:
1016 case ArrayPush:
1017 case RegExpExec:
1018 case RegExpTest:
1019 case GetGlobalVar:
1020 return true;
1021 default:
1022 return false;
1023 }
1024 }
1025
1026 SpeculatedType getHeapPrediction()
1027 {
1028 ASSERT(hasHeapPrediction());
1029 return static_cast<SpeculatedType>(m_opInfo2);
1030 }
1031
1032 bool predictHeap(SpeculatedType prediction)
1033 {
1034 ASSERT(hasHeapPrediction());
1035
1036 return mergeSpeculation(m_opInfo2, prediction);
1037 }
1038
1039 void setHeapPrediction(SpeculatedType prediction)
1040 {
1041 ASSERT(hasHeapPrediction());
1042 m_opInfo2 = prediction;
1043 }
1044
1045 bool hasFunction()
1046 {
1047 switch (op()) {
1048 case CheckFunction:
1049 case AllocationProfileWatchpoint:
1050 return true;
1051 default:
1052 return false;
1053 }
1054 }
1055
1056 JSCell* function()
1057 {
1058 ASSERT(hasFunction());
1059 JSCell* result = reinterpret_cast<JSFunction*>(m_opInfo);
1060 ASSERT(JSValue(result).isFunction());
1061 return result;
1062 }
1063
1064 bool hasExecutable()
1065 {
1066 return op() == CheckExecutable;
1067 }
1068
1069 ExecutableBase* executable()
1070 {
1071 return jsCast<ExecutableBase*>(reinterpret_cast<JSCell*>(m_opInfo));
1072 }
1073
1074 bool hasVariableWatchpointSet()
1075 {
1076 return op() == NotifyWrite || op() == VariableWatchpoint;
1077 }
1078
1079 VariableWatchpointSet* variableWatchpointSet()
1080 {
1081 return reinterpret_cast<VariableWatchpointSet*>(m_opInfo);
1082 }
1083
1084 bool hasTypedArray()
1085 {
1086 return op() == TypedArrayWatchpoint;
1087 }
1088
1089 JSArrayBufferView* typedArray()
1090 {
1091 return reinterpret_cast<JSArrayBufferView*>(m_opInfo);
1092 }
1093
1094 bool hasStoragePointer()
1095 {
1096 return op() == ConstantStoragePointer;
1097 }
1098
1099 void* storagePointer()
1100 {
1101 return reinterpret_cast<void*>(m_opInfo);
1102 }
1103
1104 bool hasStructureTransitionData()
1105 {
1106 switch (op()) {
1107 case PutStructure:
1108 case PhantomPutStructure:
1109 case AllocatePropertyStorage:
1110 case ReallocatePropertyStorage:
1111 return true;
1112 default:
1113 return false;
1114 }
1115 }
1116
1117 StructureTransitionData& structureTransitionData()
1118 {
1119 ASSERT(hasStructureTransitionData());
1120 return *reinterpret_cast<StructureTransitionData*>(m_opInfo);
1121 }
1122
1123 bool hasStructureSet()
1124 {
1125 switch (op()) {
1126 case CheckStructure:
1127 return true;
1128 default:
1129 return false;
1130 }
1131 }
1132
1133 StructureSet& structureSet()
1134 {
1135 ASSERT(hasStructureSet());
1136 return *reinterpret_cast<StructureSet*>(m_opInfo);
1137 }
1138
1139 bool hasStructure()
1140 {
1141 switch (op()) {
1142 case StructureTransitionWatchpoint:
1143 case ArrayifyToStructure:
1144 case NewObject:
1145 case NewStringObject:
1146 return true;
1147 default:
1148 return false;
1149 }
1150 }
1151
1152 Structure* structure()
1153 {
1154 ASSERT(hasStructure());
1155 return reinterpret_cast<Structure*>(m_opInfo);
1156 }
1157
1158 bool hasStorageAccessData()
1159 {
1160 return op() == GetByOffset || op() == PutByOffset;
1161 }
1162
1163 unsigned storageAccessDataIndex()
1164 {
1165 ASSERT(hasStorageAccessData());
1166 return m_opInfo;
1167 }
1168
1169 bool hasMultiGetByOffsetData()
1170 {
1171 return op() == MultiGetByOffset;
1172 }
1173
1174 MultiGetByOffsetData& multiGetByOffsetData()
1175 {
1176 return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo);
1177 }
1178
1179 bool hasMultiPutByOffsetData()
1180 {
1181 return op() == MultiPutByOffset;
1182 }
1183
1184 MultiPutByOffsetData& multiPutByOffsetData()
1185 {
1186 return *reinterpret_cast<MultiPutByOffsetData*>(m_opInfo);
1187 }
1188
1189 bool hasFunctionDeclIndex()
1190 {
1191 return op() == NewFunction
1192 || op() == NewFunctionNoCheck;
1193 }
1194
1195 unsigned functionDeclIndex()
1196 {
1197 ASSERT(hasFunctionDeclIndex());
1198 return m_opInfo;
1199 }
1200
1201 bool hasFunctionExprIndex()
1202 {
1203 return op() == NewFunctionExpression;
1204 }
1205
1206 unsigned functionExprIndex()
1207 {
1208 ASSERT(hasFunctionExprIndex());
1209 return m_opInfo;
1210 }
1211
1212 bool hasSymbolTable()
1213 {
1214 return op() == FunctionReentryWatchpoint;
1215 }
1216
1217 SymbolTable* symbolTable()
1218 {
1219 ASSERT(hasSymbolTable());
1220 return reinterpret_cast<SymbolTable*>(m_opInfo);
1221 }
1222
1223 bool hasArrayMode()
1224 {
1225 switch (op()) {
1226 case GetIndexedPropertyStorage:
1227 case GetArrayLength:
1228 case PutByValDirect:
1229 case PutByVal:
1230 case PutByValAlias:
1231 case GetByVal:
1232 case StringCharAt:
1233 case StringCharCodeAt:
1234 case CheckArray:
1235 case Arrayify:
1236 case ArrayifyToStructure:
1237 case ArrayPush:
1238 case ArrayPop:
1239 return true;
1240 default:
1241 return false;
1242 }
1243 }
1244
1245 ArrayMode arrayMode()
1246 {
1247 ASSERT(hasArrayMode());
1248 if (op() == ArrayifyToStructure)
1249 return ArrayMode::fromWord(m_opInfo2);
1250 return ArrayMode::fromWord(m_opInfo);
1251 }
1252
1253 bool setArrayMode(ArrayMode arrayMode)
1254 {
1255 ASSERT(hasArrayMode());
1256 if (this->arrayMode() == arrayMode)
1257 return false;
1258 m_opInfo = arrayMode.asWord();
1259 return true;
1260 }
1261
1262 bool hasArithMode()
1263 {
1264 switch (op()) {
1265 case ArithAdd:
1266 case ArithSub:
1267 case ArithNegate:
1268 case ArithMul:
1269 case ArithDiv:
1270 case ArithMod:
1271 case UInt32ToNumber:
1272 case DoubleAsInt32:
1273 return true;
1274 default:
1275 return false;
1276 }
1277 }
1278
1279 Arith::Mode arithMode()
1280 {
1281 ASSERT(hasArithMode());
1282 return static_cast<Arith::Mode>(m_opInfo);
1283 }
1284
1285 void setArithMode(Arith::Mode mode)
1286 {
1287 m_opInfo = mode;
1288 }
1289
1290 bool hasVirtualRegister()
1291 {
1292 return m_virtualRegister.isValid();
1293 }
1294
1295 VirtualRegister virtualRegister()
1296 {
1297 ASSERT(hasResult());
1298 ASSERT(m_virtualRegister.isValid());
1299 return m_virtualRegister;
1300 }
1301
1302 void setVirtualRegister(VirtualRegister virtualRegister)
1303 {
1304 ASSERT(hasResult());
1305 ASSERT(!m_virtualRegister.isValid());
1306 m_virtualRegister = virtualRegister;
1307 }
1308
1309 bool hasExecutionCounter()
1310 {
1311 return op() == CountExecution;
1312 }
1313
1314 Profiler::ExecutionCounter* executionCounter()
1315 {
1316 return bitwise_cast<Profiler::ExecutionCounter*>(m_opInfo);
1317 }
1318
1319 bool shouldGenerate()
1320 {
1321 return m_refCount;
1322 }
1323
1324 bool willHaveCodeGenOrOSR()
1325 {
1326 switch (op()) {
1327 case SetLocal:
1328 case MovHint:
1329 case ZombieHint:
1330 case PhantomArguments:
1331 return true;
1332 case Phantom:
1333 case HardPhantom:
1334 return child1().useKindUnchecked() != UntypedUse || child2().useKindUnchecked() != UntypedUse || child3().useKindUnchecked() != UntypedUse;
1335 default:
1336 return shouldGenerate();
1337 }
1338 }
1339
1340 bool isSemanticallySkippable()
1341 {
1342 return op() == CountExecution;
1343 }
1344
1345 unsigned refCount()
1346 {
1347 return m_refCount;
1348 }
1349
1350 unsigned postfixRef()
1351 {
1352 return m_refCount++;
1353 }
1354
1355 unsigned adjustedRefCount()
1356 {
1357 return mustGenerate() ? m_refCount - 1 : m_refCount;
1358 }
1359
1360 void setRefCount(unsigned refCount)
1361 {
1362 m_refCount = refCount;
1363 }
1364
1365 Edge& child1()
1366 {
1367 ASSERT(!(m_flags & NodeHasVarArgs));
1368 return children.child1();
1369 }
1370
1371 // This is useful if you want to do a fast check on the first child
1372 // before also doing a check on the opcode. Use this with care and
1373 // avoid it if possible.
1374 Edge child1Unchecked()
1375 {
1376 return children.child1Unchecked();
1377 }
1378
1379 Edge& child2()
1380 {
1381 ASSERT(!(m_flags & NodeHasVarArgs));
1382 return children.child2();
1383 }
1384
1385 Edge& child3()
1386 {
1387 ASSERT(!(m_flags & NodeHasVarArgs));
1388 return children.child3();
1389 }
1390
1391 unsigned firstChild()
1392 {
1393 ASSERT(m_flags & NodeHasVarArgs);
1394 return children.firstChild();
1395 }
1396
1397 unsigned numChildren()
1398 {
1399 ASSERT(m_flags & NodeHasVarArgs);
1400 return children.numChildren();
1401 }
1402
1403 UseKind binaryUseKind()
1404 {
1405 ASSERT(child1().useKind() == child2().useKind());
1406 return child1().useKind();
1407 }
1408
1409 bool isBinaryUseKind(UseKind left, UseKind right)
1410 {
1411 return child1().useKind() == left && child2().useKind() == right;
1412 }
1413
1414 bool isBinaryUseKind(UseKind useKind)
1415 {
1416 return isBinaryUseKind(useKind, useKind);
1417 }
1418
1419 Edge childFor(UseKind useKind)
1420 {
1421 if (child1().useKind() == useKind)
1422 return child1();
1423 if (child2().useKind() == useKind)
1424 return child2();
1425 if (child3().useKind() == useKind)
1426 return child3();
1427 return Edge();
1428 }
1429
1430 SpeculatedType prediction()
1431 {
1432 return m_prediction;
1433 }
1434
1435 bool predict(SpeculatedType prediction)
1436 {
1437 return mergeSpeculation(m_prediction, prediction);
1438 }
1439
1440 bool shouldSpeculateInt32()
1441 {
1442 return isInt32Speculation(prediction());
1443 }
1444
1445 bool sawBooleans()
1446 {
1447 return !!(prediction() & SpecBoolean);
1448 }
1449
1450 bool shouldSpeculateInt32OrBoolean()
1451 {
1452 return isInt32OrBooleanSpeculation(prediction());
1453 }
1454
1455 bool shouldSpeculateInt32ForArithmetic()
1456 {
1457 return isInt32SpeculationForArithmetic(prediction());
1458 }
1459
1460 bool shouldSpeculateInt32OrBooleanForArithmetic()
1461 {
1462 return isInt32OrBooleanSpeculationForArithmetic(prediction());
1463 }
1464
1465 bool shouldSpeculateInt32OrBooleanExpectingDefined()
1466 {
1467 return isInt32OrBooleanSpeculationExpectingDefined(prediction());
1468 }
1469
1470 bool shouldSpeculateMachineInt()
1471 {
1472 return isMachineIntSpeculation(prediction());
1473 }
1474
1475 bool shouldSpeculateDouble()
1476 {
1477 return isDoubleSpeculation(prediction());
1478 }
1479
1480 bool shouldSpeculateNumber()
1481 {
1482 return isFullNumberSpeculation(prediction());
1483 }
1484
1485 bool shouldSpeculateNumberOrBoolean()
1486 {
1487 return isFullNumberOrBooleanSpeculation(prediction());
1488 }
1489
1490 bool shouldSpeculateNumberOrBooleanExpectingDefined()
1491 {
1492 return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
1493 }
1494
1495 bool shouldSpeculateBoolean()
1496 {
1497 return isBooleanSpeculation(prediction());
1498 }
1499
1500 bool shouldSpeculateOther()
1501 {
1502 return isOtherSpeculation(prediction());
1503 }
1504
1505 bool shouldSpeculateMisc()
1506 {
1507 return isMiscSpeculation(prediction());
1508 }
1509
1510 bool shouldSpeculateStringIdent()
1511 {
1512 return isStringIdentSpeculation(prediction());
1513 }
1514
1515 bool shouldSpeculateNotStringVar()
1516 {
1517 return isNotStringVarSpeculation(prediction());
1518 }
1519
1520 bool shouldSpeculateString()
1521 {
1522 return isStringSpeculation(prediction());
1523 }
1524
1525 bool shouldSpeculateStringObject()
1526 {
1527 return isStringObjectSpeculation(prediction());
1528 }
1529
1530 bool shouldSpeculateStringOrStringObject()
1531 {
1532 return isStringOrStringObjectSpeculation(prediction());
1533 }
1534
1535 bool shouldSpeculateFinalObject()
1536 {
1537 return isFinalObjectSpeculation(prediction());
1538 }
1539
1540 bool shouldSpeculateFinalObjectOrOther()
1541 {
1542 return isFinalObjectOrOtherSpeculation(prediction());
1543 }
1544
1545 bool shouldSpeculateArray()
1546 {
1547 return isArraySpeculation(prediction());
1548 }
1549
1550 bool shouldSpeculateArguments()
1551 {
1552 return isArgumentsSpeculation(prediction());
1553 }
1554
1555 bool shouldSpeculateInt8Array()
1556 {
1557 return isInt8ArraySpeculation(prediction());
1558 }
1559
1560 bool shouldSpeculateInt16Array()
1561 {
1562 return isInt16ArraySpeculation(prediction());
1563 }
1564
1565 bool shouldSpeculateInt32Array()
1566 {
1567 return isInt32ArraySpeculation(prediction());
1568 }
1569
1570 bool shouldSpeculateUint8Array()
1571 {
1572 return isUint8ArraySpeculation(prediction());
1573 }
1574
1575 bool shouldSpeculateUint8ClampedArray()
1576 {
1577 return isUint8ClampedArraySpeculation(prediction());
1578 }
1579
1580 bool shouldSpeculateUint16Array()
1581 {
1582 return isUint16ArraySpeculation(prediction());
1583 }
1584
1585 bool shouldSpeculateUint32Array()
1586 {
1587 return isUint32ArraySpeculation(prediction());
1588 }
1589
1590 bool shouldSpeculateFloat32Array()
1591 {
1592 return isFloat32ArraySpeculation(prediction());
1593 }
1594
1595 bool shouldSpeculateFloat64Array()
1596 {
1597 return isFloat64ArraySpeculation(prediction());
1598 }
1599
1600 bool shouldSpeculateArrayOrOther()
1601 {
1602 return isArrayOrOtherSpeculation(prediction());
1603 }
1604
1605 bool shouldSpeculateObject()
1606 {
1607 return isObjectSpeculation(prediction());
1608 }
1609
1610 bool shouldSpeculateObjectOrOther()
1611 {
1612 return isObjectOrOtherSpeculation(prediction());
1613 }
1614
1615 bool shouldSpeculateCell()
1616 {
1617 return isCellSpeculation(prediction());
1618 }
1619
1620 static bool shouldSpeculateBoolean(Node* op1, Node* op2)
1621 {
1622 return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
1623 }
1624
1625 static bool shouldSpeculateInt32(Node* op1, Node* op2)
1626 {
1627 return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
1628 }
1629
1630 static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
1631 {
1632 return op1->shouldSpeculateInt32OrBoolean()
1633 && op2->shouldSpeculateInt32OrBoolean();
1634 }
1635
1636 static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
1637 {
1638 return op1->shouldSpeculateInt32OrBooleanForArithmetic()
1639 && op2->shouldSpeculateInt32OrBooleanForArithmetic();
1640 }
1641
1642 static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
1643 {
1644 return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
1645 && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
1646 }
1647
1648 static bool shouldSpeculateMachineInt(Node* op1, Node* op2)
1649 {
1650 return op1->shouldSpeculateMachineInt() && op2->shouldSpeculateMachineInt();
1651 }
1652
1653 static bool shouldSpeculateNumber(Node* op1, Node* op2)
1654 {
1655 return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
1656 }
1657
1658 static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2)
1659 {
1660 return op1->shouldSpeculateNumberOrBoolean()
1661 && op2->shouldSpeculateNumberOrBoolean();
1662 }
1663
1664 static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2)
1665 {
1666 return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
1667 && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
1668 }
1669
1670 static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
1671 {
1672 return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
1673 }
1674
1675 static bool shouldSpeculateArray(Node* op1, Node* op2)
1676 {
1677 return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
1678 }
1679
1680 bool canSpeculateInt32(RareCaseProfilingSource source)
1681 {
1682 return nodeCanSpeculateInt32(arithNodeFlags(), source);
1683 }
1684
1685 bool canSpeculateInt52(RareCaseProfilingSource source)
1686 {
1687 return nodeCanSpeculateInt52(arithNodeFlags(), source);
1688 }
1689
1690 RareCaseProfilingSource sourceFor(PredictionPass pass)
1691 {
1692 if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
1693 return DFGRareCase;
1694 return AllRareCases;
1695 }
1696
1697 bool canSpeculateInt32(PredictionPass pass)
1698 {
1699 return canSpeculateInt32(sourceFor(pass));
1700 }
1701
1702 bool canSpeculateInt52(PredictionPass pass)
1703 {
1704 return canSpeculateInt52(sourceFor(pass));
1705 }
1706
1707 void dumpChildren(PrintStream& out)
1708 {
1709 if (!child1())
1710 return;
1711 out.printf("@%u", child1()->index());
1712 if (!child2())
1713 return;
1714 out.printf(", @%u", child2()->index());
1715 if (!child3())
1716 return;
1717 out.printf(", @%u", child3()->index());
1718 }
1719
1720 // NB. This class must have a trivial destructor.
1721
1722 NodeOrigin origin;
1723
1724 // References to up to 3 children, or links to a variable length set of children.
1725 AdjacencyList children;
1726
1727private:
1728 unsigned m_op : 10; // real type is NodeType
1729 unsigned m_flags : 22;
1730 // The virtual register number (spill location) associated with this .
1731 VirtualRegister m_virtualRegister;
1732 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
1733 unsigned m_refCount;
1734 // The prediction ascribed to this node after propagation.
1735 SpeculatedType m_prediction;
1736 // Immediate values, accesses type-checked via accessors above. The first one is
1737 // big enough to store a pointer.
1738 uintptr_t m_opInfo;
1739 uintptr_t m_opInfo2;
1740
1741public:
1742 // Fields used by various analyses.
1743 AbstractValue value;
1744
1745 // Miscellaneous data that is usually meaningless, but can hold some analysis results
1746 // if you ask right. For example, if you do Graph::initializeNodeOwners(), misc.owner
1747 // will tell you which basic block a node belongs to. You cannot rely on this persisting
1748 // across transformations unless you do the maintenance work yourself. Other phases use
1749 // misc.replacement, but they do so manually: first you do Graph::clearReplacements()
1750 // and then you set, and use, replacement's yourself.
1751 //
1752 // Bottom line: don't use these fields unless you initialize them yourself, or by
1753 // calling some appropriate methods that initialize them the way you want. Otherwise,
1754 // these fields are meaningless.
1755 union {
1756 Node* replacement;
1757 BasicBlock* owner;
1758 } misc;
1759};
1760
1761inline bool nodeComparator(Node* a, Node* b)
1762{
1763 return a->index() < b->index();
1764}
1765
1766template<typename T>
1767CString nodeListDump(const T& nodeList)
1768{
1769 return sortedListDump(nodeList, nodeComparator);
1770}
1771
1772template<typename T>
1773CString nodeMapDump(const T& nodeMap, DumpContext* context = 0)
1774{
1775 Vector<typename T::KeyType> keys;
1776 for (
1777 typename T::const_iterator iter = nodeMap.begin();
1778 iter != nodeMap.end(); ++iter)
1779 keys.append(iter->key);
1780 std::sort(keys.begin(), keys.end(), nodeComparator);
1781 StringPrintStream out;
1782 CommaPrinter comma;
1783 for(unsigned i = 0; i < keys.size(); ++i)
1784 out.print(comma, keys[i], "=>", inContext(nodeMap.get(keys[i]), context));
1785 return out.toCString();
1786}
1787
1788} } // namespace JSC::DFG
1789
1790namespace WTF {
1791
1792void printInternal(PrintStream&, JSC::DFG::SwitchKind);
1793void printInternal(PrintStream&, JSC::DFG::Node*);
1794
1795inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
1796
1797} // namespace WTF
1798
1799using WTF::inContext;
1800
1801#endif
1802#endif