Changeset 155567 in webkit
- Timestamp:
- Sep 11, 2013 2:49:47 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r155554 r155567 1 2013-09-10 Filip Pizlo <fpizlo@apple.com> 2 3 Int32ToDouble should be predicted SpecInt48 and predictions should have nothing to do with constant folding 4 https://bugs.webkit.org/show_bug.cgi?id=121141 5 6 Reviewed by Oliver Hunt. 7 8 Fixing this means that this test no longer recompiles. 9 10 * js/script-tests/dfg-constant-fold-misprediction.js: 11 1 12 2013-09-11 Myles C. Maxfield <mmaxfield@apple.com> 2 13 -
trunk/LayoutTests/js/script-tests/dfg-constant-fold-misprediction.js
r155201 r155567 35 35 36 36 // Call foo() enough times to make it optimize three times. 37 for (var i = 0; i < 2; i = dfgIncrement({f:foo, i:i + 1, n:1, compiles:2})) 37 // NOTE: We no longer recompile this three times. 38 for (var i = 0; i < 2; i = dfgIncrement({f:foo, i:i + 1, n:1})) 38 39 shouldBe("foo(0.5)", "1000.50025"); 39 40 -
trunk/Source/JavaScriptCore/ChangeLog
r155564 r155567 1 2013-09-11 Filip Pizlo <fpizlo@apple.com> 2 3 Int32ToDouble should be predicted SpecInt48 and predictions should have nothing to do with constant folding 4 https://bugs.webkit.org/show_bug.cgi?id=121141 5 6 Reviewed by Oliver Hunt. 7 8 Just changing Int32ToDouble to be predicted SpecInt48 breaks constant folding on that 9 node because of soooper old code that prevented constant folding on mismatched 10 predictions. Kill that code. 11 12 * dfg/DFGAbstractInterpreter.h: 13 (JSC::DFG::AbstractInterpreter::setConstant): 14 * dfg/DFGAbstractInterpreterInlines.h: 15 (JSC::DFG::::executeEffects): 16 * dfg/DFGFixupPhase.cpp: 17 (JSC::DFG::FixupPhase::injectInt32ToDoubleNode): 18 1 19 2013-09-10 Filip Pizlo <fpizlo@apple.com> 2 20 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h
r154290 r155567 160 160 BooleanResult booleanResult(Node*, AbstractValue&); 161 161 162 bool trySetConstant(Node* node, JSValue value)162 void setConstant(Node* node, JSValue value) 163 163 { 164 // Make sure we don't constant fold something that will produce values that contravene165 // predictions. If that happens then we know that the code will OSR exit, forcing166 // recompilation. But if we tried to constant fold then we'll have a very degenerate167 // IR: namely we'll have a JSConstant that contravenes its own prediction. There's a168 // lot of subtle code that assumes that169 // speculationFromValue(jsConstant) == jsConstant.prediction(). "Hardening" that code170 // is probably less sane than just pulling back on constant folding.171 SpeculatedType oldType = node->prediction();172 if (mergeSpeculations(speculationFromValue(value), oldType) != oldType)173 return false;174 175 164 forNode(node).set(m_graph, value); 176 return true;165 m_state.setFoundConstants(true); 177 166 } 178 167 -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r155497 r155567 224 224 int32_t a = left.asInt32(); 225 225 int32_t b = right.asInt32(); 226 bool constantWasSet;227 226 switch (node->op()) { 228 227 case BitAnd: 229 constantWasSet = trySetConstant(node, JSValue(a & b));228 setConstant(node, JSValue(a & b)); 230 229 break; 231 230 case BitOr: 232 constantWasSet = trySetConstant(node, JSValue(a | b));231 setConstant(node, JSValue(a | b)); 233 232 break; 234 233 case BitXor: 235 constantWasSet = trySetConstant(node, JSValue(a ^ b));234 setConstant(node, JSValue(a ^ b)); 236 235 break; 237 236 case BitRShift: 238 constantWasSet = trySetConstant(node, JSValue(a >> static_cast<uint32_t>(b)));237 setConstant(node, JSValue(a >> static_cast<uint32_t>(b))); 239 238 break; 240 239 case BitLShift: 241 constantWasSet = trySetConstant(node, JSValue(a << static_cast<uint32_t>(b)));240 setConstant(node, JSValue(a << static_cast<uint32_t>(b))); 242 241 break; 243 242 case BitURShift: 244 constantWasSet = trySetConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b)));243 setConstant(node, JSValue(static_cast<uint32_t>(a) >> static_cast<uint32_t>(b))); 245 244 break; 246 245 default: 247 246 RELEASE_ASSERT_NOT_REACHED(); 248 constantWasSet = false;247 break; 249 248 } 250 if (constantWasSet) { 251 m_state.setFoundConstants(true); 252 break; 253 } 249 break; 254 250 } 255 251 forNode(node).setType(SpecInt32); … … 261 257 if (child && child.isNumber()) { 262 258 ASSERT(child.isInt32()); 263 if (trySetConstant(node, JSValue(child.asUInt32()))) { 264 m_state.setFoundConstants(true); 265 break; 266 } 259 setConstant(node, JSValue(child.asUInt32())); 260 break; 267 261 } 268 262 if (!node->canSpeculateInt32()) … … 280 274 double asDouble = child.asNumber(); 281 275 int32_t asInt = JSC::toInt32(asDouble); 282 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble) 283 && trySetConstant(node, JSValue(asInt))) { 284 m_state.setFoundConstants(true); 276 if (bitwise_cast<int64_t>(static_cast<double>(asInt)) == bitwise_cast<int64_t>(asDouble)) { 277 setConstant(node, JSValue(asInt)); 285 278 break; 286 279 } … … 294 287 JSValue child = forNode(node->child1()).value(); 295 288 if (child && child.isNumber()) { 296 bool constantWasSet;297 289 if (child.isInt32()) 298 constantWasSet = trySetConstant(node, child);290 setConstant(node, child); 299 291 else 300 constantWasSet = trySetConstant(node, JSValue(JSC::toInt32(child.asDouble()))); 301 if (constantWasSet) { 302 m_state.setFoundConstants(true); 303 break; 304 } 292 setConstant(node, JSValue(JSC::toInt32(child.asDouble()))); 293 break; 305 294 } 306 295 … … 311 300 case Int32ToDouble: { 312 301 JSValue child = forNode(node->child1()).value(); 313 if (child && child.isNumber() 314 && trySetConstant(node, JSValue(JSValue::EncodeAsDouble, child.asNumber()))) { 315 m_state.setFoundConstants(true); 302 if (child && child.isNumber()) { 303 setConstant(node, JSValue(JSValue::EncodeAsDouble, child.asNumber())); 316 304 break; 317 305 } … … 327 315 JSValue left = forNode(node->child1()).value(); 328 316 JSValue right = forNode(node->child2()).value(); 329 if (left && right && left.isNumber() && right.isNumber() 330 && trySetConstant(node, JSValue(left.asNumber() + right.asNumber()))) { 331 m_state.setFoundConstants(true); 317 if (left && right && left.isNumber() && right.isNumber()) { 318 setConstant(node, JSValue(left.asNumber() + right.asNumber())); 332 319 break; 333 320 } … … 362 349 JSValue left = forNode(node->child1()).value(); 363 350 JSValue right = forNode(node->child2()).value(); 364 if (left && right && left.isNumber() && right.isNumber() 365 && trySetConstant(node, JSValue(left.asNumber() - right.asNumber()))) { 366 m_state.setFoundConstants(true); 351 if (left && right && left.isNumber() && right.isNumber()) { 352 setConstant(node, JSValue(left.asNumber() - right.asNumber())); 367 353 break; 368 354 } … … 385 371 case ArithNegate: { 386 372 JSValue child = forNode(node->child1()).value(); 387 if (child && child.isNumber() 388 && trySetConstant(node, JSValue(-child.asNumber()))) { 389 m_state.setFoundConstants(true); 373 if (child && child.isNumber()) { 374 setConstant(node, JSValue(-child.asNumber())); 390 375 break; 391 376 } … … 409 394 JSValue left = forNode(node->child1()).value(); 410 395 JSValue right = forNode(node->child2()).value(); 411 if (left && right && left.isNumber() && right.isNumber() 412 && trySetConstant(node, JSValue(left.asNumber() * right.asNumber()))) { 413 m_state.setFoundConstants(true); 396 if (left && right && left.isNumber() && right.isNumber()) { 397 setConstant(node, JSValue(left.asNumber() * right.asNumber())); 414 398 break; 415 399 } … … 446 430 JSValue left = forNode(node->child1()).value(); 447 431 JSValue right = forNode(node->child2()).value(); 448 if (node->op() == ArithMod && right && right.isNumber() && right.asNumber() == 1 449 && trySetConstant(node, JSValue(0))) { 450 m_state.setFoundConstants(true); 432 if (node->op() == ArithMod && right && right.isNumber() && right.asNumber() == 1) { 433 setConstant(node, JSValue(0)); 451 434 break; 452 435 } … … 454 437 double a = left.asNumber(); 455 438 double b = right.asNumber(); 456 bool constantWasSet;457 439 switch (node->op()) { 458 440 case ArithDiv: 459 constantWasSet = trySetConstant(node, JSValue(a / b));441 setConstant(node, JSValue(a / b)); 460 442 break; 461 443 case ArithMin: 462 constantWasSet = trySetConstant(node, JSValue(a < b ? a : (b <= a ? b : a + b)));444 setConstant(node, JSValue(a < b ? a : (b <= a ? b : a + b))); 463 445 break; 464 446 case ArithMax: 465 constantWasSet = trySetConstant(node, JSValue(a > b ? a : (b >= a ? b : a + b)));447 setConstant(node, JSValue(a > b ? a : (b >= a ? b : a + b))); 466 448 break; 467 449 case ArithMod: 468 constantWasSet = trySetConstant(node, JSValue(fmod(a, b)));450 setConstant(node, JSValue(fmod(a, b))); 469 451 break; 470 452 default: 471 453 RELEASE_ASSERT_NOT_REACHED(); 472 constantWasSet = false;473 454 break; 474 455 } 475 if (constantWasSet) { 476 m_state.setFoundConstants(true); 477 break; 478 } 456 break; 479 457 } 480 458 switch (node->binaryUseKind()) { … … 495 473 case ArithAbs: { 496 474 JSValue child = forNode(node->child1()).value(); 497 if (child && child.isNumber() 498 && trySetConstant(node, JSValue(fabs(child.asNumber())))) { 499 m_state.setFoundConstants(true); 475 if (child && child.isNumber()) { 476 setConstant(node, JSValue(fabs(child.asNumber()))); 500 477 break; 501 478 } … … 517 494 case ArithSqrt: { 518 495 JSValue child = forNode(node->child1()).value(); 519 if (child && child.isNumber() 520 && trySetConstant(node, JSValue(sqrt(child.asNumber())))) { 521 m_state.setFoundConstants(true); 496 if (child && child.isNumber()) { 497 setConstant(node, JSValue(sqrt(child.asNumber()))); 522 498 break; 523 499 } … … 527 503 528 504 case LogicalNot: { 529 bool didSetConstant = false;530 505 switch (booleanResult(node, forNode(node->child1()))) { 531 506 case DefinitelyTrue: 532 didSetConstant = trySetConstant(node, jsBoolean(false));507 setConstant(node, jsBoolean(false)); 533 508 break; 534 509 case DefinitelyFalse: 535 didSetConstant = trySetConstant(node, jsBoolean(true));510 setConstant(node, jsBoolean(true)); 536 511 break; 537 512 default: 538 break; 539 } 540 if (didSetConstant) { 541 m_state.setFoundConstants(true); 542 break; 543 } 544 switch (node->child1().useKind()) { 545 case BooleanUse: 546 case Int32Use: 547 case NumberUse: 548 case UntypedUse: 549 break; 550 case ObjectOrOtherUse: 551 node->setCanExit(true); 552 break; 553 default: 554 RELEASE_ASSERT_NOT_REACHED(); 555 break; 556 } 557 forNode(node).setType(SpecBoolean); 513 switch (node->child1().useKind()) { 514 case BooleanUse: 515 case Int32Use: 516 case NumberUse: 517 case UntypedUse: 518 break; 519 case ObjectOrOtherUse: 520 node->setCanExit(true); 521 break; 522 default: 523 RELEASE_ASSERT_NOT_REACHED(); 524 break; 525 } 526 forNode(node).setType(SpecBoolean); 527 break; 528 } 558 529 break; 559 530 } … … 570 541 JSValue child = forNode(node->child1()).value(); 571 542 if (child) { 572 bool constantWasSet ;543 bool constantWasSet = true; 573 544 switch (node->op()) { 574 545 case IsUndefined: 575 constantWasSet = trySetConstant(node, jsBoolean(546 setConstant(node, jsBoolean( 576 547 child.isCell() 577 548 ? child.asCell()->structure()->masqueradesAsUndefined(m_codeBlock->globalObjectFor(node->codeOrigin)) … … 579 550 break; 580 551 case IsBoolean: 581 constantWasSet = trySetConstant(node, jsBoolean(child.isBoolean()));552 setConstant(node, jsBoolean(child.isBoolean())); 582 553 break; 583 554 case IsNumber: 584 constantWasSet = trySetConstant(node, jsBoolean(child.isNumber()));555 setConstant(node, jsBoolean(child.isNumber())); 585 556 break; 586 557 case IsString: 587 constantWasSet = trySetConstant(node, jsBoolean(isJSString(child)));558 setConstant(node, jsBoolean(isJSString(child))); 588 559 break; 589 560 case IsObject: 590 561 if (child.isNull() || !child.isObject()) { 591 constantWasSet = trySetConstant(node, jsBoolean(child.isNull()));562 setConstant(node, jsBoolean(child.isNull())); 592 563 break; 593 564 } 565 constantWasSet = false; 566 break; 594 567 default: 595 568 constantWasSet = false; 596 569 break; 597 570 } 598 if (constantWasSet) { 599 m_state.setFoundConstants(true); 600 break; 601 } 571 if (constantWasSet) 572 break; 602 573 } 603 574 … … 612 583 if (child) { 613 584 JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->codeOrigin), child); 614 if (trySetConstant(node, typeString)) { 615 m_state.setFoundConstants(true); 616 break; 617 } 618 } else if (isNumberSpeculation(abstractChild.m_type)) { 619 if (trySetConstant(node, vm->smallStrings.numberString())) { 620 filter(node->child1(), SpecNumber); 621 m_state.setFoundConstants(true); 622 break; 623 } 624 } else if (isStringSpeculation(abstractChild.m_type)) { 625 if (trySetConstant(node, vm->smallStrings.stringString())) { 626 filter(node->child1(), SpecString); 627 m_state.setFoundConstants(true); 628 break; 629 } 630 } else if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) { 631 if (trySetConstant(node, vm->smallStrings.objectString())) { 632 filter(node->child1(), SpecFinalObject | SpecArray | SpecArguments); 633 m_state.setFoundConstants(true); 634 break; 635 } 636 } else if (isFunctionSpeculation(abstractChild.m_type)) { 637 if (trySetConstant(node, vm->smallStrings.functionString())) { 638 filter(node->child1(), SpecFunction); 639 m_state.setFoundConstants(true); 640 break; 641 } 642 } else if (isBooleanSpeculation(abstractChild.m_type)) { 643 if (trySetConstant(node, vm->smallStrings.booleanString())) { 644 filter(node->child1(), SpecBoolean); 645 m_state.setFoundConstants(true); 646 break; 647 } 585 setConstant(node, typeString); 586 break; 587 } 588 589 if (isNumberSpeculation(abstractChild.m_type)) { 590 setConstant(node, vm->smallStrings.numberString()); 591 break; 592 } 593 594 if (isStringSpeculation(abstractChild.m_type)) { 595 setConstant(node, vm->smallStrings.stringString()); 596 break; 597 } 598 599 if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) { 600 setConstant(node, vm->smallStrings.objectString()); 601 break; 602 } 603 604 if (isFunctionSpeculation(abstractChild.m_type)) { 605 setConstant(node, vm->smallStrings.functionString()); 606 break; 607 } 608 609 if (isBooleanSpeculation(abstractChild.m_type)) { 610 setConstant(node, vm->smallStrings.booleanString()); 611 break; 648 612 } 649 613 … … 669 633 case CompareEq: 670 634 case CompareEqConstant: { 671 bool constantWasSet = false;672 673 635 JSValue leftConst = forNode(node->child1()).value(); 674 636 JSValue rightConst = forNode(node->child2()).value(); … … 679 641 switch (node->op()) { 680 642 case CompareLess: 681 constantWasSet = trySetConstant(node, jsBoolean(a < b));643 setConstant(node, jsBoolean(a < b)); 682 644 break; 683 645 case CompareLessEq: 684 constantWasSet = trySetConstant(node, jsBoolean(a <= b));646 setConstant(node, jsBoolean(a <= b)); 685 647 break; 686 648 case CompareGreater: 687 constantWasSet = trySetConstant(node, jsBoolean(a > b));649 setConstant(node, jsBoolean(a > b)); 688 650 break; 689 651 case CompareGreaterEq: 690 constantWasSet = trySetConstant(node, jsBoolean(a >= b));652 setConstant(node, jsBoolean(a >= b)); 691 653 break; 692 654 case CompareEq: 693 constantWasSet = trySetConstant(node, jsBoolean(a == b));655 setConstant(node, jsBoolean(a == b)); 694 656 break; 695 657 default: 696 658 RELEASE_ASSERT_NOT_REACHED(); 697 constantWasSet = false; 659 break; 660 } 661 break; 662 } 663 664 if (node->op() == CompareEq && leftConst.isString() && rightConst.isString()) { 665 const StringImpl* a = asString(leftConst)->tryGetValueImpl(); 666 const StringImpl* b = asString(rightConst)->tryGetValueImpl(); 667 if (a && b) { 668 setConstant(node, jsBoolean(WTF::equal(a, b))); 698 669 break; 699 670 } 700 671 } 701 702 if (!constantWasSet && node->op() == CompareEq 703 && leftConst.isString() && rightConst.isString()) { 704 const StringImpl* a = asString(leftConst)->tryGetValueImpl(); 705 const StringImpl* b = asString(rightConst)->tryGetValueImpl(); 706 if (a && b) 707 constantWasSet = trySetConstant(node, jsBoolean(WTF::equal(a, b))); 708 } 709 } 710 711 if (!constantWasSet && (node->op() == CompareEqConstant || node->op() == CompareEq)) { 672 } 673 674 if (node->op() == CompareEqConstant || node->op() == CompareEq) { 712 675 SpeculatedType leftType = forNode(node->child1()).m_type; 713 676 SpeculatedType rightType = forNode(node->child2()).m_type; 714 677 if ((isInt32Speculation(leftType) && isOtherSpeculation(rightType)) 715 || (isOtherSpeculation(leftType) && isInt32Speculation(rightType))) 716 constantWasSet = trySetConstant(node, jsBoolean(false)); 717 } 718 719 if (constantWasSet) { 720 m_state.setFoundConstants(true); 721 break; 678 || (isOtherSpeculation(leftType) && isInt32Speculation(rightType))) { 679 setConstant(node, jsBoolean(false)); 680 break; 681 } 722 682 } 723 683 … … 741 701 JSValue right = forNode(rightNode).value(); 742 702 if (left && right) { 743 if (left.isNumber() && right.isNumber() 744 && trySetConstant(node, jsBoolean(left.asNumber() == right.asNumber()))) { 745 m_state.setFoundConstants(true); 703 if (left.isNumber() && right.isNumber()) { 704 setConstant(node, jsBoolean(left.asNumber() == right.asNumber())); 746 705 break; 747 706 } … … 749 708 const StringImpl* a = asString(left)->tryGetValueImpl(); 750 709 const StringImpl* b = asString(right)->tryGetValueImpl(); 751 if (a && b && trySetConstant(node, jsBoolean(WTF::equal(a, b)))) {752 m_state.setFoundConstants(true);710 if (a && b) { 711 setConstant(node, jsBoolean(WTF::equal(a, b))); 753 712 break; 754 713 } … … 963 922 case ToPrimitive: { 964 923 JSValue childConst = forNode(node->child1()).value(); 965 if (childConst && childConst.isNumber() && trySetConstant(node, childConst)) {966 m_state.setFoundConstants(true);924 if (childConst && childConst.isNumber()) { 925 setConstant(node, childConst); 967 926 break; 968 927 } … … 1208 1167 case SkipScope: { 1209 1168 JSValue child = forNode(node->child1()).value(); 1210 if (child && trySetConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next()))) {1211 m_state.setFoundConstants(true);1169 if (child) { 1170 setConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next())); 1212 1171 break; 1213 1172 } … … 1247 1206 1248 1207 if (status.specificValue()) 1249 forNode(node).set(m_graph, status.specificValue());1208 setConstant(node, status.specificValue()); 1250 1209 else 1251 1210 forNode(node).makeHeapTop(); -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r155564 r155567 1371 1371 { 1372 1372 Node* result = m_insertionSet.insertNode( 1373 m_indexInBlock, Spec Double, Int32ToDouble,1373 m_indexInBlock, SpecInt48, Int32ToDouble, 1374 1374 m_currentNode->codeOrigin, Edge(edge.node(), NumberUse)); 1375 1375 if (direction == ForwardSpeculation)
Note: See TracChangeset
for help on using the changeset viewer.