[pypy-svn] r74406 - in pypy/trunk/pypy/module/cpyext: . test

afa at codespeak.net afa at codespeak.net
Thu May 6 13:23:51 CEST 2010


Author: afa
Date: Thu May  6 13:23:50 2010
New Revision: 74406

Modified:
   pypy/trunk/pypy/module/cpyext/__init__.py
   pypy/trunk/pypy/module/cpyext/api.py
   pypy/trunk/pypy/module/cpyext/pyobject.py
   pypy/trunk/pypy/module/cpyext/state.py
   pypy/trunk/pypy/module/cpyext/test/test_borrow.py
   pypy/trunk/pypy/module/cpyext/test/test_cpyext.py
   pypy/trunk/pypy/module/cpyext/typeobject.py
Log:
Put management of reference counted objects in its own State structure.


Modified: pypy/trunk/pypy/module/cpyext/__init__.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/__init__.py	(original)
+++ pypy/trunk/pypy/module/cpyext/__init__.py	Thu May  6 13:23:50 2010
@@ -34,8 +34,6 @@
         for func in api.INIT_FUNCTIONS:
             func(space)
             state.check_and_raise_exception()
-        if not we_are_translated():
-            state.non_heaptypes[:] = []
 
 # import these modules to register api functions by side-effect
 import pypy.module.cpyext.thread

Modified: pypy/trunk/pypy/module/cpyext/api.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/api.py	(original)
+++ pypy/trunk/pypy/module/cpyext/api.py	Thu May  6 13:23:50 2010
@@ -174,7 +174,7 @@
             def unwrapper(space, *args):
                 from pypy.module.cpyext.pyobject import Py_DecRef
                 from pypy.module.cpyext.pyobject import make_ref, from_ref
-                from pypy.module.cpyext.pyobject import BorrowedPair
+                from pypy.module.cpyext.pyobject import BorrowPair
                 newargs = ()
                 to_decref = []
                 assert len(args) == len(api_function.argtypes)
@@ -217,7 +217,7 @@
                             return api_function.error_value
                     if res is None:
                         return None
-                    elif isinstance(res, BorrowedPair):
+                    elif isinstance(res, BorrowPair):
                         return res.w_borrowed
                     else:
                         return res
@@ -400,7 +400,7 @@
     @specialize.ll()
     def wrapper(*args):
         from pypy.module.cpyext.pyobject import make_ref, from_ref
-        from pypy.module.cpyext.pyobject import BorrowedPair
+        from pypy.module.cpyext.pyobject import BorrowPair
         from pypy.module.cpyext.pyobject import NullPointerException
         # we hope that malloc removal removes the newtuple() that is
         # inserted exactly here by the varargs specializer
@@ -450,7 +450,7 @@
             elif callable.api_func.restype is PyObject:
                 if result is None:
                     retval = make_ref(space, None)
-                elif isinstance(result, BorrowedPair):
+                elif isinstance(result, BorrowPair):
                     retval = result.get_ref(space)
                 elif not rffi._isllptr(result):
                     retval = make_ref(space, result)

Modified: pypy/trunk/pypy/module/cpyext/pyobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/pyobject.py	(original)
+++ pypy/trunk/pypy/module/cpyext/pyobject.py	Thu May  6 13:23:50 2010
@@ -146,6 +146,30 @@
 #________________________________________________________
 # refcounted object support
 
+class RefcountState:
+    def __init__(self, space):
+        self.py_objects_w2r = {} # { w_obj -> raw PyObject }
+        self.py_objects_r2w = {} # { addr of raw PyObject -> w_obj }
+        self.borrow_mapping = {} # { addr of container -> { addr of containee -> None } }
+        self.borrowed_objects = {} # { addr of containee -> None }
+        self.non_heaptypes = [] # list of wrapped objects
+
+    def _freeze_(self):
+        assert not self.borrowed_objects and not self.borrow_mapping
+        self.py_objects_r2w.clear() # is not valid anymore after translation
+        return False
+
+    def init_r2w_from_w2r(self):
+        from pypy.module.cpyext.api import ADDR
+        for w_obj, obj in self.py_objects_w2r.items():
+            ptr = rffi.cast(ADDR, obj)
+            self.py_objects_r2w[ptr] = w_obj
+
+    def print_refcounts(self):
+        print "REFCOUNTS"
+        for w_obj, obj in self.py_objects_w2r.items():
+            print "%r: %i" % (w_obj, obj.c_ob_refcnt)
+
 class NullPointerException(Exception):
     pass
 
