[pypy-commit] pypy jit-refactor-tests: hg merge default
hakanardo
noreply at buildbot.pypy.org
Fri Nov 11 08:06:28 CET 2011
Author: Hakan Ardo <hakan at debian.org>
Branch: jit-refactor-tests
Changeset: r49290:f8171c00d11a
Date: 2011-11-11 07:29 +0100
http://bitbucket.org/pypy/pypy/changeset/f8171c00d11a/
Log: hg merge default
diff --git a/lib-python/2.7/test/test_os.py b/lib-python/2.7/test/test_os.py
--- a/lib-python/2.7/test/test_os.py
+++ b/lib-python/2.7/test/test_os.py
@@ -74,7 +74,8 @@
self.assertFalse(os.path.exists(name),
"file already exists for temporary file")
# make sure we can create the file
- open(name, "w")
+ f = open(name, "w")
+ f.close()
self.files.append(name)
def test_tempnam(self):
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -201,7 +201,7 @@
RegrTest('test_difflib.py'),
RegrTest('test_dircache.py', core=True),
RegrTest('test_dis.py'),
- RegrTest('test_distutils.py'),
+ RegrTest('test_distutils.py', skip=True),
RegrTest('test_dl.py', skip=True),
RegrTest('test_doctest.py', usemodules="thread"),
RegrTest('test_doctest2.py'),
diff --git a/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py b/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
--- a/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
+++ b/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
@@ -1,6 +1,5 @@
import unittest
from ctypes import *
-from ctypes.test import xfail
class MyInt(c_int):
def __cmp__(self, other):
@@ -27,7 +26,6 @@
self.assertEqual(None, cb())
- @xfail
def test_int_callback(self):
args = []
def func(arg):
diff --git a/lib-python/2.7/pkgutil.py b/lib-python/modified-2.7/pkgutil.py
copy from lib-python/2.7/pkgutil.py
copy to lib-python/modified-2.7/pkgutil.py
--- a/lib-python/2.7/pkgutil.py
+++ b/lib-python/modified-2.7/pkgutil.py
@@ -244,7 +244,8 @@
return mod
def get_data(self, pathname):
- return open(pathname, "rb").read()
+ with open(pathname, "rb") as f:
+ return f.read()
def _reopen(self):
if self.file and self.file.closed:
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -124,7 +124,8 @@
# for now, we always allow types.pointer, else a lot of tests
# break. We need to rethink how pointers are represented, though
if my_ffitype is not ffitype and ffitype is not _ffi.types.void_p:
- raise ArgumentError, "expected %s instance, got %s" % (type(value), ffitype)
+ raise ArgumentError("expected %s instance, got %s" % (type(value),
+ ffitype))
return value._get_buffer_value()
def _cast_addr(obj, _, tp):
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -17,7 +17,7 @@
if len(f) == 3:
if (not hasattr(tp, '_type_')
or not isinstance(tp._type_, str)
- or tp._type_ not in "iIhHbBlL"):
+ or tp._type_ not in "iIhHbBlLqQ"):
#XXX: are those all types?
# we just dont get the type name
# in the interp levle thrown TypeError
diff --git a/lib_pypy/pyrepl/commands.py b/lib_pypy/pyrepl/commands.py
--- a/lib_pypy/pyrepl/commands.py
+++ b/lib_pypy/pyrepl/commands.py
@@ -33,10 +33,9 @@
class Command(object):
finish = 0
kills_digit_arg = 1
- def __init__(self, reader, (event_name, event)):
+ def __init__(self, reader, cmd):
self.reader = reader
- self.event = event
- self.event_name = event_name
+ self.event_name, self.event = cmd
def do(self):
pass
diff --git a/lib_pypy/pyrepl/pygame_console.py b/lib_pypy/pyrepl/pygame_console.py
--- a/lib_pypy/pyrepl/pygame_console.py
+++ b/lib_pypy/pyrepl/pygame_console.py
@@ -130,7 +130,7 @@
s.fill(c, [0, 600 - bmargin, 800, bmargin])
s.fill(c, [800 - rmargin, 0, lmargin, 600])
- def refresh(self, screen, (cx, cy)):
+ def refresh(self, screen, cxy):
self.screen = screen
self.pygame_screen.fill(colors.bg,
[0, tmargin + self.cur_top + self.scroll,
@@ -139,8 +139,8 @@
line_top = self.cur_top
width, height = self.fontsize
- self.cxy = (cx, cy)
- cp = self.char_pos(cx, cy)
+ self.cxy = cxy
+ cp = self.char_pos(*cxy)
if cp[1] < tmargin:
self.scroll = - (cy*self.fh + self.cur_top)
self.repaint()
@@ -148,7 +148,7 @@
self.scroll += (600 - bmargin) - (cp[1] + self.fh)
self.repaint()
if self.curs_vis:
- self.pygame_screen.blit(self.cursor, self.char_pos(cx, cy))
+ self.pygame_screen.blit(self.cursor, self.char_pos(*cxy))
for line in screen:
if 0 <= line_top + self.scroll <= (600 - bmargin - tmargin - self.fh):
if line:
diff --git a/lib_pypy/pyrepl/unix_console.py b/lib_pypy/pyrepl/unix_console.py
--- a/lib_pypy/pyrepl/unix_console.py
+++ b/lib_pypy/pyrepl/unix_console.py
@@ -163,7 +163,7 @@
def change_encoding(self, encoding):
self.encoding = encoding
- def refresh(self, screen, (cx, cy)):
+ def refresh(self, screen, cxy):
# this function is still too long (over 90 lines)
if not self.__gone_tall:
@@ -198,6 +198,7 @@
# we make sure the cursor is on the screen, and that we're
# using all of the screen if we can
+ cx, cy = cxy
if cy < offset:
offset = cy
elif cy >= offset + height:
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -305,12 +305,16 @@
_clsname = ''
loop_token = None
arg_classes = '' # <-- annotation hack
- ffi_flags = 0
+ ffi_flags = 1
- def __init__(self, arg_classes, extrainfo=None, ffi_flags=0):
+ def __init__(self, arg_classes, extrainfo=None, ffi_flags=1):
self.arg_classes = arg_classes # string of "r" and "i" (ref/int)
self.extrainfo = extrainfo
self.ffi_flags = ffi_flags
+ # NB. the default ffi_flags is 1, meaning FUNCFLAG_CDECL, which
+ # makes sense on Windows as it's the one for all the C functions
+ # we are compiling together with the JIT. On non-Windows platforms
+ # it is just ignored anyway.
def __repr__(self):
res = '%s(%s)' % (self.__class__.__name__, self.arg_classes)
@@ -445,7 +449,7 @@
"""
_clsname = 'DynamicIntCallDescr'
- def __init__(self, arg_classes, result_size, result_sign, extrainfo=None, ffi_flags=0):
+ def __init__(self, arg_classes, result_size, result_sign, extrainfo, ffi_flags):
BaseIntCallDescr.__init__(self, arg_classes, extrainfo, ffi_flags)
assert isinstance(result_sign, bool)
self._result_size = chr(result_size)
diff --git a/pypy/jit/backend/llsupport/ffisupport.py b/pypy/jit/backend/llsupport/ffisupport.py
--- a/pypy/jit/backend/llsupport/ffisupport.py
+++ b/pypy/jit/backend/llsupport/ffisupport.py
@@ -8,7 +8,7 @@
class UnsupportedKind(Exception):
pass
-def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo=None, ffi_flags=0):
+def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo, ffi_flags):
"""Get a call descr: the types of result and args are represented by
rlib.libffi.types.*"""
try:
diff --git a/pypy/jit/backend/llsupport/test/test_ffisupport.py b/pypy/jit/backend/llsupport/test/test_ffisupport.py
--- a/pypy/jit/backend/llsupport/test/test_ffisupport.py
+++ b/pypy/jit/backend/llsupport/test/test_ffisupport.py
@@ -13,44 +13,46 @@
def test_call_descr_dynamic():
args = [types.sint, types.pointer]
- descr = get_call_descr_dynamic(FakeCPU(), args, types.sint, ffi_flags=42)
+ descr = get_call_descr_dynamic(FakeCPU(), args, types.sint, None,
+ ffi_flags=42)
assert isinstance(descr, DynamicIntCallDescr)
assert descr.arg_classes == 'ii'
assert descr.get_ffi_flags() == 42
args = [types.sint, types.double, types.pointer]
- descr = get_call_descr_dynamic(FakeCPU(), args, types.void)
+ descr = get_call_descr_dynamic(FakeCPU(), args, types.void, None, 42)
assert descr is None # missing floats
descr = get_call_descr_dynamic(FakeCPU(supports_floats=True),
- args, types.void, ffi_flags=43)
+ args, types.void, None, ffi_flags=43)
assert isinstance(descr, VoidCallDescr)
assert descr.arg_classes == 'ifi'
assert descr.get_ffi_flags() == 43
- descr = get_call_descr_dynamic(FakeCPU(), [], types.sint8)
+ descr = get_call_descr_dynamic(FakeCPU(), [], types.sint8, None, 42)
assert isinstance(descr, DynamicIntCallDescr)
assert descr.get_result_size(False) == 1
assert descr.is_result_signed() == True
- descr = get_call_descr_dynamic(FakeCPU(), [], types.uint8)
+ descr = get_call_descr_dynamic(FakeCPU(), [], types.uint8, None, 42)
assert isinstance(descr, DynamicIntCallDescr)
assert descr.get_result_size(False) == 1
assert descr.is_result_signed() == False
if not is_64_bit:
- descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong)
+ descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong,
+ None, 42)
assert descr is None # missing longlongs
descr = get_call_descr_dynamic(FakeCPU(supports_longlong=True),
- [], types.slonglong, ffi_flags=43)
+ [], types.slonglong, None, ffi_flags=43)
assert isinstance(descr, LongLongCallDescr)
assert descr.get_ffi_flags() == 43
else:
assert types.slonglong is types.slong
- descr = get_call_descr_dynamic(FakeCPU(), [], types.float)
+ descr = get_call_descr_dynamic(FakeCPU(), [], types.float, None, 42)
assert descr is None # missing singlefloats
descr = get_call_descr_dynamic(FakeCPU(supports_singlefloats=True),
- [], types.float, ffi_flags=44)
+ [], types.float, None, ffi_flags=44)
SingleFloatCallDescr = getCallDescrClass(rffi.FLOAT)
assert isinstance(descr, SingleFloatCallDescr)
assert descr.get_ffi_flags() == 44
diff --git a/pypy/jit/backend/x86/test/test_runner.py b/pypy/jit/backend/x86/test/test_runner.py
--- a/pypy/jit/backend/x86/test/test_runner.py
+++ b/pypy/jit/backend/x86/test/test_runner.py
@@ -455,6 +455,9 @@
EffectInfo.MOST_GENERAL,
ffi_flags=-1)
calldescr.get_call_conv = lambda: ffi # <==== hack
+ # ^^^ we patch get_call_conv() so that the test also makes sense
+ # on Linux, because clibffi.get_call_conv() would always
+ # return FFI_DEFAULT_ABI on non-Windows platforms.
funcbox = ConstInt(rawstart)
i1 = BoxInt()
i2 = BoxInt()
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -78,6 +78,9 @@
#
OS_MATH_SQRT = 100
+ # for debugging:
+ _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL])
+
def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays,
write_descrs_fields, write_descrs_arrays,
extraeffect=EF_CAN_RAISE,
@@ -116,6 +119,8 @@
result.extraeffect = extraeffect
result.can_invalidate = can_invalidate
result.oopspecindex = oopspecindex
+ if result.check_can_raise():
+ assert oopspecindex in cls._OS_CANRAISE
cls._cache[key] = result
return result
@@ -125,6 +130,10 @@
def check_can_invalidate(self):
return self.can_invalidate
+ def check_is_elidable(self):
+ return (self.extraeffect == self.EF_ELIDABLE_CAN_RAISE or
+ self.extraeffect == self.EF_ELIDABLE_CANNOT_RAISE)
+
def check_forces_virtual_or_virtualizable(self):
return self.extraeffect >= self.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
diff --git a/pypy/jit/codewriter/test/test_flatten.py b/pypy/jit/codewriter/test/test_flatten.py
--- a/pypy/jit/codewriter/test/test_flatten.py
+++ b/pypy/jit/codewriter/test/test_flatten.py
@@ -5,7 +5,7 @@
from pypy.jit.codewriter.format import assert_format
from pypy.jit.codewriter import longlong
from pypy.jit.metainterp.history import AbstractDescr
-from pypy.rpython.lltypesystem import lltype, rclass, rstr
+from pypy.rpython.lltypesystem import lltype, rclass, rstr, rffi
from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
from pypy.translator.unsimplify import varoftype
from pypy.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong
@@ -743,7 +743,6 @@
""", transform=True)
def test_force_cast(self):
- from pypy.rpython.lltypesystem import rffi
# NB: we don't need to test for INT here, the logic in jtransform is
# general enough so that if we have the below cases it should
# generalize also to INT
@@ -849,7 +848,6 @@
transform=True)
def test_force_cast_pointer(self):
- from pypy.rpython.lltypesystem import rffi
def h(p):
return rffi.cast(rffi.VOIDP, p)
self.encoding_test(h, [lltype.nullptr(rffi.CCHARP.TO)], """
@@ -857,7 +855,6 @@
""", transform=True)
def test_force_cast_floats(self):
- from pypy.rpython.lltypesystem import rffi
# Caststs to lltype.Float
def f(n):
return rffi.cast(lltype.Float, n)
@@ -964,7 +961,6 @@
""", transform=True)
def test_direct_ptradd(self):
- from pypy.rpython.lltypesystem import rffi
def f(p, n):
return lltype.direct_ptradd(p, n)
self.encoding_test(f, [lltype.nullptr(rffi.CCHARP.TO), 123], """
@@ -975,7 +971,6 @@
def check_force_cast(FROM, TO, operations, value):
"""Check that the test is correctly written..."""
- from pypy.rpython.lltypesystem import rffi
import re
r = re.compile('(\w+) \%i\d, \$(-?\d+)')
#
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -55,7 +55,7 @@
def optimize_loop_1(metainterp_sd, loop, enable_opts,
- inline_short_preamble=True, retraced=False, bridge=False):
+ inline_short_preamble=True, retraced=False):
"""Optimize loop.operations to remove internal overheadish operations.
"""
@@ -64,7 +64,7 @@
if unroll:
optimize_unroll(metainterp_sd, loop, optimizations)
else:
- optimizer = Optimizer(metainterp_sd, loop, optimizations, bridge)
+ optimizer = Optimizer(metainterp_sd, loop, optimizations)
optimizer.propagate_all_forward()
def optimize_bridge_1(metainterp_sd, bridge, enable_opts,
@@ -76,7 +76,7 @@
except KeyError:
pass
optimize_loop_1(metainterp_sd, bridge, enable_opts,
- inline_short_preamble, retraced, bridge=True)
+ inline_short_preamble, retraced)
if __name__ == '__main__':
print ALL_OPTS_NAMES
diff --git a/pypy/jit/metainterp/optimizeopt/heap.py b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -234,7 +234,7 @@
or op.is_ovf()):
self.posponedop = op
else:
- self.next_optimization.propagate_forward(op)
+ Optimization.emit_operation(self, op)
def emitting_operation(self, op):
if op.has_no_side_effect():
diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -6,6 +6,7 @@
IntUpperBound)
from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
from pypy.jit.metainterp.resoperation import rop
+from pypy.jit.metainterp.optimize import InvalidLoop
from pypy.rlib.rarithmetic import LONG_BIT
@@ -13,30 +14,10 @@
"""Keeps track of the bounds placed on integers by guards and remove
redundant guards"""
- def setup(self):
- self.posponedop = None
- self.nextop = None
-
def new(self):
- assert self.posponedop is None
return OptIntBounds()
-
- def flush(self):
- assert self.posponedop is None
-
- def setup(self):
- self.posponedop = None
- self.nextop = None
def propagate_forward(self, op):
- if op.is_ovf():
- self.posponedop = op
- return
- if self.posponedop:
- self.nextop = op
- op = self.posponedop
- self.posponedop = None
-
dispatch_opt(self, op)
def opt_default(self, op):
@@ -179,68 +160,75 @@
r = self.getvalue(op.result)
r.intbound.intersect(b)
+ def optimize_GUARD_NO_OVERFLOW(self, op):
+ lastop = self.last_emitted_operation
+ if lastop is not None:
+ opnum = lastop.getopnum()
+ args = lastop.getarglist()
+ result = lastop.result
+ # If the INT_xxx_OVF was replaced with INT_xxx, then we can kill
+ # the GUARD_NO_OVERFLOW.
+ if (opnum == rop.INT_ADD or
+ opnum == rop.INT_SUB or
+ opnum == rop.INT_MUL):
+ return
+ # Else, synthesize the non overflowing op for optimize_default to
+ # reuse, as well as the reverse op
+ elif opnum == rop.INT_ADD_OVF:
+ self.pure(rop.INT_ADD, args[:], result)
+ self.pure(rop.INT_SUB, [result, args[1]], args[0])
+ self.pure(rop.INT_SUB, [result, args[0]], args[1])
+ elif opnum == rop.INT_SUB_OVF:
+ self.pure(rop.INT_SUB, args[:], result)
+ self.pure(rop.INT_ADD, [result, args[1]], args[0])
+ self.pure(rop.INT_SUB, [args[0], result], args[1])
+ elif opnum == rop.INT_MUL_OVF:
+ self.pure(rop.INT_MUL, args[:], result)
+ self.emit_operation(op)
+
+ def optimize_GUARD_OVERFLOW(self, op):
+ # If INT_xxx_OVF was replaced by INT_xxx, *but* we still see
+ # GUARD_OVERFLOW, then the loop is invalid.
+ lastop = self.last_emitted_operation
+ if lastop is None:
+ raise InvalidLoop
+ opnum = lastop.getopnum()
+ if opnum not in (rop.INT_ADD_OVF, rop.INT_SUB_OVF, rop.INT_MUL_OVF):
+ raise InvalidLoop
+ self.emit_operation(op)
+
def optimize_INT_ADD_OVF(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
resbound = v1.intbound.add_bound(v2.intbound)
- if resbound.has_lower and resbound.has_upper and \
- self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Transform into INT_ADD and remove guard
+ if resbound.bounded():
+ # Transform into INT_ADD. The following guard will be killed
+ # by optimize_GUARD_NO_OVERFLOW; if we see instead an
+ # optimize_GUARD_OVERFLOW, then InvalidLoop.
op = op.copy_and_change(rop.INT_ADD)
- self.optimize_INT_ADD(op) # emit the op
- else:
- self.emit_operation(op)
- r = self.getvalue(op.result)
- r.intbound.intersect(resbound)
- self.emit_operation(self.nextop)
- if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Synthesize the non overflowing op for optimize_default to reuse
- self.pure(rop.INT_ADD, op.getarglist()[:], op.result)
- # Synthesize the reverse op for optimize_default to reuse
- self.pure(rop.INT_SUB, [op.result, op.getarg(1)], op.getarg(0))
- self.pure(rop.INT_SUB, [op.result, op.getarg(0)], op.getarg(1))
-
+ self.emit_operation(op) # emit the op
+ r = self.getvalue(op.result)
+ r.intbound.intersect(resbound)
def optimize_INT_SUB_OVF(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
resbound = v1.intbound.sub_bound(v2.intbound)
- if resbound.has_lower and resbound.has_upper and \
- self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Transform into INT_SUB and remove guard
+ if resbound.bounded():
op = op.copy_and_change(rop.INT_SUB)
- self.optimize_INT_SUB(op) # emit the op
- else:
- self.emit_operation(op)
- r = self.getvalue(op.result)
- r.intbound.intersect(resbound)
- self.emit_operation(self.nextop)
- if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Synthesize the non overflowing op for optimize_default to reuse
- self.pure(rop.INT_SUB, op.getarglist()[:], op.result)
- # Synthesize the reverse ops for optimize_default to reuse
- self.pure(rop.INT_ADD, [op.result, op.getarg(1)], op.getarg(0))
- self.pure(rop.INT_SUB, [op.getarg(0), op.result], op.getarg(1))
-
+ self.emit_operation(op) # emit the op
+ r = self.getvalue(op.result)
+ r.intbound.intersect(resbound)
def optimize_INT_MUL_OVF(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
resbound = v1.intbound.mul_bound(v2.intbound)
- if resbound.has_lower and resbound.has_upper and \
- self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Transform into INT_MUL and remove guard
+ if resbound.bounded():
op = op.copy_and_change(rop.INT_MUL)
- self.optimize_INT_MUL(op) # emit the op
- else:
- self.emit_operation(op)
- r = self.getvalue(op.result)
- r.intbound.intersect(resbound)
- self.emit_operation(self.nextop)
- if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
- # Synthesize the non overflowing op for optimize_default to reuse
- self.pure(rop.INT_MUL, op.getarglist()[:], op.result)
-
+ self.emit_operation(op)
+ r = self.getvalue(op.result)
+ r.intbound.intersect(resbound)
def optimize_INT_LT(self, op):
v1 = self.getvalue(op.getarg(0))
diff --git a/pypy/jit/metainterp/optimizeopt/intutils.py b/pypy/jit/metainterp/optimizeopt/intutils.py
--- a/pypy/jit/metainterp/optimizeopt/intutils.py
+++ b/pypy/jit/metainterp/optimizeopt/intutils.py
@@ -1,4 +1,4 @@
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift, LONG_BIT
+from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT
from pypy.rlib.objectmodel import we_are_translated
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.jit.metainterp.history import BoxInt, ConstInt
@@ -174,10 +174,10 @@
other.known_ge(IntBound(0, 0)) and \
other.known_lt(IntBound(LONG_BIT, LONG_BIT)):
try:
- vals = (ovfcheck_lshift(self.upper, other.upper),
- ovfcheck_lshift(self.upper, other.lower),
- ovfcheck_lshift(self.lower, other.upper),
- ovfcheck_lshift(self.lower, other.lower))
+ vals = (ovfcheck(self.upper << other.upper),
+ ovfcheck(self.upper << other.lower),
+ ovfcheck(self.lower << other.upper),
+ ovfcheck(self.lower << other.lower))
return IntBound(min4(vals), max4(vals))
except (OverflowError, ValueError):
return IntUnbounded()
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -6,7 +6,7 @@
IntLowerBound, MININT, MAXINT
from pypy.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
args_dict)
-from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.metainterp.resoperation import rop, ResOperation, AbstractResOp
from pypy.jit.metainterp.typesystem import llhelper, oohelper
from pypy.tool.pairtype import extendabletype
from pypy.rlib.debug import debug_start, debug_stop, debug_print
@@ -249,6 +249,8 @@
CVAL_ZERO_FLOAT = ConstantValue(Const._new(0.0))
llhelper.CVAL_NULLREF = ConstantValue(llhelper.CONST_NULL)
oohelper.CVAL_NULLREF = ConstantValue(oohelper.CONST_NULL)
+REMOVED = AbstractResOp(None)
+
class Optimization(object):
next_optimization = None
@@ -260,6 +262,7 @@
raise NotImplementedError
def emit_operation(self, op):
+ self.last_emitted_operation = op
self.next_optimization.propagate_forward(op)
# FIXME: Move some of these here?
@@ -327,13 +330,13 @@
def forget_numberings(self, box):
self.optimizer.forget_numberings(box)
+
class Optimizer(Optimization):
- def __init__(self, metainterp_sd, loop, optimizations=None, bridge=False):
+ def __init__(self, metainterp_sd, loop, optimizations=None):
self.metainterp_sd = metainterp_sd
self.cpu = metainterp_sd.cpu
self.loop = loop
- self.bridge = bridge
self.values = {}
self.interned_refs = self.cpu.ts.new_ref_dict()
self.interned_ints = {}
@@ -341,7 +344,6 @@
self.bool_boxes = {}
self.producer = {}
self.pendingfields = []
- self.exception_might_have_happened = False
self.quasi_immutable_deps = None
self.opaque_pointers = {}
self.replaces_guard = {}
@@ -363,6 +365,7 @@
optimizations[-1].next_optimization = self
for o in optimizations:
o.optimizer = self
+ o.last_emitted_operation = None
o.setup()
else:
optimizations = []
@@ -497,7 +500,6 @@
return CVAL_ZERO
def propagate_all_forward(self):
- self.exception_might_have_happened = self.bridge
self.clear_newoperations()
for op in self.loop.operations:
self.first_optimization.propagate_forward(op)
diff --git a/pypy/jit/metainterp/optimizeopt/pure.py b/pypy/jit/metainterp/optimizeopt/pure.py
--- a/pypy/jit/metainterp/optimizeopt/pure.py
+++ b/pypy/jit/metainterp/optimizeopt/pure.py
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization, REMOVED
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
args_dict)
@@ -61,7 +61,10 @@
oldop = self.pure_operations.get(args, None)
if oldop is not None and oldop.getdescr() is op.getdescr():
assert oldop.getopnum() == op.getopnum()
+ # this removes a CALL_PURE that has the same (non-constant)
+ # arguments as a previous CALL_PURE.
self.make_equal_to(op.result, self.getvalue(oldop.result))
+ self.last_emitted_operation = REMOVED
return
else:
self.pure_operations[args] = op
@@ -72,6 +75,13 @@
self.emit_operation(ResOperation(rop.CALL, args, op.result,
op.getdescr()))
+ def optimize_GUARD_NO_EXCEPTION(self, op):
+ if self.last_emitted_operation is REMOVED:
+ # it was a CALL_PURE that was killed; so we also kill the
+ # following GUARD_NO_EXCEPTION
+ return
+ self.emit_operation(op)
+
def flush(self):
assert self.posponedop is None
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -294,12 +294,6 @@
raise InvalidLoop
self.optimize_GUARD_CLASS(op)
- def optimize_GUARD_NO_EXCEPTION(self, op):
- if not self.optimizer.exception_might_have_happened:
- return
- self.emit_operation(op)
- self.optimizer.exception_might_have_happened = False
-
def optimize_CALL_LOOPINVARIANT(self, op):
arg = op.getarg(0)
# 'arg' must be a Const, because residual_call in codewriter
@@ -310,6 +304,7 @@
resvalue = self.loop_invariant_results.get(key, None)
if resvalue is not None:
self.make_equal_to(op.result, resvalue)
+ self.last_emitted_operation = REMOVED
return
# change the op to be a normal call, from the backend's point of view
# there is no reason to have a separate operation for this
@@ -444,10 +439,19 @@
except KeyError:
pass
else:
+ # this removes a CALL_PURE with all constant arguments.
self.make_constant(op.result, result)
+ self.last_emitted_operation = REMOVED
return
self.emit_operation(op)
+ def optimize_GUARD_NO_EXCEPTION(self, op):
+ if self.last_emitted_operation is REMOVED:
+ # it was a CALL_PURE or a CALL_LOOPINVARIANT that was killed;
+ # so we also kill the following GUARD_NO_EXCEPTION
+ return
+ self.emit_operation(op)
+
def optimize_INT_FLOORDIV(self, op):
v1 = self.getvalue(op.getarg(0))
v2 = self.getvalue(op.getarg(1))
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -681,25 +681,60 @@
# ----------
- def test_fold_guard_no_exception(self):
- ops = """
- [i]
- guard_no_exception() []
- i1 = int_add(i, 3)
- guard_no_exception() []
+ def test_keep_guard_no_exception(self):
+ ops = """
+ [i1]
i2 = call(i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
- guard_no_exception() []
- i3 = call(i2, descr=nonwritedescr)
- jump(i1) # the exception is considered lost when we loop back
- """
- expected = """
- [i]
- i1 = int_add(i, 3)
- i2 = call(i1, descr=nonwritedescr)
+ jump(i2)
+ """
+ self.optimize_loop(ops, ops)
+
+ def test_keep_guard_no_exception_with_call_pure_that_is_not_folded(self):
+ ops = """
+ [i1]
+ i2 = call_pure(123456, i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
- i3 = call(i2, descr=nonwritedescr)
- jump(i1)
+ jump(i2)
+ """
+ expected = """
+ [i1]
+ i2 = call(123456, i1, descr=nonwritedescr)
+ guard_no_exception() [i1, i2]
+ jump(i2)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_remove_guard_no_exception_with_call_pure_on_constant_args(self):
+ arg_consts = [ConstInt(i) for i in (123456, 81)]
+ call_pure_results = {tuple(arg_consts): ConstInt(5)}
+ ops = """
+ [i1]
+ i3 = same_as(81)
+ i2 = call_pure(123456, i3, descr=nonwritedescr)
+ guard_no_exception() [i1, i2]
+ jump(i2)
+ """
+ expected = """
+ [i1]
+ jump(5)
+ """
+ self.optimize_loop(ops, expected, call_pure_results)
+
+ def test_remove_guard_no_exception_with_duplicated_call_pure(self):
+ ops = """
+ [i1]
+ i2 = call_pure(123456, i1, descr=nonwritedescr)
+ guard_no_exception() [i1, i2]
+ i3 = call_pure(123456, i1, descr=nonwritedescr)
+ guard_no_exception() [i1, i2, i3]
+ jump(i3)
+ """
+ expected = """
+ [i1]
+ i2 = call(123456, i1, descr=nonwritedescr)
+ guard_no_exception() [i1, i2]
+ jump(i2)
"""
self.optimize_loop(ops, expected)
@@ -4964,6 +4999,34 @@
"""
self.optimize_loop(ops, expected)
+ def test_known_equal_ints(self):
+ py.test.skip("in-progress")
+ ops = """
+ [i0, i1, i2, p0]
+ i3 = int_eq(i0, i1)
+ guard_true(i3) []
+
+ i4 = int_lt(i2, i0)
+ guard_true(i4) []
+ i5 = int_lt(i2, i1)
+ guard_true(i5) []
+
+ i6 = getarrayitem_gc(p0, i2)
+ finish(i6)
+ """
+ expected = """
+ [i0, i1, i2, p0]
+ i3 = int_eq(i0, i1)
+ guard_true(i3) []
+
+ i4 = int_lt(i2, i0)
+ guard_true(i4) []
+
+ i6 = getarrayitem_gc(p0, i3)
+ finish(i6)
+ """
+ self.optimize_loop(ops, expected)
+
class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
pass
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -931,17 +931,14 @@
[i]
guard_no_exception() []
i1 = int_add(i, 3)
- guard_no_exception() []
i2 = call(i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
- guard_no_exception() []
i3 = call(i2, descr=nonwritedescr)
jump(i1) # the exception is considered lost when we loop back
"""
- # note that 'guard_no_exception' at the very start is kept around
- # for bridges, but not for loops
preamble = """
[i]
+ guard_no_exception() [] # occurs at the start of bridges, so keep it
i1 = int_add(i, 3)
i2 = call(i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
@@ -950,6 +947,7 @@
"""
expected = """
[i]
+ guard_no_exception() [] # occurs at the start of bridges, so keep it
i1 = int_add(i, 3)
i2 = call(i1, descr=nonwritedescr)
guard_no_exception() [i1, i2]
@@ -958,6 +956,23 @@
"""
self.optimize_loop(ops, expected, preamble)
+ def test_bug_guard_no_exception(self):
+ ops = """
+ []
+ i0 = call(123, descr=nonwritedescr)
+ p0 = call(0, "xy", descr=s2u_descr) # string -> unicode
+ guard_no_exception() []
+ escape(p0)
+ jump()
+ """
+ expected = """
+ []
+ i0 = call(123, descr=nonwritedescr)
+ escape(u"xy")
+ jump()
+ """
+ self.optimize_loop(ops, expected)
+
# ----------
def test_call_loopinvariant(self):
@@ -6281,12 +6296,15 @@
def test_str2unicode_constant(self):
ops = """
[]
+ escape(1213)
p0 = call(0, "xy", descr=s2u_descr) # string -> unicode
+ guard_no_exception() []
escape(p0)
jump()
"""
expected = """
[]
+ escape(1213)
escape(u"xy")
jump()
"""
@@ -6296,6 +6314,7 @@
ops = """
[p0]
p1 = call(0, p0, descr=s2u_descr) # string -> unicode
+ guard_no_exception() []
escape(p1)
jump(p1)
"""
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -183,6 +183,7 @@
can_invalidate=True))
arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
EffectInfo([], [arraydescr], [], [arraydescr],
+ EffectInfo.EF_CANNOT_RAISE,
oopspecindex=EffectInfo.OS_ARRAYCOPY))
@@ -212,12 +213,14 @@
_oopspecindex = getattr(EffectInfo, _os)
locals()[_name] = \
cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [], [], oopspecindex=_oopspecindex))
+ EffectInfo([], [], [], [], EffectInfo.EF_CANNOT_RAISE,
+ oopspecindex=_oopspecindex))
#
_oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI'))
locals()[_name.replace('str', 'unicode')] = \
cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [], [], oopspecindex=_oopspecindex))
+ EffectInfo([], [], [], [], EffectInfo.EF_CANNOT_RAISE,
+ oopspecindex=_oopspecindex))
s2u_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
EffectInfo([], [], [], [], oopspecindex=EffectInfo.OS_STR2UNICODE))
diff --git a/pypy/jit/metainterp/optimizeopt/vstring.py b/pypy/jit/metainterp/optimizeopt/vstring.py
--- a/pypy/jit/metainterp/optimizeopt/vstring.py
+++ b/pypy/jit/metainterp/optimizeopt/vstring.py
@@ -2,7 +2,8 @@
from pypy.jit.metainterp.history import (BoxInt, Const, ConstInt, ConstPtr,
get_const_ptr_for_string, get_const_ptr_for_unicode, BoxPtr, REF, INT)
from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
-from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1, llhelper
+from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
+from pypy.jit.metainterp.optimizeopt.optimizer import llhelper, REMOVED
from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.rlib.objectmodel import specialize, we_are_translated
@@ -529,6 +530,11 @@
optimize_CALL_PURE = optimize_CALL
+ def optimize_GUARD_NO_EXCEPTION(self, op):
+ if self.last_emitted_operation is REMOVED:
+ return
+ self.emit_operation(op)
+
def opt_call_str_STR2UNICODE(self, op):
# Constant-fold unicode("constant string").
# More generally, supporting non-constant but virtual cases is
@@ -543,6 +549,7 @@
except UnicodeDecodeError:
return False
self.make_constant(op.result, get_const_ptr_for_unicode(u))
+ self.last_emitted_operation = REMOVED
return True
def opt_call_stroruni_STR_CONCAT(self, op, mode):
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1345,10 +1345,8 @@
if effect == effectinfo.EF_LOOPINVARIANT:
return self.execute_varargs(rop.CALL_LOOPINVARIANT, allboxes,
descr, False, False)
- exc = (effect != effectinfo.EF_CANNOT_RAISE and
- effect != effectinfo.EF_ELIDABLE_CANNOT_RAISE)
- pure = (effect == effectinfo.EF_ELIDABLE_CAN_RAISE or
- effect == effectinfo.EF_ELIDABLE_CANNOT_RAISE)
+ exc = effectinfo.check_can_raise()
+ pure = effectinfo.check_is_elidable()
return self.execute_varargs(rop.CALL, allboxes, descr, exc, pure)
def do_residual_or_indirect_call(self, funcbox, calldescr, argboxes):
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -90,7 +90,10 @@
return op
def __repr__(self):
- return self.repr()
+ try:
+ return self.repr()
+ except NotImplementedError:
+ return object.__repr__(self)
def repr(self, graytext=False):
# RPython-friendly version
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -3667,3 +3667,16 @@
assert x == -42
x = self.interp_operations(f, [1000, 1], translationoptions=topt)
assert x == 999
+
+ def test_ll_arraycopy(self):
+ from pypy.rlib import rgc
+ A = lltype.GcArray(lltype.Char)
+ a = lltype.malloc(A, 10)
+ for i in range(10): a[i] = chr(i)
+ b = lltype.malloc(A, 10)
+ #
+ def f(c, d, e):
+ rgc.ll_arraycopy(a, b, c, d, e)
+ return 42
+ self.interp_operations(f, [1, 2, 3])
+ self.check_operations_history(call=1, guard_no_exception=0)
diff --git a/pypy/jit/metainterp/test/test_resume.py b/pypy/jit/metainterp/test/test_resume.py
--- a/pypy/jit/metainterp/test/test_resume.py
+++ b/pypy/jit/metainterp/test/test_resume.py
@@ -1135,16 +1135,11 @@
assert ptr2.parent.next == ptr
class CompareableConsts(object):
- def __init__(self):
- self.oldeq = None
-
def __enter__(self):
- assert self.oldeq is None
- self.oldeq = Const.__eq__
Const.__eq__ = Const.same_box
-
+
def __exit__(self, type, value, traceback):
- Const.__eq__ = self.oldeq
+ del Const.__eq__
def test_virtual_adder_make_varray():
b2s, b4s = [BoxPtr(), BoxInt(4)]
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -392,6 +392,7 @@
'Slice': 'space.gettypeobject(W_SliceObject.typedef)',
'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)',
'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)',
+ 'WrapperDescr': 'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)'
}.items():
GLOBALS['Py%s_Type#' % (cpyname, )] = ('PyTypeObject*', pypyexpr)
diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,7 +29,7 @@
#define PY_VERSION "2.7.1"
/* PyPy version as a string */
-#define PYPY_VERSION "1.6.1"
+#define PYPY_VERSION "1.7.1"
/* Subversion Revision number of this file (not of the repository).
* Empty since Mercurial migration. */
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -240,6 +240,7 @@
def PyStaticMethod_New(space, w_func):
return space.wrap(StaticMethod(w_func))
+ at cpython_api([PyObject, lltype.Ptr(PyMethodDef)], PyObject)
def PyDescr_NewMethod(space, w_type, method):
return space.wrap(W_PyCMethodObject(space, method, w_type))
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -586,10 +586,6 @@
def PyDescr_NewMember(space, type, meth):
raise NotImplementedError
- at cpython_api([PyTypeObjectPtr, PyMethodDef], PyObject)
-def PyDescr_NewMethod(space, type, meth):
- raise NotImplementedError
-
@cpython_api([PyTypeObjectPtr, wrapperbase, rffi.VOIDP], PyObject)
def PyDescr_NewWrapper(space, type, wrapper, wrapped):
raise NotImplementedError
@@ -610,14 +606,6 @@
def PyWrapper_New(space, w_d, w_self):
raise NotImplementedError
- at cpython_api([PyObject], PyObject)
-def PyDictProxy_New(space, dict):
- """Return a proxy object for a mapping which enforces read-only behavior.
- This is normally used to create a proxy to prevent modification of the
- dictionary for non-dynamic class types.
- """
- raise NotImplementedError
-
@cpython_api([PyObject, PyObject, rffi.INT_real], rffi.INT_real, error=-1)
def PyDict_Merge(space, a, b, override):
"""Iterate over mapping object b adding key-value pairs to dictionary a.
@@ -2293,15 +2281,6 @@
changes in your code for properly supporting 64-bit systems."""
raise NotImplementedError
- at cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_EncodeUTF8(space, s, size, errors):
- """Encode the Py_UNICODE buffer of the given size using UTF-8 and return a
- Python string object. Return NULL if an exception was raised by the codec.
-
- This function used an int type for size. This might require
- changes in your code for properly supporting 64-bit systems."""
- raise NotImplementedError
-
@cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP, rffi.INTP], PyObject)
def PyUnicode_DecodeUTF32(space, s, size, errors, byteorder):
"""Decode length bytes from a UTF-32 encoded buffer string and return the
@@ -2481,31 +2460,6 @@
was raised by the codec."""
raise NotImplementedError
- at cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_DecodeLatin1(space, s, size, errors):
- """Create a Unicode object by decoding size bytes of the Latin-1 encoded string
- s. Return NULL if an exception was raised by the codec.
-
- This function used an int type for size. This might require
- changes in your code for properly supporting 64-bit systems."""
- raise NotImplementedError
-
- at cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_EncodeLatin1(space, s, size, errors):
- """Encode the Py_UNICODE buffer of the given size using Latin-1 and return
- a Python string object. Return NULL if an exception was raised by the codec.
-
- This function used an int type for size. This might require
- changes in your code for properly supporting 64-bit systems."""
- raise NotImplementedError
-
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsLatin1String(space, unicode):
- """Encode a Unicode object using Latin-1 and return the result as Python string
- object. Error handling is "strict". Return NULL if an exception was raised
- by the codec."""
- raise NotImplementedError
-
@cpython_api([rffi.CCHARP, Py_ssize_t, PyObject, rffi.CCHARP], PyObject)
def PyUnicode_DecodeCharmap(space, s, size, mapping, errors):
"""Create a Unicode object by decoding size bytes of the encoded string s using
@@ -2564,13 +2518,6 @@
"""
raise NotImplementedError
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsMBCSString(space, unicode):
- """Encode a Unicode object using MBCS and return the result as Python string
- object. Error handling is "strict". Return NULL if an exception was raised
- by the codec."""
- raise NotImplementedError
-
@cpython_api([PyObject, PyObject], PyObject)
def PyUnicode_Concat(space, left, right):
"""Concat two strings giving a new Unicode string."""
@@ -2912,16 +2859,3 @@
"""Return true if ob is a proxy object.
"""
raise NotImplementedError
-
- at cpython_api([PyObject, PyObject], PyObject)
-def PyWeakref_NewProxy(space, ob, callback):
- """Return a weak reference proxy object for the object ob. This will always
- return a new reference, but is not guaranteed to create a new object; an
- existing proxy object may be returned. The second parameter, callback, can
- be a callable object that receives notification when ob is garbage
- collected; it should accept a single parameter, which will be the weak
- reference object itself. callback may also be None or NULL. If ob
- is not a weakly-referencable object, or if callback is not callable,
- None, or NULL, this will return NULL and raise TypeError.
- """
- raise NotImplementedError
diff --git a/pypy/module/cpyext/test/test_methodobject.py b/pypy/module/cpyext/test/test_methodobject.py
--- a/pypy/module/cpyext/test/test_methodobject.py
+++ b/pypy/module/cpyext/test/test_methodobject.py
@@ -79,7 +79,7 @@
raises(TypeError, mod.isSameFunction, 1)
class TestPyCMethodObject(BaseApiTest):
- def test_repr(self, space):
+ def test_repr(self, space, api):
"""
W_PyCMethodObject has a repr string which describes it as a method
and gives its name and the name of its class.
@@ -94,7 +94,7 @@
ml.c_ml_meth = rffi.cast(PyCFunction_typedef,
c_func.get_llhelper(space))
- method = PyDescr_NewMethod(space, space.w_str, ml)
+ method = api.PyDescr_NewMethod(space.w_str, ml)
assert repr(method).startswith(
"<built-in method 'func' of 'str' object ")
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -188,6 +188,12 @@
assert space.unwrap(w_u) == 'sp'
rffi.free_charp(u)
+ def test_encode_utf8(self, space, api):
+ u = rffi.unicode2wcharp(u'sp�m')
+ w_s = api.PyUnicode_EncodeUTF8(u, 4, None)
+ assert space.unwrap(w_s) == u'sp�m'.encode('utf-8')
+ rffi.free_wcharp(u)
+
def test_IS(self, space, api):
for char in [0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x85, 0xa0, 0x1680, 0x2000, 0x2001, 0x2002,
@@ -385,6 +391,24 @@
data, len(u), lltype.nullptr(rffi.CCHARP.TO))
rffi.free_wcharp(data)
+ def test_latin1(self, space, api):
+ s = 'abcdefg'
+ data = rffi.str2charp(s)
+ w_u = api.PyUnicode_DecodeLatin1(data, len(s), lltype.nullptr(rffi.CCHARP.TO))
+ assert space.eq_w(w_u, space.wrap(u"abcdefg"))
+ rffi.free_charp(data)
+
+ uni = u'abcdefg'
+ data = rffi.unicode2wcharp(uni)
+ w_s = api.PyUnicode_EncodeLatin1(data, len(uni), lltype.nullptr(rffi.CCHARP.TO))
+ assert space.eq_w(space.wrap("abcdefg"), w_s)
+ rffi.free_wcharp(data)
+
+ ustr = "abcdef"
+ w_ustr = space.wrap(ustr.decode("ascii"))
+ result = api.PyUnicode_AsLatin1String(w_ustr)
+ assert space.eq_w(space.wrap(ustr), result)
+
def test_format(self, space, api):
w_format = space.wrap(u'hi %s')
w_args = space.wrap((u'test',))
diff --git a/pypy/module/cpyext/test/test_weakref.py b/pypy/module/cpyext/test/test_weakref.py
--- a/pypy/module/cpyext/test/test_weakref.py
+++ b/pypy/module/cpyext/test/test_weakref.py
@@ -15,6 +15,12 @@
assert api.PyErr_Occurred() is space.w_TypeError
api.PyErr_Clear()
+ def test_proxy(self, space, api):
+ w_obj = space.w_Warning # some weakrefable object
+ w_proxy = api.PyWeakref_NewProxy(w_obj, None)
+ assert space.unwrap(space.str(w_proxy)) == "<type 'exceptions.Warning'>"
+ assert space.unwrap(space.repr(w_proxy)).startswith('<weak')
+
def test_weakref_lockobject(self, space, api):
# some new weakrefable object
w_obj = space.call_function(space.w_type, space.wrap("newtype"),
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -14,6 +14,7 @@
from pypy.module.sys.interp_encoding import setdefaultencoding
from pypy.objspace.std import unicodeobject, unicodetype
from pypy.rlib import runicode
+from pypy.tool.sourcetools import func_renamer
import sys
## See comment in stringobject.py.
@@ -417,26 +418,49 @@
ref[0] = rffi.cast(PyObject, py_newuni)
return 0
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsUTF8String(space, w_unicode):
- """Encode a Unicode object using UTF-8 and return the result as Python string
- object. Error handling is "strict". Return NULL if an exception was raised
- by the codec."""
- if not PyUnicode_Check(space, w_unicode):
- PyErr_BadArgument(space)
- return unicodetype.encode_object(space, w_unicode, "utf-8", "strict")
+def make_conversion_functions(suffix, encoding):
+ @cpython_api([PyObject], PyObject)
+ @func_renamer('PyUnicode_As%sString' % suffix)
+ def PyUnicode_AsXXXString(space, w_unicode):
+ """Encode a Unicode object and return the result as Python
+ string object. Error handling is "strict". Return NULL if an
+ exception was raised by the codec."""
+ if not PyUnicode_Check(space, w_unicode):
+ PyErr_BadArgument(space)
+ return unicodetype.encode_object(space, w_unicode, encoding, "strict")
- at cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING], PyObject)
-def PyUnicode_DecodeUTF8(space, s, size, errors):
- """Create a Unicode object by decoding size bytes of the UTF-8 encoded string
- s. Return NULL if an exception was raised by the codec.
- """
- w_str = space.wrap(rffi.charpsize2str(s, size))
- if errors:
- w_errors = space.wrap(rffi.charp2str(errors))
- else:
- w_errors = space.w_None
- return space.call_method(w_str, 'decode', space.wrap("utf-8"), w_errors)
+ @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING], PyObject)
+ @func_renamer('PyUnicode_Decode%s' % suffix)
+ def PyUnicode_DecodeXXX(space, s, size, errors):
+ """Create a Unicode object by decoding size bytes of the
+ encoded string s. Return NULL if an exception was raised by
+ the codec.
+ """
+ w_s = space.wrap(rffi.charpsize2str(s, size))
+ if errors:
+ w_errors = space.wrap(rffi.charp2str(errors))
+ else:
+ w_errors = space.w_None
+ return space.call_method(w_s, 'decode', space.wrap(encoding), w_errors)
+
+ @cpython_api([CONST_WSTRING, Py_ssize_t, CONST_STRING], PyObject)
+ @func_renamer('PyUnicode_Encode%s' % suffix)
+ def PyUnicode_EncodeXXX(space, s, size, errors):
+ """Encode the Py_UNICODE buffer of the given size and return a
+ Python string object. Return NULL if an exception was raised
+ by the codec."""
+ w_u = space.wrap(rffi.wcharpsize2unicode(s, size))
+ if errors:
+ w_errors = space.wrap(rffi.charp2str(errors))
+ else:
+ w_errors = space.w_None
+ return space.call_method(w_u, 'encode', space.wrap(encoding), w_errors)
+
+make_conversion_functions('UTF8', 'utf-8')
+make_conversion_functions('ASCII', 'ascii')
+make_conversion_functions('Latin1', 'latin-1')
+if sys.platform == 'win32':
+ make_conversion_functions('MBCS', 'mbcs')
@cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP, rffi.INTP], PyObject)
def PyUnicode_DecodeUTF16(space, s, size, llerrors, pbyteorder):
@@ -493,56 +517,6 @@
return space.wrap(result)
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsASCIIString(space, w_unicode):
- """Encode a Unicode object using ASCII and return the result as Python string
- object. Error handling is "strict". Return NULL if an exception was raised
- by the codec."""
- return space.call_method(w_unicode, 'encode', space.wrap('ascii')) #space.w_None for errors?
-
- at cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_DecodeASCII(space, s, size, errors):
- """Create a Unicode object by decoding size bytes of the ASCII encoded string
- s. Return NULL if an exception was raised by the codec."""
- w_s = space.wrap(rffi.charpsize2str(s, size))
- return space.call_method(w_s, 'decode', space.wrap('ascii'))
-
- at cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_EncodeASCII(space, s, size, errors):
- """Encode the Py_UNICODE buffer of the given size using ASCII and return a
- Python string object. Return NULL if an exception was raised by the codec.
- """
-
- w_s = space.wrap(rffi.wcharpsize2unicode(s, size))
- return space.call_method(w_s, 'encode', space.wrap('ascii'))
-
-if sys.platform == 'win32':
- @cpython_api([CONST_WSTRING, Py_ssize_t, CONST_STRING], PyObject)
- def PyUnicode_EncodeMBCS(space, wchar_p, length, errors):
- """Encode the Py_UNICODE buffer of the given size using MBCS and return a
- Python string object. Return NULL if an exception was raised by the codec.
- """
- w_unicode = space.wrap(rffi.wcharpsize2unicode(wchar_p, length))
- if errors:
- w_errors = space.wrap(rffi.charp2str(errors))
- else:
- w_errors = space.w_None
- return space.call_method(w_unicode, "encode",
- space.wrap("mbcs"), w_errors)
-
- @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING], PyObject)
- def PyUnicode_DecodeMBCS(space, s, size, errors):
- """Create a Unicode object by decoding size bytes of the MBCS encoded string s.
- Return NULL if an exception was raised by the codec.
- """
- w_str = space.wrap(rffi.charpsize2str(s, size))
- w_encoding = space.wrap("mbcs")
- if errors:
- w_errors = space.wrap(rffi.charp2str(errors))
- else:
- w_errors = space.w_None
- return space.call_method(w_str, 'decode', w_encoding, w_errors)
-
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-2)
def PyUnicode_Compare(space, w_left, w_right):
"""Compare two strings and return -1, 0, 1 for less than, equal, and greater
diff --git a/pypy/module/cpyext/weakrefobject.py b/pypy/module/cpyext/weakrefobject.py
--- a/pypy/module/cpyext/weakrefobject.py
+++ b/pypy/module/cpyext/weakrefobject.py
@@ -1,6 +1,6 @@
from pypy.module.cpyext.api import cpython_api
from pypy.module.cpyext.pyobject import PyObject, borrow_from
-from pypy.module._weakref.interp__weakref import W_Weakref
+from pypy.module._weakref.interp__weakref import W_Weakref, proxy
@cpython_api([PyObject, PyObject], PyObject)
def PyWeakref_NewRef(space, w_obj, w_callback):
@@ -16,6 +16,20 @@
w_weakref = space.gettypeobject(W_Weakref.typedef)
return space.call_function(w_weakref, w_obj, w_callback)
+ at cpython_api([PyObject, PyObject], PyObject)
+def PyWeakref_NewProxy(space, w_obj, w_callback):
+ """Return a weak reference proxy object for the object *ob*. This will
+ alwas return a new reference, but is not guaranteed to create a new
+ object; an existing proxy object may be returned. The second parameter,
+ *callback*, can be a callable object that receives notification when *ob*
+ is garbage collected; it should accept a single parameter, which will be
+ the weak reference object itself. *callback* may also be ``None`` or
+ *NULL*. If *ob* is not a weakly-referencable object, or if *callback* is
+ not callable, ``None``, or *NULL*, this will return *NULL* and raise
+ :exc:`TypeError`.
+ """
+ return proxy(space, w_obj, w_callback)
+
@cpython_api([PyObject], PyObject)
def PyWeakref_GetObject(space, w_ref):
"""Return the referenced object from a weak reference. If the referent is
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -201,6 +201,9 @@
def descr_get_shape(self, space):
return space.newtuple([self.descr_len(space)])
+ def descr_get_size(self, space):
+ return space.wrap(self.find_size())
+
def descr_copy(self, space):
return space.call_function(space.gettypefor(BaseArray), self, self.find_dtype())
@@ -607,6 +610,7 @@
dtype = GetSetProperty(BaseArray.descr_get_dtype),
shape = GetSetProperty(BaseArray.descr_get_shape),
+ size = GetSetProperty(BaseArray.descr_get_size),
mean = interp2app(BaseArray.descr_mean),
sum = interp2app(BaseArray.descr_sum),
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -17,6 +17,14 @@
a[13] = 5.3
assert a[13] == 5.3
+ def test_size(self):
+ from numpy import array
+ # XXX fixed on multidim branch
+ #assert array(3).size == 1
+ a = array([1, 2, 3])
+ assert a.size == 3
+ assert (a + a).size == 3
+
def test_empty(self):
"""
Test that empty() works.
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -10,7 +10,7 @@
CPYTHON_VERSION = (2, 7, 1, "final", 42) #XXX # sync patchlevel.h
CPYTHON_API_VERSION = 1013 #XXX # sync with include/modsupport.h
-PYPY_VERSION = (1, 6, 1, "dev", 0) #XXX # sync patchlevel.h
+PYPY_VERSION = (1, 7, 1, "dev", 0) #XXX # sync patchlevel.h
if platform.name == 'msvc':
COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -11,7 +11,7 @@
from pypy.interpreter.baseobjspace import ObjSpace
from pypy.interpreter.error import OperationError
from pypy.tool.sourcetools import compile2
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+from pypy.rlib.rarithmetic import ovfcheck
from pypy.objspace.flow import model
@@ -144,7 +144,7 @@
return ovfcheck(x % y)
def lshift_ovf(x, y):
- return ovfcheck_lshift(x, y)
+ return ovfcheck(x << y)
# slicing: operator.{get,set,del}slice() don't support b=None or c=None
def do_getslice(a, b, c):
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -6,7 +6,7 @@
from pypy.objspace.std.noneobject import W_NoneObject
from pypy.objspace.std.register_all import register_all
from pypy.rlib import jit
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift, LONG_BIT, r_uint
+from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, r_uint
from pypy.rlib.rbigint import rbigint
"""
@@ -245,7 +245,7 @@
b = w_int2.intval
if r_uint(b) < LONG_BIT: # 0 <= b < LONG_BIT
try:
- c = ovfcheck_lshift(a, b)
+ c = ovfcheck(a << b)
except OverflowError:
raise FailedToImplementArgs(space.w_OverflowError,
space.wrap("integer left shift"))
diff --git a/pypy/objspace/std/test/test_stdobjspace.py b/pypy/objspace/std/test/test_stdobjspace.py
--- a/pypy/objspace/std/test/test_stdobjspace.py
+++ b/pypy/objspace/std/test/test_stdobjspace.py
@@ -1,5 +1,6 @@
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import app2interp
+from pypy.conftest import gettestobjspace
class TestW_StdObjSpace:
@@ -60,3 +61,10 @@
typedef = None
assert space.isinstance_w(X(), space.w_str)
+
+ def test_withstrbuf_fastpath_isinstance(self):
+ from pypy.objspace.std.stringobject import W_StringObject
+
+ space = gettestobjspace(withstrbuf=True)
+ assert space._get_interplevel_cls(space.w_str) is W_StringObject
+
diff --git a/pypy/rlib/listsort.py b/pypy/rlib/listsort.py
--- a/pypy/rlib/listsort.py
+++ b/pypy/rlib/listsort.py
@@ -1,4 +1,4 @@
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+from pypy.rlib.rarithmetic import ovfcheck
## ------------------------------------------------------------------------
@@ -136,7 +136,7 @@
if lower(a.list[p + ofs], key):
lastofs = ofs
try:
- ofs = ovfcheck_lshift(ofs, 1)
+ ofs = ovfcheck(ofs << 1)
except OverflowError:
ofs = maxofs
else:
@@ -161,7 +161,7 @@
# key <= a[hint - ofs]
lastofs = ofs
try:
- ofs = ovfcheck_lshift(ofs, 1)
+ ofs = ovfcheck(ofs << 1)
except OverflowError:
ofs = maxofs
else:
diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -12,9 +12,6 @@
back to a signed int value
ovfcheck check on CPython whether the result of a signed
integer operation did overflow
-ovfcheck_lshift
- << with oveflow checking
- catering to 2.3/2.4 differences about <<
ovfcheck_float_to_int
convert to an integer or raise OverflowError
r_longlong
@@ -111,18 +108,6 @@
raise OverflowError, "signed integer expression did overflow"
return r
-def _local_ovfcheck(r):
- # a copy of the above, because we cannot call ovfcheck
- # in a context where no primitiveoperator is involved.
- assert not isinstance(r, r_uint), "unexpected ovf check on unsigned"
- if isinstance(r, long):
- raise OverflowError, "signed integer expression did overflow"
- return r
-
-def ovfcheck_lshift(a, b):
- "NOT_RPYTHON"
- return _local_ovfcheck(int(long(a) << b))
-
# Strange things happening for float to int on 64 bit:
# int(float(i)) != i because of rounding issues.
# These are the minimum and maximum float value that can
diff --git a/pypy/rlib/rgc.py b/pypy/rlib/rgc.py
--- a/pypy/rlib/rgc.py
+++ b/pypy/rlib/rgc.py
@@ -163,8 +163,10 @@
source_start, dest_start,
length):
# if the write barrier is not supported, copy by hand
- for i in range(length):
+ i = 0
+ while i < length:
dest[i + dest_start] = source[i + source_start]
+ i += 1
return
source_addr = llmemory.cast_ptr_to_adr(source)
dest_addr = llmemory.cast_ptr_to_adr(dest)
@@ -214,8 +216,8 @@
func._gc_no_collect_ = True
return func
-def is_light_finalizer(func):
- func._is_light_finalizer_ = True
+def must_be_light_finalizer(func):
+ func._must_be_light_finalizer_ = True
return func
# ____________________________________________________________
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -1,6 +1,6 @@
from pypy.objspace.flow.model import FunctionGraph, Constant, Variable, c_last_exception
from pypy.rlib.rarithmetic import intmask, r_uint, ovfcheck, r_longlong
-from pypy.rlib.rarithmetic import r_ulonglong, ovfcheck_lshift
+from pypy.rlib.rarithmetic import r_ulonglong
from pypy.rpython.lltypesystem import lltype, llmemory, lloperation, llheap
from pypy.rpython.lltypesystem import rclass
from pypy.rpython.ootypesystem import ootype
@@ -1035,7 +1035,7 @@
assert isinstance(x, int)
assert isinstance(y, int)
try:
- return ovfcheck_lshift(x, y)
+ return ovfcheck(x << y)
except OverflowError:
self.make_llexception()
diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -11,15 +11,17 @@
from pypy.translator.platform import platform
from pypy.rlib.rfloat import isfinite, isinf, isnan, INFINITY, NAN
+use_library_isinf_isnan = False
if sys.platform == "win32":
if platform.name == "msvc":
# When compiled with /O2 or /Oi (enable intrinsic functions)
# It's no more possible to take the address of some math functions.
# Ensure that the compiler chooses real functions instead.
eci = ExternalCompilationInfo(
- includes = ['math.h'],
+ includes = ['math.h', 'float.h'],
post_include_bits = ['#pragma function(floor)'],
)
+ use_library_isinf_isnan = True
else:
eci = ExternalCompilationInfo()
# Some math functions are C99 and not defined by the Microsoft compiler
@@ -108,18 +110,32 @@
#
# Custom implementations
+VERY_LARGE_FLOAT = 1.0
+while VERY_LARGE_FLOAT * 100.0 != INFINITY:
+ VERY_LARGE_FLOAT *= 64.0
+
+_lib_isnan = rffi.llexternal("_isnan", [lltype.Float], lltype.Signed,
+ compilation_info=eci)
+_lib_finite = rffi.llexternal("_finite", [lltype.Float], lltype.Signed,
+ compilation_info=eci)
+
def ll_math_isnan(y):
# By not calling into the external function the JIT can inline this.
# Floats are awesome.
+ if use_library_isinf_isnan and not jit.we_are_jitted():
+ return bool(_lib_isnan(y))
return y != y
def ll_math_isinf(y):
- # Use a bitwise OR so the JIT doesn't produce 2 different guards.
- return (y == INFINITY) | (y == -INFINITY)
+ if use_library_isinf_isnan and not jit.we_are_jitted():
+ return not _lib_finite(y) and not _lib_isnan(y)
+ return (y + VERY_LARGE_FLOAT) == y
def ll_math_isfinite(y):
# Use a custom hack that is reasonably well-suited to the JIT.
# Floats are awesome (bis).
+ if use_library_isinf_isnan and not jit.we_are_jitted():
+ return bool(_lib_finite(y))
z = 0.0 * y
return z == z # i.e.: z is not a NaN
@@ -136,10 +152,12 @@
Windows, FreeBSD and alpha Tru64 are amongst platforms that don't
always follow C99.
"""
- if isnan(x) or isnan(y):
+ if isnan(x):
return NAN
- if isinf(y):
+ if not isfinite(y):
+ if isnan(y):
+ return NAN
if isinf(x):
if math_copysign(1.0, x) == 1.0:
# atan2(+-inf, +inf) == +-pi/4
@@ -168,7 +186,7 @@
def ll_math_frexp(x):
# deal with special cases directly, to sidestep platform differences
- if isnan(x) or isinf(x) or not x:
+ if not isfinite(x) or not x:
mantissa = x
exponent = 0
else:
@@ -185,7 +203,7 @@
INT_MIN = int(-2**31)
def ll_math_ldexp(x, exp):
- if x == 0.0 or isinf(x) or isnan(x):
+ if x == 0.0 or not isfinite(x):
return x # NaNs, zeros and infinities are returned unchanged
if exp > INT_MAX:
# overflow (64-bit platforms only)
@@ -209,10 +227,11 @@
def ll_math_modf(x):
# some platforms don't do the right thing for NaNs and
# infinities, so we take care of special cases directly.
- if isinf(x):
- return (math_copysign(0.0, x), x)
- elif isnan(x):
- return (x, x)
+ if not isfinite(x):
+ if isnan(x):
+ return (x, x)
+ else: # isinf(x)
+ return (math_copysign(0.0, x), x)
intpart_p = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw')
try:
fracpart = math_modf(x, intpart_p)
@@ -223,13 +242,21 @@
def ll_math_fmod(x, y):
- if isinf(x) and not isnan(y):
- raise ValueError("math domain error")
+ # fmod(x, +/-Inf) returns x for finite x.
+ if isinf(y) and isfinite(x):
+ return x
- if y == 0:
- raise ValueError("math domain error")
-
- return math_fmod(x, y)
+ _error_reset()
+ r = math_fmod(x, y)
+ errno = rposix.get_errno()
+ if isnan(r):
+ if isnan(x) or isnan(y):
+ errno = 0
+ else:
+ errno = EDOM
+ if errno:
+ _likely_raise(errno, r)
+ return r
def ll_math_hypot(x, y):
@@ -242,16 +269,17 @@
_error_reset()
r = math_hypot(x, y)
errno = rposix.get_errno()
- if isnan(r):
- if isnan(x) or isnan(y):
- errno = 0
- else:
- errno = EDOM
- elif isinf(r):
- if isinf(x) or isnan(x) or isinf(y) or isnan(y):
- errno = 0
- else:
- errno = ERANGE
+ if not isfinite(r):
+ if isnan(r):
+ if isnan(x) or isnan(y):
+ errno = 0
+ else:
+ errno = EDOM
+ else: # isinf(r)
+ if isfinite(x) and isfinite(y):
+ errno = ERANGE
+ else:
+ errno = 0
if errno:
_likely_raise(errno, r)
return r
@@ -261,30 +289,30 @@
# deal directly with IEEE specials, to cope with problems on various
# platforms whose semantics don't exactly match C99
- if isnan(x):
- if y == 0.0:
- return 1.0 # NaN**0 = 1
- return x
-
- elif isnan(y):
+ if isnan(y):
if x == 1.0:
return 1.0 # 1**Nan = 1
return y
- elif isinf(x):
- odd_y = not isinf(y) and math_fmod(math_fabs(y), 2.0) == 1.0
- if y > 0.0:
- if odd_y:
- return x
- return math_fabs(x)
- elif y == 0.0:
- return 1.0
- else: # y < 0.0
- if odd_y:
- return math_copysign(0.0, x)
- return 0.0
+ if not isfinite(x):
+ if isnan(x):
+ if y == 0.0:
+ return 1.0 # NaN**0 = 1
+ return x
+ else: # isinf(x)
+ odd_y = not isinf(y) and math_fmod(math_fabs(y), 2.0) == 1.0
+ if y > 0.0:
+ if odd_y:
+ return x
+ return math_fabs(x)
+ elif y == 0.0:
+ return 1.0
+ else: # y < 0.0
+ if odd_y:
+ return math_copysign(0.0, x)
+ return 0.0
- elif isinf(y):
+ if isinf(y):
if math_fabs(x) == 1.0:
return 1.0
elif y > 0.0 and math_fabs(x) > 1.0:
@@ -299,17 +327,18 @@
_error_reset()
r = math_pow(x, y)
errno = rposix.get_errno()
- if isnan(r):
- # a NaN result should arise only from (-ve)**(finite non-integer)
- errno = EDOM
- elif isinf(r):
- # an infinite result here arises either from:
- # (A) (+/-0.)**negative (-> divide-by-zero)
- # (B) overflow of x**y with x and y finite
- if x == 0.0:
+ if not isfinite(r):
+ if isnan(r):
+ # a NaN result should arise only from (-ve)**(finite non-integer)
errno = EDOM
- else:
- errno = ERANGE
+ else: # isinf(r)
+ # an infinite result here arises either from:
+ # (A) (+/-0.)**negative (-> divide-by-zero)
+ # (B) overflow of x**y with x and y finite
+ if x == 0.0:
+ errno = EDOM
+ else:
+ errno = ERANGE
if errno:
_likely_raise(errno, r)
return r
@@ -358,18 +387,19 @@
r = c_func(x)
# Error checking fun. Copied from CPython 2.6
errno = rposix.get_errno()
- if isnan(r):
- if isnan(x):
- errno = 0
- else:
- errno = EDOM
- elif isinf(r):
- if isinf(x) or isnan(x):
- errno = 0
- elif can_overflow:
- errno = ERANGE
- else:
- errno = EDOM
+ if not isfinite(r):
+ if isnan(r):
+ if isnan(x):
+ errno = 0
+ else:
+ errno = EDOM
+ else: # isinf(r)
+ if not isfinite(x):
+ errno = 0
+ elif can_overflow:
+ errno = ERANGE
+ else:
+ errno = EDOM
if errno:
_likely_raise(errno, r)
return r
diff --git a/pypy/translator/backendopt/finalizer.py b/pypy/translator/backendopt/finalizer.py
--- a/pypy/translator/backendopt/finalizer.py
+++ b/pypy/translator/backendopt/finalizer.py
@@ -4,7 +4,7 @@
class FinalizerError(Exception):
""" __del__ marked as lightweight finalizer, but the analyzer did
- not agreed
+ not agree
"""
class FinalizerAnalyzer(graphanalyze.BoolGraphAnalyzer):
@@ -23,7 +23,7 @@
def analyze_light_finalizer(self, graph):
result = self.analyze_direct_call(graph)
if (result is self.top_result() and
- getattr(graph.func, '_is_light_finalizer_', False)):
+ getattr(graph.func, '_must_be_light_finalizer_', False)):
raise FinalizerError(FinalizerError.__doc__, graph)
return result
diff --git a/pypy/translator/backendopt/test/test_canraise.py b/pypy/translator/backendopt/test/test_canraise.py
--- a/pypy/translator/backendopt/test/test_canraise.py
+++ b/pypy/translator/backendopt/test/test_canraise.py
@@ -201,6 +201,16 @@
result = ra.can_raise(ggraph.startblock.operations[0])
assert result
+ def test_ll_arraycopy(self):
+ from pypy.rpython.lltypesystem import rffi
+ from pypy.rlib.rgc import ll_arraycopy
+ def f(a, b, c, d, e):
+ ll_arraycopy(a, b, c, d, e)
+ t, ra = self.translate(f, [rffi.CCHARP, rffi.CCHARP, int, int, int])
+ fgraph = graphof(t, f)
+ result = ra.can_raise(fgraph.startblock.operations[0])
+ assert not result
+
class TestOOType(OORtypeMixin, BaseTestCanRaise):
def test_can_raise_recursive(self):
diff --git a/pypy/translator/backendopt/test/test_finalizer.py b/pypy/translator/backendopt/test/test_finalizer.py
--- a/pypy/translator/backendopt/test/test_finalizer.py
+++ b/pypy/translator/backendopt/test/test_finalizer.py
@@ -126,13 +126,13 @@
r = self.analyze(f, [], A.__del__.im_func)
assert r
- def test_is_light_finalizer_decorator(self):
+ def test_must_be_light_finalizer_decorator(self):
S = lltype.GcStruct('S')
- @rgc.is_light_finalizer
+ @rgc.must_be_light_finalizer
def f():
lltype.malloc(S)
- @rgc.is_light_finalizer
+ @rgc.must_be_light_finalizer
def g():
pass
self.analyze(g, []) # did not explode
diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py
--- a/pypy/translator/c/genc.py
+++ b/pypy/translator/c/genc.py
@@ -521,13 +521,13 @@
rules = [
('clean', '', 'rm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) $(ASMFILES) *.gc?? ../module_cache/*.gc??'),
('clean_noprof', '', 'rm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) $(ASMFILES)'),
- ('debug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT" $(TARGET)'),
- ('debug_exc', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DDO_LOG_EXC" $(TARGET)'),
- ('debug_mem', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DTRIVIAL_MALLOC_DEBUG" $(TARGET)'),
+ ('debug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT" debug_target'),
+ ('debug_exc', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DDO_LOG_EXC" debug_target'),
+ ('debug_mem', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DTRIVIAL_MALLOC_DEBUG" debug_target'),
('no_obmalloc', '', '$(MAKE) CFLAGS="-g -O2 -DRPY_ASSERT -DNO_OBMALLOC" $(TARGET)'),
- ('linuxmemchk', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DLINUXMEMCHK" $(TARGET)'),
+ ('linuxmemchk', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DLINUXMEMCHK" debug_target'),
('llsafer', '', '$(MAKE) CFLAGS="-O2 -DRPY_LL_ASSERT" $(TARGET)'),
- ('lldebug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DRPY_LL_ASSERT" $(TARGET)'),
+ ('lldebug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
('profile', '', '$(MAKE) CFLAGS="-g -O1 -pg $(CFLAGS) -fno-omit-frame-pointer" LDFLAGS="-pg $(LDFLAGS)" $(TARGET)'),
]
if self.has_profopt():
@@ -554,7 +554,7 @@
mk.definition('ASMLBLFILES', lblsfiles)
mk.definition('GCMAPFILES', gcmapfiles)
if sys.platform == 'win32':
- mk.definition('DEBUGFLAGS', '/Zi')
+ mk.definition('DEBUGFLAGS', '/MD /Zi')
else:
mk.definition('DEBUGFLAGS', '-O2 -fomit-frame-pointer -g')
@@ -618,9 +618,13 @@
else:
if sys.platform == 'win32':
- mk.definition('DEBUGFLAGS', '/Zi')
+ mk.definition('DEBUGFLAGS', '/MD /Zi')
else:
mk.definition('DEBUGFLAGS', '-O1 -g')
+ if sys.platform == 'win32':
+ mk.rule('debug_target', 'debugmode_$(DEFAULT_TARGET)', 'rem')
+ else:
+ mk.rule('debug_target', '$(TARGET)', '#')
mk.write()
#self.translator.platform,
# ,
diff --git a/pypy/translator/cli/test/test_snippet.py b/pypy/translator/cli/test/test_snippet.py
--- a/pypy/translator/cli/test/test_snippet.py
+++ b/pypy/translator/cli/test/test_snippet.py
@@ -28,14 +28,14 @@
res = self.interpret(fn, [], backendopt=False)
def test_link_vars_overlapping(self):
- from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+ from pypy.rlib.rarithmetic import ovfcheck
def fn(maxofs):
lastofs = 0
ofs = 1
while ofs < maxofs:
lastofs = ofs
try:
- ofs = ovfcheck_lshift(ofs, 1)
+ ofs = ovfcheck(ofs << 1)
except OverflowError:
ofs = maxofs
else:
diff --git a/pypy/translator/platform/__init__.py b/pypy/translator/platform/__init__.py
--- a/pypy/translator/platform/__init__.py
+++ b/pypy/translator/platform/__init__.py
@@ -102,6 +102,8 @@
bits = [self.__class__.__name__, 'cc=%r' % self.cc]
for varname in self.relevant_environ:
bits.append('%s=%r' % (varname, os.environ.get(varname)))
+ # adding sys.maxint to disambiguate windows
+ bits.append('%s=%r' % ('sys.maxint', sys.maxint))
return ' '.join(bits)
# some helpers which seem to be cross-platform enough
diff --git a/pypy/translator/platform/windows.py b/pypy/translator/platform/windows.py
--- a/pypy/translator/platform/windows.py
+++ b/pypy/translator/platform/windows.py
@@ -294,6 +294,9 @@
['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS) /MANIFEST /MANIFESTFILE:$*.manifest',
'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1',
])
+ m.rule('debugmode_$(TARGET)', '$(OBJECTS)',
+ ['$(CC_LINK) /nologo /DEBUG $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS)',
+ ])
if shared:
m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename)
@@ -307,6 +310,9 @@
['$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@ /MANIFEST /MANIFESTFILE:$*.manifest',
'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1',
])
+ m.rule('debugmode_$(DEFAULT_TARGET)', ['debugmode_$(TARGET)', 'main.obj'],
+ ['$(CC_LINK) /nologo /DEBUG main.obj $(SHARED_IMPORT_LIB) /out:$@'
+ ])
return m
diff --git a/pypy/translator/simplify.py b/pypy/translator/simplify.py
--- a/pypy/translator/simplify.py
+++ b/pypy/translator/simplify.py
@@ -111,16 +111,13 @@
# the while loop above will simplify recursively the new link
def transform_ovfcheck(graph):
- """The special function calls ovfcheck and ovfcheck_lshift need to
+ """The special function calls ovfcheck needs to
be translated into primitive operations. ovfcheck is called directly
after an operation that should be turned into an overflow-checked
version. It is considered a syntax error if the resulting <op>_ovf
is not defined in objspace/flow/objspace.py.
- ovfcheck_lshift is special because there is no preceding operation.
- Instead, it will be replaced by an OP_LSHIFT_OVF operation.
"""
covf = Constant(rarithmetic.ovfcheck)
- covfls = Constant(rarithmetic.ovfcheck_lshift)
def check_syntax(opname):
exlis = operation.implicit_exceptions.get("%s_ovf" % (opname,), [])
@@ -154,9 +151,6 @@
op1.opname += '_ovf'
del block.operations[i]
block.renamevariables({op.result: op1.result})
- elif op.args[0] == covfls:
- op.opname = 'lshift_ovf'
- del op.args[0]
def simplify_exceptions(graph):
"""The exception handling caused by non-implicit exceptions
diff --git a/pypy/translator/test/snippet.py b/pypy/translator/test/snippet.py
--- a/pypy/translator/test/snippet.py
+++ b/pypy/translator/test/snippet.py
@@ -1210,7 +1210,7 @@
return istk.top(), sstk.top()
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+from pypy.rlib.rarithmetic import ovfcheck
def add_func(i=numtype):
try:
@@ -1253,7 +1253,7 @@
def lshift_func(i=numtype):
try:
hugo(2, 3, 5)
- return ovfcheck_lshift((-maxint-1), i)
+ return ovfcheck((-maxint-1) << i)
except (hugelmugel, OverflowError, StandardError, ValueError):
raise
More information about the pypy-commit
mailing list