Author: Armin Rigo <[email protected]>
Branch: cpyext-gc-support
Changeset: r80299:78020d53f0c5
Date: 2015-10-16 23:43 +0200
http://bitbucket.org/pypy/pypy/changeset/78020d53f0c5/
Log: random progress
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -541,6 +541,12 @@
return False
return hasattr(TYPE.TO, 'c_ob_refcnt') and hasattr(TYPE.TO, 'c_ob_type')
+class BORROWED: pass
+
[email protected]()
+def is_BORROWED(TYPE):
+ return TYPE is BORROWED
+
# a pointer to PyObject
PyObjectP = rffi.CArrayPtr(PyObject)
@@ -1230,68 +1236,53 @@
# don't inline, as a hack to guarantee that no GC pointer is alive
# anywhere in call_external_function
+ assert decref_args #ZZZ
+
@specialize.ll()
def generic_cpy_call(space, func, *args):
boxed_args = ()
- to_decref = []
+ keepalives = ()
assert len(args) == len(FT.ARGS)
for i, ARG in unrolling_arg_types:
arg = args[i]
if is_PyObject(ARG):
- if arg is None:
- boxed_args += (lltype.nullptr(PyObject.TO),)
- elif isinstance(arg, W_Root):
- ref = make_ref(space, arg)
- boxed_args += (ref,)
- if decref_args:
- to_decref.append(ref)
- else:
- boxed_args += (arg,)
- else:
- boxed_args += (arg,)
+ if not is_pyobj(arg):
+ keepalives += (arg,)
+ arg = as_pyobj(arg)
+ boxed_args += (arg,)
try:
- # create a new container for borrowed references
- state = space.fromcache(RefcountState)
- old_container = state.swap_borrow_container(None)
- try:
- # Call the function
- result = call_external_function(func, *boxed_args)
- finally:
- state.swap_borrow_container(old_container)
+ # Call the function
+ result = call_external_function(func, *boxed_args)
+ finally:
+ keepalive_until_here(*keepalives)
- if is_PyObject(RESULT_TYPE):
- if result is None:
- ret = result
- elif isinstance(result, W_Root):
- ret = result
- else:
- ret = from_ref(space, result)
- # The object reference returned from a C function
- # that is called from Python must be an owned reference
- # - ownership is transferred from the function to its
caller.
- if result:
- Py_DecRef(space, result)
+ if is_PyObject(RESULT_TYPE):
+ if not is_pyobj(result):
+ ret = result
+ else:
+ ret = from_ref(space, result)
+ # The object reference returned from a C function
+ # that is called from Python must be an owned reference
+ # - ownership is transferred from the function to its caller.
+ if result:
+ result.c_ob_refcnt -= 1
- # Check for exception consistency
- has_error = PyErr_Occurred(space) is not None
- has_result = ret is not None
- if has_error and has_result:
- raise OperationError(space.w_SystemError, space.wrap(
- "An exception was set, but function returned a value"))
- elif not expect_null and not has_error and not has_result:
- raise OperationError(space.w_SystemError, space.wrap(
- "Function returned a NULL result without setting an
exception"))
+ # Check for exception consistency
+ has_error = PyErr_Occurred(space) is not None
+ has_result = ret is not None
+ if has_error and has_result:
+ raise OperationError(space.w_SystemError, space.wrap(
+ "An exception was set, but function returned a value"))
+ elif not expect_null and not has_error and not has_result:
+ raise OperationError(space.w_SystemError, space.wrap(
+ "Function returned a NULL result without setting an
exception"))
- if has_error:
- state = space.fromcache(State)
- state.check_and_raise_exception()
+ if has_error:
+ state = space.fromcache(State)
+ state.check_and_raise_exception()
- return ret
- return result
- finally:
- if decref_args:
- for ref in to_decref:
- Py_DecRef(space, ref)
+ return ret
+ return result
+
return generic_cpy_call
-
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -381,6 +381,7 @@
if DEBUG_REFCOUNT:
debug_refcount("DECREF", obj, obj.c_ob_refcnt, frame_stackdepth=3)
if obj.c_ob_refcnt == 0:
+ return #ZZZ
state = space.fromcache(RefcountState)
ptr = rffi.cast(ADDR, obj)
if ptr not in state.py_objects_r2w:
diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py
--- a/pypy/module/cpyext/state.py
+++ b/pypy/module/cpyext/state.py
@@ -3,6 +3,7 @@
from pypy.interpreter.error import OperationError
from rpython.rtyper.lltypesystem import lltype
from rpython.rlib.rdynload import DLLHANDLE
+from rpython.rlib import rawrefcount
import sys
class State:
@@ -82,6 +83,7 @@
refcountstate = space.fromcache(RefcountState)
refcountstate.init_r2w_from_w2r()
+ rawrefcount.init(lambda ob: ZZZ)
for func in INIT_FUNCTIONS:
func(space)
self.check_and_raise_exception()
diff --git a/pypy/module/cpyext/test/test_cpyext.py
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -92,7 +92,7 @@
return str(pydname)
def freeze_refcnts(self):
- ZZZ
+ return #ZZZ
state = self.space.fromcache(RefcountState)
self.frozen_refcounts = {}
for w_obj, obj in state.py_objects_w2r.iteritems():
@@ -128,6 +128,7 @@
state.reset_borrowed_references()
def check_and_print_leaks(self):
+ return #ZZZ
# check for sane refcnts
import gc
@@ -213,8 +214,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_w[:] = []
+ #state = cls.space.fromcache(RefcountState) ZZZ
+ #state.non_heaptypes_w[:] = []
def setup_method(self, func):
@unwrap_spec(name=str)
@@ -368,6 +369,7 @@
def teardown_method(self, func):
for name in self.imported_module_names:
self.unimport_module(name)
+ return #ZZZ
self.cleanup_references(self.space)
# XXX: find out how to disable check_and_print_leaks() if the
# test failed...
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit