2 * Copyright (C) 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.
27 #include "DFGFixupPhase.h"
32 #include "DFGInsertionSet.h"
35 namespace JSC
{ namespace DFG
{
37 class FixupPhase
: public Phase
{
39 FixupPhase(Graph
& graph
)
40 : Phase(graph
, "fixup")
46 for (BlockIndex blockIndex
= 0; blockIndex
< m_graph
.m_blocks
.size(); ++blockIndex
)
47 fixupBlock(m_graph
.m_blocks
[blockIndex
].get());
51 void fixupBlock(BasicBlock
* block
)
53 for (m_indexInBlock
= 0; m_indexInBlock
< block
->size(); ++m_indexInBlock
) {
54 m_compileIndex
= block
->at(m_indexInBlock
);
55 fixupNode(m_graph
[m_compileIndex
]);
57 m_insertionSet
.execute(*block
);
60 void fixupNode(Node
& node
)
62 if (!node
.shouldGenerate())
65 NodeType op
= node
.op();
67 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
68 dataLog(" %s @%u: ", Graph::opName(op
), m_compileIndex
);
73 if (!isInt32Prediction(m_graph
[m_compileIndex
].prediction()))
75 if (codeBlock()->identifier(node
.identifierNumber()) != globalData().propertyNames
->length
)
77 bool isArray
= isArrayPrediction(m_graph
[node
.child1()].prediction());
78 bool isString
= isStringPrediction(m_graph
[node
.child1()].prediction());
79 bool isInt8Array
= m_graph
[node
.child1()].shouldSpeculateInt8Array();
80 bool isInt16Array
= m_graph
[node
.child1()].shouldSpeculateInt16Array();
81 bool isInt32Array
= m_graph
[node
.child1()].shouldSpeculateInt32Array();
82 bool isUint8Array
= m_graph
[node
.child1()].shouldSpeculateUint8Array();
83 bool isUint8ClampedArray
= m_graph
[node
.child1()].shouldSpeculateUint8ClampedArray();
84 bool isUint16Array
= m_graph
[node
.child1()].shouldSpeculateUint16Array();
85 bool isUint32Array
= m_graph
[node
.child1()].shouldSpeculateUint32Array();
86 bool isFloat32Array
= m_graph
[node
.child1()].shouldSpeculateFloat32Array();
87 bool isFloat64Array
= m_graph
[node
.child1()].shouldSpeculateFloat64Array();
88 if (!isArray
&& !isString
&& !isInt8Array
&& !isInt16Array
&& !isInt32Array
&& !isUint8Array
&& !isUint8ClampedArray
&& !isUint16Array
&& !isUint32Array
&& !isFloat32Array
&& !isFloat64Array
)
91 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
92 dataLog(" @%u -> %s", m_compileIndex
, isArray
? "GetArrayLength" : "GetStringLength");
95 node
.setOp(GetArrayLength
);
97 node
.setOp(GetStringLength
);
99 node
.setOp(GetInt8ArrayLength
);
100 else if (isInt16Array
)
101 node
.setOp(GetInt16ArrayLength
);
102 else if (isInt32Array
)
103 node
.setOp(GetInt32ArrayLength
);
104 else if (isUint8Array
)
105 node
.setOp(GetUint8ArrayLength
);
106 else if (isUint8ClampedArray
)
107 node
.setOp(GetUint8ClampedArrayLength
);
108 else if (isUint16Array
)
109 node
.setOp(GetUint16ArrayLength
);
110 else if (isUint32Array
)
111 node
.setOp(GetUint32ArrayLength
);
112 else if (isFloat32Array
)
113 node
.setOp(GetFloat32ArrayLength
);
114 else if (isFloat64Array
)
115 node
.setOp(GetFloat64ArrayLength
);
117 ASSERT_NOT_REACHED();
118 // No longer MustGenerate
119 ASSERT(node
.flags() & NodeMustGenerate
);
120 node
.clearFlags(NodeMustGenerate
);
121 m_graph
.deref(m_compileIndex
);
124 case GetIndexedPropertyStorage
: {
125 PredictedType basePrediction
= m_graph
[node
.child2()].prediction();
126 if (!(basePrediction
& PredictInt32
) && basePrediction
) {
127 node
.setOpAndDefaultFlags(Nop
);
128 m_graph
.clearAndDerefChild1(node
);
129 m_graph
.clearAndDerefChild2(node
);
130 m_graph
.clearAndDerefChild3(node
);
137 case StringCharCodeAt
: {
138 if (!!node
.child3() && m_graph
[node
.child3()].op() == Nop
)
139 node
.children
.child3() = Edge();
144 if (m_graph
[node
.child1()].shouldSpeculateNumber()) {
145 node
.clearFlags(NodeMustGenerate
);
146 m_graph
.deref(m_compileIndex
);
157 fixIntEdge(node
.children
.child1());
158 fixIntEdge(node
.children
.child2());
166 case CompareGreaterEq
:
167 case CompareStrictEq
: {
168 if (Node::shouldSpeculateInteger(m_graph
[node
.child1()], m_graph
[node
.child2()]))
170 if (!Node::shouldSpeculateNumber(m_graph
[node
.child1()], m_graph
[node
.child2()]))
178 if (m_graph
[node
.child1()].shouldSpeculateInteger())
180 if (!m_graph
[node
.child1()].shouldSpeculateNumber())
187 if (!m_graph
[node
.child1()].shouldSpeculateInteger()
188 && m_graph
[node
.child1()].shouldSpeculateNumber())
191 Node
& myNode
= m_graph
[m_compileIndex
]; // reload because the graph may have changed
192 Edge logicalNotEdge
= myNode
.child1();
193 Node
& logicalNot
= m_graph
[logicalNotEdge
];
194 if (logicalNot
.op() == LogicalNot
195 && logicalNot
.adjustedRefCount() == 1) {
196 Edge newChildEdge
= logicalNot
.child1();
197 if (m_graph
[newChildEdge
].hasBooleanResult()) {
198 m_graph
.ref(newChildEdge
);
199 m_graph
.deref(logicalNotEdge
);
200 myNode
.children
.setChild1(newChildEdge
);
202 BlockIndex toBeTaken
= myNode
.notTakenBlockIndex();
203 BlockIndex toBeNotTaken
= myNode
.takenBlockIndex();
204 myNode
.setTakenBlockIndex(toBeTaken
);
205 myNode
.setNotTakenBlockIndex(toBeNotTaken
);
212 if (m_graph
.isCaptured(node
.local()))
214 if (!node
.variableAccessData()->shouldUseDoubleFormat())
222 if (m_graph
.addShouldSpeculateInteger(node
))
224 if (!Node::shouldSpeculateNumber(m_graph
[node
.child1()], m_graph
[node
.child2()]))
232 if (m_graph
.addShouldSpeculateInteger(node
)
233 && node
.canSpeculateInteger())
241 if (m_graph
.negateShouldSpeculateInteger(node
))
251 if (Node::shouldSpeculateInteger(m_graph
[node
.child1()], m_graph
[node
.child2()])
252 && node
.canSpeculateInteger())
260 if (Node::shouldSpeculateInteger(m_graph
[node
.child1()], m_graph
[node
.child2()])
261 && node
.canSpeculateInteger()) {
267 Node
& oldDivision
= m_graph
[m_compileIndex
];
269 Node newDivision
= oldDivision
;
270 newDivision
.setRefCount(2);
271 newDivision
.predict(PredictDouble
);
272 NodeIndex newDivisionIndex
= m_graph
.size();
274 oldDivision
.setOp(DoubleAsInt32
);
275 oldDivision
.children
.initialize(Edge(newDivisionIndex
, DoubleUse
), Edge(), Edge());
277 m_graph
.append(newDivision
);
278 m_insertionSet
.append(m_indexInBlock
, newDivisionIndex
);
288 if (m_graph
[node
.child1()].shouldSpeculateInteger()
289 && node
.canSpeculateInteger())
301 if (!m_graph
[node
.child1()].prediction() || !m_graph
[node
.child2()].prediction())
303 if (!m_graph
[node
.child2()].shouldSpeculateInteger())
305 if (isActionableIntMutableArrayPrediction(m_graph
[node
.child1()].prediction())) {
306 if (m_graph
[node
.child3()].isConstant())
308 if (m_graph
[node
.child3()].shouldSpeculateInteger())
313 if (isActionableFloatMutableArrayPrediction(m_graph
[node
.child1()].prediction())) {
324 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
325 if (!(node
.flags() & NodeHasVarArgs
)) {
326 dataLog("new children: ");
327 node
.dumpChildren(WTF::dataFile());
333 void fixIntEdge(Edge
& edge
)
335 Node
& node
= m_graph
[edge
];
336 if (node
.op() != ValueToInt32
)
339 if (!m_graph
[node
.child1()].shouldSpeculateInteger())
343 Edge newEdge
= node
.child1();
345 m_graph
.ref(newEdge
);
346 m_graph
.deref(oldEdge
);
351 void fixDoubleEdge(unsigned childIndex
)
353 Node
& source
= m_graph
[m_compileIndex
];
354 Edge
& edge
= source
.children
.child(childIndex
);
356 if (!m_graph
[edge
].shouldSpeculateInteger()) {
357 edge
.setUseKind(DoubleUse
);
361 NodeIndex resultIndex
= (NodeIndex
)m_graph
.size();
363 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
364 dataLog("(replacing @%u->@%u with @%u->@%u) ",
365 m_compileIndex
, edge
.index(), m_compileIndex
, resultIndex
);
368 // Fix the edge up here because it's a reference that will be clobbered by
369 // the append() below.
370 NodeIndex oldIndex
= edge
.index();
371 edge
= Edge(resultIndex
, DoubleUse
);
373 m_graph
.append(Node(Int32ToDouble
, source
.codeOrigin
, oldIndex
));
374 m_insertionSet
.append(m_indexInBlock
, resultIndex
);
376 Node
& int32ToDouble
= m_graph
[resultIndex
];
377 int32ToDouble
.predict(PredictDouble
);
381 unsigned m_indexInBlock
;
382 NodeIndex m_compileIndex
;
383 InsertionSet
<NodeIndex
> m_insertionSet
;
386 void performFixup(Graph
& graph
)
388 runPhase
<FixupPhase
>(graph
);
391 } } // namespace JSC::DFG
393 #endif // ENABLE(DFG_JIT)