PredictedType should be called SpeculatedType
[WebKit-https.git] / Source / JavaScriptCore / 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     bool run()
45     {
46         for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex)
47             fixupBlock(m_graph.m_blocks[blockIndex].get());
48         return true;
49     }
50
51 private:
52     void fixupBlock(BasicBlock* block)
53     {
54         if (!block)
55             return;
56         ASSERT(block->isReachable);
57         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     
64     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: {
77             if (!isInt32Speculation(m_graph[m_compileIndex].prediction()))
78                 break;
79             if (codeBlock()->identifier(node.identifierNumber()) != globalData().propertyNames->length)
80                 break;
81             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());
84             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();
93             if (!isArray && !isArguments && !isString && !isInt8Array && !isInt16Array && !isInt32Array && !isUint8Array && !isUint8ClampedArray && !isUint16Array && !isUint32Array && !isFloat32Array && !isFloat64Array)
94                 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);
101             else if (isArguments)
102                 node.setOp(GetArgumentsLength);
103             else if (isString)
104                 node.setOp(GetStringLength);
105             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: {
132             SpeculatedType basePrediction = m_graph[node.child2()].prediction();
133             if ((!(basePrediction & SpecInt32) && basePrediction)
134                 || m_graph[node.child1()].shouldSpeculateArguments()
135                 || !isActionableArraySpeculation(m_graph[node.child1()].prediction())) {
136                 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             
171         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: {
196             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();
206                 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                 }
216             }
217             break;
218         }
219             
220         case SetLocal: {
221             if (node.variableAccessData()->isCaptured())
222                 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:
258         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             
267         case ArithMul: {
268             if (m_graph.mulShouldSpeculateInteger(node))
269                 break;
270             fixDoubleEdge(0);
271             fixDoubleEdge(1);
272             break;
273         }
274
275         case ArithDiv: {
276             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);
287                 newDivision.predict(SpecDouble);
288                 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                 
296                 break;
297             }
298             fixDoubleEdge(0);
299             fixDoubleEdge(1);
300             break;
301         }
302             
303         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;
321             if (isActionableIntMutableArraySpeculation(m_graph[node.child1()].prediction())) {
322                 if (m_graph[node.child3()].isConstant())
323                     break;
324                 if (m_graph[node.child3()].shouldSpeculateInteger())
325                     break;
326                 fixDoubleEdge(2);
327                 break;
328             }
329             if (isActionableFloatMutableArraySpeculation(m_graph[node.child1()].prediction())) {
330                 fixDoubleEdge(2);
331                 break;
332             }
333             break;
334         }
335             
336         default:
337             break;
338         }
339
340 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
341         if (!(node.flags() & NodeHasVarArgs)) {
342             dataLog("new children: ");
343             node.dumpChildren(WTF::dataFile());
344         }
345         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     
367     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];
393         int32ToDouble.predict(SpecDouble);
394         int32ToDouble.ref();
395     }
396     
397     unsigned m_indexInBlock;
398     NodeIndex m_compileIndex;
399     InsertionSet<NodeIndex> m_insertionSet;
400 };
401     
402 bool performFixup(Graph& graph)
403 {
404     return runPhase<FixupPhase>(graph);
405 }
406
407 } } // namespace JSC::DFG
408
409 #endif // ENABLE(DFG_JIT)
410