Skip to content

Commit e480a22

Browse files
committed
Fix corner cases in integer floordiv
1 parent a1e5431 commit e480a22

File tree

2 files changed

+52
-43
lines changed

2 files changed

+52
-43
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/ints/IntBuiltins.java

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@
157157
import com.oracle.truffle.api.library.CachedLibrary;
158158
import com.oracle.truffle.api.nodes.Node;
159159
import com.oracle.truffle.api.nodes.UnexpectedResultException;
160+
import com.oracle.truffle.api.profiles.BranchProfile;
160161
import com.oracle.truffle.api.profiles.InlinedBranchProfile;
161162
import com.oracle.truffle.api.profiles.InlinedConditionProfile;
162163
import com.oracle.truffle.api.profiles.InlinedIntValueProfile;
@@ -651,75 +652,72 @@ public static TrueDivNode create() {
651652
public abstract static class FloorDivNode extends BinaryOpBuiltinNode {
652653
public abstract Object execute(int left, int right);
653654

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+
654658
@Specialization
655-
static int doII(int left, int right,
659+
static Object doII(int left, int right,
656660
@Bind("this") Node inliningTarget,
657661
@Shared @Cached InlinedBranchProfile divisionByZeroProfile,
662+
@Shared @Cached BranchProfile overflowValueProfile,
658663
@Shared @Cached PRaiseNode.Lazy raiseNode) {
659664
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;
670668
}
671-
raiseDivisionByZero(inliningTarget, right == 0, divisionByZeroProfile, raiseNode);
672669
return Math.floorDiv(left, right);
673670
}
674671

675-
@Specialization(replaces = "doLL")
676-
static PInt doLLOverflow(long left, long right,
672+
@Specialization
673+
static Object doLL(long left, long right,
677674
@Bind("this") Node inliningTarget,
678675
@Shared @Cached InlinedBranchProfile divisionByZeroProfile,
676+
@Shared @Cached BranchProfile overflowValueProfile,
679677
@Shared @Cached PythonObjectFactory factory,
680678
@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);
691685
}
692686

693-
@Specialization(replaces = "doIPi")
694-
static int doIPiOvf(int left, PInt right,
687+
@Specialization
688+
static Object doIPi(int left, PInt right,
695689
@Bind("this") Node inliningTarget,
696690
@Shared @Cached InlinedBranchProfile divisionByZeroProfile,
691+
@Shared @Cached BranchProfile overflowValueProfile,
697692
@Shared @Cached PRaiseNode.Lazy raiseNode) {
698-
raiseDivisionByZero(inliningTarget, right.isZero(), divisionByZeroProfile, raiseNode);
699693
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);
701701
} catch (OverflowException e) {
702702
return left < 0 == right.isNegative() ? 0 : -1;
703703
}
704704
}
705705

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,
717708
@Bind("this") Node inliningTarget,
718709
@Shared @Cached InlinedBranchProfile divisionByZeroProfile,
710+
@Shared @Cached BranchProfile overflowValueProfile,
711+
@Shared @Cached PythonObjectFactory factory,
719712
@Shared @Cached PRaiseNode.Lazy raiseNode) {
720-
raiseDivisionByZero(inliningTarget, right.isZero(), divisionByZeroProfile, raiseNode);
721713
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);
723721
} catch (OverflowException e) {
724722
return left < 0 == right.isNegative() ? 0 : -1;
725723
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/lib/PyNumberFloorDivideNode.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,19 @@ public final Object executeCached(VirtualFrame frame, Object v, Object w) {
8282
* All the following fast paths need to be kept in sync with the corresponding builtin functions
8383
* in IntBuiltins, FloatBuiltins, ...
8484
*/
85-
@Specialization(rewriteOn = ArithmeticException.class)
86-
static int doII(int left, int right) {
85+
@Specialization(rewriteOn = OverflowException.class)
86+
static int doII(int left, int right) throws OverflowException {
87+
if (right == 0 || (left == Integer.MIN_VALUE && right == -1)) {
88+
throw OverflowException.INSTANCE;
89+
}
90+
return Math.floorDiv(left, right);
91+
}
92+
93+
@Specialization(rewriteOn = OverflowException.class)
94+
static long doLL(long left, long right) throws OverflowException {
95+
if (right == 0 || (left == Long.MIN_VALUE && right == -1)) {
96+
throw OverflowException.INSTANCE;
97+
}
8798
return Math.floorDiv(left, right);
8899
}
89100

0 commit comments

Comments
 (0)