[pypy-svn] pypy default: merge heads

arigo commits-noreply at bitbucket.org
Fri Apr 15 11:14:11 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r43380:556eef428694
Date: 2011-04-15 11:13 +0200
http://bitbucket.org/pypy/pypy/changeset/556eef428694/

Log:	merge heads

diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -1354,6 +1354,12 @@
         log = self.run(main, [], threshold=200)
         assert log.result == 9895050.0
         loop, = log.loops_by_filename(self.filepath)
+        #
+        # check that the overloaded __getitem__ does not introduce double
+        # array bound checks.
+        #
+        # The force_token()s are still there, but will be eliminated by the
+        # backend regalloc, so they are harmless
         assert loop.match("""
             ...
             i20 = int_ge(i18, i8)
@@ -1378,9 +1384,6 @@
             f39 = getarrayitem_raw(i13, i36, descr=...)
             ...
         """)
-        # XXX: what do we want to check here?        
-        # We want to make sure that the overloaded __getitem__
-        # not introduceds double array bound checks
 
     def test_circular(self):
         def main():
@@ -1404,6 +1407,11 @@
         log = self.run(main, [], threshold=200)
         assert log.result == 1239690.0
         loop, = log.loops_by_filename(self.filepath)
+        #
+        # check that the array bound checks are removed
+        #
+        # The force_token()s are still there, but will be eliminated by the
+        # backend regalloc, so they are harmless
         assert loop.match("""
             ...
             i17 = int_and(i14, 255)
@@ -1425,7 +1433,50 @@
             f37 = getarrayitem_raw(i8, i36, descr=...)
             ...
         """)
+
+    def test_min_max(self):
+        def main():
+            i=0
+            sa=0
+            while i < 300: 
+                sa+=min(max(i, 3000), 4000)
+                i+=1
+            return sa
+        log = self.run(main, [], threshold=200)
+        assert log.result == 300*3000
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i7 = int_lt(i4, 300)
+            guard_true(i7, descr=...)
+            i9 = int_add_ovf(i5, 3000)
+            guard_no_overflow(descr=...)
+            i11 = int_add(i4, 1)
+            --TICK--
+            jump(p0, p1, p2, p3, i11, i9, descr=<Loop0>)
+        """)
+
+    def test_silly_max(self):
+        def main():
+            i=2
+            sa=0
+            while i < 300: 
+                sa+=max(*range(i))
+                i+=1
+            return sa
+        log = self.run(main, [], threshold=200)
+        assert log.result == main()
+        loop, = log.loops_by_filename(self.filepath)
         # XXX: what do we want to check here?
-        # We want to check that the array bound checks are removed,
-        # so it's this part of the trace. However we dont care about
-        # the force_token()'s. Can they be ignored?
+
+    def test_iter_max(self):
+        def main():
+            i=2
+            sa=0
+            while i < 300:
+                sa+=max(range(i))
+                i+=1
+            return sa
+        log = self.run(main, [], threshold=200)
+        assert log.result == main()
+        loop, = log.loops_by_filename(self.filepath)
+        # XXX: what do we want to check here?

diff --git a/pypy/translator/c/test/test_database.py b/pypy/translator/c/test/test_database.py
--- a/pypy/translator/c/test/test_database.py
+++ b/pypy/translator/c/test/test_database.py
@@ -5,7 +5,7 @@
 from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
 from pypy.objspace.flow.model import Block, Link, FunctionGraph
 from pypy.rpython.typesystem import getfunctionptr
-from pypy.rpython.lltypesystem.rffi import VOIDP, INT_real, INT
+from pypy.rpython.lltypesystem.rffi import VOIDP, INT_real, INT, CArrayPtr
 
 
 def dump_on_stdout(database):
@@ -244,3 +244,15 @@
     db.get(p)
     db.complete()
     dump_on_stdout(db)
+
+def test_typedef():
+    A = Typedef(Signed, 'test4')
+    db = LowLevelDatabase()
+    assert db.gettype(A) == "test4 @"
+
+    PA = CArrayPtr(A)
+    assert db.gettype(PA) == "test4 *@"
+
+    F = FuncType((A,), A)
+    assert db.gettype(F) == "test4 (@)(test4)"
+

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
@@ -37,7 +37,7 @@
 DEBUG_WRAPPER = True
 
 # update these for other platforms
-Py_ssize_t = lltype.Signed
+Py_ssize_t = lltype.Typedef(rffi.SSIZE_T, 'Py_ssize_t')
 Py_ssize_tP = rffi.CArrayPtr(Py_ssize_t)
 size_t = rffi.ULONG
 ADDR = lltype.Signed
@@ -192,14 +192,19 @@
     - set `external` to False to get a C function pointer, but not exported by
       the API headers.
     """
