Changeset 145299 in webkit for trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
- Timestamp:
- Mar 8, 2013, 6:51:06 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r144939 r145299 107 107 } 108 108 109 bool isNotNegZero(Node* node)110 {111 if (!m_graph.isNumberConstant(node))112 return false;113 double value = m_graph.valueOfNumberConstant(node);114 return !value && 1.0 / value < 0.0;115 }116 117 bool isNotZero(Node* node)118 {119 if (!m_graph.isNumberConstant(node))120 return false;121 return !!m_graph.valueOfNumberConstant(node);122 }123 124 bool isWithinPowerOfTwoForConstant(Node* node, int power)125 {126 JSValue immediateValue = node->valueOfJSConstant(codeBlock());127 if (!immediateValue.isInt32())128 return false;129 int32_t intImmediate = immediateValue.asInt32();130 return intImmediate > -(1 << power) && intImmediate < (1 << power);131 }132 133 bool isWithinPowerOfTwoNonRecursive(Node* node, int power)134 {135 if (node->op() != JSConstant)136 return false;137 return isWithinPowerOfTwoForConstant(node, power);138 }139 140 bool isWithinPowerOfTwo(Node* node, int power)141 {142 switch (node->op()) {143 case JSConstant: {144 return isWithinPowerOfTwoForConstant(node, power);145 }146 147 case BitAnd: {148 return isWithinPowerOfTwoNonRecursive(node->child1().node(), power)149 || isWithinPowerOfTwoNonRecursive(node->child2().node(), power);150 }151 152 case BitRShift:153 case BitURShift: {154 Node* shiftAmount = node->child2().node();155 if (shiftAmount->op() != JSConstant)156 return false;157 JSValue immediateValue = shiftAmount->valueOfJSConstant(codeBlock());158 if (!immediateValue.isInt32())159 return false;160 return immediateValue > 32 - power;161 }162 163 default:164 return false;165 }166 }167 168 109 SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value) 169 110 { … … 183 124 { 184 125 NodeType op = node->op(); 185 NodeFlags flags = node->flags() & NodeBackPropMask;186 126 187 127 #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) 188 dataLog(" ", Graph::opName(op), " ", m_currentNode, ": ", nodeFlagsAsString(flags), " ");128 dataLog(" ", Graph::opName(op), " ", m_currentNode, ": ", NodeFlagsDump(node->flags()), " "); 189 129 #endif 190 130 … … 203 143 if (prediction) 204 144 changed |= mergePrediction(prediction); 205 206 // Assume conservatively that a SetLocal implies that the value may flow through a loop,207 // and so we would have overflow leading to the program "observing" numbers even if all208 // users of the value are doing toInt32. It might be worthwhile to revisit this at some209 // point and actually check if the data flow involves loops, but right now I don't think210 // we have evidence that this would be beneficial for benchmarks.211 212 changed |= variableAccessData->mergeFlags((flags & ~NodeUsedAsIntLocally) | NodeUsedAsNumber);213 145 break; 214 146 } … … 217 149 VariableAccessData* variableAccessData = node->variableAccessData(); 218 150 changed |= variableAccessData->predict(node->child1()->prediction()); 219 220 changed |= node->child1()->mergeFlags(variableAccessData->flags());221 break;222 }223 224 case Flush: {225 // Make sure that the analysis knows that flushed locals escape.226 VariableAccessData* variableAccessData = node->variableAccessData();227 changed |= variableAccessData->mergeFlags(NodeUsedAsValue);228 151 break; 229 152 } … … 236 159 case BitURShift: { 237 160 changed |= setPrediction(SpecInt32); 238 flags |= NodeUsedAsInt | NodeUsedAsIntLocally;239 flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);240 changed |= node->child1()->mergeFlags(flags);241 changed |= node->child2()->mergeFlags(flags);242 161 break; 243 162 } … … 245 164 case ValueToInt32: { 246 165 changed |= setPrediction(SpecInt32); 247 flags |= NodeUsedAsInt | NodeUsedAsIntLocally; 248 flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther); 249 changed |= node->child1()->mergeFlags(flags); 250 break; 251 } 252 253 case ArrayPop: { 254 changed |= mergePrediction(node->getHeapPrediction()); 255 changed |= mergeDefaultFlags(node); 256 break; 257 } 258 259 case ArrayPush: { 260 changed |= mergePrediction(node->getHeapPrediction()); 261 changed |= node->child1()->mergeFlags(NodeUsedAsValue); 262 changed |= node->child2()->mergeFlags(NodeUsedAsValue); 263 break; 264 } 265 166 break; 167 } 168 169 case ArrayPop: 170 case ArrayPush: 266 171 case RegExpExec: 267 case RegExpTest: { 268 changed |= mergePrediction(node->getHeapPrediction()); 269 changed |= mergeDefaultFlags(node); 172 case RegExpTest: 173 case GetById: 174 case GetByIdFlush: 175 case GetMyArgumentByValSafe: 176 case GetByOffset: 177 case Call: 178 case Construct: 179 case GetGlobalVar: 180 case GetScopedVar: 181 case Resolve: 182 case ResolveBase: 183 case ResolveBaseStrictPut: 184 case ResolveGlobal: { 185 changed |= setPrediction(node->getHeapPrediction()); 270 186 break; 271 187 } 272 188 273 189 case StringCharCodeAt: { 274 changed |= mergePrediction(SpecInt32); 275 changed |= node->child1()->mergeFlags(NodeUsedAsValue); 276 changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally); 190 changed |= setPrediction(SpecInt32); 277 191 break; 278 192 } … … 283 197 else 284 198 changed |= mergePrediction(SpecNumber); 285 286 changed |= node->child1()->mergeFlags(flags);287 199 break; 288 200 } … … 291 203 SpeculatedType left = node->child1()->prediction(); 292 204 SpeculatedType right = node->child2()->prediction(); 293 294 AddSpeculationMode mode = DontSpeculateInteger;295 205 296 206 if (left && right) { 297 207 if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) { 298 if ( (mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)208 if (m_graph.addSpeculationMode(node) != DontSpeculateInteger) 299 209 changed |= mergePrediction(SpecInt32); 300 210 else … … 306 216 changed |= mergePrediction(SpecString | SpecInt32 | SpecDouble); 307 217 } 308 309 if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))310 flags &= ~NodeNeedsNegZero;311 if (node->child1()->hasNumberResult() || node->child2()->hasNumberResult())312 flags &= ~NodeUsedAsOther;313 314 if (mode != SpeculateInteger)315 flags |= NodeUsedAsNumber;316 317 changed |= node->child1()->mergeFlags(flags);318 changed |= node->child2()->mergeFlags(flags);319 218 break; 320 219 } … … 324 223 SpeculatedType right = node->child2()->prediction(); 325 224 326 AddSpeculationMode mode = DontSpeculateInteger;327 328 225 if (left && right) { 329 if ( (mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)226 if (m_graph.addSpeculationMode(node) != DontSpeculateInteger) 330 227 changed |= mergePrediction(SpecInt32); 331 228 else 332 229 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 333 230 } 334 335 if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))336 flags &= ~NodeNeedsNegZero;337 flags &= ~NodeUsedAsOther;338 339 if (mode != SpeculateInteger)340 flags |= NodeUsedAsNumber;341 342 changed |= node->child1()->mergeFlags(flags);343 changed |= node->child2()->mergeFlags(flags);344 231 break; 345 232 } … … 349 236 SpeculatedType right = node->child2()->prediction(); 350 237 351 AddSpeculationMode mode = DontSpeculateInteger;352 353 238 if (left && right) { 354 if ( (mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)239 if (m_graph.addSpeculationMode(node) != DontSpeculateInteger) 355 240 changed |= mergePrediction(SpecInt32); 356 241 else 357 242 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 358 243 } 359 360 if (isNotZero(node->child1().node()) || isNotZero(node->child2().node()))361 flags &= ~NodeNeedsNegZero;362 flags &= ~NodeUsedAsOther;363 364 if (mode != SpeculateInteger)365 flags |= NodeUsedAsNumber;366 367 changed |= node->child1()->mergeFlags(flags);368 changed |= node->child2()->mergeFlags(flags);369 244 break; 370 245 } … … 377 252 changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction())); 378 253 } 379 380 flags &= ~NodeUsedAsOther;381 382 changed |= node->child1()->mergeFlags(flags);383 254 break; 384 255 … … 395 266 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 396 267 } 397 398 flags |= NodeUsedAsNumber;399 flags &= ~NodeUsedAsOther;400 401 changed |= node->child1()->mergeFlags(flags);402 changed |= node->child2()->mergeFlags(flags);403 268 break; 404 269 } … … 414 279 changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right)); 415 280 } 416 417 // As soon as a multiply happens, we can easily end up in the part418 // of the double domain where the point at which you do truncation419 // can change the outcome. So, ArithMul always forces its inputs to420 // check for overflow. Additionally, it will have to check for overflow421 // itself unless we can prove that there is no way for the values422 // produced to cause double rounding.423 424 if (!isWithinPowerOfTwo(node->child1().node(), 22)425 && !isWithinPowerOfTwo(node->child2().node(), 22))426 flags |= NodeUsedAsNumber;427 428 changed |= node->mergeFlags(flags);429 430 flags |= NodeUsedAsNumber | NodeNeedsNegZero;431 flags &= ~NodeUsedAsOther;432 433 changed |= node->child1()->mergeFlags(flags);434 changed |= node->child2()->mergeFlags(flags);435 281 break; 436 282 } … … 447 293 changed |= mergePrediction(SpecDouble); 448 294 } 449 450 // As soon as a multiply happens, we can easily end up in the part451 // of the double domain where the point at which you do truncation452 // can change the outcome. So, ArithDiv always checks for overflow453 // no matter what, and always forces its inputs to check as well.454 455 flags |= NodeUsedAsNumber | NodeNeedsNegZero;456 flags &= ~NodeUsedAsOther;457 458 changed |= node->child1()->mergeFlags(flags);459 changed |= node->child2()->mergeFlags(flags);460 295 break; 461 296 } … … 472 307 changed |= mergePrediction(SpecDouble); 473 308 } 474 475 flags |= NodeUsedAsNumber | NodeNeedsNegZero;476 flags &= ~NodeUsedAsOther;477 478 changed |= node->child1()->mergeFlags(flags);479 changed |= node->child2()->mergeFlags(flags);480 309 break; 481 310 } … … 483 312 case ArithSqrt: { 484 313 changed |= setPrediction(SpecDouble); 485 flags |= NodeUsedAsNumber | NodeNeedsNegZero;486 flags &= ~NodeUsedAsOther;487 changed |= node->child1()->mergeFlags(flags);488 314 break; 489 315 } … … 496 322 else 497 323 changed |= mergePrediction(speculatedDoubleTypeForPrediction(child)); 498 499 changed |= node->child1()->mergeFlags(flags);500 324 break; 501 325 } … … 518 342 case IsFunction: { 519 343 changed |= setPrediction(SpecBoolean); 520 changed |= mergeDefaultFlags(node);521 344 break; 522 345 } … … 524 347 case TypeOf: { 525 348 changed |= setPrediction(SpecString); 526 changed |= mergeDefaultFlags(node); 527 break; 528 } 529 530 case GetById: { 531 changed |= mergePrediction(node->getHeapPrediction()); 532 changed |= mergeDefaultFlags(node); 533 break; 534 } 535 536 case GetByIdFlush: 537 changed |= mergePrediction(node->getHeapPrediction()); 538 changed |= mergeDefaultFlags(node); 539 break; 540 349 break; 350 } 351 541 352 case GetByVal: { 542 353 if (node->child1()->shouldSpeculateFloat32Array() … … 545 356 else 546 357 changed |= mergePrediction(node->getHeapPrediction()); 547 548 changed |= node->child1()->mergeFlags(NodeUsedAsValue);549 changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);550 break;551 }552 553 case GetMyArgumentByValSafe: {554 changed |= mergePrediction(node->getHeapPrediction());555 changed |= node->child1()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);556 358 break; 557 359 } … … 568 370 case ReallocatePropertyStorage: { 569 371 changed |= setPrediction(SpecOther); 570 changed |= mergeDefaultFlags(node); 571 break; 572 } 573 574 case GetByOffset: { 575 changed |= mergePrediction(node->getHeapPrediction()); 576 changed |= mergeDefaultFlags(node); 577 break; 578 } 579 580 case Call: 581 case Construct: { 582 changed |= mergePrediction(node->getHeapPrediction()); 583 for (unsigned childIdx = node->firstChild(); 584 childIdx < node->firstChild() + node->numChildren(); 585 ++childIdx) 586 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue); 587 break; 588 } 589 372 break; 373 } 374 590 375 case ConvertThis: { 591 376 SpeculatedType prediction = node->child1()->prediction(); … … 597 382 changed |= mergePrediction(prediction); 598 383 } 599 changed |= mergeDefaultFlags(node);600 break;601 }602 603 case GetGlobalVar: {604 changed |= mergePrediction(node->getHeapPrediction());605 break;606 }607 608 case PutGlobalVar:609 case PutGlobalVarCheck: {610 changed |= node->child1()->mergeFlags(NodeUsedAsValue);611 break;612 }613 614 case GetScopedVar:615 case Resolve:616 case ResolveBase:617 case ResolveBaseStrictPut:618 case ResolveGlobal: {619 SpeculatedType prediction = node->getHeapPrediction();620 changed |= mergePrediction(prediction);621 384 break; 622 385 } … … 637 400 case NewObject: { 638 401 changed |= setPrediction(SpecFinalObject); 639 changed |= mergeDefaultFlags(node); 640 break; 641 } 642 643 case NewArray: { 644 changed |= setPrediction(SpecArray); 645 for (unsigned childIdx = node->firstChild(); 646 childIdx < node->firstChild() + node->numChildren(); 647 ++childIdx) 648 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue); 649 break; 650 } 651 652 case NewArrayWithSize: { 653 changed |= setPrediction(SpecArray); 654 changed |= node->child1()->mergeFlags(NodeUsedAsValue | NodeUsedAsInt | NodeUsedAsIntLocally); 655 break; 656 } 657 402 break; 403 } 404 405 case NewArray: 406 case NewArrayWithSize: 658 407 case NewArrayBuffer: { 659 408 changed |= setPrediction(SpecArray); … … 661 410 } 662 411 663 case NewRegexp: { 412 case NewRegexp: 413 case CreateActivation: { 664 414 changed |= setPrediction(SpecObjectOther); 665 415 break; 666 416 } 667 417 668 case StringCharAt: { 669 changed |= setPrediction(SpecString); 670 changed |= node->child1()->mergeFlags(NodeUsedAsValue); 671 changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally); 672 break; 673 } 674 418 case StringCharAt: 675 419 case StrCat: { 676 420 changed |= setPrediction(SpecString); 677 for (unsigned childIdx = node->firstChild();678 childIdx < node->firstChild() + node->numChildren();679 ++childIdx)680 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther);681 421 break; 682 422 } … … 700 440 changed |= mergePrediction(child); 701 441 } 702 changed |= node->child1()->mergeFlags(flags);703 break;704 }705 706 case CreateActivation: {707 changed |= setPrediction(SpecObjectOther);708 442 break; 709 443 } … … 744 478 } 745 479 746 case PutByVal:747 changed |= m_graph.varArgChild(node, 0)->mergeFlags(NodeUsedAsValue);748 changed |= m_graph.varArgChild(node, 1)->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);749 changed |= m_graph.varArgChild(node, 2)->mergeFlags(NodeUsedAsValue);750 break;751 752 case PutScopedVar:753 changed |= node->child1()->mergeFlags(NodeUsedAsValue);754 changed |= node->child3()->mergeFlags(NodeUsedAsValue);755 break;756 757 case Return:758 case Throw:759 changed |= node->child1()->mergeFlags(NodeUsedAsValue);760 break;761 762 case PutById:763 case PutByIdDirect:764 changed |= node->child1()->mergeFlags(NodeUsedAsValue);765 changed |= node->child2()->mergeFlags(NodeUsedAsValue);766 break;767 768 case PutByOffset:769 changed |= node->child1()->mergeFlags(NodeUsedAsValue);770 changed |= node->child3()->mergeFlags(NodeUsedAsValue);771 break;772 773 480 case Phi: 774 481 // Phis should not be visible here since we're iterating the all-but-Phi's … … 777 484 break; 778 485 486 case GetScope: 487 changed |= setPrediction(SpecCellOther); 488 break; 489 490 #ifndef NDEBUG 491 // These get ignored because they don't return anything. 492 case PutByVal: 493 case PutScopedVar: 494 case Return: 495 case Throw: 496 case PutById: 497 case PutByIdDirect: 498 case PutByOffset: 779 499 case SetCallee: 780 500 case SetMyScope: 781 changed |= node->child1()->mergeFlags(NodeUsedAsValue);782 break;783 784 case GetScope:785 changed |= node->child1()->mergeFlags(NodeUsedAsValue);786 changed |= setPrediction(SpecCellOther);787 break;788 789 #ifndef NDEBUG790 // These get ignored because they don't return anything.791 501 case DFG::Jump: 792 502 case Branch: … … 810 520 case AllocationProfileWatchpoint: 811 521 case Phantom: 812 changed |= mergeDefaultFlags(node); 522 case PutGlobalVar: 523 case PutGlobalVarCheck: 813 524 break; 814 525 … … 818 529 case CountExecution: 819 530 case PhantomLocal: 531 case Flush: 820 532 break; 821 533 … … 825 537 #else 826 538 default: 827 changed |= mergeDefaultFlags(node);828 539 break; 829 540 #endif … … 837 548 } 838 549 839 bool mergeDefaultFlags(Node* node)840 {841 bool changed = false;842 if (node->flags() & NodeHasVarArgs) {843 for (unsigned childIdx = node->firstChild();844 childIdx < node->firstChild() + node->numChildren();845 childIdx++) {846 if (!!m_graph.m_varArgChildren[childIdx])847 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);848 }849 } else {850 if (!node->child1())851 return changed;852 changed |= node->child1()->mergeFlags(NodeUsedAsValue);853 if (!node->child2())854 return changed;855 changed |= node->child2()->mergeFlags(NodeUsedAsValue);856 if (!node->child3())857 return changed;858 changed |= node->child3()->mergeFlags(NodeUsedAsValue);859 }860 return changed;861 }862 863 550 void propagateForward() 864 551 {
Note:
See TracChangeset
for help on using the changeset viewer.