[pypy-svn] pypy jit-longlong: Code explicitly the checks for overflow, now that the LLONG_xxx_OVF

arigo commits-noreply at bitbucket.org
Sun Jan 9 14:54:24 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: jit-longlong
Changeset: r40524:532809e8da09
Date: 2011-01-09 14:54 +0100
http://bitbucket.org/pypy/pypy/changeset/532809e8da09/

Log:	Code explicitly the checks for overflow, now that the LLONG_xxx_OVF
	variant of the operations is no longer supported. Doing so helps
	the JIT too, at least so far.

diff --git a/pypy/objspace/std/smalllongobject.py b/pypy/objspace/std/smalllongobject.py
--- a/pypy/objspace/std/smalllongobject.py
+++ b/pypy/objspace/std/smalllongobject.py
@@ -7,13 +7,15 @@
 from pypy.objspace.std.register_all import register_all
 from pypy.objspace.std.multimethod import FailedToImplementArgs
 from pypy.rlib.rarithmetic import r_longlong, r_int, r_uint
-from pypy.rlib.rarithmetic import intmask, ovfcheck, LONGLONG_BIT
+from pypy.rlib.rarithmetic import intmask, LONGLONG_BIT
 from pypy.rlib.rbigint import rbigint
 from pypy.objspace.std.longobject import W_LongObject
 from pypy.objspace.std.intobject import W_IntObject
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.interpreter.error import OperationError
 
+LONGLONG_MIN = (-1) << (LONGLONG_BIT-1)
+
 
 class W_SmallLongObject(W_Object):
     from pypy.objspace.std.longtype import long_typedef as typedef
@@ -39,6 +41,16 @@
 
 registerimplementation(W_SmallLongObject)
 
+# ____________________________________________________________
+
+from pypy.rpython.lltypesystem import lltype, rffi
+llong_mul_ovf = rffi.llexternal("op_llong_mul_ovf",
+                                [lltype.SignedLongLong] * 2,
+                                lltype.SignedLongLong,
+                                _callable=lambda x, y: x * y,
+                                _nowrapper=True, pure_function=True)
+
+# ____________________________________________________________
 
 def delegate_Bool2SmallLong(space, w_bool):
     return W_SmallLongObject(r_longlong(space.is_true(w_bool)))
@@ -169,7 +181,9 @@
     x = w_small1.longlong
     y = w_small2.longlong
     try:
-        z = ovfcheck(x + y)
+        z = x + y
+        if ((z^x)&(z^y)) < 0:
+            raise OverflowError
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                     space.wrap("integer addition"))
@@ -184,7 +198,9 @@
     x = w_small1.longlong
     y = w_small2.longlong
     try:
-        z = ovfcheck(x - y)
+        z = x - y
+        if ((z^x)&(z^~y)) < 0:
+            raise OverflowError
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                     space.wrap("integer subtraction"))
@@ -199,7 +215,7 @@
     x = w_small1.longlong
     y = w_small2.longlong
     try:
-        z = ovfcheck(x * y)
+        z = llong_mul_ovf(x, y)
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                     space.wrap("integer multiplication"))
@@ -216,7 +232,9 @@
     x = w_small1.longlong
     y = w_small2.longlong
     try:
-        z = ovfcheck(x // y)
+        if y == -1 and x == LONGLONG_MIN:
+            raise OverflowError
+        z = x // y
     except ZeroDivisionError:
         raise OperationError(space.w_ZeroDivisionError,
                              space.wrap("integer division by zero"))
@@ -236,7 +254,9 @@
     x = w_small1.longlong
     y = w_small2.longlong
     try:
-        z = ovfcheck(x % y)
+        if y == -1 and x == LONGLONG_MIN:
+            raise OverflowError
+        z = x % y
     except ZeroDivisionError:
         raise OperationError(space.w_ZeroDivisionError,
                              space.wrap("integer modulo by zero"))
@@ -254,7 +274,9 @@
     x = w_small1.longlong
     y = w_small2.longlong
     try:
-        z = ovfcheck(x // y)
+        if y == -1 and x == LONGLONG_MIN:
+            raise OverflowError
+        z = x // y
     except ZeroDivisionError:
         raise OperationError(space.w_ZeroDivisionError,
                              space.wrap("integer divmod by zero"))
@@ -284,11 +306,11 @@
     try:
         while iw > 0:
             if iw & 1:
-                ix = ovfcheck(ix*temp)
+                ix = llong_mul_ovf(ix, temp)
             iw >>= 1   #/* Shift exponent down by 1 bit */
             if iw==0:
                 break
-            temp = ovfcheck(temp*temp) #/* Square the value of temp */
+            temp = llong_mul_ovf(temp, temp) #/* Square the value of temp */
             if iz:
                 #/* If we did a multiplication, perform a modulo */
                 ix = ix % iz
@@ -322,7 +344,9 @@
 def neg__SmallLong(space, w_small):
     a = w_small.longlong
     try:
-        x = ovfcheck(-a)
+        if a == LONGLONG_MIN:
+            raise OverflowError
+        x = -a
     except OverflowError:
         raise FailedToImplementArgs(space.w_OverflowError,
                                 space.wrap("integer negation"))
@@ -361,7 +385,9 @@
     b = w_int2.intval
     if r_uint(b) < LONGLONG_BIT: # 0 <= b < LONGLONG_BIT
         try:
-            c = ovfcheck(a << b)
+            c = a << b
+            if a != (c >> b):
+                raise OverflowError
         except OverflowError:
             raise FailedToImplementArgs(space.w_OverflowError,
                                     space.wrap("integer left shift"))

diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -115,6 +115,8 @@
     # to be used as ovfcheck(x <op> y)
     # raise OverflowError if the operation did overflow
     assert not isinstance(r, r_uint), "unexpected ovf check on unsigned"
+    assert not isinstance(r, r_longlong), "ovfcheck not supported on r_longlong"
+    assert not isinstance(r,r_ulonglong),"ovfcheck not supported on r_ulonglong"
     if type(r) is long:
         raise OverflowError, "signed integer expression did overflow"
     return r


More information about the Pypy-commit mailing list