[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