[pypy-svn] r26680 - in pypy/dist/pypy: annotation rpython/rctypes rpython/rctypes/test translator/backendopt translator/backendopt/test

arigo at codespeak.net arigo at codespeak.net
Tue May 2 19:11:57 CEST 2006


Author: arigo
Date: Tue May  2 19:11:55 2006
New Revision: 26680

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/rpython/rctypes/rpyobject.py
   pypy/dist/pypy/rpython/rctypes/test/test_overhead.py
   pypy/dist/pypy/rpython/rctypes/test/test_rpyobject.py
   pypy/dist/pypy/translator/backendopt/malloc.py
   pypy/dist/pypy/translator/backendopt/test/test_malloc.py
Log:
(pedronis, arigo)  Support for mixing None and py_object() -- not other
ctypes objects, only py_object, because the rules for what 'None' means
when in ctypes are, let's say, interesting.



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Tue May  2 19:11:55 2006
@@ -810,3 +810,17 @@
             return SomeCTypesObject(s_cto1.knowntype, state)
         else:
             return SomeObject()
+
+class __extend__(pairtype(SomeCTypesObject, SomePBC)):
+    def union((obj, pbc)):
+        if pbc.isNone() and obj.can_be_none():
+            return obj
+        else:
+            return SomeObject()
+
+class __extend__(pairtype(SomePBC, SomeCTypesObject)):
+    def union((pbc, obj)):
+        if pbc.isNone() and obj.can_be_none():
+            return obj
+        else:
+            return SomeObject()

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Tue May  2 19:11:55 2006
@@ -427,7 +427,9 @@
         self.memorystate = memorystate 
 
     def can_be_none(self):
-        return False
+        # only 'py_object' can also be None
+        import ctypes
+        return issubclass(self.knowntype, ctypes.py_object)
 
     def return_annotation(self):
         """Returns either 'self' or the annotation of the unwrapped version

Modified: pypy/dist/pypy/rpython/rctypes/rpyobject.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rpyobject.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rpyobject.py	Tue May  2 19:11:55 2006
@@ -7,6 +7,12 @@
 
 class CTypesPyObjRepr(CTypesValueRepr):
 
+    def convert_const(self, value):
+        if value is None:
+            return lltype.nullptr(self.lowleveltype.TO)
+        else:
+            return super(CTypesPyObjRepr, self).convert_const(value)
+
     def initialize_const(self, p, value):
         if isinstance(value, self.ctype):
             value = value.value
@@ -29,6 +35,13 @@
                                                     pyobj_repr)
         self.setvalue(hop.llops, v_pyobj, v_newvalue)
 
+    def rtype_is_true(self, hop):
+        [v_box] = hop.inputargs(self)
+        return hop.gendirectcall(ll_pyobjbox_is_true, v_box)
+
+def ll_pyobjbox_is_true(box):
+    return bool(box) and bool(box.c_data[0])
+
 
 class __extend__(pairtype(CTypesPyObjRepr, PyObjRepr)):
     # conversion used by wrapper.py in genc when returning a py_object

Modified: pypy/dist/pypy/rpython/rctypes/test/test_overhead.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_overhead.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_overhead.py	Tue May  2 19:11:55 2006
@@ -9,7 +9,7 @@
 from pypy.rpython.test.test_llinterp import gengraph
 from pypy.translator.backendopt.all import backend_optimizations
 
-from ctypes import c_int, Structure, pointer, POINTER
+from ctypes import c_int, Structure, pointer, POINTER, py_object
 
 
 def find_mallocs(func, argtypes):
@@ -92,3 +92,16 @@
     
     mallocs = find_mallocs(func, [])
     assert not mallocs    # depends on inlining
+
+def test_using_pyobject():
+    def g(n):
+        if n == 2:
+            w = py_object()
+        else:
+            w = py_object(n)
+        return w
+    def func(n):
+        return bool(g(n))
+
+    mallocs = find_mallocs(func, [int])
+    assert not mallocs    # depends on inlining

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rpyobject.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rpyobject.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rpyobject.py	Tue May  2 19:11:55 2006
@@ -13,7 +13,7 @@
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.rpython.lltypesystem import lltype
 
-from ctypes import py_object
+from ctypes import py_object, CFUNCTYPE, c_int
 
 
 class Test_annotation:
@@ -46,6 +46,23 @@
         if conftest.option.view:
             a.translator.view()
 
+    def test_annotate_mix_with_None(self):
+        def fn(i):
+            if i == 1:
+                p = py_object(123)
+            elif i == 2:
+                p = py_object()
+            else:
+                p = None
+            return p
+
+        a = RPythonAnnotator()
+        s = a.build_types(fn, [int])
+        assert s.knowntype == py_object
+        assert s.can_be_none()    # NB. it's actually always True for now
+        if conftest.option.view:
+            a.translator.view()
+
 class Test_specialization:
     def test_specialize_wrapping(self):
         def wrap(x):
@@ -75,3 +92,23 @@
         assert res.c_data[0]._obj.value == 5
         res = interpret(fn, [1])
         assert res.c_data[0]._obj.value == "hello"
+
+    def test_specialize_with_none(self):
+        def g(i):
+            if i == 1:
+                p = py_object(123)
+            elif i == 2:
+                p = py_object()
+            else:
+                p = None
+            return p
+        def fn(i):
+            p = g(i)
+            return bool(p), p is None
+
+        res = interpret(fn, [1])
+        assert (res.item0, res.item1) == (True, False)
+        res = interpret(fn, [2])
+        assert (res.item0, res.item1) == (False, False)
+        res = interpret(fn, [3])
+        assert (res.item0, res.item1) == (False, True)

Modified: pypy/dist/pypy/translator/backendopt/malloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/malloc.py	(original)
+++ pypy/dist/pypy/translator/backendopt/malloc.py	Tue May  2 19:11:55 2006
@@ -136,11 +136,13 @@
     assert isinstance(STRUCT, lltype.GcStruct)
 
     # must be only ever accessed via getfield/setfield/getsubstruct/
-    # direct_fieldptr, or touched by keepalive.  Note that same_as and
-    # cast_pointer are not recorded in usepoints.
+    # direct_fieldptr, or touched by keepalive or ptr_iszero/ptr_nonzero.
+    # Note that same_as and cast_pointer are not recorded in usepoints.
     FIELD_ACCESS     = dict.fromkeys(["getfield",
                                       "setfield",
                                       "keepalive",
+                                      "ptr_iszero",
+                                      "ptr_nonzero",
                                       "getarrayitem",
                                       "setarrayitem"])
     SUBSTRUCT_ACCESS = dict.fromkeys(["getsubstruct",
@@ -327,6 +329,12 @@
                                                    [v, cname],
                                                    op.result)
                             newops.append(newop)
+                    elif op.opname in ("ptr_iszero", "ptr_nonzero"):
+                        # we know the pointer is not NULL if it comes from
+                        # a successful malloc
+                        c = Constant(op.opname == "ptr_nonzero", lltype.Bool)
+                        newop = SpaceOperation('same_as', [c], op.result)
+                        newops.append(newop)
                     else:
                         raise AssertionError, op.opname
                 elif op.result in vars:

Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_malloc.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py	Tue May  2 19:11:55 2006
@@ -252,3 +252,11 @@
                 s.a[index].n = 12
                 return s.a[index].n
             check(fn, [], [], 12)
+
+def test_ptr_nonzero():
+    from pypy.rpython.lltypesystem import lltype
+    S = lltype.GcStruct('S')
+    def fn():
+        s = lltype.malloc(S)
+        return bool(s)
+    check(fn, [], [], True)



More information about the Pypy-commit mailing list