@@ -178,7 +202,7 @@
     """
     # XXX looks like a PyObject_GC_TRACK
     ptr = rffi.cast(ADDR, py_obj)
-    state = space.fromcache(State)
+    state = space.fromcache(RefcountState)
     if DEBUG_REFCOUNT:
         debug_refcount("MAKREF", py_obj, w_obj)
         if not replace:
@@ -196,7 +220,7 @@
     if w_obj is None:
         return lltype.nullptr(PyObject.TO)
     assert isinstance(w_obj, W_Root)
-    state = space.fromcache(State)
+    state = space.fromcache(RefcountState)
     try:
         py_obj = state.py_objects_w2r[w_obj]
     except KeyError:
@@ -218,7 +242,7 @@
     assert lltype.typeOf(ref) == PyObject
     if not ref:
         return None
-    state = space.fromcache(State)
+    state = space.fromcache(RefcountState)
     ptr = rffi.cast(ADDR, ref)
 
     try:
@@ -247,7 +271,7 @@
     if DEBUG_REFCOUNT:
         debug_refcount("DECREF", obj, obj.c_ob_refcnt, frame_stackdepth=3)
     if obj.c_ob_refcnt == 0:
-        state = space.fromcache(State)
+        state = space.fromcache(RefcountState)
         ptr = rffi.cast(ADDR, obj)
         if ptr not in state.py_objects_r2w:
             w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
@@ -295,44 +319,49 @@
 #___________________________________________________________
 # Support for borrowed references
 
-class BorrowedPair:
+def make_borrowed_ref(space, w_container, w_borrowed):
+    """
+    Create a borrowed reference, which will live as long as the container
+    has a living reference (as a PyObject!)
+    """
+    ref = make_ref(space, w_borrowed)
+    if not ref:
+        return ref
+
+    # state.borrowed_objects owns the reference
+    state = space.fromcache(RefcountState)
+    obj_ptr = rffi.cast(ADDR, ref)
+    if obj_ptr not in state.borrowed_objects:
+        state.borrowed_objects[obj_ptr] = None
+    else:
+        Py_DecRef(space, ref) # already in borrowed list
+
+    container = make_ref(space, w_container)
+    if not container: # self-managed
+        return ref
+    Py_DecRef(space, container)
+    container_ptr = rffi.cast(ADDR, container)
+    borrowees = state.borrow_mapping.setdefault(container_ptr, {})
+    borrowees[obj_ptr] = None
+    return ref
+
+class BorrowPair:
+    """
+    Delays the creation of a borrowed reference.
+    """
     def __init__(self, w_container, w_borrowed):
-        self.w_borrowed = w_borrowed
         self.w_container = w_container
+        self.w_borrowed = w_borrowed
 
     def get_ref(self, space):
-        """
-        Create a borrowed reference, which will live as long as the container
-        has a living reference (as a PyObject!)
-        """
-        ref = make_ref(space, self.w_borrowed)
-        if not ref:
-            return ref
-
-        # state.borrowed_objects owns the reference
-        state = space.fromcache(State)
-        obj_ptr = rffi.cast(ADDR, ref)
-        if obj_ptr not in state.borrowed_objects:
-            state.borrowed_objects[obj_ptr] = None
-        else:
-            Py_DecRef(space, ref) # already in borrowed list
-
-        if self.w_container is None: # self-managed
-            return ref
-
-        container = make_ref(space, self.w_container)
-        Py_DecRef(space, container)
-        container_ptr = rffi.cast(ADDR, container)
-        borrowees = state.borrow_mapping.setdefault(container_ptr, {})
-        borrowees[obj_ptr] = None
-        return ref
+        return make_borrowed_ref(space, self.w_container, self.w_borrowed)
 
 def borrow_from(container, borrowed):
-    return BorrowedPair(container, borrowed)
+    return BorrowPair(container, borrowed)
 
 def forget_borrowee(space, w_obj):
     "De-register an object from the list of borrowed references"
-    state = space.fromcache(State)
+    state = space.fromcache(RefcountState)
     ref = state.py_objects_w2r.get(w_obj, lltype.nullptr(PyObject.TO))
     if not ref:
         if DEBUG_REFCOUNT:
@@ -354,7 +383,7 @@
     last reference.  Removes the borrowed references it contains.
     """
     ptr = rffi.cast(ADDR, py_obj)
-    state = space.fromcache(State)
+    state = space.fromcache(RefcountState)
     if ptr in state.borrow_mapping: # move to lifeline __del__
         for containee in state.borrow_mapping[ptr]:
             w_containee = state.py_objects_r2w.get(containee, None)

Modified: pypy/trunk/pypy/module/cpyext/state.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/state.py	(original)
+++ pypy/trunk/pypy/module/cpyext/state.py	Thu May  6 13:23:50 2010
@@ -12,11 +12,6 @@
 
     def reset(self):
         from pypy.module.cpyext.modsupport import PyMethodDef
-        self.py_objects_w2r = {} # { w_obj -> raw PyObject }
-        self.py_objects_r2w = {} # { addr of raw PyObject -> w_obj }
-        self.borrow_mapping = {} # { addr of container -> { addr of containee -> None } }
-        self.borrowed_objects = {} # { addr of containee -> None }
-        self.non_heaptypes = [] # list of wrapped objects
         self.operror = None
         self.new_method_def = lltype.nullptr(PyMethodDef)
 
