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