[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