]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGFixupPhase.cpp
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGFixupPhase.cpp
1 /*
2 * Copyright (C) 2012 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27 #include "DFGFixupPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGGraph.h"
32 #include "DFGInsertionSet.h"
33 #include "DFGPhase.h"
34
35 namespace JSC { namespace DFG {
36
37 class FixupPhase : public Phase {
38 public:
39 FixupPhase(Graph& graph)
40 : Phase(graph, "fixup")
41 {
42 }
43
44 void run()
45 {
46 for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex)
47 fixupBlock(m_graph.m_blocks[blockIndex].get());
48 }
49
50 private:
51 void fixupBlock(BasicBlock* block)
52 {
53 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
54 m_compileIndex = block->at(m_indexInBlock);
55 fixupNode(m_graph[m_compileIndex]);
56 }
57 m_insertionSet.execute(*block);
58 }
59
60 void fixupNode(Node& node)
61 {
62 if (!node.shouldGenerate())
63 return;
64
65 NodeType op = node.op();
66
67 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
68 dataLog(" %s @%u: ", Graph::opName(op), m_compileIndex);
69 #endif
70
71 switch (op) {
72 case GetById: {
73 if (!isInt32Prediction(m_graph[m_compileIndex].prediction()))
74 break;
75 if (codeBlock()->identifier(node.identifierNumber()) != globalData().propertyNames->length)
76 break;
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)
89 break;
90
91 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
92 dataLog(" @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength");
93 #endif
94 if (isArray)
95 node.setOp(GetArrayLength);
96 else if (isString)
97 node.setOp(GetStringLength);
98 else if (isInt8Array)
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);
116 else
117 ASSERT_NOT_REACHED();
118 // No longer MustGenerate
119 ASSERT(node.flags() & NodeMustGenerate);
120 node.clearFlags(NodeMustGenerate);
121 m_graph.deref(m_compileIndex);
122 break;
123 }
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);
131 node.setRefCount(0);
132 }
133 break;
134 }
135 case GetByVal:
136 case StringCharAt:
137 case StringCharCodeAt: {
138 if (!!node.child3() && m_graph[node.child3()].op() == Nop)
139 node.children.child3() = Edge();
140 break;
141 }
142
143 case ValueToInt32: {
144 if (m_graph[node.child1()].shouldSpeculateNumber()) {
145 node.clearFlags(NodeMustGenerate);
146 m_graph.deref(m_compileIndex);
147 }
148 break;
149 }
150
151 case BitAnd:
152 case BitOr:
153 case BitXor:
154 case BitRShift:
155 case BitLShift:
156 case BitURShift: {
157 fixIntEdge(node.children.child1());
158 fixIntEdge(node.children.child2());
159 break;
160 }
161
162 case CompareEq:
163 case CompareLess:
164 case CompareLessEq:
165 case CompareGreater:
166 case CompareGreaterEq:
167 case CompareStrictEq: {
168 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]))
169 break;
170 if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
171 break;
172 fixDoubleEdge(0);
173 fixDoubleEdge(1);
174 break;
175 }
176
177 case LogicalNot: {
178 if (m_graph[node.child1()].shouldSpeculateInteger())
179 break;
180 if (!m_graph[node.child1()].shouldSpeculateNumber())
181 break;
182 fixDoubleEdge(0);
183 break;
184 }
185
186 case Branch: {
187 if (!m_graph[node.child1()].shouldSpeculateInteger()
188 && m_graph[node.child1()].shouldSpeculateNumber())
189 fixDoubleEdge(0);
190
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);
201
202 BlockIndex toBeTaken = myNode.notTakenBlockIndex();
203 BlockIndex toBeNotTaken = myNode.takenBlockIndex();
204 myNode.setTakenBlockIndex(toBeTaken);
205 myNode.setNotTakenBlockIndex(toBeNotTaken);
206 }
207 }
208 break;
209 }
210
211 case SetLocal: {
212 if (m_graph.isCaptured(node.local()))
213 break;
214 if (!node.variableAccessData()->shouldUseDoubleFormat())
215 break;
216 fixDoubleEdge(0);
217 break;
218 }
219
220 case ArithAdd:
221 case ValueAdd: {
222 if (m_graph.addShouldSpeculateInteger(node))
223 break;
224 if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
225 break;
226 fixDoubleEdge(0);
227 fixDoubleEdge(1);
228 break;
229 }
230
231 case ArithSub: {
232 if (m_graph.addShouldSpeculateInteger(node)
233 && node.canSpeculateInteger())
234 break;
235 fixDoubleEdge(0);
236 fixDoubleEdge(1);
237 break;
238 }
239
240 case ArithNegate: {
241 if (m_graph.negateShouldSpeculateInteger(node))
242 break;
243 fixDoubleEdge(0);
244 break;
245 }
246
247 case ArithMin:
248 case ArithMax:
249 case ArithMul:
250 case ArithMod: {
251 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
252 && node.canSpeculateInteger())
253 break;
254 fixDoubleEdge(0);
255 fixDoubleEdge(1);
256 break;
257 }
258
259 case ArithDiv: {
260 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
261 && node.canSpeculateInteger()) {
262 if (isX86())
263 break;
264 fixDoubleEdge(0);
265 fixDoubleEdge(1);
266
267 Node& oldDivision = m_graph[m_compileIndex];
268
269 Node newDivision = oldDivision;
270 newDivision.setRefCount(2);
271 newDivision.predict(PredictDouble);
272 NodeIndex newDivisionIndex = m_graph.size();
273
274 oldDivision.setOp(DoubleAsInt32);
275 oldDivision.children.initialize(Edge(newDivisionIndex, DoubleUse), Edge(), Edge());
276
277 m_graph.append(newDivision);
278 m_insertionSet.append(m_indexInBlock, newDivisionIndex);
279
280 break;
281 }
282 fixDoubleEdge(0);
283 fixDoubleEdge(1);
284 break;
285 }
286
287 case ArithAbs: {
288 if (m_graph[node.child1()].shouldSpeculateInteger()
289 && node.canSpeculateInteger())
290 break;
291 fixDoubleEdge(0);
292 break;
293 }
294
295 case ArithSqrt: {
296 fixDoubleEdge(0);
297 break;
298 }
299
300 case PutByVal: {
301 if (!m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction())
302 break;
303 if (!m_graph[node.child2()].shouldSpeculateInteger())
304 break;
305 if (isActionableIntMutableArrayPrediction(m_graph[node.child1()].prediction())) {
306 if (m_graph[node.child3()].isConstant())
307 break;
308 if (m_graph[node.child3()].shouldSpeculateInteger())
309 break;
310 fixDoubleEdge(2);
311 break;
312 }
313 if (isActionableFloatMutableArrayPrediction(m_graph[node.child1()].prediction())) {
314 fixDoubleEdge(2);
315 break;
316 }
317 break;
318 }
319
320 default:
321 break;
322 }
323
324 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
325 if (!(node.flags() & NodeHasVarArgs)) {
326 dataLog("new children: ");
327 node.dumpChildren(WTF::dataFile());
328 }
329 dataLog("\n");
330 #endif
331 }
332
333 void fixIntEdge(Edge& edge)
334 {
335 Node& node = m_graph[edge];
336 if (node.op() != ValueToInt32)
337 return;
338
339 if (!m_graph[node.child1()].shouldSpeculateInteger())
340 return;
341
342 Edge oldEdge = edge;
343 Edge newEdge = node.child1();
344
345 m_graph.ref(newEdge);
346 m_graph.deref(oldEdge);
347
348 edge = newEdge;
349 }
350
351 void fixDoubleEdge(unsigned childIndex)
352 {
353 Node& source = m_graph[m_compileIndex];
354 Edge& edge = source.children.child(childIndex);
355
356 if (!m_graph[edge].shouldSpeculateInteger()) {
357 edge.setUseKind(DoubleUse);
358 return;
359 }
360
361 NodeIndex resultIndex = (NodeIndex)m_graph.size();
362
363 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
364 dataLog("(replacing @%u->@%u with @%u->@%u) ",
365 m_compileIndex, edge.index(), m_compileIndex, resultIndex);
366 #endif
367
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);
372
373 m_graph.append(Node(Int32ToDouble, source.codeOrigin, oldIndex));
374 m_insertionSet.append(m_indexInBlock, resultIndex);
375
376 Node& int32ToDouble = m_graph[resultIndex];
377 int32ToDouble.predict(PredictDouble);
378 int32ToDouble.ref();
379 }
380
381 unsigned m_indexInBlock;
382 NodeIndex m_compileIndex;
383 InsertionSet<NodeIndex> m_insertionSet;
384 };
385
386 void performFixup(Graph& graph)
387 {
388 runPhase<FixupPhase>(graph);
389 }
390
391 } } // namespace JSC::DFG
392
393 #endif // ENABLE(DFG_JIT)
394