]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGPredictionPropagationPhase.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGPredictionPropagationPhase.cpp
CommitLineData
6fe7ccc8 1/*
ed1e77d3 2 * Copyright (C) 2011-2015 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"
81345200 33#include "JSCInlines.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);
6fe7ccc8 59
ed1e77d3
A
60 propagateThroughArgumentPositions();
61
81345200
A
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
81private:
82 void propagateToFixpoint()
83 {
6fe7ccc8
A
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);
6fe7ccc8
A
100 }
101
93a37866 102 bool setPrediction(SpeculatedType prediction)
6fe7ccc8 103 {
93a37866 104 ASSERT(m_currentNode->hasResult());
6fe7ccc8
A
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
93a37866 108 // difference between setPrediction() and mergeSpeculation() other than the
6fe7ccc8 109 // increased checking to validate this property.
93a37866 110 ASSERT(m_currentNode->prediction() == SpecNone || m_currentNode->prediction() == prediction);
6fe7ccc8 111
93a37866 112 return m_currentNode->predict(prediction);
6fe7ccc8
A
113 }
114
93a37866 115 bool mergePrediction(SpeculatedType prediction)
6fe7ccc8 116 {
93a37866 117 ASSERT(m_currentNode->hasResult());
6fe7ccc8 118
93a37866 119 return m_currentNode->predict(prediction);
6fe7ccc8
A
120 }
121
93a37866 122 SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value)
6fe7ccc8 123 {
81345200
A
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;
6fe7ccc8 132 }
93a37866
A
133
134 SpeculatedType speculatedDoubleTypeForPredictions(SpeculatedType left, SpeculatedType right)
6fe7ccc8 135 {
93a37866 136 return speculatedDoubleTypeForPrediction(mergeSpeculations(left, right));
6fe7ccc8 137 }
93a37866
A
138
139 void propagate(Node* node)
6fe7ccc8 140 {
93a37866 141 NodeType op = node->op();
6fe7ccc8 142
6fe7ccc8
A
143 bool changed = false;
144
145 switch (op) {
ed1e77d3
A
146 case JSConstant: {
147 SpeculatedType type = speculationFromValue(node->asJSValue());
81345200
A
148 if (type == SpecInt52AsDouble && enableInt52())
149 type = SpecInt52;
150 changed |= setPrediction(type);
6fe7ccc8
A
151 break;
152 }
ed1e77d3
A
153 case DoubleConstant: {
154 SpeculatedType type = speculationFromValue(node->asJSValue());
155 changed |= setPrediction(type);
156 break;
157 }
6fe7ccc8
A
158
159 case GetLocal: {
81345200
A
160 VariableAccessData* variable = node->variableAccessData();
161 SpeculatedType prediction = variable->prediction();
162 if (!variable->couldRepresentInt52() && (prediction & SpecInt52))
163 prediction = (prediction | SpecInt52AsDouble) & ~SpecInt52;
6fe7ccc8
A
164 if (prediction)
165 changed |= mergePrediction(prediction);
6fe7ccc8
A
166 break;
167 }
168
169 case SetLocal: {
93a37866
A
170 VariableAccessData* variableAccessData = node->variableAccessData();
171 changed |= variableAccessData->predict(node->child1()->prediction());
6fe7ccc8
A
172 break;
173 }
174
175 case BitAnd:
176 case BitOr:
177 case BitXor:
178 case BitRShift:
179 case BitLShift:
93a37866 180 case BitURShift:
ed1e77d3
A
181 case ArithIMul:
182 case ArithClz32: {
93a37866 183 changed |= setPrediction(SpecInt32);
6fe7ccc8
A
184 break;
185 }
186
93a37866
A
187 case ArrayPop:
188 case ArrayPush:
6fe7ccc8 189 case RegExpExec:
93a37866
A
190 case RegExpTest:
191 case GetById:
192 case GetByIdFlush:
93a37866 193 case GetByOffset:
81345200 194 case MultiGetByOffset:
ed1e77d3 195 case GetDirectPname:
93a37866
A
196 case Call:
197 case Construct:
ed1e77d3
A
198 case CallVarargs:
199 case ConstructVarargs:
200 case CallForwardVarargs:
201 case ConstructForwardVarargs:
202 case NativeCall:
203 case NativeConstruct:
93a37866 204 case GetGlobalVar:
ed1e77d3
A
205 case GetClosureVar:
206 case GetFromArguments: {
93a37866 207 changed |= setPrediction(node->getHeapPrediction());
6fe7ccc8
A
208 break;
209 }
ed1e77d3
A
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 }
6fe7ccc8
A
229
230 case StringCharCodeAt: {
93a37866 231 changed |= setPrediction(SpecInt32);
6fe7ccc8
A
232 break;
233 }
234
6fe7ccc8 235 case UInt32ToNumber: {
81345200
A
236 // FIXME: Support Int52.
237 // https://bugs.webkit.org/show_bug.cgi?id=125704
238 if (node->canSpeculateInt32(m_pass))
93a37866 239 changed |= mergePrediction(SpecInt32);
6fe7ccc8 240 else
81345200 241 changed |= mergePrediction(SpecBytecodeNumber);
6fe7ccc8
A
242 break;
243 }
244
245 case ValueAdd: {
93a37866
A
246 SpeculatedType left = node->child1()->prediction();
247 SpeculatedType right = node->child2()->prediction();
6fe7ccc8
A
248
249 if (left && right) {
81345200
A
250 if (isFullNumberOrBooleanSpeculationExpectingDefined(left)
251 && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
252 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
93a37866 253 changed |= mergePrediction(SpecInt32);
81345200
A
254 else if (m_graph.addShouldSpeculateMachineInt(node))
255 changed |= mergePrediction(SpecInt52);
6fe7ccc8 256 else
93a37866 257 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
81345200
A
258 } else if (
259 !(left & (SpecFullNumber | SpecBoolean))
260 || !(right & (SpecFullNumber | SpecBoolean))) {
6fe7ccc8 261 // left or right is definitely something other than a number.
93a37866 262 changed |= mergePrediction(SpecString);
6fe7ccc8 263 } else
81345200 264 changed |= mergePrediction(SpecString | SpecInt32 | SpecBytecodeDouble);
6fe7ccc8 265 }
6fe7ccc8
A
266 break;
267 }
ed1e77d3
A
268
269 case ArithAdd:
6fe7ccc8 270 case ArithSub: {
93a37866
A
271 SpeculatedType left = node->child1()->prediction();
272 SpeculatedType right = node->child2()->prediction();
6fe7ccc8
A
273
274 if (left && right) {
81345200 275 if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
93a37866 276 changed |= mergePrediction(SpecInt32);
81345200
A
277 else if (m_graph.addShouldSpeculateMachineInt(node))
278 changed |= mergePrediction(SpecInt52);
6fe7ccc8 279 else
93a37866 280 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
6fe7ccc8 281 }
6fe7ccc8
A
282 break;
283 }
284
285 case ArithNegate:
93a37866 286 if (node->child1()->prediction()) {
81345200 287 if (m_graph.negateShouldSpeculateInt32(node, m_pass))
93a37866 288 changed |= mergePrediction(SpecInt32);
81345200
A
289 else if (m_graph.negateShouldSpeculateMachineInt(node, m_pass))
290 changed |= mergePrediction(SpecInt52);
6fe7ccc8 291 else
93a37866 292 changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
6fe7ccc8 293 }
6fe7ccc8
A
294 break;
295
296 case ArithMin:
297 case ArithMax: {
93a37866
A
298 SpeculatedType left = node->child1()->prediction();
299 SpeculatedType right = node->child2()->prediction();
6fe7ccc8
A
300
301 if (left && right) {
81345200
A
302 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
303 && node->canSpeculateInt32(m_pass))
93a37866 304 changed |= mergePrediction(SpecInt32);
6fe7ccc8 305 else
93a37866 306 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
6fe7ccc8 307 }
93a37866
A
308 break;
309 }
6fe7ccc8 310
93a37866
A
311 case ArithMul: {
312 SpeculatedType left = node->child1()->prediction();
313 SpeculatedType right = node->child2()->prediction();
314
315 if (left && right) {
81345200 316 if (m_graph.mulShouldSpeculateInt32(node, m_pass))
93a37866 317 changed |= mergePrediction(SpecInt32);
81345200
A
318 else if (m_graph.mulShouldSpeculateMachineInt(node, m_pass))
319 changed |= mergePrediction(SpecInt52);
93a37866
A
320 else
321 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
322 }
6fe7ccc8
A
323 break;
324 }
ed1e77d3
A
325
326 case ArithDiv:
93a37866
A
327 case ArithMod: {
328 SpeculatedType left = node->child1()->prediction();
329 SpeculatedType right = node->child2()->prediction();
330
331 if (left && right) {
81345200
A
332 if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
333 && node->canSpeculateInt32(m_pass))
93a37866
A
334 changed |= mergePrediction(SpecInt32);
335 else
81345200 336 changed |= mergePrediction(SpecBytecodeDouble);
93a37866 337 }
6fe7ccc8
A
338 break;
339 }
ed1e77d3
A
340
341 case ArithPow:
81345200
A
342 case ArithSqrt:
343 case ArithFRound:
344 case ArithSin:
ed1e77d3
A
345 case ArithCos:
346 case ArithLog: {
81345200 347 changed |= setPrediction(SpecBytecodeDouble);
6fe7ccc8
A
348 break;
349 }
ed1e77d3
A
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
6fe7ccc8 359 case ArithAbs: {
93a37866 360 SpeculatedType child = node->child1()->prediction();
81345200
A
361 if (isInt32OrBooleanSpeculationForArithmetic(child)
362 && node->canSpeculateInt32(m_pass))
93a37866 363 changed |= mergePrediction(SpecInt32);
6fe7ccc8 364 else
93a37866 365 changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
6fe7ccc8
A
366 break;
367 }
368
369 case LogicalNot:
370 case CompareLess:
371 case CompareLessEq:
372 case CompareGreater:
373 case CompareGreaterEq:
374 case CompareEq:
93a37866 375 case CompareEqConstant:
6fe7ccc8
A
376 case CompareStrictEq:
377 case InstanceOf:
378 case IsUndefined:
379 case IsBoolean:
380 case IsNumber:
381 case IsString:
382 case IsObject:
ed1e77d3 383 case IsObjectOrNull:
6fe7ccc8 384 case IsFunction: {
93a37866 385 changed |= setPrediction(SpecBoolean);
6fe7ccc8
A
386 break;
387 }
93a37866
A
388
389 case TypeOf: {
ed1e77d3 390 changed |= setPrediction(SpecStringIdent);
6fe7ccc8
A
391 break;
392 }
93a37866 393
6fe7ccc8 394 case GetByVal: {
81345200
A
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(),
ed1e77d3 402 SpecNone);
81345200
A
403
404 switch (arrayMode.type()) {
ed1e77d3
A
405 case Array::Int32:
406 if (arrayMode.isOutOfBounds())
407 changed |= mergePrediction(node->getHeapPrediction() | SpecInt32);
408 else
409 changed |= mergePrediction(SpecInt32);
410 break;
81345200
A
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:
ed1e77d3 422 if (isInt32SpeculationForArithmetic(node->getHeapPrediction()))
81345200
A
423 changed |= mergePrediction(SpecInt32);
424 else if (enableInt52())
425 changed |= mergePrediction(SpecMachineInt);
426 else
427 changed |= mergePrediction(SpecInt32 | SpecInt52AsDouble);
428 break;
ed1e77d3
A
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;
81345200 436 default:
93a37866 437 changed |= mergePrediction(node->getHeapPrediction());
81345200
A
438 break;
439 }
6fe7ccc8
A
440 break;
441 }
442
93a37866
A
443 case GetButterfly:
444 case GetIndexedPropertyStorage:
445 case AllocatePropertyStorage:
446 case ReallocatePropertyStorage: {
447 changed |= setPrediction(SpecOther);
6fe7ccc8
A
448 break;
449 }
93a37866 450
81345200 451 case ToThis: {
93a37866 452 SpeculatedType prediction = node->child1()->prediction();
6fe7ccc8 453 if (prediction) {
93a37866
A
454 if (prediction & ~SpecObject) {
455 prediction &= SpecObject;
456 prediction = mergeSpeculations(prediction, SpecObjectOther);
6fe7ccc8
A
457 }
458 changed |= mergePrediction(prediction);
459 }
6fe7ccc8
A
460 break;
461 }
462
93a37866
A
463 case SkipScope: {
464 changed |= setPrediction(SpecObjectOther);
6fe7ccc8
A
465 break;
466 }
467
6fe7ccc8
A
468 case CreateThis:
469 case NewObject: {
93a37866 470 changed |= setPrediction(SpecFinalObject);
6fe7ccc8
A
471 break;
472 }
473
93a37866
A
474 case NewArray:
475 case NewArrayWithSize:
6fe7ccc8 476 case NewArrayBuffer: {
93a37866 477 changed |= setPrediction(SpecArray);
6fe7ccc8
A
478 break;
479 }
480
81345200
A
481 case NewTypedArray: {
482 changed |= setPrediction(speculationFromTypedArrayType(node->typedArrayType()));
483 break;
484 }
485
93a37866
A
486 case NewRegexp:
487 case CreateActivation: {
488 changed |= setPrediction(SpecObjectOther);
6fe7ccc8
A
489 break;
490 }
491
93a37866
A
492 case StringFromCharCode: {
493 changed |= setPrediction(SpecString);
81345200 494 changed |= node->child1()->mergeFlags(NodeBytecodeUsesAsNumber | NodeBytecodeUsesAsInt);
6fe7ccc8
A
495 break;
496 }
93a37866 497 case StringCharAt:
ed1e77d3 498 case CallStringConstructor:
93a37866
A
499 case ToString:
500 case MakeRope: {
501 changed |= setPrediction(SpecString);
6fe7ccc8
A
502 break;
503 }
504
505 case ToPrimitive: {
93a37866
A
506 SpeculatedType child = node->child1()->prediction();
507 if (child)
508 changed |= mergePrediction(resultOfToPrimitive(child));
6fe7ccc8
A
509 break;
510 }
511
93a37866
A
512 case NewStringObject: {
513 changed |= setPrediction(SpecStringObject);
514 break;
515 }
516
ed1e77d3
A
517 case CreateDirectArguments: {
518 changed |= setPrediction(SpecDirectArguments);
93a37866
A
519 break;
520 }
521
ed1e77d3
A
522 case CreateScopedArguments: {
523 changed |= setPrediction(SpecScopedArguments);
6fe7ccc8
A
524 break;
525 }
526
ed1e77d3
A
527 case CreateClonedArguments: {
528 changed |= setPrediction(SpecObjectOther);
6fe7ccc8
A
529 break;
530 }
531
81345200
A
532 case FiatInt52: {
533 RELEASE_ASSERT(enableInt52());
534 changed |= setPrediction(SpecMachineInt);
535 break;
536 }
537
6fe7ccc8
A
538 case PutByValAlias:
539 case GetArrayLength:
81345200 540 case GetTypedArrayByteOffset:
93a37866
A
541 case DoubleAsInt32:
542 case GetLocalUnlinked:
93a37866
A
543 case CheckArray:
544 case Arrayify:
545 case ArrayifyToStructure:
81345200
A
546 case CheckTierUpInLoop:
547 case CheckTierUpAtReturn:
548 case CheckTierUpAndOSREnter:
ed1e77d3 549 case CheckTierUpWithNestedTriggerAndOSREnter:
81345200
A
550 case InvalidationPoint:
551 case CheckInBounds:
552 case ValueToInt32:
81345200
A
553 case DoubleRep:
554 case ValueRep:
555 case Int52Rep:
81345200
A
556 case Int52Constant:
557 case Identity:
ed1e77d3
A
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: {
6fe7ccc8
A
574 // This node should never be visible at this stage of compilation. It is
575 // inserted by fixup(), which follows this phase.
ed1e77d3 576 DFG_CRASH(m_graph, node, "Unexpected node during prediction propagation");
6fe7ccc8
A
577 break;
578 }
579
93a37866
A
580 case Phi:
581 // Phis should not be visible here since we're iterating the all-but-Phi's
582 // part of basic blocks.
81345200
A
583 RELEASE_ASSERT_NOT_REACHED();
584 break;
585
586 case Upsilon:
81345200
A
587 // These don't get inserted until we go into SSA.
588 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
589 break;
590
93a37866
A
591 case GetScope:
592 changed |= setPrediction(SpecObjectOther);
6fe7ccc8 593 break;
81345200
A
594
595 case In:
596 changed |= setPrediction(SpecBoolean);
6fe7ccc8
A
597 break;
598
ed1e77d3
A
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
6fe7ccc8
A
626#ifndef NDEBUG
627 // These get ignored because they don't return anything.
81345200 628 case PutByValDirect:
93a37866 629 case PutByVal:
81345200 630 case PutClosureVar:
ed1e77d3 631 case PutToArguments:
93a37866
A
632 case Return:
633 case Throw:
634 case PutById:
81345200 635 case PutByIdFlush:
93a37866
A
636 case PutByIdDirect:
637 case PutByOffset:
81345200 638 case MultiPutByOffset:
6fe7ccc8
A
639 case DFG::Jump:
640 case Branch:
81345200 641 case Switch:
6fe7ccc8 642 case Breakpoint:
81345200
A
643 case ProfileWillCall:
644 case ProfileDidCall:
ed1e77d3
A
645 case ProfileType:
646 case ProfileControlFlow:
6fe7ccc8
A
647 case CheckHasInstance:
648 case ThrowReferenceError:
649 case ForceOSRExit:
650 case SetArgument:
651 case CheckStructure:
ed1e77d3
A
652 case CheckCell:
653 case CheckNotEmpty:
654 case CheckBadCell:
6fe7ccc8 655 case PutStructure:
81345200 656 case VarInjectionWatchpoint:
93a37866 657 case Phantom:
81345200 658 case Check:
93a37866 659 case PutGlobalVar:
93a37866 660 case CheckWatchdogTimer:
12899fa2 661 case Unreachable:
81345200
A
662 case LoopHint:
663 case NotifyWrite:
81345200
A
664 case ConstantStoragePointer:
665 case MovHint:
666 case ZombieHint:
ed1e77d3
A
667 case LoadVarargs:
668 break;
669
670 // This gets ignored because it only pretends to produce a value.
671 case BottomValue:
81345200
A
672 break;
673
674 // This gets ignored because it already has a prediction.
675 case ExtractOSREntryLocal:
6fe7ccc8
A
676 break;
677
678 // These gets ignored because it doesn't do anything.
93a37866
A
679 case CountExecution:
680 case PhantomLocal:
681 case Flush:
6fe7ccc8
A
682 break;
683
684 case LastNodeType:
81345200 685 RELEASE_ASSERT_NOT_REACHED();
6fe7ccc8
A
686 break;
687#else
688 default:
6fe7ccc8
A
689 break;
690#endif
691 }
692
6fe7ccc8
A
693 m_changed |= changed;
694 }
695
6fe7ccc8
A
696 void propagateForward()
697 {
81345200
A
698 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
699 BasicBlock* block = m_graph.block(blockIndex);
93a37866
A
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 }
6fe7ccc8
A
708 }
709
710 void propagateBackward()
711 {
81345200
A
712 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
713 BasicBlock* block = m_graph.block(blockIndex);
93a37866
A
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 }
6fe7ccc8 721 }
6fe7ccc8
A
722 }
723
81345200 724 void doDoubleVoting(Node* node, float weight)
6fe7ccc8 725 {
81345200
A
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
93a37866
A
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
81345200
A
741 if (isFullNumberSpeculation(left)
742 && isFullNumberSpeculation(right)
743 && !m_graph.addShouldSpeculateInt32(node, m_pass)
744 && !m_graph.addShouldSpeculateMachineInt(node))
93a37866
A
745 ballot = VoteDouble;
746 else
747 ballot = VoteValue;
748
81345200
A
749 m_graph.voteNode(node->child1(), ballot, weight);
750 m_graph.voteNode(node->child2(), ballot, weight);
93a37866 751 break;
6fe7ccc8 752 }
6fe7ccc8 753
93a37866
A
754 case ArithMul: {
755 SpeculatedType left = node->child1()->prediction();
756 SpeculatedType right = node->child2()->prediction();
6fe7ccc8 757
93a37866 758 DoubleBallot ballot;
6fe7ccc8 759
81345200
A
760 if (isFullNumberSpeculation(left)
761 && isFullNumberSpeculation(right)
762 && !m_graph.mulShouldSpeculateInt32(node, m_pass)
763 && !m_graph.mulShouldSpeculateMachineInt(node, m_pass))
93a37866
A
764 ballot = VoteDouble;
765 else
766 ballot = VoteValue;
6fe7ccc8 767
81345200
A
768 m_graph.voteNode(node->child1(), ballot, weight);
769 m_graph.voteNode(node->child2(), ballot, weight);
93a37866
A
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();
6fe7ccc8 779
93a37866 780 DoubleBallot ballot;
6fe7ccc8 781
81345200
A
782 if (isFullNumberSpeculation(left)
783 && isFullNumberSpeculation(right)
784 && !(Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) && node->canSpeculateInt32(m_pass)))
93a37866
A
785 ballot = VoteDouble;
786 else
787 ballot = VoteValue;
6fe7ccc8 788
81345200
A
789 m_graph.voteNode(node->child1(), ballot, weight);
790 m_graph.voteNode(node->child2(), ballot, weight);
93a37866
A
791 break;
792 }
6fe7ccc8 793
93a37866
A
794 case ArithAbs:
795 DoubleBallot ballot;
81345200
A
796 if (node->child1()->shouldSpeculateNumber()
797 && !(node->child1()->shouldSpeculateInt32OrBooleanForArithmetic() && node->canSpeculateInt32(m_pass)))
93a37866
A
798 ballot = VoteDouble;
799 else
800 ballot = VoteValue;
6fe7ccc8 801
81345200 802 m_graph.voteNode(node->child1(), ballot, weight);
93a37866 803 break;
6fe7ccc8 804
93a37866 805 case ArithSqrt:
81345200
A
806 case ArithCos:
807 case ArithSin:
ed1e77d3 808 case ArithLog:
81345200
A
809 if (node->child1()->shouldSpeculateNumber())
810 m_graph.voteNode(node->child1(), VoteDouble, weight);
811 else
812 m_graph.voteNode(node->child1(), VoteValue, weight);
93a37866 813 break;
6fe7ccc8 814
93a37866
A
815 case SetLocal: {
816 SpeculatedType prediction = node->child1()->prediction();
817 if (isDoubleSpeculation(prediction))
81345200
A
818 node->variableAccessData()->vote(VoteDouble, weight);
819 else if (
820 !isFullNumberSpeculation(prediction)
821 || isInt32Speculation(prediction) || isMachineIntSpeculation(prediction))
822 node->variableAccessData()->vote(VoteValue, weight);
93a37866
A
823 break;
824 }
81345200
A
825
826 case PutByValDirect:
93a37866
A
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);
81345200
A
832 m_graph.voteNode(child1, VoteValue, weight);
833 m_graph.voteNode(child2, VoteValue, weight);
93a37866
A
834 switch (node->arrayMode().type()) {
835 case Array::Double:
81345200 836 m_graph.voteNode(child3, VoteDouble, weight);
93a37866 837 break;
6fe7ccc8 838 default:
81345200 839 m_graph.voteNode(child3, VoteValue, weight);
6fe7ccc8
A
840 break;
841 }
93a37866
A
842 break;
843 }
844
81345200
A
845 case MovHint:
846 // Ignore these since they have no effect on in-DFG execution.
847 break;
848
93a37866 849 default:
81345200 850 m_graph.voteChildren(node, VoteValue, weight);
93a37866
A
851 break;
852 }
853 }
854
855 void doRoundOfDoubleVoting()
856 {
93a37866
A
857 for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i)
858 m_graph.m_variableAccessData[i].find()->clearVotes();
81345200
A
859 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
860 BasicBlock* block = m_graph.block(blockIndex);
93a37866
A
861 if (!block)
862 continue;
863 ASSERT(block->isReachable);
864 for (unsigned i = 0; i < block->size(); ++i) {
865 m_currentNode = block->at(i);
81345200 866 doDoubleVoting(m_currentNode, block->executionCount);
93a37866 867 }
6fe7ccc8
A
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;
6fe7ccc8
A
873 m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat();
874 }
ed1e77d3 875 propagateThroughArgumentPositions();
6fe7ccc8
A
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;
6fe7ccc8
A
880 m_changed |= variableAccessData->makePredictionForDoubleFormat();
881 }
882 }
883
ed1e77d3
A
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
93a37866 890 Node* m_currentNode;
6fe7ccc8 891 bool m_changed;
81345200 892 PredictionPass m_pass; // We use different logic for considering predictions depending on how far along we are in propagation.
6fe7ccc8
A
893};
894
93a37866 895bool performPredictionPropagation(Graph& graph)
6fe7ccc8 896{
93a37866
A
897 SamplingRegion samplingRegion("DFG Prediction Propagation Phase");
898 return runPhase<PredictionPropagationPhase>(graph);
6fe7ccc8
A
899}
900
901} } // namespace JSC::DFG
902
903#endif // ENABLE(DFG_JIT)
904