@@ -29,18 +24,6 @@
         # already read it by that time.
         self.package_context = None
 
-
-    def _freeze_(self):
-        assert not self.borrowed_objects and not self.borrow_mapping
-        self.py_objects_r2w.clear() # is not valid anymore after translation
-        return False
-
-    def init_r2w_from_w2r(self):
-        from pypy.module.cpyext.api import ADDR
-        for w_obj, obj in self.py_objects_w2r.items():
-            ptr = rffi.cast(ADDR, obj)
-            self.py_objects_r2w[ptr] = w_obj
-
     def set_exception(self, operror):
         self.clear_exception()
         self.operror = operror
@@ -68,8 +51,3 @@
         if always:
             raise OperationError(self.space.w_SystemError, self.space.wrap(
                 "Function returned an error result without setting an exception"))
-
-    def print_refcounts(self):
-        print "REFCOUNTS"
-        for w_obj, obj in self.py_objects_w2r.items():
-            print "%r: %i" % (w_obj, obj.c_ob_refcnt)

Modified: pypy/trunk/pypy/module/cpyext/test/test_borrow.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/test/test_borrow.py	(original)
+++ pypy/trunk/pypy/module/cpyext/test/test_borrow.py	Thu May  6 13:23:50 2010
@@ -1,19 +1,17 @@
 import py
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from pypy.module.cpyext.test.test_api import BaseApiTest
-from pypy.module.cpyext.state import State
-from pypy.module.cpyext.pyobject import make_ref, borrow_from
+from pypy.module.cpyext.pyobject import make_ref, borrow_from, RefcountState
 
 
 class TestBorrowing(BaseApiTest):
     def test_borrowing(self, space, api):
-        state = space.fromcache(State)
         w_int = space.wrap(1)
         w_tuple = space.newtuple([w_int])
         api.Py_IncRef(w_tuple)
         one_pyo = borrow_from(w_tuple, w_int).get_ref(space)
-        print state.borrowed_objects
         api.Py_DecRef(w_tuple)
+        state = space.fromcache(RefcountState)
         state.print_refcounts()
         py.test.raises(AssertionError, api.Py_DecRef, one_pyo)
 

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	Thu May  6 13:23:50 2010
@@ -12,6 +12,7 @@
 from pypy.tool.udir import udir
 from pypy.module.cpyext import api, typeobject
 from pypy.module.cpyext.state import State
+from pypy.module.cpyext.pyobject import RefcountState
 from pypy.module.cpyext.pyobject import Py_DecRef, InvalidPointerException
 from pypy.translator.goal import autopath
 from pypy.lib.identity_dict import identity_dict
@@ -71,7 +72,7 @@
     return str(pydname)
 
 def freeze_refcnts(self):
-    state = self.space.fromcache(State)
+    state = self.space.fromcache(RefcountState)
     self.frozen_refcounts = {}
     for w_obj, obj in state.py_objects_w2r.iteritems():
         self.frozen_refcounts[w_obj] = obj.c_ob_refcnt
@@ -85,7 +86,7 @@
         import gc
 
         leaking = False
-        state = self.space.fromcache(State)
+        state = self.space.fromcache(RefcountState)
         gc.collect()
         lost_objects_w = identity_dict()
         lost_objects_w.update((key, None) for key in self.frozen_refcounts.keys())
@@ -136,6 +137,8 @@
         cls.space.getbuiltinmodule("cpyext")
         from pypy.module.imp.importing import importhook
         importhook(cls.space, "os") # warm up reference counts
+        state = cls.space.fromcache(RefcountState)
+        state.non_heaptypes[:] = []
 
     def compile_module(self, name, **kwds):
         """
@@ -258,7 +261,7 @@
     def teardown_method(self, func):
         for name in self.imported_module_names:
             self.unimport_module(name)
-        state = self.space.fromcache(State)
+        state = self.space.fromcache(RefcountState)
         for w_obj in state.non_heaptypes:
             Py_DecRef(self.space, w_obj)
         state.non_heaptypes[:] = []

Modified: pypy/trunk/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/typeobject.py	(original)
+++ pypy/trunk/pypy/module/cpyext/typeobject.py	Thu May  6 13:23:50 2010
@@ -17,7 +17,7 @@
     PyBufferProcs, build_type_checkers)
 from pypy.module.cpyext.pyobject import (
     PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
-    track_reference)
+    track_reference, RefcountState)
 from pypy.interpreter.module import Module
 from pypy.interpreter.function import FunctionWithFixedCode, StaticMethod
 from pypy.module.cpyext import structmemberdefs
@@ -580,7 +580,7 @@
 
     finish_type_2(space, py_type, w_obj)
 
-    state = space.fromcache(State)
+    state = space.fromcache(RefcountState)
     state.non_heaptypes.append(w_obj)
 
     return w_obj



More information about the Pypy-commit mailing list