Author: Armin Rigo <[email protected]>
Branch: cpyext-gc-support
Changeset: r80370:4df1301d6ea2
Date: 2015-10-21 10:03 +0200
http://bitbucket.org/pypy/pypy/changeset/4df1301d6ea2/

Log:    tweaks tweaks

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
@@ -372,7 +372,17 @@
         config = CConfig
     else:
         config = CConfig2
-    setattr(config, configname, rffi_platform.Struct(name, fields))
+    adtmeths = {}
+    if ("ob_type", PyTypeObjectPtr) in fields:
+        def my_str(ob):
+            r = name
+            tp = ob.c_ob_type
+            if tp:
+                r += " of type '%s'" % (rffi.charp2str(tp.c_tp_name),)
+            return r
+        adtmeths['__str__'] = my_str
+    setattr(config, configname, rffi_platform.Struct(name, fields,
+                                                     adtmeths=adtmeths))
     if forward is None:
         forward = lltype.ForwardReference()
     TYPES[configname] = forward
@@ -790,7 +800,7 @@
 # Do not call this more than once per process
 def build_bridge(space):
     "NOT_RPYTHON"
-    from pypy.module.cpyext.pyobject import setup_prebuilt_pyobj
+    from pypy.module.cpyext.pyobject import setup_prebuilt_pyobj, _Py_Dealloc
     from rpython.rlib import rawrefcount
 
     export_symbols = list(FUNCTIONS) + SYMBOLS_C + list(GLOBALS)
@@ -850,7 +860,7 @@
 
     space.fromcache(State).install_dll(eci)
 
-    rawrefcount.init(lambda ob: ZZZ)
+    rawrefcount.init(lambda ob: _Py_Dealloc(space, ob))
 
     # populate static data
     to_fill = []
@@ -1214,20 +1224,15 @@
 @specialize.ll()
 def generic_cpy_call(space, func, *args):
     FT = lltype.typeOf(func).TO
-    return make_generic_cpy_call(FT, True, False)(space, func, *args)
-
[email protected]()
-def generic_cpy_call_dont_decref(space, func, *args):
-    FT = lltype.typeOf(func).TO
-    return make_generic_cpy_call(FT, False, False)(space, func, *args)
+    return make_generic_cpy_call(FT, False)(space, func, *args)
 
 @specialize.ll()
 def generic_cpy_call_expect_null(space, func, *args):
     FT = lltype.typeOf(func).TO
-    return make_generic_cpy_call(FT, True, True)(space, func, *args)
+    return make_generic_cpy_call(FT, True)(space, func, *args)
 
 @specialize.memo()
-def make_generic_cpy_call(FT, decref_args, expect_null):
+def make_generic_cpy_call(FT, expect_null):
     from pypy.module.cpyext.pyobject import is_pyobj, as_xpyobj
     from pypy.module.cpyext.pyobject import get_w_obj_and_decref
     from pypy.module.cpyext.pyerrors import PyErr_Occurred
@@ -1254,8 +1259,6 @@
     # don't inline, as a hack to guarantee that no GC pointer is alive
     # anywhere in call_external_function
 
-    assert decref_args  #ZZZ
-
     @specialize.ll()
     def generic_cpy_call(space, func, *args):
         boxed_args = ()
diff --git a/pypy/module/cpyext/include/object.h 
b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -48,12 +48,12 @@
 #else
 /* Fast version */
 #define Py_INCREF(ob)   (((PyObject *)ob)->ob_refcnt++)
-#define Py_DECREF(ob)                                   \
+#define Py_DECREF(op)                                   \
     do {                                                \
-        if (((PyObject *)ob)->ob_refcnt > 1)            \
-            ((PyObject *)ob)->ob_refcnt--;              \
+        if (--((PyObject*)(op))->ob_refcnt != 0)        \
+            ;                                           \
         else                                            \
-            Py_DecRef((PyObject *)ob);                  \
+            _Py_Dealloc((PyObject *)(op));              \
     } while (0)
 
 #define Py_XINCREF(op) do { if ((op) == NULL) ; else Py_INCREF(op); } while (0)
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -120,6 +120,7 @@
 
 
 def rawrefcount_init_link(w_obj, ob, strength):
