]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGNode.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / dfg / DFGNode.h
CommitLineData
14957cd0 1/*
81345200 2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
14957cd0
A
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
14957cd0
A
29#if ENABLE(DFG_JIT)
30
6fe7ccc8 31#include "CodeBlock.h"
93a37866 32#include "DFGAbstractValue.h"
6fe7ccc8 33#include "DFGAdjacencyList.h"
81345200 34#include "DFGArithMode.h"
93a37866 35#include "DFGArrayMode.h"
6fe7ccc8 36#include "DFGCommon.h"
81345200 37#include "DFGLazyJSValue.h"
6fe7ccc8 38#include "DFGNodeFlags.h"
81345200 39#include "DFGNodeOrigin.h"
6fe7ccc8 40#include "DFGNodeType.h"
81345200 41#include "DFGUseKind.h"
6fe7ccc8 42#include "DFGVariableAccessData.h"
81345200 43#include "GetByIdVariant.h"
93a37866 44#include "JSCJSValue.h"
6fe7ccc8 45#include "Operands.h"
81345200 46#include "PutByIdVariant.h"
93a37866
A
47#include "SpeculatedType.h"
48#include "StructureSet.h"
6fe7ccc8 49#include "ValueProfile.h"
81345200 50#include <wtf/ListDump.h>
14957cd0
A
51
52namespace JSC { namespace DFG {
53
81345200
A
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
6fe7ccc8
A
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 }
14957cd0
A
81};
82
93a37866
A
83struct NewArrayBufferData {
84 unsigned startConstant;
85 unsigned numConstants;
86 IndexingType indexingType;
87};
88
81345200
A
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
14957cd0
A
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 -
93a37866 198// a constant index, argument, or identifier) from a Node*.
14957cd0 199struct OpInfo {
6fe7ccc8
A
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;
14957cd0
A
207};
208
209// === Node ===
210//
211// Node represents a single operation in the data flow graph.
212struct Node {
6fe7ccc8 213 enum VarArgTag { VarArg };
93a37866
A
214
215 Node() { }
216
81345200
A
217 Node(NodeType op, NodeOrigin nodeOrigin, const AdjacencyList& children)
218 : origin(nodeOrigin)
93a37866 219 , children(children)
81345200 220 , m_virtualRegister(VirtualRegister())
93a37866
A
221 , m_refCount(1)
222 , m_prediction(SpecNone)
223 {
81345200 224 misc.replacement = 0;
93a37866
A
225 setOpAndDefaultFlags(op);
226 }
227
14957cd0 228 // Construct a node with up to 3 children, no immediate value.
81345200
A
229 Node(NodeType op, NodeOrigin nodeOrigin, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
230 : origin(nodeOrigin)
6fe7ccc8 231 , children(AdjacencyList::Fixed, child1, child2, child3)
81345200 232 , m_virtualRegister(VirtualRegister())
93a37866
A
233 , m_refCount(1)
234 , m_prediction(SpecNone)
81345200
A
235 , m_opInfo(0)
236 , m_opInfo2(0)
14957cd0 237 {
81345200 238 misc.replacement = 0;
6fe7ccc8
A
239 setOpAndDefaultFlags(op);
240 ASSERT(!(m_flags & NodeHasVarArgs));
14957cd0
A
241 }
242
81345200
A
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
14957cd0 259 // Construct a node with up to 3 children and an immediate value.
81345200
A
260 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
261 : origin(nodeOrigin)
6fe7ccc8 262 , children(AdjacencyList::Fixed, child1, child2, child3)
81345200 263 , m_virtualRegister(VirtualRegister())
93a37866 264 , m_refCount(1)
81345200 265 , m_prediction(SpecNone)
14957cd0 266 , m_opInfo(imm.m_value)
81345200
A
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)
93a37866 280 , m_prediction(SpecNone)
81345200
A
281 , m_opInfo(imm.m_value)
282 , m_opInfo2(0)
14957cd0 283 {
81345200 284 misc.replacement = 0;
6fe7ccc8 285 setOpAndDefaultFlags(op);
81345200 286 setResult(result);
6fe7ccc8 287 ASSERT(!(m_flags & NodeHasVarArgs));
14957cd0
A
288 }
289
290 // Construct a node with up to 3 children and two immediate values.
81345200
A
291 Node(NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, Edge child1 = Edge(), Edge child2 = Edge(), Edge child3 = Edge())
292 : origin(nodeOrigin)
6fe7ccc8 293 , children(AdjacencyList::Fixed, child1, child2, child3)
81345200 294 , m_virtualRegister(VirtualRegister())
93a37866 295 , m_refCount(1)
93a37866 296 , m_prediction(SpecNone)
81345200
A
297 , m_opInfo(imm1.m_value)
298 , m_opInfo2(imm2.m_value)
6fe7ccc8 299 {
81345200 300 misc.replacement = 0;
6fe7ccc8
A
301 setOpAndDefaultFlags(op);
302 ASSERT(!(m_flags & NodeHasVarArgs));
303 }
304
305 // Construct a node with a variable number of children and two immediate values.
81345200
A
306 Node(VarArgTag, NodeType op, NodeOrigin nodeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren)
307 : origin(nodeOrigin)
6fe7ccc8 308 , children(AdjacencyList::Variable, firstChild, numChildren)
81345200 309 , m_virtualRegister(VirtualRegister())
93a37866 310 , m_refCount(1)
93a37866 311 , m_prediction(SpecNone)
81345200
A
312 , m_opInfo(imm1.m_value)
313 , m_opInfo2(imm2.m_value)
6fe7ccc8 314 {
81345200 315 misc.replacement = 0;
6fe7ccc8
A
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
93a37866
A
323 // This is not a fast method.
324 unsigned index() const;
325
6fe7ccc8
A
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 {
93a37866 338 ASSERT(!(flags & NodeDoesNotExit));
6fe7ccc8
A
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 {
93a37866 348 ASSERT(flags & NodeDoesNotExit);
6fe7ccc8
A
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
81345200 361 void setResult(NodeFlags result)
14957cd0 362 {
81345200
A
363 ASSERT(!(result & ~NodeResultMask));
364 clearFlags(NodeResultMask);
365 mergeFlags(result);
14957cd0 366 }
81345200
A
367
368 NodeFlags result() const
93a37866 369 {
81345200 370 return flags() & NodeResultMask;
93a37866 371 }
81345200
A
372
373 void setOpAndDefaultFlags(NodeType op)
93a37866
A
374 {
375 m_op = op;
81345200 376 m_flags = defaultFlags(op);
93a37866
A
377 }
378
379 void convertToPhantom()
380 {
81345200 381 setOpAndDefaultFlags(Phantom);
93a37866
A
382 }
383
384 void convertToPhantomUnchecked()
385 {
81345200 386 setOpAndDefaultFlags(Phantom);
93a37866
A
387 }
388
81345200 389 void convertToIdentity();
93a37866 390
14957cd0
A
391 bool mustGenerate()
392 {
6fe7ccc8 393 return m_flags & NodeMustGenerate;
14957cd0 394 }
93a37866
A
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
14957cd0
A
409 bool isConstant()
410 {
81345200
A
411 switch (op()) {
412 case JSConstant:
413 case DoubleConstant:
414 case Int52Constant:
415 return true;
416 default:
417 return false;
418 }
6fe7ccc8
A
419 }
420
421 bool isWeakConstant()
422 {
423 return op() == WeakJSConstant;
424 }
425
93a37866
A
426 bool isPhantomArguments()
427 {
428 return op() == PhantomArguments;
429 }
430
6fe7ccc8
A
431 bool hasConstant()
432 {
93a37866
A
433 switch (op()) {
434 case JSConstant:
81345200
A
435 case DoubleConstant:
436 case Int52Constant:
93a37866
A
437 case WeakJSConstant:
438 case PhantomArguments:
439 return true;
440 default:
441 return false;
442 }
14957cd0
A
443 }
444
445 unsigned constantNumber()
446 {
447 ASSERT(isConstant());
448 return m_opInfo;
449 }
6fe7ccc8 450
93a37866
A
451 void convertToConstant(unsigned constantNumber)
452 {
81345200
A
453 if (hasDoubleResult())
454 m_op = DoubleConstant;
455 else if (hasInt52Result())
456 m_op = Int52Constant;
457 else
458 m_op = JSConstant;
93a37866
A
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
81345200
A
472 void convertToConstantStoragePointer(void* pointer)
473 {
474 ASSERT(op() == GetIndexedPropertyStorage);
475 m_op = ConstantStoragePointer;
476 m_opInfo = bitwise_cast<uintptr_t>(pointer);
477 }
478
93a37866
A
479 void convertToGetLocalUnlinked(VirtualRegister local)
480 {
481 m_op = GetLocalUnlinked;
482 m_flags &= ~(NodeMustGenerate | NodeMightClobber | NodeClobbersWorld);
81345200
A
483 m_opInfo = local.offset();
484 m_opInfo2 = VirtualRegister().offset();
93a37866
A
485 children.reset();
486 }
487
488 void convertToStructureTransitionWatchpoint(Structure* structure)
489 {
81345200
A
490 ASSERT(m_op == CheckStructure || m_op == ArrayifyToStructure);
491 ASSERT(!child2());
492 ASSERT(!child3());
93a37866 493 m_opInfo = bitwise_cast<uintptr_t>(structure);
81345200 494 m_op = StructureTransitionWatchpoint;
93a37866
A
495 }
496
497 void convertToStructureTransitionWatchpoint()
498 {
499 convertToStructureTransitionWatchpoint(structureSet().singletonStructure());
500 }
501
502 void convertToGetByOffset(unsigned storageAccessDataIndex, Edge storage)
503 {
81345200 504 ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
93a37866 505 m_opInfo = storageAccessDataIndex;
81345200
A
506 children.setChild2(children.child1());
507 children.child2().setUseKind(KnownCellUse);
93a37866
A
508 children.setChild1(storage);
509 m_op = GetByOffset;
510 m_flags &= ~NodeClobbersWorld;
511 }
512
513 void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage)
514 {
81345200 515 ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == MultiPutByOffset);
93a37866
A
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);
81345200 537 m_opInfo2 = 0;
93a37866
A
538 children.setChild1(Edge(phi));
539 }
540
541 void convertToToString()
542 {
543 ASSERT(m_op == ToPrimitive);
544 m_op = ToString;
545 }
546
6fe7ccc8
A
547 JSCell* weakConstant()
548 {
93a37866 549 ASSERT(op() == WeakJSConstant);
6fe7ccc8
A
550 return bitwise_cast<JSCell*>(m_opInfo);
551 }
552
553 JSValue valueOfJSConstant(CodeBlock* codeBlock)
554 {
93a37866
A
555 switch (op()) {
556 case WeakJSConstant:
6fe7ccc8 557 return JSValue(weakConstant());
93a37866 558 case JSConstant:
81345200
A
559 case DoubleConstant:
560 case Int52Constant:
93a37866
A
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 }
6fe7ccc8 568 }
14957cd0 569
6fe7ccc8
A
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
81345200
A
590 bool isMachineIntConstant(CodeBlock* codeBlock)
591 {
592 return isConstant() && valueOfJSConstant(codeBlock).isMachineInt();
593 }
594
6fe7ccc8
A
595 bool isBooleanConstant(CodeBlock* codeBlock)
596 {
597 return isConstant() && valueOfJSConstant(codeBlock).isBoolean();
598 }
599
93a37866
A
600 bool containsMovHint()
601 {
602 switch (op()) {
93a37866 603 case MovHint:
93a37866
A
604 case ZombieHint:
605 return true;
606 default:
607 return false;
608 }
609 }
610
81345200
A
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()
6fe7ccc8
A
643 {
644 switch (op()) {
81345200
A
645 case GetLocalUnlinked:
646 case ExtractOSREntryLocal:
93a37866 647 case MovHint:
93a37866 648 case ZombieHint:
6fe7ccc8
A
649 return true;
650 default:
651 return false;
652 }
653 }
654
81345200 655 VirtualRegister unlinkedLocal()
14957cd0 656 {
81345200
A
657 ASSERT(hasUnlinkedLocal());
658 return static_cast<VirtualRegister>(m_opInfo);
14957cd0 659 }
6fe7ccc8 660
81345200 661 bool hasUnlinkedMachineLocal()
6fe7ccc8 662 {
81345200 663 return op() == GetLocalUnlinked;
6fe7ccc8
A
664 }
665
81345200 666 void setUnlinkedMachineLocal(VirtualRegister reg)
14957cd0 667 {
81345200
A
668 ASSERT(hasUnlinkedMachineLocal());
669 m_opInfo2 = reg.offset();
14957cd0 670 }
6fe7ccc8 671
81345200 672 VirtualRegister unlinkedMachineLocal()
93a37866 673 {
81345200
A
674 ASSERT(hasUnlinkedMachineLocal());
675 return VirtualRegister(m_opInfo2);
93a37866
A
676 }
677
81345200
A
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
14957cd0
A
700 bool hasIdentifier()
701 {
6fe7ccc8
A
702 switch (op()) {
703 case GetById:
704 case GetByIdFlush:
705 case PutById:
81345200 706 case PutByIdFlush:
6fe7ccc8 707 case PutByIdDirect:
6fe7ccc8
A
708 return true;
709 default:
710 return false;
711 }
14957cd0
A
712 }
713
714 unsigned identifierNumber()
715 {
716 ASSERT(hasIdentifier());
717 return m_opInfo;
718 }
6fe7ccc8 719
6fe7ccc8
A
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 {
93a37866
A
745 NodeFlags result = m_flags & NodeArithFlagsMask;
746 if (op() == ArithMul || op() == ArithDiv || op() == ArithMod || op() == ArithNegate || op() == DoubleAsInt32)
6fe7ccc8 747 return result;
81345200 748 return result & ~NodeBytecodeNeedsNegZero;
6fe7ccc8
A
749 }
750
751 bool hasConstantBuffer()
752 {
753 return op() == NewArrayBuffer;
754 }
755
93a37866 756 NewArrayBufferData* newArrayBufferData()
6fe7ccc8
A
757 {
758 ASSERT(hasConstantBuffer());
93a37866
A
759 return reinterpret_cast<NewArrayBufferData*>(m_opInfo);
760 }
761
762 unsigned startConstant()
763 {
764 return newArrayBufferData()->startConstant;
6fe7ccc8
A
765 }
766
767 unsigned numConstants()
768 {
93a37866
A
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
81345200
A
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
93a37866
A
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;
6fe7ccc8
A
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
14957cd0
A
838 bool hasVarNumber()
839 {
81345200 840 return op() == GetClosureVar || op() == PutClosureVar;
14957cd0
A
841 }
842
81345200 843 int varNumber()
14957cd0
A
844 {
845 ASSERT(hasVarNumber());
846 return m_opInfo;
847 }
93a37866 848
93a37866
A
849 bool hasRegisterPointer()
850 {
81345200 851 return op() == GetGlobalVar || op() == PutGlobalVar;
93a37866
A
852 }
853
854 WriteBarrier<Unknown>* registerPointer()
855 {
856 return bitwise_cast<WriteBarrier<Unknown>*>(m_opInfo);
6fe7ccc8 857 }
81345200 858
14957cd0
A
859 bool hasResult()
860 {
81345200 861 return !!result();
14957cd0
A
862 }
863
864 bool hasInt32Result()
865 {
81345200
A
866 return result() == NodeResultInt32;
867 }
868
869 bool hasInt52Result()
870 {
871 return result() == NodeResultInt52;
14957cd0 872 }
6fe7ccc8
A
873
874 bool hasNumberResult()
14957cd0 875 {
81345200
A
876 return result() == NodeResultNumber;
877 }
878
879 bool hasDoubleResult()
880 {
881 return result() == NodeResultDouble;
14957cd0 882 }
6fe7ccc8 883
14957cd0
A
884 bool hasJSResult()
885 {
81345200 886 return result() == NodeResultJS;
14957cd0 887 }
6fe7ccc8
A
888
889 bool hasBooleanResult()
14957cd0 890 {
81345200 891 return result() == NodeResultBoolean;
14957cd0
A
892 }
893
93a37866
A
894 bool hasStorageResult()
895 {
81345200
A
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());
93a37866
A
907 }
908
6fe7ccc8 909 bool isJump()
14957cd0 910 {
6fe7ccc8 911 return op() == Jump;
14957cd0
A
912 }
913
6fe7ccc8 914 bool isBranch()
14957cd0 915 {
6fe7ccc8 916 return op() == Branch;
14957cd0 917 }
81345200
A
918
919 bool isSwitch()
920 {
921 return op() == Switch;
922 }
14957cd0 923
6fe7ccc8 924 bool isTerminal()
14957cd0 925 {
6fe7ccc8
A
926 switch (op()) {
927 case Jump:
928 case Branch:
81345200 929 case Switch:
6fe7ccc8 930 case Return:
12899fa2 931 case Unreachable:
6fe7ccc8
A
932 return true;
933 default:
934 return false;
935 }
14957cd0
A
936 }
937
81345200 938 unsigned targetBytecodeOffsetDuringParsing()
14957cd0 939 {
81345200 940 ASSERT(isJump());
6fe7ccc8 941 return m_opInfo;
14957cd0
A
942 }
943
81345200 944 BasicBlock*& targetBlock()
14957cd0 945 {
81345200
A
946 ASSERT(isJump());
947 return *bitwise_cast<BasicBlock**>(&m_opInfo);
14957cd0 948 }
6fe7ccc8 949
81345200 950 BranchData* branchData()
14957cd0 951 {
6fe7ccc8 952 ASSERT(isBranch());
81345200 953 return bitwise_cast<BranchData*>(m_opInfo);
14957cd0 954 }
6fe7ccc8 955
81345200 956 SwitchData* switchData()
14957cd0 957 {
81345200
A
958 ASSERT(isSwitch());
959 return bitwise_cast<SwitchData*>(m_opInfo);
6fe7ccc8
A
960 }
961
93a37866
A
962 unsigned numSuccessors()
963 {
964 switch (op()) {
965 case Jump:
966 return 1;
967 case Branch:
968 return 2;
81345200
A
969 case Switch:
970 return switchData()->cases.size() + 1;
93a37866
A
971 default:
972 return 0;
973 }
974 }
975
81345200 976 BasicBlock*& successor(unsigned index)
93a37866 977 {
81345200
A
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 }
93a37866
A
984 switch (index) {
985 case 0:
81345200
A
986 if (isJump())
987 return targetBlock();
988 return branchData()->taken.block;
93a37866 989 case 1:
81345200 990 return branchData()->notTaken.block;
93a37866
A
991 default:
992 RELEASE_ASSERT_NOT_REACHED();
81345200 993 return targetBlock();
93a37866
A
994 }
995 }
996
81345200 997 BasicBlock*& successorForCondition(bool condition)
93a37866 998 {
81345200 999 return branchData()->forCondition(condition);
93a37866
A
1000 }
1001
6fe7ccc8
A
1002 bool hasHeapPrediction()
1003 {
1004 switch (op()) {
1005 case GetById:
1006 case GetByIdFlush:
1007 case GetByVal:
93a37866
A
1008 case GetMyArgumentByVal:
1009 case GetMyArgumentByValSafe:
6fe7ccc8
A
1010 case Call:
1011 case Construct:
1012 case GetByOffset:
81345200
A
1013 case MultiGetByOffset:
1014 case GetClosureVar:
6fe7ccc8
A
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
93a37866 1026 SpeculatedType getHeapPrediction()
6fe7ccc8
A
1027 {
1028 ASSERT(hasHeapPrediction());
93a37866 1029 return static_cast<SpeculatedType>(m_opInfo2);
6fe7ccc8
A
1030 }
1031
93a37866 1032 bool predictHeap(SpeculatedType prediction)
6fe7ccc8
A
1033 {
1034 ASSERT(hasHeapPrediction());
1035
93a37866 1036 return mergeSpeculation(m_opInfo2, prediction);
6fe7ccc8
A
1037 }
1038
81345200
A
1039 void setHeapPrediction(SpeculatedType prediction)
1040 {
1041 ASSERT(hasHeapPrediction());
1042 m_opInfo2 = prediction;
1043 }
1044
93a37866 1045 bool hasFunction()
6fe7ccc8 1046 {
93a37866
A
1047 switch (op()) {
1048 case CheckFunction:
1049 case AllocationProfileWatchpoint:
1050 return true;
1051 default:
1052 return false;
1053 }
14957cd0
A
1054 }
1055
93a37866
A
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()
6fe7ccc8 1070 {
93a37866 1071 return jsCast<ExecutableBase*>(reinterpret_cast<JSCell*>(m_opInfo));
6fe7ccc8 1072 }
81345200
A
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 }
6fe7ccc8
A
1103
1104 bool hasStructureTransitionData()
1105 {
93a37866
A
1106 switch (op()) {
1107 case PutStructure:
1108 case PhantomPutStructure:
1109 case AllocatePropertyStorage:
1110 case ReallocatePropertyStorage:
1111 return true;
1112 default:
1113 return false;
1114 }
6fe7ccc8
A
1115 }
1116
1117 StructureTransitionData& structureTransitionData()
1118 {
1119 ASSERT(hasStructureTransitionData());
1120 return *reinterpret_cast<StructureTransitionData*>(m_opInfo);
1121 }
1122
1123 bool hasStructureSet()
1124 {
93a37866
A
1125 switch (op()) {
1126 case CheckStructure:
93a37866
A
1127 return true;
1128 default:
1129 return false;
1130 }
6fe7ccc8
A
1131 }
1132
1133 StructureSet& structureSet()
1134 {
1135 ASSERT(hasStructureSet());
1136 return *reinterpret_cast<StructureSet*>(m_opInfo);
1137 }
1138
93a37866
A
1139 bool hasStructure()
1140 {
1141 switch (op()) {
1142 case StructureTransitionWatchpoint:
93a37866
A
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
6fe7ccc8
A
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
81345200
A
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
6fe7ccc8
A
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
81345200
A
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
93a37866
A
1223 bool hasArrayMode()
1224 {
1225 switch (op()) {
1226 case GetIndexedPropertyStorage:
1227 case GetArrayLength:
81345200 1228 case PutByValDirect:
93a37866
A
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
81345200
A
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
6fe7ccc8
A
1290 bool hasVirtualRegister()
1291 {
81345200 1292 return m_virtualRegister.isValid();
6fe7ccc8
A
1293 }
1294
14957cd0
A
1295 VirtualRegister virtualRegister()
1296 {
1297 ASSERT(hasResult());
81345200 1298 ASSERT(m_virtualRegister.isValid());
14957cd0
A
1299 return m_virtualRegister;
1300 }
93a37866 1301
14957cd0
A
1302 void setVirtualRegister(VirtualRegister virtualRegister)
1303 {
1304 ASSERT(hasResult());
81345200 1305 ASSERT(!m_virtualRegister.isValid());
14957cd0
A
1306 m_virtualRegister = virtualRegister;
1307 }
93a37866 1308
93a37866
A
1309 bool hasExecutionCounter()
1310 {
1311 return op() == CountExecution;
1312 }
1313
1314 Profiler::ExecutionCounter* executionCounter()
1315 {
1316 return bitwise_cast<Profiler::ExecutionCounter*>(m_opInfo);
1317 }
14957cd0
A
1318
1319 bool shouldGenerate()
1320 {
6fe7ccc8 1321 return m_refCount;
14957cd0 1322 }
93a37866
A
1323
1324 bool willHaveCodeGenOrOSR()
1325 {
1326 switch (op()) {
1327 case SetLocal:
1328 case MovHint:
1329 case ZombieHint:
93a37866
A
1330 case PhantomArguments:
1331 return true;
93a37866 1332 case Phantom:
81345200 1333 case HardPhantom:
93a37866
A
1334 return child1().useKindUnchecked() != UntypedUse || child2().useKindUnchecked() != UntypedUse || child3().useKindUnchecked() != UntypedUse;
1335 default:
1336 return shouldGenerate();
1337 }
1338 }
81345200
A
1339
1340 bool isSemanticallySkippable()
1341 {
1342 return op() == CountExecution;
1343 }
14957cd0
A
1344
1345 unsigned refCount()
1346 {
1347 return m_refCount;
1348 }
1349
93a37866 1350 unsigned postfixRef()
14957cd0 1351 {
93a37866 1352 return m_refCount++;
14957cd0
A
1353 }
1354
1355 unsigned adjustedRefCount()
1356 {
1357 return mustGenerate() ? m_refCount - 1 : m_refCount;
1358 }
6fe7ccc8
A
1359
1360 void setRefCount(unsigned refCount)
1361 {
1362 m_refCount = refCount;
1363 }
1364
93a37866 1365 Edge& child1()
6fe7ccc8
A
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
93a37866 1379 Edge& child2()
6fe7ccc8
A
1380 {
1381 ASSERT(!(m_flags & NodeHasVarArgs));
1382 return children.child2();
1383 }
1384
93a37866 1385 Edge& child3()
6fe7ccc8
A
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
93a37866
A
1403 UseKind binaryUseKind()
1404 {
1405 ASSERT(child1().useKind() == child2().useKind());
1406 return child1().useKind();
1407 }
1408
81345200
A
1409 bool isBinaryUseKind(UseKind left, UseKind right)
1410 {
1411 return child1().useKind() == left && child2().useKind() == right;
1412 }
1413
93a37866
A
1414 bool isBinaryUseKind(UseKind useKind)
1415 {
81345200
A
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();
93a37866
A
1428 }
1429
1430 SpeculatedType prediction()
6fe7ccc8
A
1431 {
1432 return m_prediction;
1433 }
1434
93a37866 1435 bool predict(SpeculatedType prediction)
6fe7ccc8 1436 {
93a37866 1437 return mergeSpeculation(m_prediction, prediction);
6fe7ccc8
A
1438 }
1439
81345200 1440 bool shouldSpeculateInt32()
6fe7ccc8 1441 {
93a37866
A
1442 return isInt32Speculation(prediction());
1443 }
1444
81345200
A
1445 bool sawBooleans()
1446 {
1447 return !!(prediction() & SpecBoolean);
1448 }
1449
1450 bool shouldSpeculateInt32OrBoolean()
1451 {
1452 return isInt32OrBooleanSpeculation(prediction());
1453 }
1454
1455 bool shouldSpeculateInt32ForArithmetic()
93a37866
A
1456 {
1457 return isInt32SpeculationForArithmetic(prediction());
1458 }
1459
81345200
A
1460 bool shouldSpeculateInt32OrBooleanForArithmetic()
1461 {
1462 return isInt32OrBooleanSpeculationForArithmetic(prediction());
1463 }
1464
1465 bool shouldSpeculateInt32OrBooleanExpectingDefined()
1466 {
1467 return isInt32OrBooleanSpeculationExpectingDefined(prediction());
1468 }
1469
1470 bool shouldSpeculateMachineInt()
93a37866 1471 {
81345200 1472 return isMachineIntSpeculation(prediction());
6fe7ccc8
A
1473 }
1474
1475 bool shouldSpeculateDouble()
1476 {
93a37866
A
1477 return isDoubleSpeculation(prediction());
1478 }
1479
81345200 1480 bool shouldSpeculateNumber()
93a37866 1481 {
81345200 1482 return isFullNumberSpeculation(prediction());
6fe7ccc8
A
1483 }
1484
81345200 1485 bool shouldSpeculateNumberOrBoolean()
6fe7ccc8 1486 {
81345200 1487 return isFullNumberOrBooleanSpeculation(prediction());
93a37866
A
1488 }
1489
81345200 1490 bool shouldSpeculateNumberOrBooleanExpectingDefined()
93a37866 1491 {
81345200 1492 return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
6fe7ccc8
A
1493 }
1494
1495 bool shouldSpeculateBoolean()
1496 {
93a37866
A
1497 return isBooleanSpeculation(prediction());
1498 }
81345200
A
1499
1500 bool shouldSpeculateOther()
1501 {
1502 return isOtherSpeculation(prediction());
1503 }
1504
1505 bool shouldSpeculateMisc()
1506 {
1507 return isMiscSpeculation(prediction());
1508 }
93a37866 1509
81345200
A
1510 bool shouldSpeculateStringIdent()
1511 {
1512 return isStringIdentSpeculation(prediction());
1513 }
1514
1515 bool shouldSpeculateNotStringVar()
1516 {
1517 return isNotStringVarSpeculation(prediction());
1518 }
1519
93a37866
A
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());
6fe7ccc8
A
1533 }
1534
1535 bool shouldSpeculateFinalObject()
1536 {
93a37866 1537 return isFinalObjectSpeculation(prediction());
6fe7ccc8
A
1538 }
1539
1540 bool shouldSpeculateFinalObjectOrOther()
1541 {
93a37866 1542 return isFinalObjectOrOtherSpeculation(prediction());
6fe7ccc8
A
1543 }
1544
1545 bool shouldSpeculateArray()
1546 {
93a37866
A
1547 return isArraySpeculation(prediction());
1548 }
1549
1550 bool shouldSpeculateArguments()
1551 {
1552 return isArgumentsSpeculation(prediction());
6fe7ccc8
A
1553 }
1554
1555 bool shouldSpeculateInt8Array()
1556 {
93a37866 1557 return isInt8ArraySpeculation(prediction());
6fe7ccc8
A
1558 }
1559
1560 bool shouldSpeculateInt16Array()
1561 {
93a37866 1562 return isInt16ArraySpeculation(prediction());
6fe7ccc8
A
1563 }
1564
1565 bool shouldSpeculateInt32Array()
1566 {
93a37866 1567 return isInt32ArraySpeculation(prediction());
6fe7ccc8
A
1568 }
1569
1570 bool shouldSpeculateUint8Array()
1571 {
93a37866 1572 return isUint8ArraySpeculation(prediction());
6fe7ccc8
A
1573 }
1574
1575 bool shouldSpeculateUint8ClampedArray()
1576 {
93a37866 1577 return isUint8ClampedArraySpeculation(prediction());
6fe7ccc8
A
1578 }
1579
1580 bool shouldSpeculateUint16Array()
1581 {
93a37866 1582 return isUint16ArraySpeculation(prediction());
6fe7ccc8
A
1583 }
1584
1585 bool shouldSpeculateUint32Array()
1586 {
93a37866 1587 return isUint32ArraySpeculation(prediction());
6fe7ccc8
A
1588 }
1589
1590 bool shouldSpeculateFloat32Array()
1591 {
93a37866 1592 return isFloat32ArraySpeculation(prediction());
6fe7ccc8
A
1593 }
1594
1595 bool shouldSpeculateFloat64Array()
1596 {
93a37866 1597 return isFloat64ArraySpeculation(prediction());
6fe7ccc8
A
1598 }
1599
1600 bool shouldSpeculateArrayOrOther()
1601 {
93a37866 1602 return isArrayOrOtherSpeculation(prediction());
6fe7ccc8
A
1603 }
1604
1605 bool shouldSpeculateObject()
1606 {
93a37866 1607 return isObjectSpeculation(prediction());
6fe7ccc8
A
1608 }
1609
93a37866
A
1610 bool shouldSpeculateObjectOrOther()
1611 {
1612 return isObjectOrOtherSpeculation(prediction());
1613 }
1614
6fe7ccc8
A
1615 bool shouldSpeculateCell()
1616 {
93a37866
A
1617 return isCellSpeculation(prediction());
1618 }
1619
1620 static bool shouldSpeculateBoolean(Node* op1, Node* op2)
1621 {
1622 return op1->shouldSpeculateBoolean() && op2->shouldSpeculateBoolean();
1623 }
1624
81345200 1625 static bool shouldSpeculateInt32(Node* op1, Node* op2)
93a37866 1626 {
81345200 1627 return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
93a37866
A
1628 }
1629
81345200 1630 static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
93a37866 1631 {
81345200
A
1632 return op1->shouldSpeculateInt32OrBoolean()
1633 && op2->shouldSpeculateInt32OrBoolean();
93a37866
A
1634 }
1635
81345200 1636 static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
93a37866 1637 {
81345200
A
1638 return op1->shouldSpeculateInt32OrBooleanForArithmetic()
1639 && op2->shouldSpeculateInt32OrBooleanForArithmetic();
6fe7ccc8
A
1640 }
1641
81345200 1642 static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
6fe7ccc8 1643 {
81345200
A
1644 return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
1645 && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
1646 }
1647
1648 static bool shouldSpeculateMachineInt(Node* op1, Node* op2)
1649 {
1650 return op1->shouldSpeculateMachineInt() && op2->shouldSpeculateMachineInt();
6fe7ccc8
A
1651 }
1652
93a37866 1653 static bool shouldSpeculateNumber(Node* op1, Node* op2)
6fe7ccc8 1654 {
93a37866 1655 return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
6fe7ccc8
A
1656 }
1657
81345200
A
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)
6fe7ccc8 1665 {
81345200
A
1666 return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
1667 && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
93a37866
A
1668 }
1669
1670 static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
1671 {
1672 return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
6fe7ccc8 1673 }
14957cd0 1674
93a37866 1675 static bool shouldSpeculateArray(Node* op1, Node* op2)
6fe7ccc8 1676 {
93a37866 1677 return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
6fe7ccc8
A
1678 }
1679
81345200
A
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)
6fe7ccc8 1698 {
81345200
A
1699 return canSpeculateInt32(sourceFor(pass));
1700 }
1701
1702 bool canSpeculateInt52(PredictionPass pass)
1703 {
1704 return canSpeculateInt52(sourceFor(pass));
6fe7ccc8
A
1705 }
1706
93a37866 1707 void dumpChildren(PrintStream& out)
6fe7ccc8
A
1708 {
1709 if (!child1())
1710 return;
93a37866 1711 out.printf("@%u", child1()->index());
6fe7ccc8
A
1712 if (!child2())
1713 return;
93a37866 1714 out.printf(", @%u", child2()->index());
6fe7ccc8
A
1715 if (!child3())
1716 return;
93a37866 1717 out.printf(", @%u", child3()->index());
6fe7ccc8
A
1718 }
1719
93a37866 1720 // NB. This class must have a trivial destructor.
81345200
A
1721
1722 NodeOrigin origin;
1723
6fe7ccc8
A
1724 // References to up to 3 children, or links to a variable length set of children.
1725 AdjacencyList children;
14957cd0
A
1726
1727private:
93a37866
A
1728 unsigned m_op : 10; // real type is NodeType
1729 unsigned m_flags : 22;
14957cd0
A
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;
81345200
A
1734 // The prediction ascribed to this node after propagation.
1735 SpeculatedType m_prediction;
6fe7ccc8
A
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;
81345200 1739 uintptr_t m_opInfo2;
93a37866
A
1740
1741public:
1742 // Fields used by various analyses.
1743 AbstractValue value;
81345200
A
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;
14957cd0
A
1759};
1760
81345200
A
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
14957cd0
A
1788} } // namespace JSC::DFG
1789
93a37866
A
1790namespace WTF {
1791
81345200 1792void printInternal(PrintStream&, JSC::DFG::SwitchKind);
93a37866
A
1793void printInternal(PrintStream&, JSC::DFG::Node*);
1794
81345200
A
1795inline JSC::DFG::Node* inContext(JSC::DFG::Node* node, JSC::DumpContext*) { return node; }
1796
93a37866
A
1797} // namespace WTF
1798
81345200
A
1799using WTF::inContext;
1800
14957cd0
A
1801#endif
1802#endif