[pypy-svn] r72603 - in pypy/branch/cpython-extension/pypy/module/cpyext: . test
xoraxax at codespeak.net
xoraxax at codespeak.net
Tue Mar 23 01:52:20 CET 2010
Author: xoraxax
Date: Tue Mar 23 01:52:18 2010
New Revision: 72603
Modified:
pypy/branch/cpython-extension/pypy/module/cpyext/api.py
pypy/branch/cpython-extension/pypy/module/cpyext/macros.py
pypy/branch/cpython-extension/pypy/module/cpyext/methodobject.py
pypy/branch/cpython-extension/pypy/module/cpyext/object.py
pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py
pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
Log:
Reworked memory handling, please review.
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/api.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/api.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/api.py Tue Mar 23 01:52:18 2010
@@ -45,16 +45,17 @@
class ApiFunction:
- def __init__(self, argtypes, restype, callable, borrowed):
+ def __init__(self, argtypes, restype, callable, borrowed, dont_deref):
self.argtypes = argtypes
self.restype = restype
self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype))
self.callable = callable
self.borrowed = borrowed
+ self.dont_deref = dont_deref
-def cpython_api(argtypes, restype, borrowed=False):
+def cpython_api(argtypes, restype, borrowed=False, dont_deref=False):
def decorate(func):
- api_function = ApiFunction(argtypes, restype, func, borrowed)
+ api_function = ApiFunction(argtypes, restype, func, borrowed, dont_deref)
FUNCTIONS[func.func_name] = api_function
func.api_func = api_function
return func
@@ -177,6 +178,47 @@
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)))
+def make_wrapper(space, callable):
+ def wrapper(*args):
+ boxed_args = []
+ # XXX use unrolling_iterable here
+ print >>sys.stderr, callable,
+ for i, typ in enumerate(callable.api_func.argtypes):
+ arg = args[i]
+ if typ is PyObject and not callable.api_func.dont_deref:
+ arg = from_ref(space, arg)
+ boxed_args.append(arg)
+ state = space.fromcache(State)
+ try:
+ retval = callable(space, *boxed_args)
+ print >>sys.stderr, " DONE"
+ except OperationError, e:
+ e.normalize_exception(space)
+ state.exc_type = e.w_type
+ state.exc_value = e.get_w_value(space)
+ except BaseException, e:
+ state.exc_type = space.w_SystemError
+ state.exc_value = space.wrap(str(e))
+ import traceback
+ traceback.print_exc()
+
+ if state.exc_value is not None:
+ restype = callable.api_func.restype
+ if restype is lltype.Void:
+ return
+ if restype is PyObject:
+ return lltype.nullptr(PyObject.TO)
+ if restype in (Py_ssize_t, rffi.INT_real):
+ return rffi.cast(restype, -1)
+ assert False, "Unknown return type"
+
+ if callable.api_func.restype is PyObject:
+ retval = make_ref(space, retval, borrowed=callable.api_func.borrowed)
+ if callable.api_func.restype is rffi.INT_real:
+ retval = rffi.cast(rffi.INT_real, retval)
+ return retval
+ return wrapper
+
#_____________________________________________________
# Build the bridge DLL, Allow extension DLLs to call
# back into Pypy space functions
@@ -279,51 +321,11 @@
ptr.value = ctypes.cast(ll2ctypes.lltype2ctypes(make_ref(space, w_obj)),
ctypes.c_void_p).value
- def make_wrapper(callable):
- def wrapper(*args):
- boxed_args = []
- # XXX use unrolling_iterable here
- print >>sys.stderr, callable,
- for i, typ in enumerate(callable.api_func.argtypes):
- arg = args[i]
- if typ is PyObject:
- arg = from_ref(space, arg)
- boxed_args.append(arg)
- state = space.fromcache(State)
- try:
- retval = callable(space, *boxed_args)
- print >>sys.stderr, " DONE"
- except OperationError, e:
- e.normalize_exception(space)
- state.exc_type = e.w_type
- state.exc_value = e.get_w_value(space)
- except BaseException, e:
- state.exc_type = space.w_SystemError
- state.exc_value = space.wrap(str(e))
- import traceback
- traceback.print_exc()
-
- if state.exc_value is not None:
- restype = callable.api_func.restype
- if restype is lltype.Void:
- return
- if restype is PyObject:
- return lltype.nullptr(PyObject.TO)
- if restype in (Py_ssize_t, rffi.INT_real):
- return rffi.cast(restype, -1)
- assert False, "Unknown return type"
-
- if callable.api_func.restype is PyObject:
- retval = make_ref(space, retval, borrowed=callable.api_func.borrowed)
- if callable.api_func.restype is rffi.INT_real:
- retval = rffi.cast(rffi.INT_real, retval)
- return retval
- return wrapper
-
# implement structure initialization code
for name, func in FUNCTIONS.iteritems():
pypyAPI[structindex[name]] = ctypes.cast(
- ll2ctypes.lltype2ctypes(llhelper(func.functype, make_wrapper(func.callable))),
+ ll2ctypes.lltype2ctypes(llhelper(func.functype,
+ make_wrapper(space, func.callable))),
ctypes.c_void_p)
return modulename.new(ext='')
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/macros.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/macros.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/macros.py Tue Mar 23 01:52:18 2010
@@ -7,15 +7,15 @@
# XXX Optimize these functions and put them into macro definitions
@cpython_api([PyObject], lltype.Void)
def Py_DECREF(space, w_obj):
+ print "DECREF", w_obj
state = space.fromcache(State)
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]
ptr = ctypes.addressof(obj._obj._storage)
+ _Py_Dealloc(space, w_obj)
+ del state.py_objects_w2r[w_obj]
del state.py_objects_r2w[ptr]
- # XXX this will likely be somewhere else when we have grown a type object
- lltype.free(obj, flavor='raw')
else:
assert obj.c_obj_refcnt > 0
return
@@ -26,3 +26,19 @@
obj = state.py_objects_w2r.get(w_obj)
obj.c_obj_refcnt += 1
+
+def _Py_Dealloc(space, w_obj):
+ from pypy.module.cpyext.typeobject import PyTypeObjectPtr
+ from pypy.module.cpyext.methodobject import generic_cpy_call
+ state = space.fromcache(State)
+ w_type = space.type(w_obj)
+ pto = make_ref(space, w_type)
+ pto = rffi.cast(PyTypeObjectPtr, pto)
+ try:
+ print "Calling ", pto.c_tp_dealloc, "of", w_obj, "'s type which is", w_type
+ generic_cpy_call(space, pto.c_tp_dealloc, w_obj, decref_args=False)
+ finally:
+ # XXX uncommenting the next line gives double frees, why?
+ #Py_DECREF(space, w_type) # make_ref bumps refcount
+ pass
+
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/methodobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/methodobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/methodobject.py Tue Mar 23 01:52:18 2010
@@ -28,7 +28,9 @@
raise
return ret
-def generic_cpy_call(space, func, *args):
+def generic_cpy_call(space, func, *args, **kwargs):
+ decref_args = kwargs.pop("decref_args", False)
+ assert not decref_args
boxed_args = []
for arg in args: # XXX ur needed
if isinstance(arg, W_Root) or arg is None:
@@ -37,13 +39,16 @@
boxed_args.append(arg)
result = func(*boxed_args)
try:
- ret = from_ref_ex(space, result)
- Py_DECREF(space, ret)
- return ret
+ FT = lltype.typeOf(func).TO
+ if FT.RESULT is not lltype.Void:
+ ret = from_ref_ex(space, result)
+ Py_DECREF(space, ret)
+ return ret
finally:
- for arg in args: # XXX ur needed
- if arg is not None and isinstance(arg, W_Root):
- Py_DECREF(space, arg)
+ if decref_args:
+ for arg in args: # XXX ur needed
+ if arg is not None and isinstance(arg, W_Root):
+ Py_DECREF(space, arg)
# XXX use Function as a parent class?
class W_PyCFunctionObject(Wrappable):
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/object.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/object.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/object.py Tue Mar 23 01:52:18 2010
@@ -1,5 +1,6 @@
from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import cpython_api, PyObject, make_ref
+from pypy.module.cpyext.api import cpython_api, PyObject, make_ref, from_ref
+from pypy.module.cpyext.state import State
from pypy.module.cpyext.typeobject import PyTypeObjectPtr, W_PyCTypeObject, W_PyCObject
from pypy.objspace.std.objectobject import W_ObjectObject
@@ -8,9 +9,17 @@
def _PyObject_New(space, w_type):
if isinstance(w_type, W_PyCTypeObject):
w_pycobj = space.allocate_instance(W_PyCObject, w_type)
+ w_pycobj.__init__(space)
return w_pycobj
assert False, "Please add more cases in get_cls_for_type_object!"
@cpython_api([rffi.VOIDP_real], lltype.Void)
-def PyObject_Del(space, w_obj):
- pass # XXX move lltype.free here
+def PyObject_Del(space, obj):
+ # XXX cast object according to the basesize in pto
+ lltype.free(obj, flavor='raw')
+
+ at cpython_api([PyObject], lltype.Void, dont_deref=True)
+def PyObject_Del_cast(space, obj):
+ # XXX cast object according to the basesize in pto
+ lltype.free(obj, flavor='raw')
+
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/test/test_cpyext.py Tue Mar 23 01:52:18 2010
@@ -117,7 +117,6 @@
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()
Modified: pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py
==============================================================================
--- pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py (original)
+++ pypy/branch/cpython-extension/pypy/module/cpyext/typeobject.py Tue Mar 23 01:52:18 2010
@@ -2,6 +2,7 @@
from pypy.rpython.lltypesystem import rffi, lltype
from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void
+from pypy.rpython.annlowlevel import llhelper
from pypy.interpreter.gateway import ObjSpace, W_Root
from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.baseobjspace import Wrappable
@@ -11,6 +12,7 @@
from pypy.module.cpyext.api import cpython_api, cpython_api_c, cpython_struct
from pypy.module.cpyext.api import PyObject, PyVarObjectFields, Py_ssize_t
from pypy.module.cpyext.api import Py_TPFLAGS_READYING, Py_TPFLAGS_READY
+from pypy.module.cpyext.api import make_wrapper
from pypy.interpreter.module import Module
from pypy.module.cpyext.modsupport import PyMethodDef, convert_method_defs
from pypy.module.cpyext.state import State
@@ -204,16 +206,25 @@
bases_w or [space.w_object], dict_w)
class W_PyCObject(Wrappable):
- pass
+ def __init__(self, space):
+ self.space = space
+
+ def __del__(self):
+ space = self.space
+ self.clear_all_weakrefs()
+ w_type = space.type(self)
+ assert isinstance(w_type, W_PyCTypeObject)
+ pto = w_type.pto
+ generic_cpy_call(space, pto.c_tp_dealloc, self)
- at unwrap_spec(ObjSpace, W_Root, W_Root)
-def cobject_descr_getattr(space, w_obj, w_name):
- name = space.str_w(w_name)
- return w_name
def allocate_type_obj(space, w_obj):
+ from pypy.module.cpyext.object import PyObject_Del_cast
pto = lltype.malloc(PyTypeObject, None, flavor="raw")
+ callable = PyObject_Del_cast
+ pto.c_tp_dealloc = llhelper(callable.api_func.functype,
+ make_wrapper(space, callable))
# XXX fill slots in pto
return pto
More information about the Pypy-commit
mailing list