| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * [InvokeDynamicSpecializer] and its subclasses are helpers to | 8 * [InvokeDynamicSpecializer] and its subclasses are helpers to |
| 9 * optimize intercepted dynamic calls. It knows what input types | 9 * optimize intercepted dynamic calls. It knows what input types |
| 10 * would be beneficial for performance, and how to change a invoke | 10 * would be beneficial for performance, and how to change a invoke |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 } else if (selector.name == const SourceString('>>')) { | 58 } else if (selector.name == const SourceString('>>')) { |
| 59 return const ShiftRightSpecializer(); | 59 return const ShiftRightSpecializer(); |
| 60 } else if (selector.name == const SourceString('<<')) { | 60 } else if (selector.name == const SourceString('<<')) { |
| 61 return const ShiftLeftSpecializer(); | 61 return const ShiftLeftSpecializer(); |
| 62 } else if (selector.name == const SourceString('&')) { | 62 } else if (selector.name == const SourceString('&')) { |
| 63 return const BitAndSpecializer(); | 63 return const BitAndSpecializer(); |
| 64 } else if (selector.name == const SourceString('|')) { | 64 } else if (selector.name == const SourceString('|')) { |
| 65 return const BitOrSpecializer(); | 65 return const BitOrSpecializer(); |
| 66 } else if (selector.name == const SourceString('^')) { | 66 } else if (selector.name == const SourceString('^')) { |
| 67 return const BitXorSpecializer(); | 67 return const BitXorSpecializer(); |
| 68 } else if (selector.name == const SourceString('==')) { |
| 69 return const EqualsSpecializer(); |
| 70 } else if (selector.name == const SourceString('<')) { |
| 71 return const LessSpecializer(); |
| 72 } else if (selector.name == const SourceString('<=')) { |
| 73 return const LessEqualSpecializer(); |
| 74 } else if (selector.name == const SourceString('>')) { |
| 75 return const GreaterSpecializer(); |
| 76 } else if (selector.name == const SourceString('>=')) { |
| 77 return const GreaterEqualSpecializer(); |
| 68 } | 78 } |
| 69 } | 79 } |
| 70 return const InvokeDynamicSpecializer(); | 80 return const InvokeDynamicSpecializer(); |
| 71 } | 81 } |
| 72 } | 82 } |
| 73 | 83 |
| 74 class IndexAssignSpecializer extends InvokeDynamicSpecializer { | 84 class IndexAssignSpecializer extends InvokeDynamicSpecializer { |
| 75 const IndexAssignSpecializer(); | 85 const IndexAssignSpecializer(); |
| 76 | 86 |
| 77 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, | 87 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 const BitXorSpecializer(); | 479 const BitXorSpecializer(); |
| 470 | 480 |
| 471 BinaryOperation operation(ConstantSystem constantSystem) { | 481 BinaryOperation operation(ConstantSystem constantSystem) { |
| 472 return constantSystem.bitXor; | 482 return constantSystem.bitXor; |
| 473 } | 483 } |
| 474 | 484 |
| 475 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { | 485 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { |
| 476 return new HBitXor(left, right); | 486 return new HBitXor(left, right); |
| 477 } | 487 } |
| 478 } | 488 } |
| 489 |
| 490 class RelationalSpecializer extends InvokeDynamicSpecializer { |
| 491 const RelationalSpecializer(); |
| 492 |
| 493 HType computeTypeFromInputTypes(HInvokeDynamicMethod instruction, |
| 494 HTypeMap types, |
| 495 Compiler compiler) { |
| 496 if (types[instruction.inputs[1]].isPrimitiveOrNull()) return HType.BOOLEAN; |
| 497 return HType.UNKNOWN; |
| 498 } |
| 499 |
| 500 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, |
| 501 HInstruction input, |
| 502 HTypeMap types, |
| 503 Compiler compiler) { |
| 504 if (input == instruction.inputs[0]) return HType.UNKNOWN; |
| 505 HType propagatedType = types[instruction]; |
| 506 // For all relational operations except HIdentity, we expect to get numbers |
| 507 // only. With numbers the outgoing type is a boolean. If something else |
| 508 // is desired, then numbers are incorrect, though. |
| 509 if (propagatedType.isUnknown() || propagatedType.isBoolean()) { |
| 510 HInstruction left = instruction.inputs[1]; |
| 511 if (left.isTypeUnknown(types) || left.isNumber(types)) { |
| 512 return HType.NUMBER; |
| 513 } |
| 514 } |
| 515 return HType.UNKNOWN; |
| 516 } |
| 517 |
| 518 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, |
| 519 HTypeMap types) { |
| 520 HInstruction left = instruction.inputs[1]; |
| 521 HInstruction right = instruction.inputs[2]; |
| 522 if (left.isNumber(types) && right.isNumber(types)) { |
| 523 return newBuiltinVariant(left, right); |
| 524 } |
| 525 return null; |
| 526 } |
| 527 |
| 528 HInstruction newBuiltinVariant(HInstruction left, HInstruction right); |
| 529 } |
| 530 |
| 531 class EqualsSpecializer extends RelationalSpecializer { |
| 532 const EqualsSpecializer(); |
| 533 |
| 534 HType computeDesiredTypeForInput(HInvokeDynamicMethod instruction, |
| 535 HInstruction input, |
| 536 HTypeMap types, |
| 537 Compiler compiler) { |
| 538 HInstruction left = instruction.inputs[1]; |
| 539 HInstruction right = instruction.inputs[2]; |
| 540 HType propagatedType = types[instruction]; |
| 541 if (input == left && types[right].isUseful()) { |
| 542 // All our useful types have 'identical' semantics. But we don't want to |
| 543 // speculatively test for all possible types. Therefore we try to match |
| 544 // the two types. That is, if we see x == 3, then we speculatively test |
| 545 // if x is a number and bailout if it isn't. |
| 546 // If right is a number we don't need more than a number (no need to match |
| 547 // the exact type of right). |
| 548 if (right.isNumber(types)) return HType.NUMBER; |
| 549 return types[right]; |
| 550 } |
| 551 // String equality testing is much more common than array equality testing. |
| 552 if (input == left && left.isIndexablePrimitive(types)) { |
| 553 return HType.READABLE_ARRAY; |
| 554 } |
| 555 // String equality testing is much more common than array equality testing. |
| 556 if (input == right && right.isIndexablePrimitive(types)) { |
| 557 return HType.STRING; |
| 558 } |
| 559 return HType.UNKNOWN; |
| 560 } |
| 561 |
| 562 HInstruction tryConvertToBuiltin(HInvokeDynamicMethod instruction, |
| 563 HTypeMap types) { |
| 564 HInstruction left = instruction.inputs[1]; |
| 565 HInstruction right = instruction.inputs[2]; |
| 566 if (types[left].isPrimitiveOrNull() || right.isConstantNull()) { |
| 567 return newBuiltinVariant(left, right); |
| 568 } |
| 569 return null; |
| 570 } |
| 571 |
| 572 BinaryOperation operation(ConstantSystem constantSystem) { |
| 573 return constantSystem.equal; |
| 574 } |
| 575 |
| 576 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { |
| 577 return new HIdentity(left, right); |
| 578 } |
| 579 } |
| 580 |
| 581 class LessSpecializer extends RelationalSpecializer { |
| 582 const LessSpecializer(); |
| 583 |
| 584 BinaryOperation operation(ConstantSystem constantSystem) { |
| 585 return constantSystem.less; |
| 586 } |
| 587 |
| 588 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { |
| 589 return new HLess(left, right); |
| 590 } |
| 591 } |
| 592 |
| 593 class GreaterSpecializer extends RelationalSpecializer { |
| 594 const GreaterSpecializer(); |
| 595 |
| 596 BinaryOperation operation(ConstantSystem constantSystem) { |
| 597 return constantSystem.greater; |
| 598 } |
| 599 |
| 600 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { |
| 601 return new HGreater(left, right); |
| 602 } |
| 603 } |
| 604 |
| 605 class GreaterEqualSpecializer extends RelationalSpecializer { |
| 606 const GreaterEqualSpecializer(); |
| 607 |
| 608 BinaryOperation operation(ConstantSystem constantSystem) { |
| 609 return constantSystem.greaterEqual; |
| 610 } |
| 611 |
| 612 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { |
| 613 return new HGreaterEqual(left, right); |
| 614 } |
| 615 } |
| 616 |
| 617 class LessEqualSpecializer extends RelationalSpecializer { |
| 618 const LessEqualSpecializer(); |
| 619 |
| 620 BinaryOperation operation(ConstantSystem constantSystem) { |
| 621 return constantSystem.lessEqual; |
| 622 } |
| 623 |
| 624 HInstruction newBuiltinVariant(HInstruction left, HInstruction right) { |
| 625 return new HLessEqual(left, right); |
| 626 } |
| 627 } |
| OLD | NEW |