Fix style issues in DFG Phase classes
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGPredictionPropagationPhase.cpp
1 /*
2  * Copyright (C) 2011 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 "DFGPredictionPropagationPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGGraph.h"
32 #include "DFGPhase.h"
33
34 namespace JSC { namespace DFG {
35
36 class PredictionPropagationPhase : public Phase {
37 public:
38     PredictionPropagationPhase(Graph& graph)
39         : Phase(graph, "prediction propagation")
40     {
41     }
42     
43     void run()
44     {
45 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
46         m_count = 0;
47 #endif
48         // Two stage process: first propagate predictions, then propagate while doing double voting.
49         
50         do {
51             m_changed = false;
52             
53             // Forward propagation is near-optimal for both topologically-sorted and
54             // DFS-sorted code.
55             propagateForward();
56             if (!m_changed)
57                 break;
58             
59             // Backward propagation reduces the likelihood that pathological code will
60             // cause slowness. Loops (especially nested ones) resemble backward flow.
61             // This pass captures two cases: (1) it detects if the forward fixpoint
62             // found a sound solution and (2) short-circuits backward flow.
63             m_changed = false;
64             propagateBackward();
65         } while (m_changed);
66         
67         do {
68             m_changed = false;
69             doRoundOfDoubleVoting();
70             propagateForward();
71             if (!m_changed)
72                 break;
73             
74             m_changed = false;
75             doRoundOfDoubleVoting();
76             propagateBackward();
77         } while (m_changed);
78         
79         fixup();
80     }
81     
82 private:
83     bool setPrediction(PredictedType prediction)
84     {
85         ASSERT(m_graph[m_compileIndex].hasResult());
86         
87         // setPrediction() is used when we know that there is no way that we can change
88         // our minds about what the prediction is going to be. There is no semantic
89         // difference between setPrediction() and mergePrediction() other than the
90         // increased checking to validate this property.
91         ASSERT(m_graph[m_compileIndex].prediction() == PredictNone || m_graph[m_compileIndex].prediction() == prediction);
92         
93         return m_graph[m_compileIndex].predict(prediction);
94     }
95     
96     bool mergePrediction(PredictedType prediction)
97     {
98         ASSERT(m_graph[m_compileIndex].hasResult());
99         
100         return m_graph[m_compileIndex].predict(prediction);
101     }
102     
103     void propagate(Node& node)
104     {
105         if (!node.shouldGenerate())
106             return;
107         
108         NodeType op = node.op;
109
110 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
111         dataLog("   %s @%u: ", Graph::opName(op), m_compileIndex);
112 #endif
113         
114         bool changed = false;
115         
116         switch (op) {
117         case JSConstant:
118         case WeakJSConstant: {
119             changed |= setPrediction(predictionFromValue(m_graph.valueOfJSConstant(m_compileIndex)));
120             break;
121         }
122             
123         case GetLocal: {
124             PredictedType prediction = node.variableAccessData()->prediction();
125             if (prediction)
126                 changed |= mergePrediction(prediction);
127             break;
128         }
129             
130         case SetLocal: {
131             changed |= node.variableAccessData()->predict(m_graph[node.child1()].prediction());
132             break;
133         }
134             
135         case BitAnd:
136         case BitOr:
137         case BitXor:
138         case BitRShift:
139         case BitLShift:
140         case BitURShift:
141         case ValueToInt32: {
142             changed |= setPrediction(PredictInt32);
143             break;
144         }
145             
146         case ArrayPop:
147         case ArrayPush: {
148             if (node.getHeapPrediction())
149                 changed |= mergePrediction(node.getHeapPrediction());
150             break;
151         }
152
153         case StringCharCodeAt: {
154             changed |= mergePrediction(PredictInt32);
155             break;
156         }
157
158         case ArithMod: {
159             PredictedType left = m_graph[node.child1()].prediction();
160             PredictedType right = m_graph[node.child2()].prediction();
161             
162             if (left && right) {
163                 if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags()))
164                     changed |= mergePrediction(PredictInt32);
165                 else
166                     changed |= mergePrediction(PredictDouble);
167             }
168             break;
169         }
170             
171         case UInt32ToNumber: {
172             if (nodeCanSpeculateInteger(node.arithNodeFlags()))
173                 changed |= setPrediction(PredictInt32);
174             else
175                 changed |= setPrediction(PredictNumber);
176             break;
177         }
178
179         case ValueAdd: {
180             PredictedType left = m_graph[node.child1()].prediction();
181             PredictedType right = m_graph[node.child2()].prediction();
182             
183             if (left && right) {
184                 if (isNumberPrediction(left) && isNumberPrediction(right)) {
185                     if (m_graph.addShouldSpeculateInteger(node))
186                         changed |= mergePrediction(PredictInt32);
187                     else
188                         changed |= mergePrediction(PredictDouble);
189                 } else if (!(left & PredictNumber) || !(right & PredictNumber)) {
190                     // left or right is definitely something other than a number.
191                     changed |= mergePrediction(PredictString);
192                 } else
193                     changed |= mergePrediction(PredictString | PredictInt32 | PredictDouble);
194             }
195             break;
196         }
197             
198         case ArithAdd:
199         case ArithSub: {
200             PredictedType left = m_graph[node.child1()].prediction();
201             PredictedType right = m_graph[node.child2()].prediction();
202             
203             if (left && right) {
204                 if (m_graph.addShouldSpeculateInteger(node))
205                     changed |= mergePrediction(PredictInt32);
206                 else
207                     changed |= mergePrediction(PredictDouble);
208             }
209             break;
210         }
211             
212         case ArithMul:
213         case ArithMin:
214         case ArithMax:
215         case ArithDiv: {
216             PredictedType left = m_graph[node.child1()].prediction();
217             PredictedType right = m_graph[node.child2()].prediction();
218             
219             if (left && right) {
220                 if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags()))
221                     changed |= mergePrediction(PredictInt32);
222                 else
223                     changed |= mergePrediction(PredictDouble);
224             }
225             break;
226         }
227             
228         case ArithSqrt: {
229             changed |= setPrediction(PredictDouble);
230             break;
231         }
232             
233         case ArithAbs: {
234             PredictedType child = m_graph[node.child1()].prediction();
235             if (child) {
236                 if (nodeCanSpeculateInteger(node.arithNodeFlags()))
237                     changed |= mergePrediction(child);
238                 else
239                     changed |= setPrediction(PredictDouble);
240             }
241             break;
242         }
243             
244         case LogicalNot:
245         case CompareLess:
246         case CompareLessEq:
247         case CompareGreater:
248         case CompareGreaterEq:
249         case CompareEq:
250         case CompareStrictEq:
251         case InstanceOf: {
252             changed |= setPrediction(PredictBoolean);
253             break;
254         }
255             
256         case GetById: {
257             if (node.getHeapPrediction())
258                 changed |= mergePrediction(node.getHeapPrediction());
259             else if (codeBlock()->identifier(node.identifierNumber()) == globalData().propertyNames->length) {
260                 // If there is no prediction from value profiles, check if we might be
261                 // able to infer the type ourselves.
262                 bool isArray = isArrayPrediction(m_graph[node.child1()].prediction());
263                 bool isString = isStringPrediction(m_graph[node.child1()].prediction());
264                 bool isByteArray = m_graph[node.child1()].shouldSpeculateByteArray();
265                 bool isInt8Array = m_graph[node.child1()].shouldSpeculateInt8Array();
266                 bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array();
267                 bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array();
268                 bool isUint8Array = m_graph[node.child1()].shouldSpeculateUint8Array();
269                 bool isUint8ClampedArray = m_graph[node.child1()].shouldSpeculateUint8ClampedArray();
270                 bool isUint16Array = m_graph[node.child1()].shouldSpeculateUint16Array();
271                 bool isUint32Array = m_graph[node.child1()].shouldSpeculateUint32Array();
272                 bool isFloat32Array = m_graph[node.child1()].shouldSpeculateFloat32Array();
273                 bool isFloat64Array = m_graph[node.child1()].shouldSpeculateFloat64Array();
274                 if (isArray || isString || isByteArray || isInt8Array || isInt16Array || isInt32Array || isUint8Array || isUint8ClampedArray || isUint16Array || isUint32Array || isFloat32Array || isFloat64Array)
275                     changed |= mergePrediction(PredictInt32);
276             }
277             break;
278         }
279             
280         case GetByIdFlush:
281             if (node.getHeapPrediction())
282                 changed |= mergePrediction(node.getHeapPrediction());
283             break;
284             
285         case GetByVal: {
286             if (m_graph[node.child1()].shouldSpeculateUint32Array() || m_graph[node.child1()].shouldSpeculateFloat32Array() || m_graph[node.child1()].shouldSpeculateFloat64Array())
287                 changed |= mergePrediction(PredictDouble);
288             else if (node.getHeapPrediction())
289                 changed |= mergePrediction(node.getHeapPrediction());
290             break;
291         }
292             
293         case GetPropertyStorage: 
294         case GetIndexedPropertyStorage: {
295             changed |= setPrediction(PredictOther);
296             break;
297         }
298
299         case GetByOffset: {
300             if (node.getHeapPrediction())
301                 changed |= mergePrediction(node.getHeapPrediction());
302             break;
303         }
304             
305         case Call:
306         case Construct: {
307             if (node.getHeapPrediction())
308                 changed |= mergePrediction(node.getHeapPrediction());
309             break;
310         }
311             
312         case ConvertThis: {
313             PredictedType prediction = m_graph[node.child1()].prediction();
314             if (prediction) {
315                 if (prediction & ~PredictObjectMask) {
316                     prediction &= PredictObjectMask;
317                     prediction = mergePredictions(prediction, PredictObjectOther);
318                 }
319                 changed |= mergePrediction(prediction);
320             }
321             break;
322         }
323             
324         case GetGlobalVar: {
325             PredictedType prediction = m_graph.getGlobalVarPrediction(node.varNumber());
326             if (prediction)
327                 changed |= mergePrediction(prediction);
328             break;
329         }
330             
331         case PutGlobalVar: {
332             changed |= m_graph.predictGlobalVar(node.varNumber(), m_graph[node.child1()].prediction());
333             break;
334         }
335             
336         case GetScopedVar:
337         case Resolve:
338         case ResolveBase:
339         case ResolveBaseStrictPut:
340         case ResolveGlobal: {
341             PredictedType prediction = node.getHeapPrediction();
342             if (prediction)
343                 changed |= mergePrediction(prediction);
344             break;
345         }
346             
347         case GetScopeChain: {
348             changed |= setPrediction(PredictCellOther);
349             break;
350         }
351             
352         case GetCallee: {
353             changed |= setPrediction(PredictFunction);
354             break;
355         }
356             
357         case CreateThis:
358         case NewObject: {
359             changed |= setPrediction(PredictFinalObject);
360             break;
361         }
362             
363         case NewArray:
364         case NewArrayBuffer: {
365             changed |= setPrediction(PredictArray);
366             break;
367         }
368             
369         case NewRegexp: {
370             changed |= setPrediction(PredictObjectOther);
371             break;
372         }
373         
374         case StringCharAt:
375         case StrCat: {
376             changed |= setPrediction(PredictString);
377             break;
378         }
379             
380         case ToPrimitive: {
381             PredictedType child = m_graph[node.child1()].prediction();
382             if (child) {
383                 if (isObjectPrediction(child)) {
384                     // I'd love to fold this case into the case below, but I can't, because
385                     // removing PredictObjectMask from something that only has an object
386                     // prediction and nothing else means we have an ill-formed PredictedType
387                     // (strong predict-none). This should be killed once we remove all traces
388                     // of static (aka weak) predictions.
389                     changed |= mergePrediction(PredictString);
390                 } else if (child & PredictObjectMask) {
391                     // Objects get turned into strings. So if the input has hints of objectness,
392                     // the output will have hinsts of stringiness.
393                     changed |= mergePrediction(mergePredictions(child & ~PredictObjectMask, PredictString));
394                 } else
395                     changed |= mergePrediction(child);
396             }
397             break;
398         }
399             
400         case GetArrayLength:
401         case GetByteArrayLength:
402         case GetInt8ArrayLength:
403         case GetInt16ArrayLength:
404         case GetInt32ArrayLength:
405         case GetUint8ArrayLength:
406         case GetUint8ClampedArrayLength:
407         case GetUint16ArrayLength:
408         case GetUint32ArrayLength:
409         case GetFloat32ArrayLength:
410         case GetFloat64ArrayLength:
411         case GetStringLength: {
412             // This node should never be visible at this stage of compilation. It is
413             // inserted by fixup(), which follows this phase.
414             ASSERT_NOT_REACHED();
415             break;
416         }
417         
418 #ifndef NDEBUG
419         // These get ignored because they don't return anything.
420         case PutScopedVar:
421         case DFG::Jump:
422         case Branch:
423         case Breakpoint:
424         case Return:
425         case CheckHasInstance:
426         case Phi:
427         case Flush:
428         case Throw:
429         case ThrowReferenceError:
430         case ForceOSRExit:
431         case SetArgument:
432         case PutByVal:
433         case PutByValAlias:
434         case PutById:
435         case PutByIdDirect:
436         case CheckStructure:
437         case CheckFunction:
438         case PutStructure:
439         case PutByOffset:
440             break;
441             
442         // These gets ignored because it doesn't do anything.
443         case Phantom:
444         case InlineStart:
445         case Nop:
446             break;
447 #else
448         default:
449             break;
450 #endif
451         }
452
453 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
454         dataLog("%s\n", predictionToString(m_graph[m_compileIndex].prediction()));
455 #endif
456         
457         m_changed |= changed;
458     }
459     
460     void propagateForward()
461     {
462 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
463         dataLog("Propagating predictions forward [%u]\n", ++m_count);
464 #endif
465         for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex)
466             propagate(m_graph[m_compileIndex]);
467     }
468     
469     void propagateBackward()
470     {
471 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
472         dataLog("Propagating predictions backward [%u]\n", ++m_count);
473 #endif
474         for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;)
475             propagate(m_graph[m_compileIndex]);
476     }
477
478     void vote(NodeUse nodeUse, VariableAccessData::Ballot ballot)
479     {
480         switch (m_graph[nodeUse].op) {
481         case ValueToInt32:
482         case UInt32ToNumber:
483             nodeUse = m_graph[nodeUse].child1();
484             break;
485         default:
486             break;
487         }
488         
489         if (m_graph[nodeUse].op == GetLocal)
490             m_graph[nodeUse].variableAccessData()->vote(ballot);
491     }
492     
493     void vote(Node& node, VariableAccessData::Ballot ballot)
494     {
495         if (node.op & NodeHasVarArgs) {
496             for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++)
497                 vote(m_graph.m_varArgChildren[childIdx], ballot);
498             return;
499         }
500         
501         if (!node.child1())
502             return;
503         vote(node.child1(), ballot);
504         if (!node.child2())
505             return;
506         vote(node.child2(), ballot);
507         if (!node.child3())
508             return;
509         vote(node.child3(), ballot);
510     }
511     
512     void doRoundOfDoubleVoting()
513     {
514 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
515         dataLog("Voting on double uses of locals [%u]\n", m_count);
516 #endif
517         for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i)
518             m_graph.m_variableAccessData[i].find()->clearVotes();
519         for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) {
520             Node& node = m_graph[m_compileIndex];
521             switch (node.op) {
522             case ValueAdd:
523             case ArithAdd:
524             case ArithSub: {
525                 PredictedType left = m_graph[node.child1()].prediction();
526                 PredictedType right = m_graph[node.child2()].prediction();
527                 
528                 VariableAccessData::Ballot ballot;
529                 
530                 if (isNumberPrediction(left) && isNumberPrediction(right)
531                     && !m_graph.addShouldSpeculateInteger(node))
532                     ballot = VariableAccessData::VoteDouble;
533                 else
534                     ballot = VariableAccessData::VoteValue;
535                 
536                 vote(node.child1(), ballot);
537                 vote(node.child2(), ballot);
538                 break;
539             }
540                 
541             case ArithMul:
542             case ArithMin:
543             case ArithMax:
544             case ArithMod:
545             case ArithDiv: {
546                 PredictedType left = m_graph[node.child1()].prediction();
547                 PredictedType right = m_graph[node.child2()].prediction();
548                 
549                 VariableAccessData::Ballot ballot;
550                 
551                 if (isNumberPrediction(left) && isNumberPrediction(right) && !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()]) && node.canSpeculateInteger()))
552                     ballot = VariableAccessData::VoteDouble;
553                 else
554                     ballot = VariableAccessData::VoteValue;
555                 
556                 vote(node.child1(), ballot);
557                 vote(node.child2(), ballot);
558                 break;
559             }
560                 
561             case ArithAbs:
562                 VariableAccessData::Ballot ballot;
563                 if (!(m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger()))
564                     ballot = VariableAccessData::VoteDouble;
565                 else
566                     ballot = VariableAccessData::VoteValue;
567                 
568                 vote(node.child1(), ballot);
569                 break;
570                 
571             case ArithSqrt:
572                 vote(node.child1(), VariableAccessData::VoteDouble);
573                 break;
574                 
575             case SetLocal: {
576                 PredictedType prediction = m_graph[node.child1()].prediction();
577                 if (isDoublePrediction(prediction))
578                     node.variableAccessData()->vote(VariableAccessData::VoteDouble);
579                 else if (!isNumberPrediction(prediction) || isInt32Prediction(prediction))
580                     node.variableAccessData()->vote(VariableAccessData::VoteValue);
581                 break;
582             }
583                 
584             default:
585                 vote(node, VariableAccessData::VoteValue);
586                 break;
587             }
588         }
589         for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i)
590             m_changed |= m_graph.m_variableAccessData[i].find()->tallyVotesForShouldUseDoubleFormat();
591     }
592     
593     void fixupNode(Node& node)
594     {
595         if (!node.shouldGenerate())
596             return;
597         
598         NodeType op = node.op;
599
600 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
601         dataLog("   %s @%u: ", Graph::opName(op), m_compileIndex);
602 #endif
603         
604         switch (op) {
605         case GetById: {
606             if (!isInt32Prediction(m_graph[m_compileIndex].prediction()))
607                 break;
608             if (codeBlock()->identifier(node.identifierNumber()) != globalData().propertyNames->length)
609                 break;
610             bool isArray = isArrayPrediction(m_graph[node.child1()].prediction());
611             bool isString = isStringPrediction(m_graph[node.child1()].prediction());
612             bool isByteArray = m_graph[node.child1()].shouldSpeculateByteArray();
613             bool isInt8Array = m_graph[node.child1()].shouldSpeculateInt8Array();
614             bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array();
615             bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array();
616             bool isUint8Array = m_graph[node.child1()].shouldSpeculateUint8Array();
617             bool isUint8ClampedArray = m_graph[node.child1()].shouldSpeculateUint8ClampedArray();
618             bool isUint16Array = m_graph[node.child1()].shouldSpeculateUint16Array();
619             bool isUint32Array = m_graph[node.child1()].shouldSpeculateUint32Array();
620             bool isFloat32Array = m_graph[node.child1()].shouldSpeculateFloat32Array();
621             bool isFloat64Array = m_graph[node.child1()].shouldSpeculateFloat64Array();
622             if (!isArray && !isString && !isByteArray && !isInt8Array && !isInt16Array && !isInt32Array && !isUint8Array && !isUint8ClampedArray && !isUint16Array && !isUint32Array && !isFloat32Array && !isFloat64Array)
623                 break;
624             
625 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
626             dataLog("  @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength");
627 #endif
628             if (isArray)
629                 node.op = GetArrayLength;
630             else if (isString)
631                 node.op = GetStringLength;
632             else if (isByteArray)
633                 node.op = GetByteArrayLength;
634             else if (isInt8Array)
635                 node.op = GetInt8ArrayLength;
636             else if (isInt16Array)
637                 node.op = GetInt16ArrayLength;
638             else if (isInt32Array)
639                 node.op = GetInt32ArrayLength;
640             else if (isUint8Array)
641                 node.op = GetUint8ArrayLength;
642             else if (isUint8ClampedArray)
643                 node.op = GetUint8ClampedArrayLength;
644             else if (isUint16Array)
645                 node.op = GetUint16ArrayLength;
646             else if (isUint32Array)
647                 node.op = GetUint32ArrayLength;
648             else if (isFloat32Array)
649                 node.op = GetFloat32ArrayLength;
650             else if (isFloat64Array)
651                 node.op = GetFloat64ArrayLength;
652             else
653                 ASSERT_NOT_REACHED();
654             m_graph.deref(m_compileIndex); // No longer MustGenerate
655             break;
656         }
657         case GetIndexedPropertyStorage: {
658             PredictedType basePrediction = m_graph[node.child2()].prediction();
659             if (!(basePrediction & PredictInt32) && basePrediction) {
660                 node.op = Nop;
661                 m_graph.clearAndDerefChild1(node);
662                 m_graph.clearAndDerefChild2(node);
663                 m_graph.clearAndDerefChild3(node);
664                 node.setRefCount(0);
665             }
666             break;
667         }
668         case GetByVal:
669         case StringCharAt:
670         case StringCharCodeAt: {
671             if (!!node.child3() && m_graph[node.child3()].op == Nop)
672                 node.children.child3() = NodeUse();
673             break;
674         }
675         default:
676             break;
677         }
678
679 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
680         dataLog("\n");
681 #endif
682     }
683     
684     void fixup()
685     {
686 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
687         dataLog("Performing Fixup\n");
688 #endif
689         for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex)
690             fixupNode(m_graph[m_compileIndex]);
691     }
692     
693     NodeIndex m_compileIndex;
694     bool m_changed;
695
696 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
697     unsigned m_count;
698 #endif
699 };
700     
701 void performPredictionPropagation(Graph& graph)
702 {
703     runPhase<PredictionPropagationPhase>(graph);
704 }
705
706 } } // namespace JSC::DFG
707
708 #endif // ENABLE(DFG_JIT)
709