| 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 // integer or throw an error. | 135 // integer or throw an error. |
| 136 JavaScriptBackend backend = compiler.backend; | 136 JavaScriptBackend backend = compiler.backend; |
| 137 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) { | 137 if (instruction.inputs[1].isPrimitiveOrNull(compiler)) { |
| 138 return backend.uint32Type; | 138 return backend.uint32Type; |
| 139 } | 139 } |
| 140 return super.computeTypeFromInputTypes(instruction, compiler); | 140 return super.computeTypeFromInputTypes(instruction, compiler); |
| 141 } | 141 } |
| 142 | 142 |
| 143 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 143 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 144 Compiler compiler) { | 144 Compiler compiler) { |
| 145 JavaScriptBackend backend = compiler.backend; | |
| 146 HInstruction input = instruction.inputs[1]; | 145 HInstruction input = instruction.inputs[1]; |
| 147 if (input.isNumber(compiler)) { | 146 if (input.isNumber(compiler)) { |
| 148 return new HBitNot(input, instruction.selector, | 147 return new HBitNot(input, instruction.selector, |
| 149 computeTypeFromInputTypes(instruction, compiler)); | 148 computeTypeFromInputTypes(instruction, compiler)); |
| 150 } | 149 } |
| 151 return null; | 150 return null; |
| 152 } | 151 } |
| 153 } | 152 } |
| 154 | 153 |
| 155 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { | 154 class UnaryNegateSpecializer extends InvokeDynamicSpecializer { |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 } | 409 } |
| 411 if (left.isUInt32(compiler) && isTwoOrGreater(right, compiler)) { | 410 if (left.isUInt32(compiler) && isTwoOrGreater(right, compiler)) { |
| 412 return true; | 411 return true; |
| 413 } | 412 } |
| 414 } | 413 } |
| 415 return false; | 414 return false; |
| 416 } | 415 } |
| 417 | 416 |
| 418 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 417 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 419 Compiler compiler) { | 418 Compiler compiler) { |
| 420 HInstruction left = instruction.inputs[1]; | |
| 421 HInstruction right = instruction.inputs[2]; | 419 HInstruction right = instruction.inputs[2]; |
| 422 if (isBuiltin(instruction, compiler)) { | 420 if (isBuiltin(instruction, compiler)) { |
| 423 if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { | 421 if (right.isPositiveInteger(compiler) && isNotZero(right, compiler)) { |
| 424 if (hasUint31Result(instruction, compiler)) { | 422 if (hasUint31Result(instruction, compiler)) { |
| 425 return newBuiltinVariant(instruction, compiler); | 423 return newBuiltinVariant(instruction, compiler); |
| 426 } | 424 } |
| 427 // We can call _tdivFast because the rhs is a 32bit integer | 425 // We can call _tdivFast because the rhs is a 32bit integer |
| 428 // and not 0, nor -1. | 426 // and not 0, nor -1. |
| 429 instruction.selector = renameToOptimizedSelector( | 427 instruction.selector = renameToOptimizedSelector( |
| 430 '_tdivFast', instruction.selector, compiler); | 428 '_tdivFast', instruction.selector, compiler); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 HInstruction left = instruction.inputs[1]; | 482 HInstruction left = instruction.inputs[1]; |
| 485 HInstruction right = instruction.inputs[2]; | 483 HInstruction right = instruction.inputs[2]; |
| 486 if (left.isNumber(compiler)) { | 484 if (left.isNumber(compiler)) { |
| 487 if (argumentLessThan32(right)) { | 485 if (argumentLessThan32(right)) { |
| 488 return newBuiltinVariant(instruction, compiler); | 486 return newBuiltinVariant(instruction, compiler); |
| 489 } | 487 } |
| 490 // Even if there is no builtin equivalent instruction, we know | 488 // Even if there is no builtin equivalent instruction, we know |
| 491 // the instruction does not have any side effect, and that it | 489 // the instruction does not have any side effect, and that it |
| 492 // can be GVN'ed. | 490 // can be GVN'ed. |
| 493 clearAllSideEffects(instruction); | 491 clearAllSideEffects(instruction); |
| 494 Selector selector = instruction.selector; | |
| 495 if (isPositive(right, compiler)) { | 492 if (isPositive(right, compiler)) { |
| 496 instruction.selector = renameToOptimizedSelector( | 493 instruction.selector = renameToOptimizedSelector( |
| 497 '_shlPositive', instruction.selector, compiler); | 494 '_shlPositive', instruction.selector, compiler); |
| 498 } | 495 } |
| 499 } | 496 } |
| 500 return null; | 497 return null; |
| 501 } | 498 } |
| 502 | 499 |
| 503 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 500 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 504 Compiler compiler) { | 501 Compiler compiler) { |
| 505 JavaScriptBackend backend = compiler.backend; | |
| 506 return new HShiftLeft( | 502 return new HShiftLeft( |
| 507 instruction.inputs[1], instruction.inputs[2], | 503 instruction.inputs[1], instruction.inputs[2], |
| 508 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 504 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); |
| 509 } | 505 } |
| 510 } | 506 } |
| 511 | 507 |
| 512 class ShiftRightSpecializer extends BinaryBitOpSpecializer { | 508 class ShiftRightSpecializer extends BinaryBitOpSpecializer { |
| 513 const ShiftRightSpecializer(); | 509 const ShiftRightSpecializer(); |
| 514 | 510 |
| 515 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, | 511 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
| 516 Compiler compiler) { | 512 Compiler compiler) { |
| 517 HInstruction left = instruction.inputs[1]; | 513 HInstruction left = instruction.inputs[1]; |
| 518 HInstruction right = instruction.inputs[2]; | |
| 519 JavaScriptBackend backend = compiler.backend; | |
| 520 if (left.isUInt32(compiler)) return left.instructionType; | 514 if (left.isUInt32(compiler)) return left.instructionType; |
| 521 return super.computeTypeFromInputTypes(instruction, compiler); | 515 return super.computeTypeFromInputTypes(instruction, compiler); |
| 522 } | 516 } |
| 523 | 517 |
| 524 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 518 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 525 Compiler compiler) { | 519 Compiler compiler) { |
| 526 HInstruction left = instruction.inputs[1]; | 520 HInstruction left = instruction.inputs[1]; |
| 527 HInstruction right = instruction.inputs[2]; | 521 HInstruction right = instruction.inputs[2]; |
| 528 if (left.isNumber(compiler)) { | 522 if (left.isNumber(compiler)) { |
| 529 if (argumentLessThan32(right) && isPositive(left, compiler)) { | 523 if (argumentLessThan32(right) && isPositive(left, compiler)) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 542 } else if (isPositive(right, compiler)) { | 536 } else if (isPositive(right, compiler)) { |
| 543 instruction.selector = renameToOptimizedSelector( | 537 instruction.selector = renameToOptimizedSelector( |
| 544 '_shrOtherPositive', instruction.selector, compiler); | 538 '_shrOtherPositive', instruction.selector, compiler); |
| 545 } | 539 } |
| 546 } | 540 } |
| 547 return null; | 541 return null; |
| 548 } | 542 } |
| 549 | 543 |
| 550 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 544 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 551 Compiler compiler) { | 545 Compiler compiler) { |
| 552 JavaScriptBackend backend = compiler.backend; | |
| 553 return new HShiftRight( | 546 return new HShiftRight( |
| 554 instruction.inputs[1], instruction.inputs[2], | 547 instruction.inputs[1], instruction.inputs[2], |
| 555 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 548 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); |
| 556 } | 549 } |
| 557 | 550 |
| 558 BinaryOperation operation(ConstantSystem constantSystem) { | 551 BinaryOperation operation(ConstantSystem constantSystem) { |
| 559 return constantSystem.shiftRight; | 552 return constantSystem.shiftRight; |
| 560 } | 553 } |
| 561 } | 554 } |
| 562 | 555 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 573 HInstruction right = instruction.inputs[2]; | 566 HInstruction right = instruction.inputs[2]; |
| 574 JavaScriptBackend backend = compiler.backend; | 567 JavaScriptBackend backend = compiler.backend; |
| 575 if (left.isUInt31(compiler) && right.isUInt31(compiler)) { | 568 if (left.isUInt31(compiler) && right.isUInt31(compiler)) { |
| 576 return backend.uint31Type; | 569 return backend.uint31Type; |
| 577 } | 570 } |
| 578 return super.computeTypeFromInputTypes(instruction, compiler); | 571 return super.computeTypeFromInputTypes(instruction, compiler); |
| 579 } | 572 } |
| 580 | 573 |
| 581 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 574 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 582 Compiler compiler) { | 575 Compiler compiler) { |
| 583 JavaScriptBackend backend = compiler.backend; | |
| 584 return new HBitOr( | 576 return new HBitOr( |
| 585 instruction.inputs[1], instruction.inputs[2], | 577 instruction.inputs[1], instruction.inputs[2], |
| 586 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 578 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); |
| 587 } | 579 } |
| 588 } | 580 } |
| 589 | 581 |
| 590 class BitAndSpecializer extends BinaryBitOpSpecializer { | 582 class BitAndSpecializer extends BinaryBitOpSpecializer { |
| 591 const BitAndSpecializer(); | 583 const BitAndSpecializer(); |
| 592 | 584 |
| 593 BinaryOperation operation(ConstantSystem constantSystem) { | 585 BinaryOperation operation(ConstantSystem constantSystem) { |
| 594 return constantSystem.bitAnd; | 586 return constantSystem.bitAnd; |
| 595 } | 587 } |
| 596 | 588 |
| 597 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, | 589 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
| 598 Compiler compiler) { | 590 Compiler compiler) { |
| 599 HInstruction left = instruction.inputs[1]; | 591 HInstruction left = instruction.inputs[1]; |
| 600 HInstruction right = instruction.inputs[2]; | 592 HInstruction right = instruction.inputs[2]; |
| 601 JavaScriptBackend backend = compiler.backend; | 593 JavaScriptBackend backend = compiler.backend; |
| 602 if (left.isPrimitiveOrNull(compiler) && | 594 if (left.isPrimitiveOrNull(compiler) && |
| 603 (left.isUInt31(compiler) || right.isUInt31(compiler))) { | 595 (left.isUInt31(compiler) || right.isUInt31(compiler))) { |
| 604 return backend.uint31Type; | 596 return backend.uint31Type; |
| 605 } | 597 } |
| 606 return super.computeTypeFromInputTypes(instruction, compiler); | 598 return super.computeTypeFromInputTypes(instruction, compiler); |
| 607 } | 599 } |
| 608 | 600 |
| 609 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 601 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 610 Compiler compiler) { | 602 Compiler compiler) { |
| 611 JavaScriptBackend backend = compiler.backend; | |
| 612 return new HBitAnd( | 603 return new HBitAnd( |
| 613 instruction.inputs[1], instruction.inputs[2], | 604 instruction.inputs[1], instruction.inputs[2], |
| 614 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 605 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); |
| 615 } | 606 } |
| 616 } | 607 } |
| 617 | 608 |
| 618 class BitXorSpecializer extends BinaryBitOpSpecializer { | 609 class BitXorSpecializer extends BinaryBitOpSpecializer { |
| 619 const BitXorSpecializer(); | 610 const BitXorSpecializer(); |
| 620 | 611 |
| 621 BinaryOperation operation(ConstantSystem constantSystem) { | 612 BinaryOperation operation(ConstantSystem constantSystem) { |
| 622 return constantSystem.bitXor; | 613 return constantSystem.bitXor; |
| 623 } | 614 } |
| 624 | 615 |
| 625 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, | 616 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
| 626 Compiler compiler) { | 617 Compiler compiler) { |
| 627 HInstruction left = instruction.inputs[1]; | 618 HInstruction left = instruction.inputs[1]; |
| 628 HInstruction right = instruction.inputs[2]; | 619 HInstruction right = instruction.inputs[2]; |
| 629 JavaScriptBackend backend = compiler.backend; | 620 JavaScriptBackend backend = compiler.backend; |
| 630 if (left.isUInt31(compiler) && right.isUInt31(compiler)) { | 621 if (left.isUInt31(compiler) && right.isUInt31(compiler)) { |
| 631 return backend.uint31Type; | 622 return backend.uint31Type; |
| 632 } | 623 } |
| 633 return super.computeTypeFromInputTypes(instruction, compiler); | 624 return super.computeTypeFromInputTypes(instruction, compiler); |
| 634 } | 625 } |
| 635 | 626 |
| 636 HInstruction newBuiltinVariant(HInvokeDynamic instruction, | 627 HInstruction newBuiltinVariant(HInvokeDynamic instruction, |
| 637 Compiler compiler) { | 628 Compiler compiler) { |
| 638 JavaScriptBackend backend = compiler.backend; | |
| 639 return new HBitXor( | 629 return new HBitXor( |
| 640 instruction.inputs[1], instruction.inputs[2], | 630 instruction.inputs[1], instruction.inputs[2], |
| 641 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); | 631 instruction.selector, computeTypeFromInputTypes(instruction, compiler)); |
| 642 } | 632 } |
| 643 } | 633 } |
| 644 | 634 |
| 645 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { | 635 abstract class RelationalSpecializer extends InvokeDynamicSpecializer { |
| 646 const RelationalSpecializer(); | 636 const RelationalSpecializer(); |
| 647 | 637 |
| 648 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, | 638 TypeMask computeTypeFromInputTypes(HInvokeDynamic instruction, |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 return constantSystem.codeUnitAt; | 766 return constantSystem.codeUnitAt; |
| 777 } | 767 } |
| 778 | 768 |
| 779 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, | 769 HInstruction tryConvertToBuiltin(HInvokeDynamic instruction, |
| 780 Compiler compiler) { | 770 Compiler compiler) { |
| 781 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index | 771 // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index |
| 782 // bounds checking optimizations as for HIndex. | 772 // bounds checking optimizations as for HIndex. |
| 783 return null; | 773 return null; |
| 784 } | 774 } |
| 785 } | 775 } |
| OLD | NEW |