[pypy-svn] r72798 - in pypy/branch/cpython-extension/pypy/module/cpyext: . test
xoraxax at codespeak.net
xoraxax at codespeak.net
Thu Mar 25 14:02:06 CET 2010
Author: xoraxax
Date: Thu Mar 25 14:02:04 2010
New Revision: 72798
Modified:
pypy/branch/cpython-extension/pypy/module/cpyext/api.py
pypy/branch/cpython-extension/pypy/module/cpyext/macros.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_boolobject.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py
pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
Log:
Implement refcount checking for our tests. Only one test is failing, amaury may fix it :-) Refcounts are now checked against the baseline after every test is run.
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/api.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/api.py Thu Mar 25 14:02:04 2010
@@ -208,7 +208,7 @@
hints["padding"] = hints["padding"] + tuple(pad_fields)
return lltype.Struct(hints["c_name"], hints=hints, *new_fields)
-def make_ref(space, w_obj, borrowed=False):
+def make_ref(space, w_obj, borrowed=False, steal=False):
if w_obj is None:
return lltype.nullptr(PyObject.TO)
assert isinstance(w_obj, W_Root)
@@ -242,7 +242,7 @@
py_obj = rffi.cast(PyObject, py_obj)
state.py_objects_w2r[w_obj] = py_obj
state.py_objects_r2w[ptr] = w_obj
- else:
+ elif not steal:
py_obj.c_obj_refcnt += 1
# XXX borrowed references?
return py_obj
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/macros.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/macros.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/macros.py Thu Mar 25 14:02:04 2010
@@ -21,6 +21,10 @@
def Py_INCREF(space, obj):
obj.c_obj_refcnt += 1
+ at cpython_api([PyObject], lltype.Void)
+def Py_XDECREF(space, obj):
+ if obj:
+ Py_DECREF(space, obj)
def _Py_Dealloc(space, obj):
from pypy.module.cpyext.typeobject import PyTypeObjectPtr
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_boolobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_boolobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_boolobject.py Thu Mar 25 14:02:04 2010
@@ -44,4 +44,3 @@
assert module.get_false() == False
assert module.test_FromLong() == True
assert module.test_Check() == True
- self.check_refcnts("FOOOOOO %r")
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py Thu Mar 25 14:02:04 2010
@@ -69,6 +69,7 @@
class AppTestCpythonExtensionBase:
def setup_class(cls):
cls.space = gettestobjspace(usemodules=['cpyext'])
+ cls.freeze_refcnts()
def import_module(self, name, init=None, body=''):
if init is not None:
@@ -129,9 +130,7 @@
def setup_method(self, func):
self.w_import_module = self.space.wrap(self.import_module)
self.w_import_extension = self.space.wrap(self.import_extension)
- self.w_check_refcnts = self.space.wrap(self.check_refcnts)
- self.check_refcnts("Object has refcnt != 1: %r -- Not executing test!")
- #self.space.fromcache(State).print_refcounts()
+ #self.check_and_print_leaks("Object %r leaked some time ago (refcount %i) -- Not executing test!")
def teardown_method(self, func):
try:
@@ -142,16 +141,31 @@
Py_DECREF(self.space, w_mod)
except OperationError:
pass
- self.space.fromcache(State).print_refcounts()
- self.check_refcnts("Test leaks object: %r")
+ if self.check_and_print_leaks():
+ assert False, "Test leaks object(s)."
- def check_refcnts(self, message):
+ @classmethod
+ def freeze_refcnts(cls):
+ state = cls.space.fromcache(State)
+ cls.frozen_refcounts = {}
+ for w_obj, obj in state.py_objects_w2r.iteritems():
+ cls.frozen_refcounts[w_obj] = obj.c_obj_refcnt
+
+ def check_and_print_leaks(self):
# check for sane refcnts
- for w_obj in (self.space.w_True, self.space.w_False,
- self.space.w_None):
- state = self.space.fromcache(State)
- obj = state.py_objects_w2r.get(w_obj)
- assert obj.c_obj_refcnt == 1, message % (w_obj, )
+ leaking = False
+ state = self.space.fromcache(State)
+ global_objects_w = set()
+ for w_obj, obj in state.py_objects_w2r.iteritems():
+ base_refcnt = self.frozen_refcounts.get(w_obj)
+ delta = obj.c_obj_refcnt
+ if base_refcnt is not None:
+ delta -= base_refcnt
+ if delta != 0:
+ leaking = True
+ print >>sys.stderr, "Leaking %r: %i references" % (w_obj, delta)
+ return leaking
+
class AppTestCpythonExtension(AppTestCpythonExtensionBase):
def test_createmodule(self):
@@ -324,7 +338,7 @@
refcnt_after = Py_REFCNT(true);
Py_DECREF(true);
Py_DECREF(true);
- printf("REFCNT %i %i\\n", refcnt, refcnt_after);
+ fprintf(stderr, "REFCNT %i %i\\n", refcnt, refcnt_after);
return PyBool_FromLong(refcnt_after == refcnt+2 && refcnt < 3);
}
static PyObject* foo_bar(PyObject* self, PyObject *args)
@@ -339,8 +353,9 @@
if (PyTuple_SetItem(tup, 0, true) < 0)
return NULL;
refcnt_after = Py_REFCNT(true);
- printf("REFCNT2 %i %i\\n", refcnt, refcnt_after);
- return PyBool_FromLong(refcnt_after == refcnt && refcnt < 3);
+ Py_DECREF(tup);
+ fprintf(stderr, "REFCNT2 %i %i\\n", refcnt, refcnt_after);
+ return PyBool_FromLong(refcnt_after == refcnt);
}
static PyMethodDef methods[] = {
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py Thu Mar 25 14:02:04 2010
@@ -16,7 +16,7 @@
from pypy.module.cpyext.modsupport import PyMethodDef, convert_method_defs
from pypy.module.cpyext.state import State
from pypy.module.cpyext.methodobject import generic_cpy_call
-from pypy.module.cpyext.macros import Py_DECREF
+from pypy.module.cpyext.macros import Py_DECREF, Py_XDECREF
PyTypeObject = lltype.ForwardReference()
@@ -225,7 +225,8 @@
assert pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE
base = pto
this_func_ptr = subtype_dealloc.api_func.get_llhelper(space)
- ref_of_object_type = rffi.cast(PyTypeObjectPtr, make_ref(space, space.w_object))
+ ref_of_object_type = rffi.cast(PyTypeObjectPtr,
+ make_ref(space, space.w_object, steal=True))
while base.c_tp_dealloc == this_func_ptr:
base = base.c_tp_base
assert base
@@ -240,13 +241,16 @@
def type_dealloc(space, obj):
obj_pto = rffi.cast(PyTypeObjectPtr, obj)
type_pto = rffi.cast(PyTypeObjectPtr, obj.c_obj_type)
+ Py_XDECREF(space, obj_pto.c_tp_base)
# type_dealloc code follows:
- # XXX XDECREF tp_base, tp_dict, tp_bases, tp_mro, tp_cache,
+ # XXX XDECREF tp_dict, tp_bases, tp_mro, tp_cache,
# tp_subclasses
# free tp_doc
lltype.free(obj_pto.c_tp_name, flavor="raw")
obj_pto_voidp = rffi.cast(rffi.VOIDP_real, obj_pto)
generic_cpy_call(space, type_pto.c_tp_free, obj_pto_voidp)
+ pto = rffi.cast(PyObject, type_pto)
+ Py_DECREF(space, type_pto)
def allocate_type_obj(space, w_type):
""" Allocates a pto from a w_type which must be a PyPy type. """
More information about the Pypy-commit
mailing list