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