+    if isinstance(restype, lltype.Typedef):
+        real_restype = restype.OF
+    else:
+        real_restype = restype
+
     if error is _NOT_SPECIFIED:
-        if isinstance(restype, lltype.Ptr):
-            error = lltype.nullptr(restype.TO)
-        elif restype is lltype.Void:
+        if isinstance(real_restype, lltype.Ptr):
+            error = lltype.nullptr(real_restype.TO)
+        elif real_restype is lltype.Void:
             error = CANNOT_FAIL
     if type(error) is int:
-        error = rffi.cast(restype, error)
-    expect_integer = (isinstance(restype, lltype.Primitive) and
+        error = rffi.cast(real_restype, error)
+    expect_integer = (isinstance(real_restype, lltype.Primitive) and
                       rffi.cast(restype, 0) == 0)
 
     def decorate(func):

diff --git a/pypy/module/pypyjit/test/test_pypy_c.py b/pypy/module/pypyjit/test/test_pypy_c.py
--- a/pypy/module/pypyjit/test/test_pypy_c.py
+++ b/pypy/module/pypyjit/test/test_pypy_c.py
@@ -223,39 +223,6 @@
             return total
         ''' % startvalue, 170, ([], startvalue + 4999450000L))
 
-    def test_min_max(self):
-        self.run_source('''
-        def main():
-            i=0
-            sa=0
-            while i < 2000: 
-                sa+=min(max(i, 3000), 4000)
-                i+=1
-            return sa
-        ''', 51, ([], 2000*3000))
-
-    def test_silly_max(self):
-        self.run_source('''
-        def main():
-            i=2
-            sa=0
-            while i < 2000: 
-                sa+=max(*range(i))
-                i+=1
-            return sa
-        ''', 125, ([], 1997001))
-
-    def test_iter_max(self):
-        self.run_source('''
-        def main():
-            i=2
-            sa=0
-            while i < 2000: 
-                sa+=max(range(i))
-                i+=1
-            return sa
-        ''', 88, ([], 1997001))
-
     def test__ffi_call(self):
         from pypy.rlib.test.test_libffi import get_libm_name
         libm_name = get_libm_name(sys.platform)

diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -818,6 +818,8 @@
     """Similar to llmemory.sizeof() but tries hard to return a integer
     instead of a symbolic value.
     """
+    if isinstance(tp, lltype.Typedef):
+        tp = tp.OF
     if isinstance(tp, lltype.FixedSizeArray):
         return sizeof(tp.OF) * tp.length
     if isinstance(tp, lltype.Struct):

diff --git a/pypy/module/cpyext/test/test_api.py b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -70,11 +70,35 @@
         if self.check_and_print_leaks():
             assert False, "Test leaks or loses object(s)."
 
+ at api.cpython_api([api.Py_ssize_t], api.Py_ssize_t, error=-1)
+def PyPy_TypedefTest1(space, arg):
+    assert lltype.typeOf(arg) == api.Py_ssize_t
+    return 0
+
+ at api.cpython_api([api.Py_ssize_tP], api.Py_ssize_tP)
+def PyPy_TypedefTest2(space, arg):
+    assert lltype.typeOf(arg) == api.Py_ssize_tP
+    return None
+
 class TestConversion(BaseApiTest):
     def test_conversions(self, space, api):
         api.PyPy_GetWrapped(space.w_None)
         api.PyPy_GetReference(space.w_None)
 
+    def test_typedef(self, space):
+        from pypy.translator.c.database import LowLevelDatabase
+        db = LowLevelDatabase()
+        assert (api.c_function_signature(db, api.FUNCTIONS['PyPy_TypedefTest1'])
+                == ('Py_ssize_t', 'Py_ssize_t arg0'))
+        assert (api.c_function_signature(db, api.FUNCTIONS['PyPy_TypedefTest2'])
+                == ('Py_ssize_t *', 'Py_ssize_t *arg0'))
+
+        PyPy_TypedefTest1(space, 0)
+        ppos = lltype.malloc(api.Py_ssize_tP.TO, 1, flavor='raw')
+        ppos[0] = 0
+        PyPy_TypedefTest2(space, ppos)
+        lltype.free(ppos, flavor='raw')
+
 
 def test_copy_header_files(tmpdir):
     api.copy_header_files(tmpdir)

diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py
--- a/pypy/rpython/lltypesystem/ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/ll2ctypes.py
@@ -255,6 +255,9 @@
         return cls
 
 def build_new_ctypes_type(T, delayed_builders):
+    if isinstance(T, lltype.Typedef):
+        T = T.OF
+
     if isinstance(T, lltype.Ptr):
         if isinstance(T.TO, lltype.FuncType):
             argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS
@@ -758,6 +761,8 @@
     """
     if T is lltype.Void:
         return None
+    if isinstance(T, lltype.Typedef):
+        T = T.OF
     if isinstance(T, lltype.Ptr):
         if not cobj or not ctypes.cast(cobj, ctypes.c_void_p).value:   # NULL pointer
             # CFunctionType.__nonzero__ is broken before Python 2.6

diff --git a/pypy/rpython/lltypesystem/module/test/test_ll_math.py b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
--- a/pypy/rpython/lltypesystem/module/test/test_ll_math.py
+++ b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
@@ -3,6 +3,7 @@
 
 from pypy.rpython.lltypesystem.module import ll_math
 from pypy.module.math.test.test_direct import MathTests, get_tester
+from pypy.translator.c.test.test_genc import compile
 
 
 class TestMath(MathTests):
@@ -21,6 +22,13 @@
         assert ll_math.ll_math_isnan(nan)
         assert not ll_math.ll_math_isnan(inf)
 
+    def test_compiled_isinf(self):
+        def f(x):
+            return ll_math.ll_math_isinf(1. / x)
+        f = compile(f, [float], backendopt=False)
+        assert f(5.5e-309)
+
+
 def make_test_case((fnname, args, expected), dict):
     #
     def test_func(self):

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
@@ -20,8 +20,7 @@
         separate_module_files=[cdir.join('src', 'll_math.c')],
         export_symbols=['_pypy_math_acosh', '_pypy_math_asinh',
                         '_pypy_math_atanh',
-                        '_pypy_math_expm1', '_pypy_math_log1p',
-                        '_pypy_math_isinf'],
+                        '_pypy_math_expm1', '_pypy_math_log1p'],
         )
     math_prefix = '_pypy_math_'
 else:
@@ -95,9 +94,9 @@
     # are awesome.
     return y != y
 
- at jit.purefunction
 def ll_math_isinf(y):
-    return bool(math_isinf(y))
+    # Use a bitwise OR so the JIT doesn't produce 2 different guards.
+    return (y == INFINITY) | (y == -INFINITY)
 
 
 ll_math_copysign = math_copysign

diff --git a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
--- a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
+++ b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
@@ -1000,6 +1000,13 @@
         p = ctypes2lltype(lltype.Ptr(NODE), ctypes.pointer(pc))
         assert p.pong.ping == p
 
+    def test_typedef(self):
+        assert ctypes2lltype(lltype.Typedef(lltype.Signed, 'test'), 6) == 6
+        assert ctypes2lltype(lltype.Typedef(lltype.Float, 'test2'), 3.4) == 3.4
+
+        assert get_ctypes_type(lltype.Signed) == get_ctypes_type(
+            lltype.Typedef(lltype.Signed, 'test3'))
+
     def test_cast_adr_to_int(self):
         class someaddr(object):
             def _cast_to_int(self):

diff --git a/pypy/rpython/lltypesystem/test/test_rffi.py b/pypy/rpython/lltypesystem/test/test_rffi.py
--- a/pypy/rpython/lltypesystem/test/test_rffi.py
+++ b/pypy/rpython/lltypesystem/test/test_rffi.py
@@ -728,6 +728,7 @@
     
         for ll, ctp in cache.items():
             assert sizeof(ll) == ctypes.sizeof(ctp)
+            assert sizeof(lltype.Typedef(ll, 'test')) == sizeof(ll)
         assert not size_and_sign(lltype.Signed)[1]
         assert not size_and_sign(lltype.Char)[1]
         assert not size_and_sign(lltype.UniChar)[1]

diff --git a/pypy/translator/c/src/ll_math.h b/pypy/translator/c/src/ll_math.h
--- a/pypy/translator/c/src/ll_math.h
+++ b/pypy/translator/c/src/ll_math.h
@@ -1,8 +1,6 @@
 /* Definitions of some C99 math library functions, for those platforms
    that don't implement these functions already. */
 
-int _pypy_math_isinf(double x);
-
 double _pypy_math_acosh(double x);
 double _pypy_math_asinh(double x);
 double _pypy_math_atanh(double x);

diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -641,6 +641,8 @@
     except TypeError:
         s = None    # unhashable T, e.g. a Ptr(GcForwardReference())
     if s is None:
+        if isinstance(T, lltype.Typedef):
+            return lltype_to_annotation(T.OF)
         if isinstance(T, lltype.Number):
             return SomeInteger(knowntype=T._type)
         if isinstance(T, (ootype.Instance, ootype.BuiltinType)):

diff --git a/pypy/rpython/lltypesystem/lltype.py b/pypy/rpython/lltypesystem/lltype.py
--- a/pypy/rpython/lltypesystem/lltype.py
+++ b/pypy/rpython/lltypesystem/lltype.py
@@ -95,6 +95,8 @@
     __slots__ = ['__dict__', '__cached_hash']
 
     def __eq__(self, other):
+        if isinstance(other, Typedef):
+            return other.__eq__(self)
         return self.__class__ is other.__class__ and (
             self is other or safe_equal(self.__dict__, other.__dict__))
 
@@ -194,6 +196,36 @@
         raise NotImplementedError
 
 
+class Typedef(LowLevelType):
+    """A typedef is just another name for an existing type"""
+    def __init__(self, OF, c_name):
+        """
+        @param OF: the equivalent rffi type
+        @param c_name: the name we want in C code
+        """
+        assert isinstance(OF, LowLevelType)
+        # Look through typedefs, so other places don't have to
+        if isinstance(OF, Typedef):
+            OF = OF.OF # haha
+        self.OF = OF
+        self.c_name = c_name
+
+    def __repr__(self):
+        return '<Typedef "%s" of %r>' % (self.c_name, self.OF)
+
+    def __eq__(self, other):
+        return other == self.OF
+
+    def __getattr__(self, name):
+        return self.OF.get(name)
+
+    def _defl(self, parent=None, parentindex=None):
+        return self.OF._defl()
+
+    def _allocate(self, initialization, parent=None, parentindex=None):
+        return self.OF._allocate(initialization, parent, parentindex)
+
+
 class Struct(ContainerType):
     _gckind = 'raw'
 

diff --git a/pypy/translator/c/src/ll_math.c b/pypy/translator/c/src/ll_math.c
--- a/pypy/translator/c/src/ll_math.c
+++ b/pypy/translator/c/src/ll_math.c
@@ -22,12 +22,6 @@
 #endif
 #define PyPy_NAN (HUGE_VAL * 0.)
 
-int
-_pypy_math_isinf(double x)
-{
-    return PyPy_IS_INFINITY(x);
-}
-
 /* The following copyright notice applies to the original
    implementations of acosh, asinh and atanh. */
 

diff --git a/pypy/translator/c/database.py b/pypy/translator/c/database.py
--- a/pypy/translator/c/database.py
+++ b/pypy/translator/c/database.py
@@ -1,7 +1,7 @@
-from pypy.rpython.lltypesystem.lltype import \
-     Primitive, Ptr, typeOf, RuntimeTypeInfo, \
-     Struct, Array, FuncType, PyObject, Void, \
-     ContainerType, OpaqueType, FixedSizeArray, _uninitialized
+
+from pypy.rpython.lltypesystem.lltype import (
+    Primitive, Ptr, typeOf, RuntimeTypeInfo, Struct, Array, FuncType, PyObject,
+    Void, ContainerType, OpaqueType, FixedSizeArray, _uninitialized, Typedef)
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython.lltypesystem.llmemory import WeakRef, _WeakRefType, GCREF
 from pypy.rpython.lltypesystem.rffi import CConstant
@@ -100,6 +100,8 @@
     def gettype(self, T, varlength=1, who_asks=None, argnames=[]):
         if isinstance(T, Primitive) or T == GCREF:
             return PrimitiveType[T]
+        elif isinstance(T, Typedef):
+            return '%s @' % T.c_name
         elif isinstance(T, Ptr):
             if (isinstance(T.TO, OpaqueType) and
                 T.TO.hints.get('c_pointer_typedef') is not None):

diff --git a/pypy/rpython/lltypesystem/test/test_lltype.py b/pypy/rpython/lltypesystem/test/test_lltype.py
--- a/pypy/rpython/lltypesystem/test/test_lltype.py
+++ b/pypy/rpython/lltypesystem/test/test_lltype.py
@@ -804,6 +804,21 @@
                  hints={'immutable_fields': FieldListAccessor({'x':'[*]'})})
     assert S._immutable_field('x') == '[*]'
 
+def test_typedef():
+    T = Typedef(Signed, 'T')
+    assert T == Signed
+    assert Signed == T
+    T2 = Typedef(T, 'T2')
+    assert T2 == T
+    assert T2.OF is Signed
+    py.test.raises(TypeError, Ptr, T)
+    assert rffi.CArrayPtr(T) == rffi.CArrayPtr(Signed)
+    assert rffi.CArrayPtr(Signed) == rffi.CArrayPtr(T)
+
+    F = FuncType((T,), T)
+    assert F.RESULT == Signed
+    assert F.ARGS == (Signed,)
+
 
 class TestTrackAllocation:
     def test_automatic_tracking(self):


More information about the Pypy-commit mailing list