2 * Copyright (C) 2011, 2012 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.
29 #include <wtf/Platform.h>
33 #include "CodeBlock.h"
34 #include "CodeOrigin.h"
35 #include "DFGAdjacencyList.h"
36 #include "DFGCommon.h"
37 #include "DFGNodeFlags.h"
38 #include "DFGNodeType.h"
39 #include "DFGVariableAccessData.h"
42 #include "PredictedType.h"
43 #include "ValueProfile.h"
45 namespace JSC
{ namespace DFG
{
47 struct StructureTransitionData
{
48 Structure
* previousStructure
;
49 Structure
* newStructure
;
51 StructureTransitionData() { }
53 StructureTransitionData(Structure
* previousStructure
, Structure
* newStructure
)
54 : previousStructure(previousStructure
)
55 , newStructure(newStructure
)
60 // This type used in passing an immediate argument to Node constructor;
61 // distinguishes an immediate value (typically an index into a CodeBlock data structure -
62 // a constant index, argument, or identifier) from a NodeIndex.
64 explicit OpInfo(int32_t value
) : m_value(static_cast<uintptr_t>(value
)) { }
65 explicit OpInfo(uint32_t value
) : m_value(static_cast<uintptr_t>(value
)) { }
66 #if OS(DARWIN) || USE(JSVALUE64)
67 explicit OpInfo(size_t value
) : m_value(static_cast<uintptr_t>(value
)) { }
69 explicit OpInfo(void* value
) : m_value(reinterpret_cast<uintptr_t>(value
)) { }
75 // Node represents a single operation in the data flow graph.
77 enum VarArgTag
{ VarArg
};
79 // Construct a node with up to 3 children, no immediate value.
80 Node(NodeType op
, CodeOrigin codeOrigin
, NodeIndex child1
= NoNode
, NodeIndex child2
= NoNode
, NodeIndex child3
= NoNode
)
81 : codeOrigin(codeOrigin
)
82 , children(AdjacencyList::Fixed
, child1
, child2
, child3
)
83 , m_virtualRegister(InvalidVirtualRegister
)
85 , m_prediction(PredictNone
)
87 setOpAndDefaultFlags(op
);
88 ASSERT(!(m_flags
& NodeHasVarArgs
));
91 // Construct a node with up to 3 children and an immediate value.
92 Node(NodeType op
, CodeOrigin codeOrigin
, OpInfo imm
, NodeIndex child1
= NoNode
, NodeIndex child2
= NoNode
, NodeIndex child3
= NoNode
)
93 : codeOrigin(codeOrigin
)
94 , children(AdjacencyList::Fixed
, child1
, child2
, child3
)
95 , m_virtualRegister(InvalidVirtualRegister
)
97 , m_opInfo(imm
.m_value
)
98 , m_prediction(PredictNone
)
100 setOpAndDefaultFlags(op
);
101 ASSERT(!(m_flags
& NodeHasVarArgs
));
104 // Construct a node with up to 3 children and two immediate values.
105 Node(NodeType op
, CodeOrigin codeOrigin
, OpInfo imm1
, OpInfo imm2
, NodeIndex child1
= NoNode
, NodeIndex child2
= NoNode
, NodeIndex child3
= NoNode
)
106 : codeOrigin(codeOrigin
)
107 , children(AdjacencyList::Fixed
, child1
, child2
, child3
)
108 , m_virtualRegister(InvalidVirtualRegister
)
110 , m_opInfo(imm1
.m_value
)
111 , m_opInfo2(safeCast
<unsigned>(imm2
.m_value
))
112 , m_prediction(PredictNone
)
114 setOpAndDefaultFlags(op
);
115 ASSERT(!(m_flags
& NodeHasVarArgs
));
118 // Construct a node with a variable number of children and two immediate values.
119 Node(VarArgTag
, NodeType op
, CodeOrigin codeOrigin
, OpInfo imm1
, OpInfo imm2
, unsigned firstChild
, unsigned numChildren
)
120 : codeOrigin(codeOrigin
)
121 , children(AdjacencyList::Variable
, firstChild
, numChildren
)
122 , m_virtualRegister(InvalidVirtualRegister
)
124 , m_opInfo(imm1
.m_value
)
125 , m_opInfo2(safeCast
<unsigned>(imm2
.m_value
))
126 , m_prediction(PredictNone
)
128 setOpAndDefaultFlags(op
);
129 ASSERT(m_flags
& NodeHasVarArgs
);
132 NodeType
op() const { return static_cast<NodeType
>(m_op
); }
133 NodeFlags
flags() const { return m_flags
; }
135 void setOp(NodeType op
)
140 void setFlags(NodeFlags flags
)
145 bool mergeFlags(NodeFlags flags
)
147 NodeFlags newFlags
= m_flags
| flags
;
148 if (newFlags
== m_flags
)
154 bool filterFlags(NodeFlags flags
)
156 NodeFlags newFlags
= m_flags
& flags
;
157 if (newFlags
== m_flags
)
163 bool clearFlags(NodeFlags flags
)
165 return filterFlags(~flags
);
168 void setOpAndDefaultFlags(NodeType op
)
171 m_flags
= defaultFlags(op
);
176 return m_flags
& NodeMustGenerate
;
181 return op() == JSConstant
;
184 bool isWeakConstant()
186 return op() == WeakJSConstant
;
191 return isConstant() || isWeakConstant();
194 unsigned constantNumber()
196 ASSERT(isConstant());
200 JSCell
* weakConstant()
202 return bitwise_cast
<JSCell
*>(m_opInfo
);
205 JSValue
valueOfJSConstant(CodeBlock
* codeBlock
)
207 if (op() == WeakJSConstant
)
208 return JSValue(weakConstant());
209 return codeBlock
->constantRegister(FirstConstantRegisterIndex
+ constantNumber()).get();
212 bool isInt32Constant(CodeBlock
* codeBlock
)
214 return isConstant() && valueOfJSConstant(codeBlock
).isInt32();
217 bool isDoubleConstant(CodeBlock
* codeBlock
)
219 bool result
= isConstant() && valueOfJSConstant(codeBlock
).isDouble();
221 ASSERT(!isInt32Constant(codeBlock
));
225 bool isNumberConstant(CodeBlock
* codeBlock
)
227 bool result
= isConstant() && valueOfJSConstant(codeBlock
).isNumber();
228 ASSERT(result
== (isInt32Constant(codeBlock
) || isDoubleConstant(codeBlock
)));
232 bool isBooleanConstant(CodeBlock
* codeBlock
)
234 return isConstant() && valueOfJSConstant(codeBlock
).isBoolean();
237 bool hasVariableAccessData()
253 return hasVariableAccessData();
256 VariableAccessData
* variableAccessData()
258 ASSERT(hasVariableAccessData());
259 return reinterpret_cast<VariableAccessData
*>(m_opInfo
)->find();
262 VirtualRegister
local()
264 return variableAccessData()->local();
276 case ResolveBaseStrictPut
:
283 unsigned identifierNumber()
285 ASSERT(hasIdentifier());
289 unsigned resolveGlobalDataIndex()
291 ASSERT(op() == ResolveGlobal
);
295 bool hasArithNodeFlags()
315 // This corrects the arithmetic node flags, so that irrelevant bits are
316 // ignored. In particular, anything other than ArithMul does not need
317 // to know if it can speculate on negative zero.
318 NodeFlags
arithNodeFlags()
320 NodeFlags result
= m_flags
;
321 if (op() == ArithMul
|| op() == ArithDiv
|| op() == ArithMod
)
323 return result
& ~NodeNeedsNegZero
;
326 bool hasConstantBuffer()
328 return op() == NewArrayBuffer
;
331 unsigned startConstant()
333 ASSERT(hasConstantBuffer());
337 unsigned numConstants()
339 ASSERT(hasConstantBuffer());
343 bool hasRegexpIndex()
345 return op() == NewRegexp
;
348 unsigned regexpIndex()
350 ASSERT(hasRegexpIndex());
356 return op() == GetGlobalVar
|| op() == PutGlobalVar
|| op() == GetScopedVar
|| op() == PutScopedVar
;
361 ASSERT(hasVarNumber());
365 bool hasScopeChainDepth()
367 return op() == GetScopeChain
;
370 unsigned scopeChainDepth()
372 ASSERT(hasScopeChainDepth());
378 return m_flags
& NodeResultMask
;
381 bool hasInt32Result()
383 return (m_flags
& NodeResultMask
) == NodeResultInt32
;
386 bool hasNumberResult()
388 return (m_flags
& NodeResultMask
) == NodeResultNumber
;
393 return (m_flags
& NodeResultMask
) == NodeResultJS
;
396 bool hasBooleanResult()
398 return (m_flags
& NodeResultMask
) == NodeResultBoolean
;
408 return op() == Branch
;
418 case ThrowReferenceError
:
425 unsigned takenBytecodeOffsetDuringParsing()
427 ASSERT(isBranch() || isJump());
431 unsigned notTakenBytecodeOffsetDuringParsing()
437 void setTakenBlockIndex(BlockIndex blockIndex
)
439 ASSERT(isBranch() || isJump());
440 m_opInfo
= blockIndex
;
443 void setNotTakenBlockIndex(BlockIndex blockIndex
)
446 m_opInfo2
= blockIndex
;
449 BlockIndex
takenBlockIndex()
451 ASSERT(isBranch() || isJump());
455 BlockIndex
notTakenBlockIndex()
461 bool hasHeapPrediction()
473 case ResolveBaseStrictPut
:
486 PredictedType
getHeapPrediction()
488 ASSERT(hasHeapPrediction());
489 return static_cast<PredictedType
>(m_opInfo2
);
492 bool predictHeap(PredictedType prediction
)
494 ASSERT(hasHeapPrediction());
496 return mergePrediction(m_opInfo2
, prediction
);
499 bool hasFunctionCheckData()
501 return op() == CheckFunction
;
504 JSFunction
* function()
506 ASSERT(hasFunctionCheckData());
507 return reinterpret_cast<JSFunction
*>(m_opInfo
);
510 bool hasStructureTransitionData()
512 return op() == PutStructure
;
515 StructureTransitionData
& structureTransitionData()
517 ASSERT(hasStructureTransitionData());
518 return *reinterpret_cast<StructureTransitionData
*>(m_opInfo
);
521 bool hasStructureSet()
523 return op() == CheckStructure
;
526 StructureSet
& structureSet()
528 ASSERT(hasStructureSet());
529 return *reinterpret_cast<StructureSet
*>(m_opInfo
);
532 bool hasStorageAccessData()
534 return op() == GetByOffset
|| op() == PutByOffset
;
537 unsigned storageAccessDataIndex()
539 ASSERT(hasStorageAccessData());
543 bool hasFunctionDeclIndex()
545 return op() == NewFunction
546 || op() == NewFunctionNoCheck
;
549 unsigned functionDeclIndex()
551 ASSERT(hasFunctionDeclIndex());
555 bool hasFunctionExprIndex()
557 return op() == NewFunctionExpression
;
560 unsigned functionExprIndex()
562 ASSERT(hasFunctionExprIndex());
566 bool hasVirtualRegister()
568 return m_virtualRegister
!= InvalidVirtualRegister
;
571 VirtualRegister
virtualRegister()
574 ASSERT(m_virtualRegister
!= InvalidVirtualRegister
);
575 return m_virtualRegister
;
578 void setVirtualRegister(VirtualRegister virtualRegister
)
581 ASSERT(m_virtualRegister
== InvalidVirtualRegister
);
582 m_virtualRegister
= virtualRegister
;
585 bool shouldGenerate()
595 // returns true when ref count passes from 0 to 1.
598 return !m_refCount
++;
601 unsigned adjustedRefCount()
603 return mustGenerate() ? m_refCount
- 1 : m_refCount
;
606 void setRefCount(unsigned refCount
)
608 m_refCount
= refCount
;
611 // Derefs the node and returns true if the ref count reached zero.
612 // In general you don't want to use this directly; use Graph::deref
617 return !--m_refCount
;
622 ASSERT(!(m_flags
& NodeHasVarArgs
));
623 return children
.child1();
626 // This is useful if you want to do a fast check on the first child
627 // before also doing a check on the opcode. Use this with care and
628 // avoid it if possible.
629 Edge
child1Unchecked()
631 return children
.child1Unchecked();
636 ASSERT(!(m_flags
& NodeHasVarArgs
));
637 return children
.child2();
642 ASSERT(!(m_flags
& NodeHasVarArgs
));
643 return children
.child3();
646 unsigned firstChild()
648 ASSERT(m_flags
& NodeHasVarArgs
);
649 return children
.firstChild();
652 unsigned numChildren()
654 ASSERT(m_flags
& NodeHasVarArgs
);
655 return children
.numChildren();
658 PredictedType
prediction()
663 bool predict(PredictedType prediction
)
665 return mergePrediction(m_prediction
, prediction
);
668 bool shouldSpeculateInteger()
670 return isInt32Prediction(prediction());
673 bool shouldSpeculateDouble()
675 return isDoublePrediction(prediction());
678 bool shouldSpeculateNumber()
680 return isNumberPrediction(prediction());
683 bool shouldSpeculateBoolean()
685 return isBooleanPrediction(prediction());
688 bool shouldSpeculateFinalObject()
690 return isFinalObjectPrediction(prediction());
693 bool shouldSpeculateFinalObjectOrOther()
695 return isFinalObjectOrOtherPrediction(prediction());
698 bool shouldSpeculateArray()
700 return isArrayPrediction(prediction());
703 bool shouldSpeculateInt8Array()
705 return isInt8ArrayPrediction(prediction());
708 bool shouldSpeculateInt16Array()
710 return isInt16ArrayPrediction(prediction());
713 bool shouldSpeculateInt32Array()
715 return isInt32ArrayPrediction(prediction());
718 bool shouldSpeculateUint8Array()
720 return isUint8ArrayPrediction(prediction());
723 bool shouldSpeculateUint8ClampedArray()
725 return isUint8ClampedArrayPrediction(prediction());
728 bool shouldSpeculateUint16Array()
730 return isUint16ArrayPrediction(prediction());
733 bool shouldSpeculateUint32Array()
735 return isUint32ArrayPrediction(prediction());
738 bool shouldSpeculateFloat32Array()
740 return isFloat32ArrayPrediction(prediction());
743 bool shouldSpeculateFloat64Array()
745 return isFloat64ArrayPrediction(prediction());
748 bool shouldSpeculateArrayOrOther()
750 return isArrayOrOtherPrediction(prediction());
753 bool shouldSpeculateObject()
755 return isObjectPrediction(prediction());
758 bool shouldSpeculateCell()
760 return isCellPrediction(prediction());
763 static bool shouldSpeculateInteger(Node
& op1
, Node
& op2
)
765 return op1
.shouldSpeculateInteger() && op2
.shouldSpeculateInteger();
768 static bool shouldSpeculateNumber(Node
& op1
, Node
& op2
)
770 return op1
.shouldSpeculateNumber() && op2
.shouldSpeculateNumber();
773 static bool shouldSpeculateFinalObject(Node
& op1
, Node
& op2
)
775 return op1
.shouldSpeculateFinalObject() && op2
.shouldSpeculateFinalObject();
778 static bool shouldSpeculateArray(Node
& op1
, Node
& op2
)
780 return op1
.shouldSpeculateArray() && op2
.shouldSpeculateArray();
783 bool canSpeculateInteger()
785 return nodeCanSpeculateInteger(arithNodeFlags());
788 void dumpChildren(FILE* out
)
792 fprintf(out
, "@%u", child1().index());
795 fprintf(out
, ", @%u", child2().index());
798 fprintf(out
, ", @%u", child3().index());
801 // Used to look up exception handling information (currently implemented as a bytecode index).
802 CodeOrigin codeOrigin
;
803 // References to up to 3 children, or links to a variable length set of children.
804 AdjacencyList children
;
807 uint16_t m_op
; // real type is NodeType
809 // The virtual register number (spill location) associated with this .
810 VirtualRegister m_virtualRegister
;
811 // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
813 // Immediate values, accesses type-checked via accessors above. The first one is
814 // big enough to store a pointer.
817 // The prediction ascribed to this node after propagation.
818 PredictedType m_prediction
;
821 } } // namespace JSC::DFG