2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
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"
46 #include "PutByIdVariant.h"
47 #include "SpeculatedType.h"
48 #include "StructureSet.h"
49 #include "ValueProfile.h"
50 #include <wtf/ListDump.h>
52 namespace JSC
{ namespace DFG
{
57 struct MultiGetByOffsetData
{
58 unsigned identifierNumber
;
59 Vector
<GetByIdVariant
, 2> variants
;
62 struct MultiPutByOffsetData
{
63 unsigned identifierNumber
;
64 Vector
<PutByIdVariant
, 2> variants
;
66 bool writesStructures() const;
67 bool reallocatesStorage() const;
70 struct StructureTransitionData
{
71 Structure
* previousStructure
;
72 Structure
* newStructure
;
74 StructureTransitionData() { }
76 StructureTransitionData(Structure
* previousStructure
, Structure
* newStructure
)
77 : previousStructure(previousStructure
)
78 , newStructure(newStructure
)
83 struct NewArrayBufferData
{
84 unsigned startConstant
;
85 unsigned numConstants
;
86 IndexingType indexingType
;
96 explicit BranchTarget(BasicBlock
* block
)
102 void setBytecodeIndex(unsigned bytecodeIndex
)
104 block
= bitwise_cast
<BasicBlock
*>(static_cast<uintptr_t>(bytecodeIndex
));
106 unsigned bytecodeIndex() const { return bitwise_cast
<uintptr_t>(block
); }
108 void dump(PrintStream
&) const;
115 static BranchData
withBytecodeIndices(
116 unsigned takenBytecodeIndex
, unsigned notTakenBytecodeIndex
)
119 result
.taken
.block
= bitwise_cast
<BasicBlock
*>(static_cast<uintptr_t>(takenBytecodeIndex
));
120 result
.notTaken
.block
= bitwise_cast
<BasicBlock
*>(static_cast<uintptr_t>(notTakenBytecodeIndex
));
124 unsigned takenBytecodeIndex() const { return taken
.bytecodeIndex(); }
125 unsigned notTakenBytecodeIndex() const { return notTaken
.bytecodeIndex(); }
127 BasicBlock
*& forCondition(bool condition
)
131 return notTaken
.block
;
135 BranchTarget notTaken
;
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.
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
154 SwitchCase(LazyJSValue value
, BasicBlock
* target
)
160 static SwitchCase
withBytecodeIndex(LazyJSValue value
, unsigned bytecodeIndex
)
163 result
.value
= value
;
164 result
.target
.setBytecodeIndex(bytecodeIndex
);
179 // Initializes most fields to obviously invalid values. Anyone
180 // constructing this should make sure to initialize everything they
181 // care about manually.
183 : kind(static_cast<SwitchKind
>(-1))
184 , switchTableIndex(UINT_MAX
)
185 , didUseJumpTable(false)
189 Vector
<SwitchCase
> cases
;
190 BranchTarget fallThrough
;
192 unsigned switchTableIndex
;
193 bool didUseJumpTable
;
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*.
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
)) { }
205 explicit OpInfo(void* value
) : m_value(reinterpret_cast<uintptr_t>(value
)) { }
211 // Node represents a single operation in the data flow graph.
213 enum VarArgTag
{ VarArg
};
217 Node(NodeType op
, NodeOrigin nodeOrigin
, const AdjacencyList
& children
)
220 , m_virtualRegister(VirtualRegister())
222 , m_prediction(SpecNone
)
224 misc
.replacement
= 0;
225 setOpAndDefaultFlags(op
);
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())
231 , children(AdjacencyList::Fixed
, child1
, child2
, child3
)
232 , m_virtualRegister(VirtualRegister())
234 , m_prediction(SpecNone
)
238 misc
.replacement
= 0;
239 setOpAndDefaultFlags(op
);
240 ASSERT(!(m_flags
& NodeHasVarArgs
));
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())
246 , children(AdjacencyList::Fixed
, child1
, child2
, child3
)
247 , m_virtualRegister(VirtualRegister())
249 , m_prediction(SpecNone
)
253 misc
.replacement
= 0;
254 setOpAndDefaultFlags(op
);
256 ASSERT(!(m_flags
& NodeHasVarArgs
));
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())
262 , children(AdjacencyList::Fixed
, child1
, child2
, child3
)
263 , m_virtualRegister(VirtualRegister())
265 , m_prediction(SpecNone
)
266 , m_opInfo(imm
.m_value
)
269 misc
.replacement
= 0;
270 setOpAndDefaultFlags(op
);
271 ASSERT(!(m_flags
& NodeHasVarArgs
));
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())
277 , children(AdjacencyList::Fixed
, child1
, child2
, child3
)
278 , m_virtualRegister(VirtualRegister())
280 , m_prediction(SpecNone
)
281 , m_opInfo(imm
.m_value
)
284 misc
.replacement
= 0;
285 setOpAndDefaultFlags(op
);
287 ASSERT(!(m_flags
& NodeHasVarArgs
));
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())
293 , children(AdjacencyList::Fixed
, child1
, child2
, child3
)
294 , m_virtualRegister(VirtualRegister())
296 , m_prediction(SpecNone
)
297 , m_opInfo(imm1
.m_value
)
298 , m_opInfo2(imm2
.m_value
)
300 misc
.replacement
= 0;
301 setOpAndDefaultFlags(op
);
302 ASSERT(!(m_flags
& NodeHasVarArgs
));
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
)
308 , children(AdjacencyList::Variable
, firstChild
, numChildren
)
309 , m_virtualRegister(VirtualRegister())
311 , m_prediction(SpecNone
)
312 , m_opInfo(imm1
.m_value
)
313 , m_opInfo2(imm2
.m_value
)
315 misc
.replacement
= 0;
316 setOpAndDefaultFlags(op
);
317 ASSERT(m_flags
& NodeHasVarArgs
);
320 NodeType
op() const { return static_cast<NodeType
>(m_op
); }
321 NodeFlags
flags() const { return m_flags
; }
323 // This is not a fast method.
324 unsigned index() const;
326 void setOp(NodeType op
)
331 void setFlags(NodeFlags flags
)
336 bool mergeFlags(NodeFlags flags
)
338 ASSERT(!(flags
& NodeDoesNotExit
));
339 NodeFlags newFlags
= m_flags
| flags
;
340 if (newFlags
== m_flags
)
346 bool filterFlags(NodeFlags flags
)
348 ASSERT(flags
& NodeDoesNotExit
);
349 NodeFlags newFlags
= m_flags
& flags
;
350 if (newFlags
== m_flags
)
356 bool clearFlags(NodeFlags flags
)
358 return filterFlags(~flags
);
361 void setResult(NodeFlags result
)
363 ASSERT(!(result
& ~NodeResultMask
));
364 clearFlags(NodeResultMask
);
368 NodeFlags
result() const
370 return flags() & NodeResultMask
;
373 void setOpAndDefaultFlags(NodeType op
)
376 m_flags
= defaultFlags(op
);
379 void convertToPhantom()
381 setOpAndDefaultFlags(Phantom
);
384 void convertToPhantomUnchecked()
386 setOpAndDefaultFlags(Phantom
);
389 void convertToIdentity();
393 return m_flags
& NodeMustGenerate
;
396 void setCanExit(bool exits
)
399 m_flags
&= ~NodeDoesNotExit
;
401 m_flags
|= NodeDoesNotExit
;
406 return !(m_flags
& NodeDoesNotExit
);
421 bool isWeakConstant()
423 return op() == WeakJSConstant
;
426 bool isPhantomArguments()
428 return op() == PhantomArguments
;
438 case PhantomArguments
:
445 unsigned constantNumber()
447 ASSERT(isConstant());
451 void convertToConstant(unsigned constantNumber
)
453 if (hasDoubleResult())
454 m_op
= DoubleConstant
;
455 else if (hasInt52Result())
456 m_op
= Int52Constant
;
459 m_flags
&= ~(NodeMustGenerate
| NodeMightClobber
| NodeClobbersWorld
);
460 m_opInfo
= constantNumber
;
464 void convertToWeakConstant(JSCell
* cell
)
466 m_op
= WeakJSConstant
;
467 m_flags
&= ~(NodeMustGenerate
| NodeMightClobber
| NodeClobbersWorld
);
468 m_opInfo
= bitwise_cast
<uintptr_t>(cell
);
472 void convertToConstantStoragePointer(void* pointer
)
474 ASSERT(op() == GetIndexedPropertyStorage
);
475 m_op
= ConstantStoragePointer
;
476 m_opInfo
= bitwise_cast
<uintptr_t>(pointer
);
479 void convertToGetLocalUnlinked(VirtualRegister local
)
481 m_op
= GetLocalUnlinked
;
482 m_flags
&= ~(NodeMustGenerate
| NodeMightClobber
| NodeClobbersWorld
);
483 m_opInfo
= local
.offset();
484 m_opInfo2
= VirtualRegister().offset();
488 void convertToStructureTransitionWatchpoint(Structure
* structure
)
490 ASSERT(m_op
== CheckStructure
|| m_op
== ArrayifyToStructure
);
493 m_opInfo
= bitwise_cast
<uintptr_t>(structure
);
494 m_op
= StructureTransitionWatchpoint
;
497 void convertToStructureTransitionWatchpoint()
499 convertToStructureTransitionWatchpoint(structureSet().singletonStructure());
502 void convertToGetByOffset(unsigned storageAccessDataIndex
, Edge storage
)
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
);
510 m_flags
&= ~NodeClobbersWorld
;
513 void convertToPutByOffset(unsigned storageAccessDataIndex
, Edge storage
)
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
);
521 m_flags
&= ~NodeClobbersWorld
;
524 void convertToPhantomLocal()
526 ASSERT(m_op
== Phantom
&& (child1()->op() == Phi
|| child1()->op() == SetLocal
|| child1()->op() == SetArgument
));
528 m_opInfo
= child1()->m_opInfo
; // Copy the variableAccessData.
529 children
.setChild1(Edge());
532 void convertToGetLocal(VariableAccessData
* variable
, Node
* phi
)
534 ASSERT(m_op
== GetLocalUnlinked
);
536 m_opInfo
= bitwise_cast
<uintptr_t>(variable
);
538 children
.setChild1(Edge(phi
));
541 void convertToToString()
543 ASSERT(m_op
== ToPrimitive
);
547 JSCell
* weakConstant()
549 ASSERT(op() == WeakJSConstant
);
550 return bitwise_cast
<JSCell
*>(m_opInfo
);
553 JSValue
valueOfJSConstant(CodeBlock
* codeBlock
)
557 return JSValue(weakConstant());
561 return codeBlock
->constantRegister(FirstConstantRegisterIndex
+ constantNumber()).get();
562 case PhantomArguments
:
565 RELEASE_ASSERT_NOT_REACHED();
566 return JSValue(); // Have to return something in release mode.
570 bool isInt32Constant(CodeBlock
* codeBlock
)
572 return isConstant() && valueOfJSConstant(codeBlock
).isInt32();
575 bool isDoubleConstant(CodeBlock
* codeBlock
)
577 bool result
= isConstant() && valueOfJSConstant(codeBlock
).isDouble();
579 ASSERT(!isInt32Constant(codeBlock
));
583 bool isNumberConstant(CodeBlock
* codeBlock
)
585 bool result
= isConstant() && valueOfJSConstant(codeBlock
).isNumber();
586 ASSERT(result
== (isInt32Constant(codeBlock
) || isDoubleConstant(codeBlock
)));
590 bool isMachineIntConstant(CodeBlock
* codeBlock
)
592 return isConstant() && valueOfJSConstant(codeBlock
).isMachineInt();
595 bool isBooleanConstant(CodeBlock
* codeBlock
)
597 return isConstant() && valueOfJSConstant(codeBlock
).isBoolean();
600 bool containsMovHint()
611 bool hasVariableAccessData(Graph
&);
612 bool hasLocal(Graph
& graph
)
614 return hasVariableAccessData(graph
);
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()
621 VariableAccessData
* result
= reinterpret_cast<VariableAccessData
*>(m_opInfo
);
624 return result
->find();
627 VariableAccessData
* variableAccessData()
629 return reinterpret_cast<VariableAccessData
*>(m_opInfo
)->find();
632 VirtualRegister
local()
634 return variableAccessData()->local();
637 VirtualRegister
machineLocal()
639 return variableAccessData()->machineLocal();
642 bool hasUnlinkedLocal()
645 case GetLocalUnlinked
:
646 case ExtractOSREntryLocal
:
655 VirtualRegister
unlinkedLocal()
657 ASSERT(hasUnlinkedLocal());
658 return static_cast<VirtualRegister
>(m_opInfo
);
661 bool hasUnlinkedMachineLocal()
663 return op() == GetLocalUnlinked
;
666 void setUnlinkedMachineLocal(VirtualRegister reg
)
668 ASSERT(hasUnlinkedMachineLocal());
669 m_opInfo2
= reg
.offset();
672 VirtualRegister
unlinkedMachineLocal()
674 ASSERT(hasUnlinkedMachineLocal());
675 return VirtualRegister(m_opInfo2
);
680 return op() == Upsilon
;
686 return bitwise_cast
<Node
*>(m_opInfo
);
689 bool isStoreBarrier()
693 case StoreBarrierWithNullCheck
:
714 unsigned identifierNumber()
716 ASSERT(hasIdentifier());
720 bool hasArithNodeFlags()
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()
745 NodeFlags result
= m_flags
& NodeArithFlagsMask
;
746 if (op() == ArithMul
|| op() == ArithDiv
|| op() == ArithMod
|| op() == ArithNegate
|| op() == DoubleAsInt32
)
748 return result
& ~NodeBytecodeNeedsNegZero
;
751 bool hasConstantBuffer()
753 return op() == NewArrayBuffer
;
756 NewArrayBufferData
* newArrayBufferData()
758 ASSERT(hasConstantBuffer());
759 return reinterpret_cast<NewArrayBufferData
*>(m_opInfo
);
762 unsigned startConstant()
764 return newArrayBufferData()->startConstant
;
767 unsigned numConstants()
769 return newArrayBufferData()->numConstants
;
772 bool hasIndexingType()
776 case NewArrayWithSize
:
784 IndexingType
indexingType()
786 ASSERT(hasIndexingType());
787 if (op() == NewArrayBuffer
)
788 return newArrayBufferData()->indexingType
;
792 bool hasTypedArrayType()
802 TypedArrayType
typedArrayType()
804 ASSERT(hasTypedArrayType());
805 TypedArrayType result
= static_cast<TypedArrayType
>(m_opInfo
);
806 ASSERT(isTypedView(result
));
810 bool hasInlineCapacity()
812 return op() == CreateThis
;
815 unsigned inlineCapacity()
817 ASSERT(hasInlineCapacity());
821 void setIndexingType(IndexingType indexingType
)
823 ASSERT(hasIndexingType());
824 m_opInfo
= indexingType
;
827 bool hasRegexpIndex()
829 return op() == NewRegexp
;
832 unsigned regexpIndex()
834 ASSERT(hasRegexpIndex());
840 return op() == GetClosureVar
|| op() == PutClosureVar
;
845 ASSERT(hasVarNumber());
849 bool hasRegisterPointer()
851 return op() == GetGlobalVar
|| op() == PutGlobalVar
;
854 WriteBarrier
<Unknown
>* registerPointer()
856 return bitwise_cast
<WriteBarrier
<Unknown
>*>(m_opInfo
);
864 bool hasInt32Result()
866 return result() == NodeResultInt32
;
869 bool hasInt52Result()
871 return result() == NodeResultInt52
;
874 bool hasNumberResult()
876 return result() == NodeResultNumber
;
879 bool hasDoubleResult()
881 return result() == NodeResultDouble
;
886 return result() == NodeResultJS
;
889 bool hasBooleanResult()
891 return result() == NodeResultBoolean
;
894 bool hasStorageResult()
896 return result() == NodeResultStorage
;
899 UseKind
defaultUseKind()
901 return useKindForResult(result());
906 return Edge(this, defaultUseKind());
916 return op() == Branch
;
921 return op() == Switch
;
938 unsigned targetBytecodeOffsetDuringParsing()
944 BasicBlock
*& targetBlock()
947 return *bitwise_cast
<BasicBlock
**>(&m_opInfo
);
950 BranchData
* branchData()
953 return bitwise_cast
<BranchData
*>(m_opInfo
);
956 SwitchData
* switchData()
959 return bitwise_cast
<SwitchData
*>(m_opInfo
);
962 unsigned numSuccessors()
970 return switchData()->cases
.size() + 1;
976 BasicBlock
*& successor(unsigned index
)
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
;
987 return targetBlock();
988 return branchData()->taken
.block
;
990 return branchData()->notTaken
.block
;
992 RELEASE_ASSERT_NOT_REACHED();
993 return targetBlock();
997 BasicBlock
*& successorForCondition(bool condition
)
999 return branchData()->forCondition(condition
);
1002 bool hasHeapPrediction()
1008 case GetMyArgumentByVal
:
1009 case GetMyArgumentByValSafe
:
1013 case MultiGetByOffset
:
1026 SpeculatedType
getHeapPrediction()
1028 ASSERT(hasHeapPrediction());
1029 return static_cast<SpeculatedType
>(m_opInfo2
);
1032 bool predictHeap(SpeculatedType prediction
)
1034 ASSERT(hasHeapPrediction());
1036 return mergeSpeculation(m_opInfo2
, prediction
);
1039 void setHeapPrediction(SpeculatedType prediction
)
1041 ASSERT(hasHeapPrediction());
1042 m_opInfo2
= prediction
;
1049 case AllocationProfileWatchpoint
:
1058 ASSERT(hasFunction());
1059 JSCell
* result
= reinterpret_cast<JSFunction
*>(m_opInfo
);
1060 ASSERT(JSValue(result
).isFunction());
1064 bool hasExecutable()
1066 return op() == CheckExecutable
;
1069 ExecutableBase
* executable()
1071 return jsCast
<ExecutableBase
*>(reinterpret_cast<JSCell
*>(m_opInfo
));
1074 bool hasVariableWatchpointSet()
1076 return op() == NotifyWrite
|| op() == VariableWatchpoint
;
1079 VariableWatchpointSet
* variableWatchpointSet()
1081 return reinterpret_cast<VariableWatchpointSet
*>(m_opInfo
);
1084 bool hasTypedArray()
1086 return op() == TypedArrayWatchpoint
;
1089 JSArrayBufferView
* typedArray()
1091 return reinterpret_cast<JSArrayBufferView
*>(m_opInfo
);
1094 bool hasStoragePointer()
1096 return op() == ConstantStoragePointer
;
1099 void* storagePointer()
1101 return reinterpret_cast<void*>(m_opInfo
);
1104 bool hasStructureTransitionData()
1108 case PhantomPutStructure
:
1109 case AllocatePropertyStorage
:
1110 case ReallocatePropertyStorage
:
1117 StructureTransitionData
& structureTransitionData()
1119 ASSERT(hasStructureTransitionData());
1120 return *reinterpret_cast<StructureTransitionData
*>(m_opInfo
);
1123 bool hasStructureSet()
1126 case CheckStructure
:
1133 StructureSet
& structureSet()
1135 ASSERT(hasStructureSet());
1136 return *reinterpret_cast<StructureSet
*>(m_opInfo
);
1142 case StructureTransitionWatchpoint
:
1143 case ArrayifyToStructure
:
1145 case NewStringObject
:
1152 Structure
* structure()
1154 ASSERT(hasStructure());
1155 return reinterpret_cast<Structure
*>(m_opInfo
);
1158 bool hasStorageAccessData()
1160 return op() == GetByOffset
|| op() == PutByOffset
;
1163 unsigned storageAccessDataIndex()
1165 ASSERT(hasStorageAccessData());
1169 bool hasMultiGetByOffsetData()
1171 return op() == MultiGetByOffset
;
1174 MultiGetByOffsetData
& multiGetByOffsetData()
1176 return *reinterpret_cast<MultiGetByOffsetData
*>(m_opInfo
);
1179 bool hasMultiPutByOffsetData()
1181 return op() == MultiPutByOffset
;
1184 MultiPutByOffsetData
& multiPutByOffsetData()
1186 return *reinterpret_cast<MultiPutByOffsetData
*>(m_opInfo
);
1189 bool hasFunctionDeclIndex()
1191 return op() == NewFunction
1192 || op() == NewFunctionNoCheck
;
1195 unsigned functionDeclIndex()
1197 ASSERT(hasFunctionDeclIndex());
1201 bool hasFunctionExprIndex()
1203 return op() == NewFunctionExpression
;
1206 unsigned functionExprIndex()
1208 ASSERT(hasFunctionExprIndex());
1212 bool hasSymbolTable()
1214 return op() == FunctionReentryWatchpoint
;
1217 SymbolTable
* symbolTable()
1219 ASSERT(hasSymbolTable());
1220 return reinterpret_cast<SymbolTable
*>(m_opInfo
);
1226 case GetIndexedPropertyStorage
:
1227 case GetArrayLength
:
1228 case PutByValDirect
:
1233 case StringCharCodeAt
:
1236 case ArrayifyToStructure
:
1245 ArrayMode
arrayMode()
1247 ASSERT(hasArrayMode());
1248 if (op() == ArrayifyToStructure
)
1249 return ArrayMode::fromWord(m_opInfo2
);
1250 return ArrayMode::fromWord(m_opInfo
);
1253 bool setArrayMode(ArrayMode arrayMode
)
1255 ASSERT(hasArrayMode());
1256 if (this->arrayMode() == arrayMode
)
1258 m_opInfo
= arrayMode
.asWord();
1271 case UInt32ToNumber
:
1279 Arith::Mode
arithMode()
1281 ASSERT(hasArithMode());
1282 return static_cast<Arith::Mode
>(m_opInfo
);
1285 void setArithMode(Arith::Mode mode
)
1290 bool hasVirtualRegister()
1292 return m_virtualRegister
.isValid();
1295 VirtualRegister
virtualRegister()
1297 ASSERT(hasResult());
1298 ASSERT(m_virtualRegister
.isValid());
1299 return m_virtualRegister
;
1302 void setVirtualRegister(VirtualRegister virtualRegister
)
1304 ASSERT(hasResult());
1305 ASSERT(!m_virtualRegister
.isValid());
1306 m_virtualRegister
= virtualRegister
;
1309 bool hasExecutionCounter()
1311 return op() == CountExecution
;
1314 Profiler::ExecutionCounter
* executionCounter()
1316 return bitwise_cast
<Profiler::ExecutionCounter
*>(m_opInfo
);
1319 bool shouldGenerate()
1324 bool willHaveCodeGenOrOSR()
1330 case PhantomArguments
:
1334 return child1().useKindUnchecked() != UntypedUse
|| child2().useKindUnchecked() != UntypedUse
|| child3().useKindUnchecked() != UntypedUse
;
1336 return shouldGenerate();
1340 bool isSemanticallySkippable()
1342 return op() == CountExecution
;
1350 unsigned postfixRef()
1352 return m_refCount
++;
1355 unsigned adjustedRefCount()
1357 return mustGenerate() ? m_refCount
- 1 : m_refCount
;
1360 void setRefCount(unsigned refCount
)
1362 m_refCount
= refCount
;
1367 ASSERT(!(m_flags
& NodeHasVarArgs
));
1368 return children
.child1();
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()
1376 return children
.child1Unchecked();
1381 ASSERT(!(m_flags
& NodeHasVarArgs
));
1382 return children
.child2();
1387 ASSERT(!(m_flags
& NodeHasVarArgs
));
1388 return children
.child3();
1391 unsigned firstChild()
1393 ASSERT(m_flags
& NodeHasVarArgs
);
1394 return children
.firstChild();
1397 unsigned numChildren()
1399 ASSERT(m_flags
& NodeHasVarArgs
);
1400 return children
.numChildren();
1403 UseKind
binaryUseKind()
1405 ASSERT(child1().useKind() == child2().useKind());
1406 return child1().useKind();
1409 bool isBinaryUseKind(UseKind left
, UseKind right
)
1411 return child1().useKind() == left
&& child2().useKind() == right
;
1414 bool isBinaryUseKind(UseKind useKind
)
1416 return isBinaryUseKind(useKind
, useKind
);
1419 Edge
childFor(UseKind useKind
)
1421 if (child1().useKind() == useKind
)
1423 if (child2().useKind() == useKind
)
1425 if (child3().useKind() == useKind
)
1430 SpeculatedType
prediction()
1432 return m_prediction
;
1435 bool predict(SpeculatedType prediction
)
1437 return mergeSpeculation(m_prediction
, prediction
);
1440 bool shouldSpeculateInt32()
1442 return isInt32Speculation(prediction());
1447 return !!(prediction() & SpecBoolean
);
1450 bool shouldSpeculateInt32OrBoolean()
1452 return isInt32OrBooleanSpeculation(prediction());
1455 bool shouldSpeculateInt32ForArithmetic()
1457 return isInt32SpeculationForArithmetic(prediction());
1460 bool shouldSpeculateInt32OrBooleanForArithmetic()
1462 return isInt32OrBooleanSpeculationForArithmetic(prediction());
1465 bool shouldSpeculateInt32OrBooleanExpectingDefined()
1467 return isInt32OrBooleanSpeculationExpectingDefined(prediction());
1470 bool shouldSpeculateMachineInt()
1472 return isMachineIntSpeculation(prediction());
1475 bool shouldSpeculateDouble()
1477 return isDoubleSpeculation(prediction());
1480 bool shouldSpeculateNumber()
1482 return isFullNumberSpeculation(prediction());
1485 bool shouldSpeculateNumberOrBoolean()
1487 return isFullNumberOrBooleanSpeculation(prediction());
1490 bool shouldSpeculateNumberOrBooleanExpectingDefined()
1492 return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
1495 bool shouldSpeculateBoolean()
1497 return isBooleanSpeculation(prediction());
1500 bool shouldSpeculateOther()
1502 return isOtherSpeculation(prediction());
1505 bool shouldSpeculateMisc()
1507 return isMiscSpeculation(prediction());
1510 bool shouldSpeculateStringIdent()
1512 return isStringIdentSpeculation(prediction());
1515 bool shouldSpeculateNotStringVar()
1517 return isNotStringVarSpeculation(prediction());
1520 bool shouldSpeculateString()
1522 return isStringSpeculation(prediction());
1525 bool shouldSpeculateStringObject()
1527 return isStringObjectSpeculation(prediction());
1530 bool shouldSpeculateStringOrStringObject()
1532 return isStringOrStringObjectSpeculation(prediction());
1535 bool shouldSpeculateFinalObject()
1537 return isFinalObjectSpeculation(prediction());
1540 bool shouldSpeculateFinalObjectOrOther()
1542 return isFinalObjectOrOtherSpeculation(prediction());
1545 bool shouldSpeculateArray()
1547 return isArraySpeculation(prediction());
1550 bool shouldSpeculateArguments()
1552 return isArgumentsSpeculation(prediction());
1555 bool shouldSpeculateInt8Array()
1557 return isInt8ArraySpeculation(prediction());
1560 bool shouldSpeculateInt16Array()
1562 return isInt16ArraySpeculation(prediction());
1565 bool shouldSpeculateInt32Array()
1567 return isInt32ArraySpeculation(prediction());
1570 bool shouldSpeculateUint8Array()
1572 return isUint8ArraySpeculation(prediction());
1575 bool shouldSpeculateUint8ClampedArray()
1577 return isUint8ClampedArraySpeculation(prediction());
1580 bool shouldSpeculateUint16Array()
1582 return isUint16ArraySpeculation(prediction());
1585 bool shouldSpeculateUint32Array()
1587 return isUint32ArraySpeculation(prediction());
1590 bool shouldSpeculateFloat32Array()
1592 return isFloat32ArraySpeculation(prediction());
1595 bool shouldSpeculateFloat64Array()
1597 return isFloat64ArraySpeculation(prediction());
1600 bool shouldSpeculateArrayOrOther()
1602 return isArrayOrOtherSpeculation(prediction());
1605 bool shouldSpeculateObject()
1607 return isObjectSpeculation(prediction());
1610 bool shouldSpeculateObjectOrOther()
1612 return isObjectOrOtherSpeculation(prediction());
1615 bool shouldSpeculateCell()
1617 return isCellSpeculation(prediction());
1620 static bool shouldSpeculateBoolean(Node
* op1
, Node
* op2
)
1622 return op1
->shouldSpeculateBoolean() && op2
->shouldSpeculateBoolean();
1625 static bool shouldSpeculateInt32(Node
* op1
, Node
* op2
)
1627 return op1
->shouldSpeculateInt32() && op2
->shouldSpeculateInt32();
1630 static bool shouldSpeculateInt32OrBoolean(Node
* op1
, Node
* op2
)
1632 return op1
->shouldSpeculateInt32OrBoolean()
1633 && op2
->shouldSpeculateInt32OrBoolean();
1636 static bool shouldSpeculateInt32OrBooleanForArithmetic(Node
* op1
, Node
* op2
)
1638 return op1
->shouldSpeculateInt32OrBooleanForArithmetic()
1639 && op2
->shouldSpeculateInt32OrBooleanForArithmetic();
1642 static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node
* op1
, Node
* op2
)
1644 return op1
->shouldSpeculateInt32OrBooleanExpectingDefined()
1645 && op2
->shouldSpeculateInt32OrBooleanExpectingDefined();
1648 static bool shouldSpeculateMachineInt(Node
* op1
, Node
* op2
)
1650 return op1
->shouldSpeculateMachineInt() && op2
->shouldSpeculateMachineInt();
1653 static bool shouldSpeculateNumber(Node
* op1
, Node
* op2
)
1655 return op1
->shouldSpeculateNumber() && op2
->shouldSpeculateNumber();
1658 static bool shouldSpeculateNumberOrBoolean(Node
* op1
, Node
* op2
)
1660 return op1
->shouldSpeculateNumberOrBoolean()
1661 && op2
->shouldSpeculateNumberOrBoolean();
1664 static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node
* op1
, Node
* op2
)
1666 return op1
->shouldSpeculateNumberOrBooleanExpectingDefined()
1667 && op2
->shouldSpeculateNumberOrBooleanExpectingDefined();
1670 static bool shouldSpeculateFinalObject(Node
* op1
, Node
* op2
)
1672 return op1
->shouldSpeculateFinalObject() && op2
->shouldSpeculateFinalObject();
1675 static bool shouldSpeculateArray(Node
* op1
, Node
* op2
)
1677 return op1
->shouldSpeculateArray() && op2
->shouldSpeculateArray();
1680 bool canSpeculateInt32(RareCaseProfilingSource source
)
1682 return nodeCanSpeculateInt32(arithNodeFlags(), source
);
1685 bool canSpeculateInt52(RareCaseProfilingSource source
)
1687 return nodeCanSpeculateInt52(arithNodeFlags(), source
);
1690 RareCaseProfilingSource
sourceFor(PredictionPass pass
)
1692 if (pass
== PrimaryPass
|| child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
1694 return AllRareCases
;
1697 bool canSpeculateInt32(PredictionPass pass
)
1699 return canSpeculateInt32(sourceFor(pass
));
1702 bool canSpeculateInt52(PredictionPass pass
)
1704 return canSpeculateInt52(sourceFor(pass
));
1707 void dumpChildren(PrintStream
& out
)
1711 out
.printf("@%u", child1()->index());
1714 out
.printf(", @%u", child2()->index());
1717 out
.printf(", @%u", child3()->index());
1720 // NB. This class must have a trivial destructor.
1724 // References to up to 3 children, or links to a variable length set of children.
1725 AdjacencyList children
;
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.
1739 uintptr_t m_opInfo2
;
1742 // Fields used by various analyses.
1743 AbstractValue value
;
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.
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.
1761 inline bool nodeComparator(Node
* a
, Node
* b
)
1763 return a
->index() < b
->index();
1766 template<typename T
>
1767 CString
nodeListDump(const T
& nodeList
)
1769 return sortedListDump(nodeList
, nodeComparator
);
1772 template<typename T
>
1773 CString
nodeMapDump(const T
& nodeMap
, DumpContext
* context
= 0)
1775 Vector
<typename
T::KeyType
> keys
;
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
;
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();
1788 } } // namespace JSC::DFG
1792 void printInternal(PrintStream
&, JSC::DFG::SwitchKind
);
1793 void printInternal(PrintStream
&, JSC::DFG::Node
*);
1795 inline JSC::DFG::Node
* inContext(JSC::DFG::Node
* node
, JSC::DumpContext
*) { return node
; }
1799 using WTF::inContext
;