DFG implementation of op_strcat should inline rope allocations
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGPredictionPropagationPhase.cpp
1 /*
2  * Copyright (C) 2011, 2012, 2013 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 #include "Operations.h"
34
35 namespace JSC { namespace DFG {
36
37 class PredictionPropagationPhase : public Phase {
38 public:
39     PredictionPropagationPhase(Graph& graph)
40         : Phase(graph, "prediction propagation")
41     {
42     }
43     
44     bool run()
45     {
46         ASSERT(m_graph.m_form == ThreadedCPS);
47         ASSERT(m_graph.m_unificationState == GloballyUnified);
48         
49 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
50         m_count = 0;
51 #endif
52         // 1) propagate predictions
53
54         do {
55             m_changed = false;
56             
57             // Forward propagation is near-optimal for both topologically-sorted and
58             // DFS-sorted code.
59             propagateForward();
60             if (!m_changed)
61                 break;
62             
63             // Backward propagation reduces the likelihood that pathological code will
64             // cause slowness. Loops (especially nested ones) resemble backward flow.
65             // This pass captures two cases: (1) it detects if the forward fixpoint
66             // found a sound solution and (2) short-circuits backward flow.
67             m_changed = false;
68             propagateBackward();
69         } while (m_changed);
70         
71         // 2) repropagate predictions while doing double voting.
72
73         do {
74             m_changed = false;
75             doRoundOfDoubleVoting();
76             if (!m_changed)
77                 break;
78             m_changed = false;
79             propagateForward();
80         } while (m_changed);
81         
82         return true;
83     }
84     
85 private:
86     bool setPrediction(SpeculatedType prediction)
87     {
88         ASSERT(m_currentNode->hasResult());
89         
90         // setPrediction() is used when we know that there is no way that we can change
91         // our minds about what the prediction is going to be. There is no semantic
92         // difference between setPrediction() and mergeSpeculation() other than the
93         // increased checking to validate this property.
94         ASSERT(m_currentNode->prediction() == SpecNone || m_currentNode->prediction() == prediction);
95         
96         return m_currentNode->predict(prediction);
97     }
98     
99     bool mergePrediction(SpeculatedType prediction)
100     {
101         ASSERT(m_currentNode->hasResult());
102         
103         return m_currentNode->predict(prediction);
104     }
105     
106     SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value)
107     {
108         if (!isNumberSpeculation(value))
109             return SpecDouble;
110         if (value & SpecDoubleNaN)
111             return SpecDouble;
112         return SpecDoubleReal;
113     }
114
115     SpeculatedType speculatedDoubleTypeForPredictions(SpeculatedType left, SpeculatedType right)
116     {
117         return speculatedDoubleTypeForPrediction(mergeSpeculations(left, right));
118     }
119
120     void propagate(Node* node)
121     {
122         NodeType op = node->op();
123
124 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
125         dataLog("   ", Graph::opName(op), " ", m_currentNode, ": ", NodeFlagsDump(node->flags()), " ");
126 #endif
127         
128         bool changed = false;
129         
130         switch (op) {
131         case JSConstant:
132         case WeakJSConstant: {
133             changed |= setPrediction(speculationFromValue(m_graph.valueOfJSConstant(node)));
134             break;
135         }
136             
137         case GetLocal: {
138             VariableAccessData* variableAccessData = node->variableAccessData();
139             SpeculatedType prediction = variableAccessData->prediction();
140             if (prediction)
141                 changed |= mergePrediction(prediction);
142             break;
143         }
144             
145         case SetLocal: {
146             VariableAccessData* variableAccessData = node->variableAccessData();
147             changed |= variableAccessData->predict(node->child1()->prediction());
148             break;
149         }
150             
151         case BitAnd:
152         case BitOr:
153         case BitXor:
154         case BitRShift:
155         case BitLShift:
156         case BitURShift: {
157             changed |= setPrediction(SpecInt32);
158             break;
159         }
160             
161         case ValueToInt32: {
162             changed |= setPrediction(SpecInt32);
163             break;
164         }
165             
166         case ArrayPop:
167         case ArrayPush:
168         case RegExpExec:
169         case RegExpTest:
170         case GetById:
171         case GetByIdFlush:
172         case GetMyArgumentByValSafe:
173         case GetByOffset:
174         case Call:
175         case Construct:
176         case GetGlobalVar:
177         case GetScopedVar:
178         case Resolve:
179         case ResolveBase:
180         case ResolveBaseStrictPut:
181         case ResolveGlobal: {
182             changed |= setPrediction(node->getHeapPrediction());
183             break;
184         }
185
186         case StringCharCodeAt: {
187             changed |= setPrediction(SpecInt32);
188             break;
189         }
190
191         case UInt32ToNumber: {
192             if (nodeCanSpeculateInteger(node->arithNodeFlags()))
193                 changed |= mergePrediction(SpecInt32);
194             else
195                 changed |= mergePrediction(SpecNumber);
196             break;
197         }
198
199         case ValueAdd: {
200             SpeculatedType left = node->child1()->prediction();
201             SpeculatedType right = node->child2()->prediction();
202             
203             if (left && right) {
204                 if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) {
205                     if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
206                         changed |= mergePrediction(SpecInt32);
207                     else
208                         changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
209                 } else if (!(left & SpecNumber) || !(right & SpecNumber)) {
210                     // left or right is definitely something other than a number.
211                     changed |= mergePrediction(SpecString);
212                 } else
213                     changed |= mergePrediction(SpecString | SpecInt32 | SpecDouble);
214             }
215             break;
216         }
217             
218         case ArithAdd: {
219             SpeculatedType left = node->child1()->prediction();
220             SpeculatedType right = node->child2()->prediction();
221             
222             if (left && right) {
223                 if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
224                     changed |= mergePrediction(SpecInt32);
225                 else
226                     changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
227             }
228             break;
229         }
230             
231         case ArithSub: {
232             SpeculatedType left = node->child1()->prediction();
233             SpeculatedType right = node->child2()->prediction();
234             
235             if (left && right) {
236                 if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
237                     changed |= mergePrediction(SpecInt32);
238                 else
239                     changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
240             }
241             break;
242         }
243             
244         case ArithNegate:
245             if (node->child1()->prediction()) {
246                 if (m_graph.negateShouldSpeculateInteger(node))
247                     changed |= mergePrediction(SpecInt32);
248                 else
249                     changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
250             }
251             break;
252             
253         case ArithMin:
254         case ArithMax: {
255             SpeculatedType left = node->child1()->prediction();
256             SpeculatedType right = node->child2()->prediction();
257             
258             if (left && right) {
259                 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
260                     && nodeCanSpeculateInteger(node->arithNodeFlags()))
261                     changed |= mergePrediction(SpecInt32);
262                 else
263                     changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
264             }
265             break;
266         }
267
268         case ArithMul: {
269             SpeculatedType left = node->child1()->prediction();
270             SpeculatedType right = node->child2()->prediction();
271             
272             if (left && right) {
273                 if (m_graph.mulShouldSpeculateInteger(node))
274                     changed |= mergePrediction(SpecInt32);
275                 else
276                     changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
277             }
278             break;
279         }
280             
281         case ArithDiv: {
282             SpeculatedType left = node->child1()->prediction();
283             SpeculatedType right = node->child2()->prediction();
284             
285             if (left && right) {
286                 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
287                     && nodeCanSpeculateInteger(node->arithNodeFlags()))
288                     changed |= mergePrediction(SpecInt32);
289                 else
290                     changed |= mergePrediction(SpecDouble);
291             }
292             break;
293         }
294             
295         case ArithMod: {
296             SpeculatedType left = node->child1()->prediction();
297             SpeculatedType right = node->child2()->prediction();
298             
299             if (left && right) {
300                 if (Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node())
301                     && nodeCanSpeculateInteger(node->arithNodeFlags()))
302                     changed |= mergePrediction(SpecInt32);
303                 else
304                     changed |= mergePrediction(SpecDouble);
305             }
306             break;
307         }
308             
309         case ArithSqrt: {
310             changed |= setPrediction(SpecDouble);
311             break;
312         }
313             
314         case ArithAbs: {
315             SpeculatedType child = node->child1()->prediction();
316             if (isInt32SpeculationForArithmetic(child)
317                 && nodeCanSpeculateInteger(node->arithNodeFlags()))
318                 changed |= mergePrediction(SpecInt32);
319             else
320                 changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
321             break;
322         }
323             
324         case LogicalNot:
325         case CompareLess:
326         case CompareLessEq:
327         case CompareGreater:
328         case CompareGreaterEq:
329         case CompareEq:
330         case CompareEqConstant:
331         case CompareStrictEq:
332         case CompareStrictEqConstant:
333         case InstanceOf:
334         case IsUndefined:
335         case IsBoolean:
336         case IsNumber:
337         case IsString:
338         case IsObject:
339         case IsFunction: {
340             changed |= setPrediction(SpecBoolean);
341             break;
342         }
343
344         case TypeOf: {
345             changed |= setPrediction(SpecString);
346             break;
347         }
348
349         case GetByVal: {
350             if (node->child1()->shouldSpeculateFloat32Array()
351                 || node->child1()->shouldSpeculateFloat64Array())
352                 changed |= mergePrediction(SpecDouble);
353             else
354                 changed |= mergePrediction(node->getHeapPrediction());
355             break;
356         }
357             
358         case GetMyArgumentsLengthSafe: {
359             changed |= setPrediction(SpecInt32);
360             break;
361         }
362
363         case GetScopeRegisters:            
364         case GetButterfly: 
365         case GetIndexedPropertyStorage:
366         case AllocatePropertyStorage:
367         case ReallocatePropertyStorage: {
368             changed |= setPrediction(SpecOther);
369             break;
370         }
371
372         case ConvertThis: {
373             SpeculatedType prediction = node->child1()->prediction();
374             if (prediction) {
375                 if (prediction & ~SpecObject) {
376                     prediction &= SpecObject;
377                     prediction = mergeSpeculations(prediction, SpecObjectOther);
378                 }
379                 changed |= mergePrediction(prediction);
380             }
381             break;
382         }
383             
384         case GetMyScope:
385         case SkipTopScope:
386         case SkipScope: {
387             changed |= setPrediction(SpecCellOther);
388             break;
389         }
390             
391         case GetCallee: {
392             changed |= setPrediction(SpecFunction);
393             break;
394         }
395             
396         case CreateThis:
397         case NewObject: {
398             changed |= setPrediction(SpecFinalObject);
399             break;
400         }
401             
402         case NewArray:
403         case NewArrayWithSize:
404         case NewArrayBuffer: {
405             changed |= setPrediction(SpecArray);
406             break;
407         }
408             
409         case NewRegexp:
410         case CreateActivation: {
411             changed |= setPrediction(SpecObjectOther);
412             break;
413         }
414         
415         case StringCharAt:
416         case ToString:
417         case MakeRope: {
418             changed |= setPrediction(SpecString);
419             break;
420         }
421             
422         case ToPrimitive: {
423             SpeculatedType child = node->child1()->prediction();
424             if (child) {
425                 if (isObjectSpeculation(child)) {
426                     // I'd love to fold this case into the case below, but I can't, because
427                     // removing SpecObject from something that only has an object
428                     // prediction and nothing else means we have an ill-formed SpeculatedType
429                     // (strong predict-none). This should be killed once we remove all traces
430                     // of static (aka weak) predictions.
431                     changed |= mergePrediction(SpecString);
432                 } else if (child & SpecObject) {
433                     // Objects get turned into strings. So if the input has hints of objectness,
434                     // the output will have hinsts of stringiness.
435                     changed |= mergePrediction(
436                         mergeSpeculations(child & ~SpecObject, SpecString));
437                 } else
438                     changed |= mergePrediction(child);
439             }
440             break;
441         }
442             
443         case NewStringObject: {
444             changed |= setPrediction(SpecStringObject);
445             break;
446         }
447             
448         case CreateArguments: {
449             changed |= setPrediction(SpecArguments);
450             break;
451         }
452             
453         case NewFunction:
454         case NewFunctionNoCheck:
455         case NewFunctionExpression: {
456             changed |= setPrediction(SpecFunction);
457             break;
458         }
459             
460         case PutByValAlias:
461         case GetArrayLength:
462         case Int32ToDouble:
463         case ForwardInt32ToDouble:
464         case DoubleAsInt32:
465         case GetLocalUnlinked:
466         case GetMyArgumentsLength:
467         case GetMyArgumentByVal:
468         case PhantomPutStructure:
469         case PhantomArguments:
470         case CheckArray:
471         case Arrayify:
472         case ArrayifyToStructure:
473         case Identity:
474         case MovHint:
475         case MovHintAndCheck:
476         case ZombieHint: {
477             // This node should never be visible at this stage of compilation. It is
478             // inserted by fixup(), which follows this phase.
479             CRASH();
480             break;
481         }
482         
483         case Phi:
484             // Phis should not be visible here since we're iterating the all-but-Phi's
485             // part of basic blocks.
486             CRASH();
487             break;
488
489         case GetScope:
490             changed |= setPrediction(SpecCellOther);
491             break;
492
493 #ifndef NDEBUG
494         // These get ignored because they don't return anything.
495         case PutByVal:
496         case PutScopedVar:
497         case Return:
498         case Throw:
499         case PutById:
500         case PutByIdDirect:
501         case PutByOffset:
502         case SetCallee:
503         case SetMyScope:
504         case DFG::Jump:
505         case Branch:
506         case Breakpoint:
507         case CheckHasInstance:
508         case ThrowReferenceError:
509         case ForceOSRExit:
510         case SetArgument:
511         case CheckStructure:
512         case CheckExecutable:
513         case ForwardCheckStructure:
514         case StructureTransitionWatchpoint:
515         case ForwardStructureTransitionWatchpoint:
516         case CheckFunction:
517         case PutStructure:
518         case TearOffActivation:
519         case TearOffArguments:
520         case CheckArgumentsNotCreated:
521         case GlobalVarWatchpoint:
522         case GarbageValue:
523         case AllocationProfileWatchpoint:
524         case Phantom:
525         case PutGlobalVar:
526         case PutGlobalVarCheck:
527             break;
528             
529         // These gets ignored because it doesn't do anything.
530         case InlineStart:
531         case Nop:
532         case CountExecution:
533         case PhantomLocal:
534         case Flush:
535             break;
536             
537         case LastNodeType:
538             CRASH();
539             break;
540 #else
541         default:
542             break;
543 #endif
544         }
545
546 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
547         dataLog(SpeculationDump(node->prediction()), "\n");
548 #endif
549         
550         m_changed |= changed;
551     }
552         
553     void propagateForward()
554     {
555 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
556         dataLogF("Propagating predictions forward [%u]\n", ++m_count);
557 #endif
558         for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
559             BasicBlock* block = m_graph.m_blocks[blockIndex].get();
560             if (!block)
561                 continue;
562             ASSERT(block->isReachable);
563             for (unsigned i = 0; i < block->size(); ++i) {
564                 m_currentNode = block->at(i);
565                 propagate(m_currentNode);
566             }
567         }
568     }
569     
570     void propagateBackward()
571     {
572 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
573         dataLogF("Propagating predictions backward [%u]\n", ++m_count);
574 #endif
575         for (BlockIndex blockIndex = m_graph.m_blocks.size(); blockIndex--;) {
576             BasicBlock* block = m_graph.m_blocks[blockIndex].get();
577             if (!block)
578                 continue;
579             ASSERT(block->isReachable);
580             for (unsigned i = block->size(); i--;) {
581                 m_currentNode = block->at(i);
582                 propagate(m_currentNode);
583             }
584         }
585     }
586     
587     void doDoubleVoting(Node* node)
588     {
589         switch (node->op()) {
590         case ValueAdd:
591         case ArithAdd:
592         case ArithSub: {
593             SpeculatedType left = node->child1()->prediction();
594             SpeculatedType right = node->child2()->prediction();
595                 
596             DoubleBallot ballot;
597                 
598             if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)
599                 && !m_graph.addShouldSpeculateInteger(node))
600                 ballot = VoteDouble;
601             else
602                 ballot = VoteValue;
603                 
604             m_graph.voteNode(node->child1(), ballot);
605             m_graph.voteNode(node->child2(), ballot);
606             break;
607         }
608                 
609         case ArithMul: {
610             SpeculatedType left = node->child1()->prediction();
611             SpeculatedType right = node->child2()->prediction();
612                 
613             DoubleBallot ballot;
614                 
615             if (isNumberSpeculation(left) && isNumberSpeculation(right)
616                 && !m_graph.mulShouldSpeculateInteger(node))
617                 ballot = VoteDouble;
618             else
619                 ballot = VoteValue;
620                 
621             m_graph.voteNode(node->child1(), ballot);
622             m_graph.voteNode(node->child2(), ballot);
623             break;
624         }
625
626         case ArithMin:
627         case ArithMax:
628         case ArithMod:
629         case ArithDiv: {
630             SpeculatedType left = node->child1()->prediction();
631             SpeculatedType right = node->child2()->prediction();
632                 
633             DoubleBallot ballot;
634                 
635             if (isNumberSpeculation(left) && isNumberSpeculation(right)
636                 && !(Node::shouldSpeculateIntegerForArithmetic(node->child1().node(), node->child2().node()) && node->canSpeculateInteger()))
637                 ballot = VoteDouble;
638             else
639                 ballot = VoteValue;
640                 
641             m_graph.voteNode(node->child1(), ballot);
642             m_graph.voteNode(node->child2(), ballot);
643             break;
644         }
645                 
646         case ArithAbs:
647             DoubleBallot ballot;
648             if (!(node->child1()->shouldSpeculateIntegerForArithmetic() && node->canSpeculateInteger()))
649                 ballot = VoteDouble;
650             else
651                 ballot = VoteValue;
652                 
653             m_graph.voteNode(node->child1(), ballot);
654             break;
655                 
656         case ArithSqrt:
657             m_graph.voteNode(node->child1(), VoteDouble);
658             break;
659                 
660         case SetLocal: {
661             SpeculatedType prediction = node->child1()->prediction();
662             if (isDoubleSpeculation(prediction))
663                 node->variableAccessData()->vote(VoteDouble);
664             else if (!isNumberSpeculation(prediction) || isInt32Speculation(prediction))
665                 node->variableAccessData()->vote(VoteValue);
666             break;
667         }
668                 
669         case PutByVal:
670         case PutByValAlias: {
671             Edge child1 = m_graph.varArgChild(node, 0);
672             Edge child2 = m_graph.varArgChild(node, 1);
673             Edge child3 = m_graph.varArgChild(node, 2);
674             m_graph.voteNode(child1, VoteValue);
675             m_graph.voteNode(child2, VoteValue);
676             switch (node->arrayMode().type()) {
677             case Array::Double:
678                 m_graph.voteNode(child3, VoteDouble);
679                 break;
680             default:
681                 m_graph.voteNode(child3, VoteValue);
682                 break;
683             }
684             break;
685         }
686             
687         default:
688             m_graph.voteChildren(node, VoteValue);
689             break;
690         }
691     }
692     
693     void doRoundOfDoubleVoting()
694     {
695 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
696         dataLogF("Voting on double uses of locals [%u]\n", m_count);
697 #endif
698         for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i)
699             m_graph.m_variableAccessData[i].find()->clearVotes();
700         for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) {
701             BasicBlock* block = m_graph.m_blocks[blockIndex].get();
702             if (!block)
703                 continue;
704             ASSERT(block->isReachable);
705             for (unsigned i = 0; i < block->size(); ++i) {
706                 m_currentNode = block->at(i);
707                 doDoubleVoting(m_currentNode);
708             }
709         }
710         for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
711             VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
712             if (!variableAccessData->isRoot())
713                 continue;
714             m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat();
715         }
716         for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i)
717             m_changed |= m_graph.m_argumentPositions[i].mergeArgumentPredictionAwareness();
718         for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
719             VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
720             if (!variableAccessData->isRoot())
721                 continue;
722             m_changed |= variableAccessData->makePredictionForDoubleFormat();
723         }
724     }
725     
726     Node* m_currentNode;
727     bool m_changed;
728
729 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
730     unsigned m_count;
731 #endif
732 };
733     
734 bool performPredictionPropagation(Graph& graph)
735 {
736     SamplingRegion samplingRegion("DFG Prediction Propagation Phase");
737     return runPhase<PredictionPropagationPhase>(graph);
738 }
739
740 } } // namespace JSC::DFG
741
742 #endif // ENABLE(DFG_JIT)
743