[pypy-svn] r72512 - in pypy/trunk/pypy/module/cpyext: . test
xoraxax at codespeak.net
xoraxax at codespeak.net
Sun Mar 21 22:42:03 CET 2010
Author: xoraxax
Date: Sun Mar 21 22:42:01 2010
New Revision: 72512
Modified:
pypy/trunk/pypy/module/cpyext/__init__.py
pypy/trunk/pypy/module/cpyext/api.py
pypy/trunk/pypy/module/cpyext/macros.py
pypy/trunk/pypy/module/cpyext/methodobject.py
pypy/trunk/pypy/module/cpyext/state.py
pypy/trunk/pypy/module/cpyext/test/test_boolobject.py
pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
Log:
Fix refcounting at various places and instantiate the bridge only once!
Modified: pypy/trunk/pypy/module/cpyext/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/__init__.py (original)
+++ pypy/trunk/pypy/module/cpyext/__init__.py Sun Mar 21 22:42:01 2010
@@ -15,7 +15,7 @@
"""NOT_RPYTHON"""
state = self.space.fromcache(State)
if not we_are_translated():
- state.api_lib = str(pypy.module.cpyext.api.build_bridge(space))
+ state.api_lib = str(pypy.module.cpyext.api.build_bridge(self.space))
else:
XXX # build an import library when translating pypy.
Modified: pypy/trunk/pypy/module/cpyext/api.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/api.py (original)
+++ pypy/trunk/pypy/module/cpyext/api.py Sun Mar 21 22:42:01 2010
@@ -156,10 +156,18 @@
try:
obj = state.py_objects_r2w[ptr]
except KeyError:
- import pdb; pdb.set_trace()
- raise InvalidPointerException("Got invalid reference to a PyObject")
+ raise InvalidPointerException("Got invalid reference to a PyObject: %r" % (ref, ))
return obj
+def clear_memory(space):
+ from pypy.module.cpyext.macros import Py_DECREF
+ state = space.fromcache(State)
+ while state.py_objects_w2r:
+ key = state.py_objects_w2r.keys()[0]
+ Py_DECREF(space, key)
+ state.reset()
+
+
def general_check(space, w_obj, w_type):
w_obj_type = space.type(w_obj)
return int(space.is_w(w_obj_type, w_type) or space.is_true(space.issubtype(w_obj_type, w_type)))
Modified: pypy/trunk/pypy/module/cpyext/macros.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/macros.py (original)
+++ pypy/trunk/pypy/module/cpyext/macros.py Sun Mar 21 22:42:01 2010
@@ -8,7 +8,7 @@
@cpython_api([PyObject], lltype.Void)
def Py_DECREF(space, w_obj):
state = space.fromcache(State)
- obj = state.py_objects_w2r.get(w_obj)
+ obj = state.py_objects_w2r[w_obj]
obj.c_obj_refcnt -= 1
if obj.c_obj_refcnt == 0:
del state.py_objects_w2r[w_obj]
Modified: pypy/trunk/pypy/module/cpyext/methodobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/methodobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/methodobject.py Sun Mar 21 22:42:01 2010
@@ -8,6 +8,7 @@
from pypy.module.cpyext.api import PyObject, from_ref, NullPointerException, \
InvalidPointerException, make_ref
from pypy.module.cpyext.state import State
+from pypy.module.cpyext.macros import Py_DECREF
from pypy.rlib.objectmodel import we_are_translated
@@ -26,9 +27,11 @@
w_self = self.w_self
result = self.ml.c_ml_meth(make_ref(space, w_self), make_ref(space, args_tuple))
try:
- if result:
- result.c_obj_refcnt -= 1
ret = from_ref(space, result)
+ Py_DECREF(space, ret)
+ if w_self:
+ Py_DECREF(space, w_self)
+ Py_DECREF(space, args_tuple)
except NullPointerException:
state = space.fromcache(State)
state.check_and_raise_exception()
Modified: pypy/trunk/pypy/module/cpyext/state.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/state.py (original)
+++ pypy/trunk/pypy/module/cpyext/state.py Sun Mar 21 22:42:01 2010
@@ -4,6 +4,9 @@
class State:
def __init__(self, space):
+ self.reset()
+
+ def reset(self):
self.py_objects_w2r = identity_dict() # w_obj -> raw PyObject
self.py_objects_r2w = {} # addr of raw PyObject -> w_obj
self.exc_type = None
@@ -18,3 +21,7 @@
op_err = OperationError(exc_type, exc_value)
raise op_err
+ def print_refcounts(self):
+ print "REFCOUNTS"
+ for w_obj, obj in self.py_objects_w2r.items():
+ print "%r: %i" % (w_obj, obj.c_obj_refcnt)
Modified: pypy/trunk/pypy/module/cpyext/test/test_boolobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_boolobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/test/test_boolobject.py Sun Mar 21 22:42:01 2010
@@ -64,3 +64,4 @@
assert module.get_false() == False
assert module.test_FromLong() == True
assert module.test_Check() == True
+ self.check_refcnts("FOOOOOO %r")
Modified: pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_cpyext.py (original)
+++ pypy/trunk/pypy/module/cpyext/test/test_cpyext.py Sun Mar 21 22:42:01 2010
@@ -8,6 +8,8 @@
from pypy.translator.tool.cbuild import ExternalCompilationInfo
from pypy.translator import platform
from pypy.module.cpyext import api
+from pypy.module.cpyext.state import State
+from pypy.module.cpyext.macros import Py_DECREF
from pypy.translator.goal import autopath
@@ -44,7 +46,7 @@
class AppTestCpythonExtensionBase:
def setup_class(cls):
- cls.api_library = api.build_bridge(cls.space, rename=True)
+ cls.space = gettestobjspace(usemodules=['cpyext'])
def import_module(self, name, init=None, body=''):
if init is not None:
@@ -63,10 +65,12 @@
/ 'cpyext'/ 'test' / (name + ".c")
kwds = dict(separate_module_files=[filename])
+ state = self.space.fromcache(State)
+ api_library = state.api_lib
if sys.platform == 'win32':
- kwds["libraries"] = [self.api_library]
+ kwds["libraries"] = [api_library]
else:
- kwds["link_files"] = [str(self.api_library + '.so')]
+ kwds["link_files"] = [str(api_library + '.so')]
mod = compile_module(name, **kwds)
api.load_extension_module(self.space, mod, name)
@@ -76,13 +80,29 @@
def setup_method(self, func):
self.w_import_module = self.space.wrap(self.import_module)
+ 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()
def teardown_method(self, func):
try:
+ w_mod = self.space.getitem(self.space.sys.get('modules'),
+ self.space.wrap('foo'))
self.space.delitem(self.space.sys.get('modules'),
self.space.wrap('foo'))
+ Py_DECREF(self.space, w_mod)
except OperationError:
pass
+ self.space.fromcache(State).print_refcounts()
+ #self.check_refcnts("Test leaks object: %r")
+
+ def check_refcnts(self, message):
+ # 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, )
class AppTestCpythonExtension(AppTestCpythonExtensionBase):
def test_createmodule(self):
@@ -128,8 +148,8 @@
{
if (my_objects[0] == NULL) {
my_objects[0] = PyFloat_FromDouble(3.14);
- Py_INCREF(my_objects[0]);
}
+ Py_INCREF(my_objects[0]);
return my_objects[0];
}
static PyObject* foo_drop_pi(PyObject* self, PyObject *args)
@@ -154,10 +174,16 @@
"""
module = self.import_module(name='foo', init=init, body=body)
assert module.return_pi() == 3.14
+ print "A"
module.drop_pi()
+ print "B"
module.drop_pi()
+ print "C"
assert module.return_pi() == 3.14
+ print "D"
assert module.return_pi() == 3.14
+ print "E"
+ module.drop_pi()
skip("Hmm, how to check for the exception?")
raises(api.InvalidPointerException, module.return_invalid_pointer)
@@ -198,11 +224,13 @@
int refcnt = Py_REFCNT(true);
int refcnt_after;
Py_INCREF(true);
+ Py_INCREF(true);
PyBool_Check(true);
- Py_DECREF(true);
refcnt_after = Py_REFCNT(true);
+ Py_DECREF(true);
+ Py_DECREF(true);
printf("REFCNT %i %i\\n", refcnt, refcnt_after);
- return PyBool_FromLong(refcnt_after == refcnt && refcnt < 3);
+ return PyBool_FromLong(refcnt_after == refcnt+2 && refcnt < 3);
}
static PyMethodDef methods[] = {
{ "test_refcount", foo_pi, METH_NOARGS },
More information about the Pypy-commit
mailing list