+    assert lltype.typeOf(ob) == PyObject
     if strength == RRC_PERMANENT:
         ob.c_ob_refcnt += rawrefcount.REFCNT_FROM_PYPY
         rawrefcount.create_link_pypy(w_obj, ob)
@@ -141,7 +142,6 @@
 
 
 def setup_prebuilt_pyobj(w_obj, py_obj):
-    assert lltype.typeOf(py_obj) == PyObject
     rawrefcount_init_link(w_obj, py_obj, RRC_PERMANENT)
     if isinstance(w_obj, W_TypeObject):
         w_obj.cpyext_c_type_object = rffi.cast(PyTypeObjectPtr, py_obj)
@@ -394,6 +394,36 @@
 INTERPLEVEL_API['new_pyobj'] = staticmethod(new_pyobj)
 
 
[email protected]()
+def incref(space, obj):
+    get_pyobj_and_incref(space, obj)
+INTERPLEVEL_API['incref'] = incref
+
[email protected]()
+def xincref(space, obj):
+    get_pyobj_and_xincref(space, obj)
+INTERPLEVEL_API['xincref'] = xincref
+
[email protected]()
+def decref(space, obj):
+    if is_pyobj(obj):
+        obj = rffi.cast(PyObject, obj)
+        assert obj.c_ob_refcnt > 0
+        obj.c_ob_refcnt -= 1
+        if obj.c_ob_refcnt == 0:
+            _Py_Dealloc(space, obj)
+    else:
+        get_w_obj_and_decref(space, obj)
+INTERPLEVEL_API['decref'] = decref
+
[email protected]()
+def xdecref(space, obj):
+    if obj:
+        decref(space, obj)
+INTERPLEVEL_API['xdecref'] = xdecref
+
+# ----------
+
 def make_ref(space, w_obj):
     ZZZ
 
@@ -424,62 +454,30 @@
     return get_typedescr(w_type.instancetypedef).realize(space, ref)
 
 
-# XXX Optimize these functions and put them into macro definitions
+@cpython_api([PyObject], lltype.Void)
+def Py_IncRef(space, obj):
+    xincref(space, obj)
+
 @cpython_api([PyObject], lltype.Void)
 def Py_DecRef(space, obj):
-    if not obj:
-        return
-    assert lltype.typeOf(obj) == PyObject
+    xdecref(space, obj)
 
-    obj.c_ob_refcnt -= 1
-    if DEBUG_REFCOUNT:
-        debug_refcount("DECREF", obj, obj.c_ob_refcnt, frame_stackdepth=3)
-    if obj.c_ob_refcnt == 0:
-        return #ZZZ
-        state = space.fromcache(RefcountState)
-        ptr = rffi.cast(ADDR, obj)
-        if ptr not in state.py_objects_r2w:
-            # this is a half-allocated object, lets call the deallocator
-            # without modifying the r2w/w2r dicts
-            _Py_Dealloc(space, obj)
-        else:
-            w_obj = state.py_objects_r2w[ptr]
-            del state.py_objects_r2w[ptr]
-            w_type = space.type(w_obj)
-            if not w_type.is_cpytype():
-                _Py_Dealloc(space, obj)
-            del state.py_objects_w2r[w_obj]
-            # if the object was a container for borrowed references
-            state.delete_borrower(w_obj)
-    else:
-        if not we_are_translated() and obj.c_ob_refcnt < 0:
-            message = "Negative refcount for obj %s with type %s" % (
-                obj, rffi.charp2str(obj.c_ob_type.c_tp_name))
-            print >>sys.stderr, message
-            assert False, message
-
-@cpython_api([PyObject], lltype.Void)
-def Py_IncRef(space, obj):
-    if not obj:
-        return
-    obj.c_ob_refcnt += 1
-    assert obj.c_ob_refcnt > 0
-    if DEBUG_REFCOUNT:
-        debug_refcount("INCREF", obj, obj.c_ob_refcnt, frame_stackdepth=3)
 
 @cpython_api([PyObject], lltype.Void)
 def _Py_NewReference(space, obj):
+    ZZZ
     obj.c_ob_refcnt = 1
     w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
     assert isinstance(w_type, W_TypeObject)
     get_typedescr(w_type.instancetypedef).realize(space, obj)
 
+@cpython_api([PyObject], lltype.Void)
 def _Py_Dealloc(space, obj):
