|
157 | 157 | import com.oracle.truffle.api.library.CachedLibrary;
|
158 | 158 | import com.oracle.truffle.api.nodes.Node;
|
159 | 159 | import com.oracle.truffle.api.nodes.UnexpectedResultException;
|
| 160 | +import com.oracle.truffle.api.profiles.BranchProfile; |
160 | 161 | import com.oracle.truffle.api.profiles.InlinedBranchProfile;
|
161 | 162 | import com.oracle.truffle.api.profiles.InlinedConditionProfile;
|
162 | 163 | import com.oracle.truffle.api.profiles.InlinedIntValueProfile;
|
@@ -651,75 +652,72 @@ public static TrueDivNode create() {
|
651 | 652 | public abstract static class FloorDivNode extends BinaryOpBuiltinNode {
|
652 | 653 | public abstract Object execute(int left, int right);
|
653 | 654 |
|
| 655 | + private static final long INT_OVERFLOW_VALUE = (long) Integer.MAX_VALUE + 1; |
| 656 | + private static final BigInteger LONG_OVERFLOW_VALUE = BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE); |
| 657 | + |
654 | 658 | @Specialization
|
655 |
| - static int doII(int left, int right, |
| 659 | + static Object doII(int left, int right, |
656 | 660 | @Bind("this") Node inliningTarget,
|
657 | 661 | @Shared @Cached InlinedBranchProfile divisionByZeroProfile,
|
| 662 | + @Shared @Cached BranchProfile overflowValueProfile, |
658 | 663 | @Shared @Cached PRaiseNode.Lazy raiseNode) {
|
659 | 664 | raiseDivisionByZero(inliningTarget, right == 0, divisionByZeroProfile, raiseNode);
|
660 |
| - return Math.floorDiv(left, right); |
661 |
| - } |
662 |
| - |
663 |
| - @Specialization(rewriteOn = OverflowException.class) |
664 |
| - static long doLL(long left, long right, |
665 |
| - @Bind("this") Node inliningTarget, |
666 |
| - @Shared @Cached InlinedBranchProfile divisionByZeroProfile, |
667 |
| - @Shared @Cached PRaiseNode.Lazy raiseNode) throws OverflowException { |
668 |
| - if (left == Long.MIN_VALUE && right == -1) { |
669 |
| - throw OverflowException.INSTANCE; |
| 665 | + if (left == Integer.MIN_VALUE && right == -1) { |
| 666 | + overflowValueProfile.enter(); |
| 667 | + return INT_OVERFLOW_VALUE; |
670 | 668 | }
|
671 |
| - raiseDivisionByZero(inliningTarget, right == 0, divisionByZeroProfile, raiseNode); |
672 | 669 | return Math.floorDiv(left, right);
|
673 | 670 | }
|
674 | 671 |
|
675 |
| - @Specialization(replaces = "doLL") |
676 |
| - static PInt doLLOverflow(long left, long right, |
| 672 | + @Specialization |
| 673 | + static Object doLL(long left, long right, |
677 | 674 | @Bind("this") Node inliningTarget,
|
678 | 675 | @Shared @Cached InlinedBranchProfile divisionByZeroProfile,
|
| 676 | + @Shared @Cached BranchProfile overflowValueProfile, |
679 | 677 | @Shared @Cached PythonObjectFactory factory,
|
680 | 678 | @Shared @Cached PRaiseNode.Lazy raiseNode) {
|
681 |
| - return doPiPi(factory.createInt(left), factory.createInt(right), inliningTarget, divisionByZeroProfile, factory, raiseNode); |
682 |
| - } |
683 |
| - |
684 |
| - @Specialization(rewriteOn = OverflowException.class) |
685 |
| - static int doIPi(int left, PInt right, |
686 |
| - @Bind("this") Node inliningTarget, |
687 |
| - @Shared @Cached InlinedBranchProfile divisionByZeroProfile, |
688 |
| - @Shared @Cached PRaiseNode.Lazy raiseNode) throws OverflowException { |
689 |
| - raiseDivisionByZero(inliningTarget, right.isZero(), divisionByZeroProfile, raiseNode); |
690 |
| - return Math.floorDiv(left, right.intValueExact()); |
| 679 | + raiseDivisionByZero(inliningTarget, right == 0, divisionByZeroProfile, raiseNode); |
| 680 | + if (left == Long.MIN_VALUE && right == -1) { |
| 681 | + overflowValueProfile.enter(); |
| 682 | + return factory.createInt(LONG_OVERFLOW_VALUE); |
| 683 | + } |
| 684 | + return Math.floorDiv(left, right); |
691 | 685 | }
|
692 | 686 |
|
693 |
| - @Specialization(replaces = "doIPi") |
694 |
| - static int doIPiOvf(int left, PInt right, |
| 687 | + @Specialization |
| 688 | + static Object doIPi(int left, PInt right, |
695 | 689 | @Bind("this") Node inliningTarget,
|
696 | 690 | @Shared @Cached InlinedBranchProfile divisionByZeroProfile,
|
| 691 | + @Shared @Cached BranchProfile overflowValueProfile, |
697 | 692 | @Shared @Cached PRaiseNode.Lazy raiseNode) {
|
698 |
| - raiseDivisionByZero(inliningTarget, right.isZero(), divisionByZeroProfile, raiseNode); |
699 | 693 | try {
|
700 |
| - return Math.floorDiv(left, right.intValueExact()); |
| 694 | + int rightValue = right.intValueExact(); |
| 695 | + raiseDivisionByZero(inliningTarget, rightValue == 0, divisionByZeroProfile, raiseNode); |
| 696 | + if (left == Integer.MIN_VALUE && rightValue == -1) { |
| 697 | + overflowValueProfile.enter(); |
| 698 | + return INT_OVERFLOW_VALUE; |
| 699 | + } |
| 700 | + return Math.floorDiv(left, rightValue); |
701 | 701 | } catch (OverflowException e) {
|
702 | 702 | return left < 0 == right.isNegative() ? 0 : -1;
|
703 | 703 | }
|
704 | 704 | }
|
705 | 705 |
|
706 |
| - @Specialization(rewriteOn = OverflowException.class) |
707 |
| - static long doLPi(long left, PInt right, |
708 |
| - @Bind("this") Node inliningTarget, |
709 |
| - @Shared @Cached InlinedBranchProfile divisionByZeroProfile, |
710 |
| - @Shared @Cached PRaiseNode.Lazy raiseNode) throws OverflowException { |
711 |
| - raiseDivisionByZero(inliningTarget, right.isZero(), divisionByZeroProfile, raiseNode); |
712 |
| - return Math.floorDiv(left, right.longValueExact()); |
713 |
| - } |
714 |
| - |
715 |
| - @Specialization(replaces = "doLPi") |
716 |
| - static long doLPiOvf(long left, PInt right, |
| 706 | + @Specialization |
| 707 | + static Object doLPi(long left, PInt right, |
717 | 708 | @Bind("this") Node inliningTarget,
|
718 | 709 | @Shared @Cached InlinedBranchProfile divisionByZeroProfile,
|
| 710 | + @Shared @Cached BranchProfile overflowValueProfile, |
| 711 | + @Shared @Cached PythonObjectFactory factory, |
719 | 712 | @Shared @Cached PRaiseNode.Lazy raiseNode) {
|
720 |
| - raiseDivisionByZero(inliningTarget, right.isZero(), divisionByZeroProfile, raiseNode); |
721 | 713 | try {
|
722 |
| - return Math.floorDiv(left, right.longValueExact()); |
| 714 | + long rightValue = right.longValueExact(); |
| 715 | + raiseDivisionByZero(inliningTarget, rightValue == 0, divisionByZeroProfile, raiseNode); |
| 716 | + if (left == Long.MIN_VALUE && rightValue == -1) { |
| 717 | + overflowValueProfile.enter(); |
| 718 | + return factory.createInt(LONG_OVERFLOW_VALUE); |
| 719 | + } |
| 720 | + return Math.floorDiv(left, rightValue); |
723 | 721 | } catch (OverflowException e) {
|
724 | 722 | return left < 0 == right.isNegative() ? 0 : -1;
|
725 | 723 | }
|
|
0 commit comments