]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGPredictionPropagationPhase.cpp
6a35b9cbd7edab74dc4cbf3c388e8ab33ecc0a8a
[apple/javascriptcore.git] / dfg / DFGPredictionPropagationPhase.cpp
1 /*
2 * Copyright (C) 2011, 2012, 2013, 2014 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 "JSCInlines.h"
34
35 namespace JSC { namespace DFG {
36
37 SpeculatedType resultOfToPrimitive(SpeculatedType type)
38 {
39 if (type & SpecObject) {
40 // Objects get turned into strings. So if the input has hints of objectness,
41 // the output will have hinsts of stringiness.
42 return mergeSpeculations(type & ~SpecObject, SpecString);
43 }
44
45 return type;
46 }
47
48 class PredictionPropagationPhase : public Phase {
49 public:
50 PredictionPropagationPhase(Graph& graph)
51 : Phase(graph, "prediction propagation")
52 {
53 }
54
55 bool run()
56 {
57 ASSERT(m_graph.m_form == ThreadedCPS);
58 ASSERT(m_graph.m_unificationState == GloballyUnified);
59
60 m_pass = PrimaryPass;
61 propagateToFixpoint();
62
63 m_pass = RareCasePass;
64 propagateToFixpoint();
65
66 m_pass = DoubleVotingPass;
67 do {
68 m_changed = false;
69 doRoundOfDoubleVoting();
70 if (!m_changed)
71 break;
72 m_changed = false;
73 propagateForward();
74 } while (m_changed);
75
76 return true;
77 }
78
79 private:
80 void propagateToFixpoint()
81 {
82 do {
83 m_changed = false;
84
85 // Forward propagation is near-optimal for both topologically-sorted and
86 // DFS-sorted code.
87 propagateForward();
88 if (!m_changed)
89 break;
90
91 // Backward propagation reduces the likelihood that pathological code will
92 // cause slowness. Loops (especially nested ones) resemble backward flow.
93 // This pass captures two cases: (1) it detects if the forward fixpoint
94 // found a sound solution and (2) short-circuits backward flow.
95 m_changed = false;
96 propagateBackward();
97 } while (m_changed);
98 }
99
100 bool setPrediction(SpeculatedType prediction)
101 {
102 ASSERT(m_currentNode->hasResult());
103
104 // setPrediction() is used when we know that there is no way that we can change
105 // our minds about what the prediction is going to be. There is no semantic
106 // difference between setPrediction() and mergeSpeculation() other than the
107 // increased checking to validate this property.
108 ASSERT(m_currentNode->prediction() == SpecNone || m_currentNode->prediction() == prediction);
109
110 return m_currentNode->predict(prediction);
111 }
112
113 bool mergePrediction(SpeculatedType prediction)
114 {
115 ASSERT(m_currentNode->hasResult());
116
117 return m_currentNode->predict(prediction);
118 }
119
120 SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value)
121 {
122 SpeculatedType result = SpecDoubleReal;
123 if (value & SpecDoubleImpureNaN)
124 result |= SpecDoubleImpureNaN;
125 if (value & SpecDoublePureNaN)
126 result |= SpecDoublePureNaN;
127 if (!isFullNumberOrBooleanSpeculation(value))
128 result |= SpecDoublePureNaN;
129 return result;
130 }
131
132 SpeculatedType speculatedDoubleTypeForPredictions(SpeculatedType left, SpeculatedType right)
133 {
134 return speculatedDoubleTypeForPrediction(mergeSpeculations(left, right));
135 }
136
137 void propagate(Node* node)
138 {
139 NodeType op = node->op();
140
141 bool changed = false;
142
143 switch (op) {
144 case JSConstant:
145 case WeakJSConstant: {
146 SpeculatedType type = speculationFromValue(m_graph.valueOfJSConstant(node));
147 if (type == SpecInt52AsDouble && enableInt52())
148 type = SpecInt52;
149 changed |= setPrediction(type);
150 break;
151 }
152
153 case GetLocal: {
154 VariableAccessData* variable = node->variableAccessData();
155 SpeculatedType prediction = variable->prediction();
156 if (!variable->couldRepresentInt52() && (prediction & SpecInt52))
157 prediction = (prediction | SpecInt52AsDouble) & ~SpecInt52;
158 if (prediction)
159 changed |= mergePrediction(prediction);
160 break;
161 }
162
163 case SetLocal: {
164 VariableAccessData* variableAccessData = node->variableAccessData();
165 changed |= variableAccessData->predict(node->child1()->prediction());
166 break;
167 }
168
169 case BitAnd:
170 case BitOr:
171 case BitXor:
172 case BitRShift:
173 case BitLShift:
174 case BitURShift:
175 case ArithIMul: {
176 changed |= setPrediction(SpecInt32);
177 break;
178 }
179
180 case ArrayPop:
181 case ArrayPush:
182 case RegExpExec:
183 case RegExpTest:
184 case GetById:
185 case GetByIdFlush:
186 case GetMyArgumentByValSafe:
187 case GetByOffset:
188 case MultiGetByOffset:
189 case Call:
190 case Construct:
191 case GetGlobalVar:
192 case GetClosureVar: {
193 changed |= setPrediction(node->getHeapPrediction());
194 break;
195 }
196
197 case StringCharCodeAt: {
198 changed |= setPrediction(SpecInt32);
199 break;
200 }
201
202 case UInt32ToNumber: {
203 // FIXME: Support Int52.
204 // https://bugs.webkit.org/show_bug.cgi?id=125704
205 if (node->canSpeculateInt32(m_pass))
206 changed |= mergePrediction(SpecInt32);
207 else
208 changed |= mergePrediction(SpecBytecodeNumber);
209 break;
210 }
211
212 case ValueAdd: {
213 SpeculatedType left = node->child1()->prediction();
214 SpeculatedType right = node->child2()->prediction();
215
216 if (left && right) {
217 if (isFullNumberOrBooleanSpeculationExpectingDefined(left)
218 && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
219 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
220 changed |= mergePrediction(SpecInt32);
221 else if (m_graph.addShouldSpeculateMachineInt(node))
222 changed |= mergePrediction(SpecInt52);
223 else
224 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
225 } else if (
226 !(left & (SpecFullNumber | SpecBoolean))
227 || !(right & (SpecFullNumber | SpecBoolean))) {
228 // left or right is definitely something other than a number.
229 changed |= mergePrediction(SpecString);
230 } else
231 changed |= mergePrediction(SpecString | SpecInt32 | SpecBytecodeDouble);
232 }
233 break;
234 }
235
236 case ArithAdd: {
237 SpeculatedType left = node->child1()->prediction();
238 SpeculatedType right = node->child2()->prediction();
239
240 if (left && right) {
241 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
242 changed |= mergePrediction(SpecInt32);
243 else if (m_graph.addShouldSpeculateMachineInt(node))
244 changed |= mergePrediction(SpecInt52);
245 else
246 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
247 }
248 break;
249 }
250
251 case ArithSub: {
252 SpeculatedType left = node->child1()->prediction();
253 SpeculatedType right = node->child2()->prediction();
254
255 if (left && right) {
256 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
257 changed |= mergePrediction(SpecInt32);
258 else if (m_graph.addShouldSpeculateMachineInt(node))
259 changed |= mergePrediction(SpecInt52);
260 else
261 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
262 }
263 break;
264 }
265
266 case ArithNegate:
267 if (node->child1()->prediction()) {
268 if (m_graph.negateShouldSpeculateInt32(node, m_pass))
269 changed |= mergePrediction(SpecInt32);
270 else if (m_graph.negateShouldSpeculateMachineInt(node, m_pass))
271 changed |= mergePrediction(SpecInt52);
272 else
273 changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
274 }
275 break;
276
277 case ArithMin:
278 case ArithMax: {
279 SpeculatedType left = node->child1()->prediction();
280 SpeculatedType right = node->child2()->prediction();
281
282 if (left && right) {
283 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
284 && node->canSpeculateInt32(m_pass))
285 changed |= mergePrediction(SpecInt32);
286 else
287 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
288 }
289 break;
290 }
291
292 case ArithMul: {
293 SpeculatedType left = node->child1()->prediction();
294 SpeculatedType right = node->child2()->prediction();
295
296 if (left && right) {
297 if (m_graph.mulShouldSpeculateInt32(node, m_pass))
298 changed |= mergePrediction(SpecInt32);
299 else if (m_graph.mulShouldSpeculateMachineInt(node, m_pass))
300 changed |= mergePrediction(SpecInt52);
301 else
302 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
303 }
304 break;
305 }
306
307 case ArithDiv: {
308 SpeculatedType left = node->child1()->prediction();
309 SpeculatedType right = node->child2()->prediction();
310
311 if (left && right) {
312 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
313 && node->canSpeculateInt32(m_pass))
314 changed |= mergePrediction(SpecInt32);
315 else
316 changed |= mergePrediction(SpecBytecodeDouble);
317 }
318 break;
319 }
320
321 case ArithMod: {
322 SpeculatedType left = node->child1()->prediction();
323 SpeculatedType right = node->child2()->prediction();
324
325 if (left && right) {
326 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
327 && node->canSpeculateInt32(m_pass))
328 changed |= mergePrediction(SpecInt32);
329 else
330 changed |= mergePrediction(SpecBytecodeDouble);
331 }
332 break;
333 }
334
335 case ArithSqrt:
336 case ArithFRound:
337 case ArithSin:
338 case ArithCos: {
339 changed |= setPrediction(SpecBytecodeDouble);
340 break;
341 }
342
343 case ArithAbs: {
344 SpeculatedType child = node->child1()->prediction();
345 if (isInt32OrBooleanSpeculationForArithmetic(child)
346 && node->canSpeculateInt32(m_pass))
347 changed |= mergePrediction(SpecInt32);
348 else
349 changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
350 break;
351 }
352
353 case LogicalNot:
354 case CompareLess:
355 case CompareLessEq:
356 case CompareGreater:
357 case CompareGreaterEq:
358 case CompareEq:
359 case CompareEqConstant:
360 case CompareStrictEq:
361 case InstanceOf:
362 case IsUndefined:
363 case IsBoolean:
364 case IsNumber:
365 case IsString:
366 case IsObject:
367 case IsFunction: {
368 changed |= setPrediction(SpecBoolean);
369 break;
370 }
371
372 case TypeOf: {
373 changed |= setPrediction(SpecString);
374 break;
375 }
376
377 case GetByVal: {
378 if (!node->child1()->prediction())
379 break;
380
381 ArrayMode arrayMode = node->arrayMode().refine(
382 m_graph, node,
383 node->child1()->prediction(),
384 node->child2()->prediction(),
385 SpecNone, node->flags());
386
387 switch (arrayMode.type()) {
388 case Array::Double:
389 if (arrayMode.isOutOfBounds())
390 changed |= mergePrediction(node->getHeapPrediction() | SpecDoubleReal);
391 else
392 changed |= mergePrediction(SpecDoubleReal);
393 break;
394 case Array::Float32Array:
395 case Array::Float64Array:
396 changed |= mergePrediction(SpecFullDouble);
397 break;
398 case Array::Uint32Array:
399 if (isInt32Speculation(node->getHeapPrediction()))
400 changed |= mergePrediction(SpecInt32);
401 else if (enableInt52())
402 changed |= mergePrediction(SpecMachineInt);
403 else
404 changed |= mergePrediction(SpecInt32 | SpecInt52AsDouble);
405 break;
406 default:
407 changed |= mergePrediction(node->getHeapPrediction());
408 break;
409 }
410 break;
411 }
412
413 case GetMyArgumentsLengthSafe: {
414 changed |= setPrediction(SpecInt32);
415 break;
416 }
417
418 case GetClosureRegisters:
419 case GetButterfly:
420 case GetIndexedPropertyStorage:
421 case AllocatePropertyStorage:
422 case ReallocatePropertyStorage: {
423 changed |= setPrediction(SpecOther);
424 break;
425 }
426
427 case ToThis: {
428 SpeculatedType prediction = node->child1()->prediction();
429 if (prediction) {
430 if (prediction & ~SpecObject) {
431 prediction &= SpecObject;
432 prediction = mergeSpeculations(prediction, SpecObjectOther);
433 }
434 changed |= mergePrediction(prediction);
435 }
436 break;
437 }
438
439 case GetMyScope:
440 case SkipTopScope:
441 case SkipScope: {
442 changed |= setPrediction(SpecObjectOther);
443 break;
444 }
445
446 case GetCallee: {
447 changed |= setPrediction(SpecFunction);
448 break;
449 }
450
451 case CreateThis:
452 case NewObject: {
453 changed |= setPrediction(SpecFinalObject);
454 break;
455 }
456
457 case NewArray:
458 case NewArrayWithSize:
459 case NewArrayBuffer: {
460 changed |= setPrediction(SpecArray);
461 break;
462 }
463
464 case NewTypedArray: {
465 changed |= setPrediction(speculationFromTypedArrayType(node->typedArrayType()));
466 break;
467 }
468
469 case NewRegexp:
470 case CreateActivation: {
471 changed |= setPrediction(SpecObjectOther);
472 break;
473 }
474
475 case StringFromCharCode: {
476 changed |= setPrediction(SpecString);
477 changed |= node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsInt);
478 break;
479 }
480 case StringCharAt:
481 case ToString:
482 case MakeRope: {
483 changed |= setPrediction(SpecString);
484 break;
485 }
486
487 case ToPrimitive: {
488 SpeculatedType child = node->child1()->prediction();
489 if (child)
490 changed |= mergePrediction(resultOfToPrimitive(child));
491 break;
492 }
493
494 case NewStringObject: {
495 changed |= setPrediction(SpecStringObject);
496 break;
497 }
498
499 case CreateArguments: {
500 changed |= setPrediction(SpecArguments);
501 break;
502 }
503
504 case NewFunction: {
505 SpeculatedType child = node->child1()->prediction();
506 if (child & SpecEmpty)
507 changed |= mergePrediction((child & ~SpecEmpty) | SpecFunction);
508 else
509 changed |= mergePrediction(child);
510 break;
511 }
512
513 case NewFunctionNoCheck:
514 case NewFunctionExpression: {
515 changed |= setPrediction(SpecFunction);
516 break;
517 }
518
519 case FiatInt52: {
520 RELEASE_ASSERT(enableInt52());
521 changed |= setPrediction(SpecMachineInt);
522 break;
523 }
524
525 case PutByValAlias:
526 case GetArrayLength:
527 case GetTypedArrayByteOffset:
528 case DoubleAsInt32:
529 case GetLocalUnlinked:
530 case GetMyArgumentsLength:
531 case GetMyArgumentByVal:
532 case PhantomPutStructure:
533 case PhantomArguments:
534 case CheckArray:
535 case Arrayify:
536 case ArrayifyToStructure:
537 case CheckTierUpInLoop:
538 case CheckTierUpAtReturn:
539 case CheckTierUpAndOSREnter:
540 case InvalidationPoint:
541 case CheckInBounds:
542 case ValueToInt32:
543 case HardPhantom:
544 case DoubleRep:
545 case ValueRep:
546 case Int52Rep:
547 case DoubleConstant:
548 case Int52Constant:
549 case Identity:
550 case BooleanToNumber: {
551 // This node should never be visible at this stage of compilation. It is
552 // inserted by fixup(), which follows this phase.
553 RELEASE_ASSERT_NOT_REACHED();
554 break;
555 }
556
557 case Phi:
558 // Phis should not be visible here since we're iterating the all-but-Phi's
559 // part of basic blocks.
560 RELEASE_ASSERT_NOT_REACHED();
561 break;
562
563 case Upsilon:
564 case GetArgument:
565 // These don't get inserted until we go into SSA.
566 RELEASE_ASSERT_NOT_REACHED();
567 break;
568
569 case GetScope:
570 changed |= setPrediction(SpecObjectOther);
571 break;
572
573 case In:
574 changed |= setPrediction(SpecBoolean);
575 break;
576
577 #ifndef NDEBUG
578 // These get ignored because they don't return anything.
579 case StoreBarrier:
580 case StoreBarrierWithNullCheck:
581 case PutByValDirect:
582 case PutByVal:
583 case PutClosureVar:
584 case Return:
585 case Throw:
586 case PutById:
587 case PutByIdFlush:
588 case PutByIdDirect:
589 case PutByOffset:
590 case MultiPutByOffset:
591 case DFG::Jump:
592 case Branch:
593 case Switch:
594 case Breakpoint:
595 case ProfileWillCall:
596 case ProfileDidCall:
597 case CheckHasInstance:
598 case ThrowReferenceError:
599 case ForceOSRExit:
600 case SetArgument:
601 case CheckStructure:
602 case CheckExecutable:
603 case StructureTransitionWatchpoint:
604 case CheckFunction:
605 case PutStructure:
606 case TearOffActivation:
607 case TearOffArguments:
608 case CheckArgumentsNotCreated:
609 case VariableWatchpoint:
610 case VarInjectionWatchpoint:
611 case AllocationProfileWatchpoint:
612 case Phantom:
613 case Check:
614 case PutGlobalVar:
615 case CheckWatchdogTimer:
616 case Unreachable:
617 case LoopHint:
618 case NotifyWrite:
619 case FunctionReentryWatchpoint:
620 case TypedArrayWatchpoint:
621 case ConstantStoragePointer:
622 case MovHint:
623 case ZombieHint:
624 break;
625
626 // This gets ignored because it already has a prediction.
627 case ExtractOSREntryLocal:
628 break;
629
630 // These gets ignored because it doesn't do anything.
631 case CountExecution:
632 case PhantomLocal:
633 case Flush:
634 break;
635
636 case LastNodeType:
637 RELEASE_ASSERT_NOT_REACHED();
638 break;
639 #else
640 default:
641 break;
642 #endif
643 }
644
645 m_changed |= changed;
646 }
647
648 void propagateForward()
649 {
650 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
651 BasicBlock* block = m_graph.block(blockIndex);
652 if (!block)
653 continue;
654 ASSERT(block->isReachable);
655 for (unsigned i = 0; i < block->size(); ++i) {
656 m_currentNode = block->at(i);
657 propagate(m_currentNode);
658 }
659 }
660 }
661
662 void propagateBackward()
663 {
664 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
665 BasicBlock* block = m_graph.block(blockIndex);
666 if (!block)
667 continue;
668 ASSERT(block->isReachable);
669 for (unsigned i = block->size(); i--;) {
670 m_currentNode = block->at(i);
671 propagate(m_currentNode);
672 }
673 }
674 }
675
676 void doDoubleVoting(Node* node, float weight)
677 {
678 // Loop pre-headers created by OSR entrypoint creation may have NaN weight to indicate
679 // that we actually don't know they weight. Assume that they execute once. This turns
680 // out to be an OK assumption since the pre-header doesn't have any meaningful code.
681 if (weight != weight)
682 weight = 1;
683
684 switch (node->op()) {
685 case ValueAdd:
686 case ArithAdd:
687 case ArithSub: {
688 SpeculatedType left = node->child1()->prediction();
689 SpeculatedType right = node->child2()->prediction();
690
691 DoubleBallot ballot;
692
693 if (isFullNumberSpeculation(left)
694 && isFullNumberSpeculation(right)
695 && !m_graph.addShouldSpeculateInt32(node, m_pass)
696 && !m_graph.addShouldSpeculateMachineInt(node))
697 ballot = VoteDouble;
698 else
699 ballot = VoteValue;
700
701 m_graph.voteNode(node->child1(), ballot, weight);
702 m_graph.voteNode(node->child2(), ballot, weight);
703 break;
704 }
705
706 case ArithMul: {
707 SpeculatedType left = node->child1()->prediction();
708 SpeculatedType right = node->child2()->prediction();
709
710 DoubleBallot ballot;
711
712 if (isFullNumberSpeculation(left)
713 && isFullNumberSpeculation(right)
714 && !m_graph.mulShouldSpeculateInt32(node, m_pass)
715 && !m_graph.mulShouldSpeculateMachineInt(node, m_pass))
716 ballot = VoteDouble;
717 else
718 ballot = VoteValue;
719
720 m_graph.voteNode(node->child1(), ballot, weight);
721 m_graph.voteNode(node->child2(), ballot, weight);
722 break;
723 }
724
725 case ArithMin:
726 case ArithMax:
727 case ArithMod:
728 case ArithDiv: {
729 SpeculatedType left = node->child1()->prediction();
730 SpeculatedType right = node->child2()->prediction();
731
732 DoubleBallot ballot;
733
734 if (isFullNumberSpeculation(left)
735 && isFullNumberSpeculation(right)
736 && !(Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) && node->canSpeculateInt32(m_pass)))
737 ballot = VoteDouble;
738 else
739 ballot = VoteValue;
740
741 m_graph.voteNode(node->child1(), ballot, weight);
742 m_graph.voteNode(node->child2(), ballot, weight);
743 break;
744 }
745
746 case ArithAbs:
747 DoubleBallot ballot;
748 if (node->child1()->shouldSpeculateNumber()
749 && !(node->child1()->shouldSpeculateInt32OrBooleanForArithmetic() && node->canSpeculateInt32(m_pass)))
750 ballot = VoteDouble;
751 else
752 ballot = VoteValue;
753
754 m_graph.voteNode(node->child1(), ballot, weight);
755 break;
756
757 case ArithSqrt:
758 case ArithCos:
759 case ArithSin:
760 if (node->child1()->shouldSpeculateNumber())
761 m_graph.voteNode(node->child1(), VoteDouble, weight);
762 else
763 m_graph.voteNode(node->child1(), VoteValue, weight);
764 break;
765
766 case SetLocal: {
767 SpeculatedType prediction = node->child1()->prediction();
768 if (isDoubleSpeculation(prediction))
769 node->variableAccessData()->vote(VoteDouble, weight);
770 else if (
771 !isFullNumberSpeculation(prediction)
772 || isInt32Speculation(prediction) || isMachineIntSpeculation(prediction))
773 node->variableAccessData()->vote(VoteValue, weight);
774 break;
775 }
776
777 case PutByValDirect:
778 case PutByVal:
779 case PutByValAlias: {
780 Edge child1 = m_graph.varArgChild(node, 0);
781 Edge child2 = m_graph.varArgChild(node, 1);
782 Edge child3 = m_graph.varArgChild(node, 2);
783 m_graph.voteNode(child1, VoteValue, weight);
784 m_graph.voteNode(child2, VoteValue, weight);
785 switch (node->arrayMode().type()) {
786 case Array::Double:
787 m_graph.voteNode(child3, VoteDouble, weight);
788 break;
789 default:
790 m_graph.voteNode(child3, VoteValue, weight);
791 break;
792 }
793 break;
794 }
795
796 case MovHint:
797 // Ignore these since they have no effect on in-DFG execution.
798 break;
799
800 default:
801 m_graph.voteChildren(node, VoteValue, weight);
802 break;
803 }
804 }
805
806 void doRoundOfDoubleVoting()
807 {
808 for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i)
809 m_graph.m_variableAccessData[i].find()->clearVotes();
810 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
811 BasicBlock* block = m_graph.block(blockIndex);
812 if (!block)
813 continue;
814 ASSERT(block->isReachable);
815 for (unsigned i = 0; i < block->size(); ++i) {
816 m_currentNode = block->at(i);
817 doDoubleVoting(m_currentNode, block->executionCount);
818 }
819 }
820 for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
821 VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
822 if (!variableAccessData->isRoot())
823 continue;
824 m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat();
825 }
826 for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i)
827 m_changed |= m_graph.m_argumentPositions[i].mergeArgumentPredictionAwareness();
828 for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) {
829 VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i];
830 if (!variableAccessData->isRoot())
831 continue;
832 m_changed |= variableAccessData->makePredictionForDoubleFormat();
833 }
834 }
835
836 Node* m_currentNode;
837 bool m_changed;
838 PredictionPass m_pass; // We use different logic for considering predictions depending on how far along we are in propagation.
839 };
840
841 bool performPredictionPropagation(Graph& graph)
842 {
843 SamplingRegion samplingRegion("DFG Prediction Propagation Phase");
844 return runPhase<PredictionPropagationPhase>(graph);
845 }
846
847 } } // namespace JSC::DFG
848
849 #endif // ENABLE(DFG_JIT)
850