-    from pypy.module.cpyext.api import generic_cpy_call_dont_decref
+    from pypy.module.cpyext.api import generic_cpy_call
     pto = obj.c_ob_type
     #print >>sys.stderr, "Calling dealloc slot", pto.c_tp_dealloc, "of", obj, \
     #      "'s type which is", rffi.charp2str(pto.c_tp_name)
-    generic_cpy_call_dont_decref(space, pto.c_tp_dealloc, obj)
+    generic_cpy_call(space, pto.c_tp_dealloc, obj)
 
 #___________________________________________________________
 # Support for "lifelines"
diff --git a/pypy/module/cpyext/test/test_cpyext.py 
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -107,6 +107,7 @@
     spaceconfig = dict(usemodules=['cpyext', 'thread', '_rawffi', 'array',
                                    'itertools', 'time', 'binascii', 
'micronumpy'])
     spaceconfig['std.withmethodcache'] = True
+    spaceconfig['std.withspecialisedtuple'] = True
 
     enable_leak_checking = True
 
diff --git a/pypy/module/cpyext/test/test_tupleobject.py 
b/pypy/module/cpyext/test/test_tupleobject.py
--- a/pypy/module/cpyext/test/test_tupleobject.py
+++ b/pypy/module/cpyext/test/test_tupleobject.py
@@ -41,7 +41,7 @@
         w_obj2 = space.newlist([])
         pyobj2 = api.get_pyobj_and_incref(w_obj2)
         py_tuple = api.PyTuple_New(2)
-        assert not pyobj_has_w_obj(py_tuple)
+        assert not api.pyobj_has_w_obj(py_tuple)
 
         assert pyobj1.c_ob_refcnt == REFCNT_FROM_PYPY_LIGHT + 1
         assert pyobj2.c_ob_refcnt == REFCNT_FROM_PYPY_LIGHT + 1
@@ -57,7 +57,7 @@
         assert pyobj1.c_ob_refcnt == REFCNT_FROM_PYPY_LIGHT + 0
         assert pyobj2.c_ob_refcnt == REFCNT_FROM_PYPY_LIGHT + 1
 
-        assert not pyobj_has_w_obj(py_tuple)
+        assert not api.pyobj_has_w_obj(py_tuple)
         w_tup = api.from_pyobj(py_tuple)
         assert w_tup is api.from_pyobj(py_tuple)
         assert api.PyTuple_GetItem(py_tuple, 1) == pyobj2
diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py 
b/rpython/rtyper/lltypesystem/ll2ctypes.py
--- a/rpython/rtyper/lltypesystem/ll2ctypes.py
+++ b/rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -615,11 +615,14 @@
             return object.__hash__(self)
 
     def __repr__(self):
+        if '__str__' in self._TYPE._adtmeths:
+            r = self._TYPE._adtmeths['__str__'](self)
+        else:
+            r = 'C object %s' % (self._TYPE,)
         if self._storage is None:
-            return '<freed C object %s>' % (self._TYPE,)
+            return '<freed %s>' % (r,)
         else:
-            return '<C object %s at 0x%x>' % (self._TYPE,
-                                              fixid(self._addressof_storage()))
+            return '<%s at 0x%x>' % (r, fixid(self._addressof_storage()))
 
     def __str__(self):
         return repr(self)
diff --git a/rpython/rtyper/tool/rffi_platform.py 
b/rpython/rtyper/tool/rffi_platform.py
--- a/rpython/rtyper/tool/rffi_platform.py
+++ b/rpython/rtyper/tool/rffi_platform.py
@@ -263,10 +263,11 @@
     """An entry in a CConfig class that stands for an externally
     defined structure.
     """
-    def __init__(self, name, interesting_fields, ifdef=None):
+    def __init__(self, name, interesting_fields, ifdef=None, adtmeths={}):
         self.name = name
         self.interesting_fields = interesting_fields
         self.ifdef = ifdef
+        self.adtmeths = adtmeths
 
     def prepare_code(self):
         if self.ifdef is not None:
@@ -355,7 +356,7 @@
             name = name[7:]
         else:
             hints['typedef'] = True
-        kwds = {'hints': hints}
+        kwds = {'hints': hints, 'adtmeths': self.adtmeths}
         return rffi.CStruct(name, *fields, **kwds)
 
 class SimpleType(CConfigEntry):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to