blob: b256faca3fef82a74b06d53308d72eb77aaa2976 [file] [log] [blame]
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +00001/*
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"
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000032#include "DFGInsertionSet.h"
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000033#include "DFGPhase.h"
34
35namespace JSC { namespace DFG {
36
37class FixupPhase : public Phase {
38public:
39 FixupPhase(Graph& graph)
40 : Phase(graph, "fixup")
41 {
42 }
43
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000044 bool run()
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000045 {
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000046 for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex)
47 fixupBlock(m_graph.m_blocks[blockIndex].get());
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000048 return true;
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000049 }
50
51private:
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000052 void fixupBlock(BasicBlock* block)
53 {
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +000054 if (!block)
55 return;
56 ASSERT(block->isReachable);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +000057 for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
58 m_compileIndex = block->at(m_indexInBlock);
59 fixupNode(m_graph[m_compileIndex]);
60 }
61 m_insertionSet.execute(*block);
62 }
63
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000064 void fixupNode(Node& node)
65 {
66 if (!node.shouldGenerate())
67 return;
68
69 NodeType op = node.op();
70
71#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
72 dataLog(" %s @%u: ", Graph::opName(op), m_compileIndex);
73#endif
74
75 switch (op) {
76 case GetById: {
fpizlo@apple.com62336162012-06-07 01:35:59 +000077 if (!isInt32Speculation(m_graph[m_compileIndex].prediction()))
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000078 break;
79 if (codeBlock()->identifier(node.identifierNumber()) != globalData().propertyNames->length)
80 break;
fpizlo@apple.com62336162012-06-07 01:35:59 +000081 bool isArray = isArraySpeculation(m_graph[node.child1()].prediction());
82 bool isArguments = isArgumentsSpeculation(m_graph[node.child1()].prediction());
83 bool isString = isStringSpeculation(m_graph[node.child1()].prediction());
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000084 bool isInt8Array = m_graph[node.child1()].shouldSpeculateInt8Array();
85 bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array();
86 bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array();
87 bool isUint8Array = m_graph[node.child1()].shouldSpeculateUint8Array();
88 bool isUint8ClampedArray = m_graph[node.child1()].shouldSpeculateUint8ClampedArray();
89 bool isUint16Array = m_graph[node.child1()].shouldSpeculateUint16Array();
90 bool isUint32Array = m_graph[node.child1()].shouldSpeculateUint32Array();
91 bool isFloat32Array = m_graph[node.child1()].shouldSpeculateFloat32Array();
92 bool isFloat64Array = m_graph[node.child1()].shouldSpeculateFloat64Array();
fpizlo@apple.comc6446112012-05-23 20:52:42 +000093 if (!isArray && !isArguments && !isString && !isInt8Array && !isInt16Array && !isInt32Array && !isUint8Array && !isUint8ClampedArray && !isUint16Array && !isUint32Array && !isFloat32Array && !isFloat64Array)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +000094 break;
95
96#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
97 dataLog(" @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength");
98#endif
99 if (isArray)
100 node.setOp(GetArrayLength);
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000101 else if (isArguments)
102 node.setOp(GetArgumentsLength);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000103 else if (isString)
104 node.setOp(GetStringLength);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000105 else if (isInt8Array)
106 node.setOp(GetInt8ArrayLength);
107 else if (isInt16Array)
108 node.setOp(GetInt16ArrayLength);
109 else if (isInt32Array)
110 node.setOp(GetInt32ArrayLength);
111 else if (isUint8Array)
112 node.setOp(GetUint8ArrayLength);
113 else if (isUint8ClampedArray)
114 node.setOp(GetUint8ClampedArrayLength);
115 else if (isUint16Array)
116 node.setOp(GetUint16ArrayLength);
117 else if (isUint32Array)
118 node.setOp(GetUint32ArrayLength);
119 else if (isFloat32Array)
120 node.setOp(GetFloat32ArrayLength);
121 else if (isFloat64Array)
122 node.setOp(GetFloat64ArrayLength);
123 else
124 ASSERT_NOT_REACHED();
125 // No longer MustGenerate
126 ASSERT(node.flags() & NodeMustGenerate);
127 node.clearFlags(NodeMustGenerate);
128 m_graph.deref(m_compileIndex);
129 break;
130 }
131 case GetIndexedPropertyStorage: {
fpizlo@apple.com62336162012-06-07 01:35:59 +0000132 SpeculatedType basePrediction = m_graph[node.child2()].prediction();
133 if ((!(basePrediction & SpecInt32) && basePrediction)
fpizlo@apple.comf860f9b2012-05-22 20:02:25 +0000134 || m_graph[node.child1()].shouldSpeculateArguments()
fpizlo@apple.com62336162012-06-07 01:35:59 +0000135 || !isActionableArraySpeculation(m_graph[node.child1()].prediction())) {
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000136 node.setOpAndDefaultFlags(Nop);
137 m_graph.clearAndDerefChild1(node);
138 m_graph.clearAndDerefChild2(node);
139 m_graph.clearAndDerefChild3(node);
140 node.setRefCount(0);
141 }
142 break;
143 }
144 case GetByVal:
145 case StringCharAt:
146 case StringCharCodeAt: {
147 if (!!node.child3() && m_graph[node.child3()].op() == Nop)
148 node.children.child3() = Edge();
149 break;
150 }
151
152 case ValueToInt32: {
153 if (m_graph[node.child1()].shouldSpeculateNumber()) {
154 node.clearFlags(NodeMustGenerate);
155 m_graph.deref(m_compileIndex);
156 }
157 break;
158 }
159
160 case BitAnd:
161 case BitOr:
162 case BitXor:
163 case BitRShift:
164 case BitLShift:
165 case BitURShift: {
166 fixIntEdge(node.children.child1());
167 fixIntEdge(node.children.child2());
168 break;
169 }
170
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000171 case CompareEq:
172 case CompareLess:
173 case CompareLessEq:
174 case CompareGreater:
175 case CompareGreaterEq:
176 case CompareStrictEq: {
177 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]))
178 break;
179 if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
180 break;
181 fixDoubleEdge(0);
182 fixDoubleEdge(1);
183 break;
184 }
185
186 case LogicalNot: {
187 if (m_graph[node.child1()].shouldSpeculateInteger())
188 break;
189 if (!m_graph[node.child1()].shouldSpeculateNumber())
190 break;
191 fixDoubleEdge(0);
192 break;
193 }
194
195 case Branch: {
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000196 if (!m_graph[node.child1()].shouldSpeculateInteger()
197 && m_graph[node.child1()].shouldSpeculateNumber())
198 fixDoubleEdge(0);
199
200 Node& myNode = m_graph[m_compileIndex]; // reload because the graph may have changed
201 Edge logicalNotEdge = myNode.child1();
202 Node& logicalNot = m_graph[logicalNotEdge];
203 if (logicalNot.op() == LogicalNot
204 && logicalNot.adjustedRefCount() == 1) {
205 Edge newChildEdge = logicalNot.child1();
fpizlo@apple.coma6c889b2012-04-12 04:19:07 +0000206 if (m_graph[newChildEdge].hasBooleanResult()) {
207 m_graph.ref(newChildEdge);
208 m_graph.deref(logicalNotEdge);
209 myNode.children.setChild1(newChildEdge);
210
211 BlockIndex toBeTaken = myNode.notTakenBlockIndex();
212 BlockIndex toBeNotTaken = myNode.takenBlockIndex();
213 myNode.setTakenBlockIndex(toBeTaken);
214 myNode.setNotTakenBlockIndex(toBeNotTaken);
215 }
fpizlo@apple.come2967fd2012-04-04 21:14:48 +0000216 }
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000217 break;
218 }
219
220 case SetLocal: {
fpizlo@apple.com1688cc12012-05-23 07:29:02 +0000221 if (node.variableAccessData()->isCaptured())
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000222 break;
223 if (!node.variableAccessData()->shouldUseDoubleFormat())
224 break;
225 fixDoubleEdge(0);
226 break;
227 }
228
229 case ArithAdd:
230 case ValueAdd: {
231 if (m_graph.addShouldSpeculateInteger(node))
232 break;
233 if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()]))
234 break;
235 fixDoubleEdge(0);
236 fixDoubleEdge(1);
237 break;
238 }
239
240 case ArithSub: {
241 if (m_graph.addShouldSpeculateInteger(node)
242 && node.canSpeculateInteger())
243 break;
244 fixDoubleEdge(0);
245 fixDoubleEdge(1);
246 break;
247 }
248
249 case ArithNegate: {
250 if (m_graph.negateShouldSpeculateInteger(node))
251 break;
252 fixDoubleEdge(0);
253 break;
254 }
255
256 case ArithMin:
257 case ArithMax:
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000258 case ArithMod: {
259 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
260 && node.canSpeculateInteger())
261 break;
262 fixDoubleEdge(0);
263 fixDoubleEdge(1);
264 break;
265 }
266
fpizlo@apple.comfa9f10c2012-05-22 17:18:21 +0000267 case ArithMul: {
268 if (m_graph.mulShouldSpeculateInteger(node))
269 break;
270 fixDoubleEdge(0);
271 fixDoubleEdge(1);
272 break;
273 }
274
fpizlo@apple.com0cf017f2012-04-18 22:31:54 +0000275 case ArithDiv: {
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000276 if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])
277 && node.canSpeculateInteger()) {
278 if (isX86())
279 break;
280 fixDoubleEdge(0);
281 fixDoubleEdge(1);
282
283 Node& oldDivision = m_graph[m_compileIndex];
284
285 Node newDivision = oldDivision;
286 newDivision.setRefCount(2);
fpizlo@apple.com62336162012-06-07 01:35:59 +0000287 newDivision.predict(SpecDouble);
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000288 NodeIndex newDivisionIndex = m_graph.size();
289
290 oldDivision.setOp(DoubleAsInt32);
291 oldDivision.children.initialize(Edge(newDivisionIndex, DoubleUse), Edge(), Edge());
292
293 m_graph.append(newDivision);
294 m_insertionSet.append(m_indexInBlock, newDivisionIndex);
295
fpizlo@apple.com0cf017f2012-04-18 22:31:54 +0000296 break;
fpizlo@apple.com3d223382012-04-24 19:19:35 +0000297 }
fpizlo@apple.com0cf017f2012-04-18 22:31:54 +0000298 fixDoubleEdge(0);
299 fixDoubleEdge(1);
300 break;
301 }
302
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000303 case ArithAbs: {
304 if (m_graph[node.child1()].shouldSpeculateInteger()
305 && node.canSpeculateInteger())
306 break;
307 fixDoubleEdge(0);
308 break;
309 }
310
311 case ArithSqrt: {
312 fixDoubleEdge(0);
313 break;
314 }
315
316 case PutByVal: {
317 if (!m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction())
318 break;
319 if (!m_graph[node.child2()].shouldSpeculateInteger())
320 break;
fpizlo@apple.com62336162012-06-07 01:35:59 +0000321 if (isActionableIntMutableArraySpeculation(m_graph[node.child1()].prediction())) {
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000322 if (m_graph[node.child3()].isConstant())
323 break;
324 if (m_graph[node.child3()].shouldSpeculateInteger())
325 break;
326 fixDoubleEdge(2);
327 break;
328 }
fpizlo@apple.com62336162012-06-07 01:35:59 +0000329 if (isActionableFloatMutableArraySpeculation(m_graph[node.child1()].prediction())) {
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000330 fixDoubleEdge(2);
331 break;
332 }
333 break;
334 }
335
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000336 default:
337 break;
338 }
339
340#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000341 if (!(node.flags() & NodeHasVarArgs)) {
342 dataLog("new children: ");
343 node.dumpChildren(WTF::dataFile());
344 }
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000345 dataLog("\n");
346#endif
347 }
348
349 void fixIntEdge(Edge& edge)
350 {
351 Node& node = m_graph[edge];
352 if (node.op() != ValueToInt32)
353 return;
354
355 if (!m_graph[node.child1()].shouldSpeculateInteger())
356 return;
357
358 Edge oldEdge = edge;
359 Edge newEdge = node.child1();
360
361 m_graph.ref(newEdge);
362 m_graph.deref(oldEdge);
363
364 edge = newEdge;
365 }
366
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000367 void fixDoubleEdge(unsigned childIndex)
368 {
369 Node& source = m_graph[m_compileIndex];
370 Edge& edge = source.children.child(childIndex);
371
372 if (!m_graph[edge].shouldSpeculateInteger()) {
373 edge.setUseKind(DoubleUse);
374 return;
375 }
376
377 NodeIndex resultIndex = (NodeIndex)m_graph.size();
378
379#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
380 dataLog("(replacing @%u->@%u with @%u->@%u) ",
381 m_compileIndex, edge.index(), m_compileIndex, resultIndex);
382#endif
383
384 // Fix the edge up here because it's a reference that will be clobbered by
385 // the append() below.
386 NodeIndex oldIndex = edge.index();
387 edge = Edge(resultIndex, DoubleUse);
388
389 m_graph.append(Node(Int32ToDouble, source.codeOrigin, oldIndex));
390 m_insertionSet.append(m_indexInBlock, resultIndex);
391
392 Node& int32ToDouble = m_graph[resultIndex];
fpizlo@apple.com62336162012-06-07 01:35:59 +0000393 int32ToDouble.predict(SpecDouble);
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000394 int32ToDouble.ref();
395 }
396
397 unsigned m_indexInBlock;
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000398 NodeIndex m_compileIndex;
fpizlo@apple.com96cfc6b2012-03-25 23:50:24 +0000399 InsertionSet<NodeIndex> m_insertionSet;
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000400};
401
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000402bool performFixup(Graph& graph)
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000403{
fpizlo@apple.com79c51ee2012-05-18 22:30:24 +0000404 return runPhase<FixupPhase>(graph);
fpizlo@apple.coma73f21d2012-03-24 03:23:02 +0000405}
406
407} } // namespace JSC::DFG
408
409#endif // ENABLE(DFG_JIT)
410