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