aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'pypy/objspace/std/intobject.py')
-rw-r--r--pypy/objspace/std/intobject.py22
1 files changed, 19 insertions, 3 deletions
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
index 21008c89bb..668c916d60 100644
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -760,11 +760,15 @@ class W_IntObject(W_AbstractIntObject):
descr_or, descr_ror = _make_generic_descr_binop('or', ovf=False)
descr_xor, descr_rxor = _make_generic_descr_binop('xor', ovf=False)
- def _make_descr_binop(func, ovf=True, ovf2small=None):
+ def _make_descr_binop(func, ovf=True, ovf2small=None, ovf_func=None):
opname = func.__name__[1:]
descr_name, descr_rname = 'descr_' + opname, 'descr_r' + opname
if ovf:
- ovf2long = _make_ovf2long(opname, ovf2small)
+ if ovf_func:
+ ovf2long = ovf_func
+ assert not ovf2small # must be part of ovf_func
+ else:
+ ovf2long = _make_ovf2long(opname, ovf2small)
@func_renamer(descr_name)
def descr_binop(self, space, w_other):
@@ -802,8 +806,20 @@ class W_IntObject(W_AbstractIntObject):
return descr_binop, descr_rbinop
+ def _ovf2long_lshift(space, x, w_x, y, w_y):
+ if _recover_with_smalllong(space):
+ return _lshift_ovf2small(space, x, y)
+
+ from pypy.objspace.std.longobject import W_LongObject, W_AbstractLongObject
+ if w_x is None or not isinstance(w_x, W_AbstractLongObject):
+ w_x = W_LongObject.fromint(space, x)
+
+ # crucially, *don't* convert w_y to W_LongObject, it will just be
+ # converted back (huge lshifts always overflow)
+ return w_x._int_lshift(space, y)
+
descr_lshift, descr_rlshift = _make_descr_binop(
- _lshift, ovf2small=_lshift_ovf2small)
+ _lshift, ovf_func=_ovf2long_lshift)
descr_rshift, descr_rrshift = _make_descr_binop(_rshift, ovf=False)
descr_floordiv, descr_rfloordiv = _make_descr_binop(_floordiv)