[pypy-svn] r74392 - in pypy/trunk/pypy/module/cpyext: . test
afa at codespeak.net
afa at codespeak.net
Thu May 6 01:09:24 CEST 2010
Author: afa
Date: Thu May 6 01:09:22 2010
New Revision: 74392
Modified:
pypy/trunk/pypy/module/cpyext/api.py
pypy/trunk/pypy/module/cpyext/dictobject.py
pypy/trunk/pypy/module/cpyext/funcobject.py
pypy/trunk/pypy/module/cpyext/listobject.py
pypy/trunk/pypy/module/cpyext/modsupport.py
pypy/trunk/pypy/module/cpyext/object.py
pypy/trunk/pypy/module/cpyext/pyerrors.py
pypy/trunk/pypy/module/cpyext/pyobject.py
pypy/trunk/pypy/module/cpyext/sequence.py
pypy/trunk/pypy/module/cpyext/state.py
pypy/trunk/pypy/module/cpyext/sysmodule.py
pypy/trunk/pypy/module/cpyext/test/test_borrow.py
pypy/trunk/pypy/module/cpyext/tupleobject.py
pypy/trunk/pypy/module/cpyext/weakrefobject.py
Log:
Start to refactor the "borrowed references" system:
now functions may return a BorrowedPair that ties the container with the returned object
the idiom is now:
"return borrow_from(w_container, w_obj)"
'borrowed=True' disappears from the api signatures,
state.last_container is gone.
Let's see if this translates...
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 01:09:22 2010
@@ -104,13 +104,11 @@
#
class ApiFunction:
- def __init__(self, argtypes, restype, callable,
- borrowed=False, error=_NOT_SPECIFIED):
+ def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED):
self.argtypes = argtypes
self.restype = restype
self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype))
self.callable = callable
- self.borrowed = borrowed
if error is not _NOT_SPECIFIED:
self.error_value = error
@@ -141,7 +139,7 @@
wrapper.relax_sig_check = True
return wrapper
-def cpython_api(argtypes, restype, borrowed=False, error=_NOT_SPECIFIED,
+def cpython_api(argtypes, restype, error=_NOT_SPECIFIED,
external=True, name=None):
if error is _NOT_SPECIFIED:
if restype is PyObject:
@@ -157,7 +155,7 @@
else:
func_name = name
func = func_with_new_name(func, name)
- api_function = ApiFunction(argtypes, restype, func, borrowed, error)
+ api_function = ApiFunction(argtypes, restype, func, error)
func.api_func = api_function
assert func_name not in FUNCTIONS
@@ -176,6 +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
newargs = ()
to_decref = []
assert len(args) == len(api_function.argtypes)
@@ -204,7 +203,7 @@
newargs += (arg, )
try:
try:
- return func(space, *newargs)
+ res = func(space, *newargs)
except OperationError, e:
if not catch_exception:
raise
@@ -216,10 +215,11 @@
return None
else:
return api_function.error_value
+ if isinstance(res, BorrowedPair):
+ return res.w_borrowed
+ else:
+ return res
finally:
- if api_function.borrowed:
- state = space.fromcache(State)
- state.last_container = 0
for arg in to_decref:
Py_DecRef(space, arg)
unwrapper.func = func
@@ -398,7 +398,7 @@
@specialize.ll()
def wrapper(*args):
from pypy.module.cpyext.pyobject import make_ref, from_ref
- from pypy.module.cpyext.pyobject import add_borrowed_object
+ from pypy.module.cpyext.pyobject import BorrowedPair
from pypy.module.cpyext.pyobject import NullPointerException
# we hope that malloc removal removes the newtuple() that is
# inserted exactly here by the varargs specializer
@@ -446,13 +446,12 @@
retval = error_value
elif callable.api_func.restype is PyObject:
- borrowed = callable.api_func.borrowed
- if not rffi._isllptr(result):
- retval = make_ref(space, result, borrowed=borrowed)
+ if isinstance(result, BorrowedPair):
+ retval = result.get_ref(space)
+ elif not rffi._isllptr(result):
+ retval = make_ref(space, result)
else:
retval = result
- if borrowed:
- add_borrowed_object(space, retval)
elif callable.api_func.restype is not lltype.Void:
retval = rffi.cast(callable.api_func.restype, result)
except NullPointerException:
Modified: pypy/trunk/pypy/module/cpyext/dictobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/dictobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/dictobject.py Thu May 6 01:09:22 2010
@@ -1,7 +1,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, build_type_checkers,\
Py_ssize_t, PyObjectP, CONST_STRING
-from pypy.module.cpyext.pyobject import PyObject, register_container
+from pypy.module.cpyext.pyobject import PyObject, borrow_from
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.interpreter.error import OperationError
@@ -11,14 +11,13 @@
PyDict_Check, PyDict_CheckExact = build_type_checkers("Dict")
- at cpython_api([PyObject, PyObject], PyObject, borrowed=True, error=CANNOT_FAIL)
+ at cpython_api([PyObject, PyObject], PyObject, error=CANNOT_FAIL)
def PyDict_GetItem(space, w_dict, w_key):
try:
w_res = space.getitem(w_dict, w_key)
except:
return None
- register_container(space, w_dict)
- return w_res
+ return borrow_from(w_dict, w_res)
@cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, error=-1)
def PyDict_SetItem(space, w_dict, w_key, w_obj):
@@ -47,7 +46,7 @@
else:
PyErr_BadInternalCall(space)
- at cpython_api([PyObject, CONST_STRING], PyObject, borrowed=True, error=CANNOT_FAIL)
+ at cpython_api([PyObject, CONST_STRING], PyObject, error=CANNOT_FAIL)
def PyDict_GetItemString(space, w_dict, key):
"""This is the same as PyDict_GetItem(), but key is specified as a
char*, rather than a PyObject*."""
@@ -57,8 +56,7 @@
w_res = None
if w_res is None:
return None
- register_container(space, w_dict)
- return w_res
+ return borrow_from(w_dict, w_res)
@cpython_api([PyObject], Py_ssize_t, error=-1)
def PyDict_Size(space, w_obj):
Modified: pypy/trunk/pypy/module/cpyext/funcobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/funcobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/funcobject.py Thu May 6 01:09:22 2010
@@ -3,7 +3,7 @@
PyObjectFields, generic_cpy_call,
cpython_api, bootstrap_function, cpython_struct, build_type_checkers)
from pypy.module.cpyext.pyobject import (
- PyObject, make_ref, from_ref, Py_DecRef, make_typedescr, register_container)
+ PyObject, make_ref, from_ref, Py_DecRef, make_typedescr, borrow_from)
from pypy.interpreter.function import Function, Method
PyFunctionObjectStruct = lltype.ForwardReference()
@@ -43,18 +43,16 @@
class which provides the unbound method."""
return Method(space, w_func, w_self, w_cls)
- at cpython_api([PyObject], PyObject, borrowed=True)
+ at cpython_api([PyObject], PyObject)
def PyMethod_Function(space, w_method):
"""Return the function object associated with the method meth."""
assert isinstance(w_method, Method)
- register_container(space, w_method)
- return w_method.w_function
+ return borrow_from(w_method, w_method.w_function)
- at cpython_api([PyObject], PyObject, borrowed=True)
+ at cpython_api([PyObject], PyObject)
def PyMethod_Class(space, w_method):
"""Return the class object from which the method meth was created; if this was
created from an instance, it will be the class of the instance."""
assert isinstance(w_method, Method)
- register_container(space, w_method)
- return w_method.w_class
+ return borrow_from(w_method, w_method.w_class)
Modified: pypy/trunk/pypy/module/cpyext/listobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/listobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/listobject.py Thu May 6 01:09:22 2010
@@ -3,7 +3,7 @@
from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, Py_ssize_t,
build_type_checkers)
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
-from pypy.module.cpyext.pyobject import Py_DecRef, PyObject, register_container
+from pypy.module.cpyext.pyobject import Py_DecRef, PyObject, borrow_from
from pypy.objspace.std.listobject import W_ListObject
from pypy.interpreter.error import OperationError
@@ -39,20 +39,19 @@
wrappeditems[index] = w_item
return 0
- at cpython_api([PyObject, Py_ssize_t], PyObject, borrowed=True)
+ at cpython_api([PyObject, Py_ssize_t], PyObject)
def PyList_GetItem(space, w_list, index):
"""Return the object at position pos in the list pointed to by p. The
position must be positive, indexing from the end of the list is not
supported. If pos is out of bounds, return NULL and set an
IndexError exception."""
- register_container(space, w_list)
if not isinstance(w_list, W_ListObject):
PyErr_BadInternalCall(space)
wrappeditems = w_list.wrappeditems
if index < 0 or index >= len(wrappeditems):
raise OperationError(space.w_IndexError, space.wrap(
"list index out of range"))
- return wrappeditems[index]
+ return borrow_from(w_list, wrappeditems[index])
@cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
Modified: pypy/trunk/pypy/module/cpyext/modsupport.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/modsupport.py (original)
+++ pypy/trunk/pypy/module/cpyext/modsupport.py Thu May 6 01:09:22 2010
@@ -1,14 +1,14 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import cpython_api, cpython_struct, \
METH_STATIC, METH_CLASS, METH_COEXIST, CANNOT_FAIL, CONST_STRING
-from pypy.module.cpyext.pyobject import PyObject, register_container
+from pypy.module.cpyext.pyobject import PyObject, borrow_from
from pypy.interpreter.module import Module
from pypy.module.cpyext.methodobject import W_PyCFunctionObject, PyCFunction_NewEx, PyDescr_NewMethod, PyMethodDef, PyCFunction
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.module.cpyext.state import State
from pypy.interpreter.error import OperationError
-#@cpython_api([rffi.CCHARP], PyObject, borrowed=True)
+#@cpython_api([rffi.CCHARP], PyObject)
def PyImport_AddModule(space, name):
"""Return the module object corresponding to a module name. The name argument
may be of the form package.module. First check the modules dictionary if
@@ -30,7 +30,7 @@
return w_mod
@cpython_api([CONST_STRING, lltype.Ptr(PyMethodDef), CONST_STRING,
- PyObject, rffi.INT_real], PyObject, borrowed=False) # we cannot borrow here
+ PyObject, rffi.INT_real], PyObject)
def Py_InitModule4(space, name, methods, doc, w_self, apiver):
"""
Create a new module object based on a name and table of functions, returning
@@ -58,6 +58,7 @@
if doc:
space.setattr(w_mod, space.wrap("__doc__"),
space.wrap(rffi.charp2str(doc)))
+ # we cannot borrow here
return w_mod
@@ -108,13 +109,12 @@
return int(space.is_w(w_type, w_obj_type) or
space.is_true(space.issubtype(w_obj_type, w_type)))
- at cpython_api([PyObject], PyObject, borrowed=True)
+ at cpython_api([PyObject], PyObject)
def PyModule_GetDict(space, w_mod):
if PyModule_Check(space, w_mod):
assert isinstance(w_mod, Module)
w_dict = w_mod.getdict()
- register_container(space, w_mod)
- return w_dict
+ return borrow_from(w_mod, w_dict)
else:
PyErr_BadInternalCall(space)
Modified: pypy/trunk/pypy/module/cpyext/object.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/object.py (original)
+++ pypy/trunk/pypy/module/cpyext/object.py Thu May 6 01:09:22 2010
@@ -144,7 +144,7 @@
This is the equivalent of the Python expression o[key]."""
return space.getitem(w_obj, w_key)
- at cpython_api([PyObject, PyTypeObjectPtr], PyObject, borrowed=True)
+ at cpython_api([PyObject, PyTypeObjectPtr], PyObject)
def PyObject_Init(space, op, type):
"""Initialize a newly-allocated object op with its type and initial
reference. Returns the initialized object. If type indicates that the
@@ -157,7 +157,7 @@
op.c_ob_refcnt = 1
return from_ref(space, op) # XXX will give an exception
- at cpython_api([PyVarObject, PyTypeObjectPtr, Py_ssize_t], PyObject, borrowed=True)
+ at cpython_api([PyVarObject, PyTypeObjectPtr, Py_ssize_t], PyObject)
def PyObject_InitVar(space, op, type, size):
"""This does everything PyObject_Init() does, and also initializes the
length information for a variable-size object."""
Modified: pypy/trunk/pypy/module/cpyext/pyerrors.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/pyerrors.py (original)
+++ pypy/trunk/pypy/module/cpyext/pyerrors.py Thu May 6 01:09:22 2010
@@ -5,7 +5,7 @@
from pypy.module.cpyext.api import cpython_api, CANNOT_FAIL, CONST_STRING
from pypy.module.exceptions.interp_exceptions import W_RuntimeWarning
from pypy.module.cpyext.pyobject import (
- PyObject, PyObjectP, make_ref, Py_DecRef, register_container)
+ PyObject, PyObjectP, make_ref, Py_DecRef, borrow_from)
from pypy.module.cpyext.state import State
from pypy.module.cpyext.import_ import PyImport_Import
from pypy.rlib.rposix import get_errno
@@ -27,13 +27,12 @@
"""This is a shorthand for PyErr_SetObject(type, Py_None)."""
PyErr_SetObject(space, w_type, space.w_None)
- at cpython_api([], PyObject, borrowed=True)
+ at cpython_api([], PyObject)
def PyErr_Occurred(space):
state = space.fromcache(State)
if state.operror is None:
return None
- register_container(space, lltype.nullptr(PyObject.TO))
- return state.operror.w_type
+ return borrow_from(None, state.operror.w_type)
@cpython_api([], lltype.Void)
def PyErr_Clear(space):
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 01:09:22 2010
@@ -319,29 +319,28 @@
#___________________________________________________________
# Support for borrowed references
- at cpython_api([PyObject], lltype.Void, external=False)
-def register_container(space, container):
- state = space.fromcache(State)
- if not container: # self-managed
- container_ptr = -1
- else:
+class BorrowedPair:
+ def __init__(self, w_container, w_borrowed):
+ self.w_borrowed = w_borrowed
+ self.w_container = w_container
+
+ def get_ref(self, space):
+ if self.w_borrowed is None:
+ return lltype.nullptr(PyObject.TO)
+ state = space.fromcache(State)
+ container = make_ref(space, self.w_container)
+ Py_DecRef(space, container)
container_ptr = rffi.cast(ADDR, container)
- assert not state.last_container, "Last container was not fetched"
- state.last_container = container_ptr
+ ref = make_ref(space, self.w_borrowed, borrowed=True)
+ if self.w_container is None: # self-managed
+ return ref
+ obj_ptr = rffi.cast(ADDR, ref)
+ borrowees = state.borrow_mapping.setdefault(container_ptr, {})
+ borrowees[obj_ptr] = None
+ return ref
-def add_borrowed_object(space, obj):
- state = space.fromcache(State)
- container_ptr = state.last_container
- state.last_container = 0
- if not obj:
- return
- if not container_ptr:
- raise NullPointerException
- if container_ptr == -1:
- return
- obj_ptr = rffi.cast(ADDR, obj)
- borrowees = state.borrow_mapping.setdefault(container_ptr, {})
- borrowees[obj_ptr] = None
+def borrow_from(container, borrowed):
+ return BorrowedPair(container, borrowed)
#___________________________________________________________
Modified: pypy/trunk/pypy/module/cpyext/sequence.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/sequence.py (original)
+++ pypy/trunk/pypy/module/cpyext/sequence.py Thu May 6 01:09:22 2010
@@ -2,7 +2,7 @@
from pypy.interpreter.error import OperationError
from pypy.module.cpyext.api import (
cpython_api, CANNOT_FAIL, CONST_STRING, Py_ssize_t)
-from pypy.module.cpyext.pyobject import PyObject, register_container
+from pypy.module.cpyext.pyobject import PyObject, borrow_from
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.objspace.std import listobject, tupleobject
@@ -40,7 +40,7 @@
except OperationError:
raise OperationError(space.w_TypeError, space.wrap(rffi.charp2str(m)))
- at cpython_api([PyObject, Py_ssize_t], PyObject, borrowed=True)
+ at cpython_api([PyObject, Py_ssize_t], PyObject)
def PySequence_Fast_GET_ITEM(space, w_obj, index):
"""Return the ith element of o, assuming that o was returned by
PySequence_Fast(), o is not NULL, and that i is within bounds.
@@ -50,8 +50,7 @@
else:
assert isinstance(w_obj, tupleobject.W_TupleObject)
w_res = w_obj.wrappeditems[index]
- register_container(space, w_obj)
- return w_res
+ return borrow_from(w_obj, w_res)
@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
def PySequence_Fast_GET_SIZE(space, w_obj):
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 01:09:22 2010
@@ -17,7 +17,6 @@
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.last_container = 0 # addr of last container
self.operror = None
self.new_method_def = lltype.nullptr(PyMethodDef)
Modified: pypy/trunk/pypy/module/cpyext/sysmodule.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/sysmodule.py (original)
+++ pypy/trunk/pypy/module/cpyext/sysmodule.py Thu May 6 01:09:22 2010
@@ -1,17 +1,16 @@
from pypy.interpreter.error import OperationError
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import CANNOT_FAIL, cpython_api, CONST_STRING
-from pypy.module.cpyext.pyobject import PyObject, register_container
+from pypy.module.cpyext.pyobject import PyObject, borrow_from
- at cpython_api([CONST_STRING], PyObject, borrowed=True, error=CANNOT_FAIL)
+ at cpython_api([CONST_STRING], PyObject, error=CANNOT_FAIL)
def PySys_GetObject(space, name):
"""Return the object name from the sys module or NULL if it does
not exist, without setting an exception."""
name = rffi.charp2str(name)
w_dict = space.sys.getdict()
w_obj = space.finditem_str(w_dict, name)
- register_container(space, w_dict)
- return w_obj
+ return borrow_from(w_dict, w_obj)
@cpython_api([CONST_STRING, PyObject], rffi.INT_real, error=-1)
def PySys_SetObject(space, name, w_obj):
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 01:09:22 2010
@@ -2,7 +2,7 @@
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, add_borrowed_object
+from pypy.module.cpyext.pyobject import make_ref, borrow_from
class TestBorrowing(BaseApiTest):
@@ -11,9 +11,7 @@
w_int = space.wrap(1)
w_tuple = space.newtuple([w_int])
api.Py_IncRef(w_tuple)
- api.register_container(w_tuple)
- one_pyo = make_ref(space, w_int, borrowed=True)
- add_borrowed_object(space, one_pyo)
+ one_pyo = borrow_from(w_tuple, w_int).get_ref(space)
print state.borrowed_objects
api.Py_DecRef(w_tuple)
state.print_refcounts()
Modified: pypy/trunk/pypy/module/cpyext/tupleobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/tupleobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/tupleobject.py Thu May 6 01:09:22 2010
@@ -2,7 +2,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL,
build_type_checkers)
-from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, register_container
+from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, borrow_from
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.objspace.std.tupleobject import W_TupleObject
@@ -23,14 +23,13 @@
Py_DecRef(space, w_obj) # SetItem steals a reference!
return 0
- at cpython_api([PyObject, Py_ssize_t], PyObject, borrowed=True)
+ at cpython_api([PyObject, Py_ssize_t], PyObject)
def PyTuple_GetItem(space, w_t, pos):
if not PyTuple_Check(space, w_t):
PyErr_BadInternalCall(space)
assert isinstance(w_t, W_TupleObject)
w_obj = w_t.wrappeditems[pos]
- register_container(space, w_t)
- return w_obj
+ return borrow_from(w_t, w_obj)
@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
def PyTuple_GET_SIZE(space, w_t):
Modified: pypy/trunk/pypy/module/cpyext/weakrefobject.py
==============================================================================
--- pypy/trunk/pypy/module/cpyext/weakrefobject.py (original)
+++ pypy/trunk/pypy/module/cpyext/weakrefobject.py Thu May 6 01:09:22 2010
@@ -1,5 +1,5 @@
from pypy.module.cpyext.api import cpython_api
-from pypy.module.cpyext.pyobject import PyObject, register_container
+from pypy.module.cpyext.pyobject import PyObject, borrow_from
from pypy.module._weakref.interp__weakref import W_Weakref
@cpython_api([PyObject, PyObject], PyObject)
@@ -16,13 +16,12 @@
w_weakref = space.gettypeobject(W_Weakref.typedef)
return space.call_function(w_weakref, w_obj, w_callback)
- at cpython_api([PyObject], PyObject, borrowed=True)
+ at cpython_api([PyObject], PyObject)
def PyWeakref_GetObject(space, w_ref):
"""Return the referenced object from a weak reference. If the referent is
no longer live, returns None. This function returns a borrowed reference.
"""
- register_container(space, w_ref)
- return space.call_function(w_ref)
+ return borrow_from(w_ref, space.call_function(w_ref))
@cpython_api([PyObject], PyObject)
def PyWeakref_LockObject(space, w_ref):
More information about the Pypy-commit
mailing list