Author: Armin Rigo <[email protected]>
Branch: cpyext-avoid-roundtrip
Changeset: r92550:087ef45836c2
Date: 2017-10-02 12:14 +0200
http://bitbucket.org/pypy/pypy/changeset/087ef45836c2/
Log: (antocuni, arigo)
Move subtype_dealloc to C. Lots of messes that might not be
necessary any more thanks to d519061c7cf0.
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
@@ -1038,7 +1038,7 @@
return wrapper_second_level
-def setup_init_functions(eci, prefix, space):
+def setup_init_functions(eci, prefix):
# jump through hoops to avoid releasing the GIL during initialization
# of the cpyext module. The C functions are called with no wrapper,
# but must not do anything like calling back PyType_Ready(). We
@@ -1072,6 +1072,8 @@
_reinit_tls()
add_fork_hook('child', reinit_tls)
+
+def attach_c_functions(space, eci):
state = space.fromcache(State)
state.C._Py_Dealloc = rffi.llexternal('_Py_Dealloc',
[PyObject], lltype.Void,
@@ -1080,6 +1082,10 @@
_, state.C.set_marker = rffi.CExternVariable(
Py_ssize_t, '_pypy_rawrefcount_w_marker_deallocating',
eci, _nowrapper=True, c_type='Py_ssize_t')
+ # XXX meeeeeeeeessssss mmmmmmmmmmmmmmmeeeeeeeeeeeeeeeeeeeeeessssssssssss
+ state.C._PyPy_get_subtype_dealloc = rffi.llexternal(
+ '_PyPy_get_subtype_dealloc', [], rffi.VOIDP,
+ compilation_info=eci, _nowrapper=True)
def init_function(func):
@@ -1150,6 +1156,7 @@
space.fromcache(State).install_dll(eci)
modulename = py.path.local(eci.libraries[-1])
+ attach_c_functions(space, eci)
run_bootstrap_functions(space)
# load the bridge, and init structure
@@ -1201,7 +1208,7 @@
ll2ctypes.lltype2ctypes(func.get_llhelper(space)),
ctypes.c_void_p)
- setup_init_functions(eci, prefix, space)
+ setup_init_functions(eci, prefix)
return modulename.new(ext='')
def attach_recursively(space, static_pyobjs, static_objs_w, attached_objs, i):
@@ -1394,6 +1401,7 @@
source_dir / "missing.c",
source_dir / "pymem.c",
source_dir / "object.c",
+ source_dir / "typeobject.c",
]
def build_eci(code, use_micronumpy=False, translating=False):
@@ -1488,6 +1496,7 @@
eci = build_eci(code, use_micronumpy, translating=True)
space.fromcache(State).install_dll(eci)
+ attach_c_functions(space, eci)
run_bootstrap_functions(space)
# emit uninitialized static data
@@ -1532,7 +1541,7 @@
relax=True)
deco(func.get_wrapper(space))
- setup_init_functions(eci, prefix, space)
+ setup_init_functions(eci, prefix)
trunk_include = pypydir.dirpath() / 'include'
copy_header_files(cts, trunk_include, use_micronumpy)
diff --git a/pypy/module/cpyext/include/object.h
b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -335,6 +335,7 @@
PyAPI_FUNC(int) PyPyType_Register(PyTypeObject *);
#define PyObject_Length PyObject_Size
#define _PyObject_GC_Del PyObject_GC_Del
+PyAPI_FUNC(void *) _PyPy_get_subtype_dealloc(void);
#ifdef __cplusplus
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
@@ -7,7 +7,7 @@
from pypy.module.cpyext.api import (
cpython_api, bootstrap_function, PyObject, PyObjectP, ADDR,
CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr, is_PyObject,
- PyVarObject, Py_ssize_t, init_function)
+ PyVarObject, Py_ssize_t, init_function, cts)
from pypy.module.cpyext.state import State
from pypy.objspace.std.typeobject import W_TypeObject
from pypy.objspace.std.objectobject import W_ObjectObject
@@ -27,8 +27,8 @@
W_BaseObject = W_ObjectObject
def get_dealloc(self, space):
- from pypy.module.cpyext.typeobject import subtype_dealloc
- return subtype_dealloc.api_func.get_llhelper(space)
+ state = space.fromcache(State)
+ return cts.cast('destructor', state.C._PyPy_get_subtype_dealloc())
def allocate(self, space, w_type, itemcount=0, immortal=False):
# typically called from PyType_GenericAlloc via typedescr.allocate
diff --git a/pypy/module/cpyext/src/typeobject.c
b/pypy/module/cpyext/src/typeobject.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/src/typeobject.c
@@ -0,0 +1,35 @@
+#include "Python.h"
+
+static void subtype_dealloc(PyObject *obj)
+{
+ PyTypeObject *pto = obj->ob_type;
+ PyTypeObject *base = pto;
+ /* This wrapper is created on a specific type, call it w_A.
+ We wish to call the dealloc function from one of the base classes of
w_A,
+ the first of which is not this function itself.
+ w_obj is an instance of w_A or one of its subclasses. So climb up the
+ inheritance chain until base.c_tp_dealloc is exactly this_func, and then
+ continue on up until they differ.
+ */
+ while (base->tp_dealloc != &subtype_dealloc)
+ {
+ base = base->tp_base;
+ assert(base);
+ }
+ while (base->tp_dealloc == &subtype_dealloc)
+ {
+ base = base->tp_base;
+ assert(base);
+ }
+ /* XXX call tp_del if necessary */
+ base->tp_dealloc(obj);
+ /* XXX cpy decrefs the pto here but we do it in the base-dealloc
+ hopefully this does not clash with the memory model assumed in
+ extension modules */
+}
+
+PyAPI_FUNC(void *)
+_PyPy_get_subtype_dealloc(void)
+{
+ return &subtype_dealloc;
+}
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -529,36 +529,6 @@
realize=type_realize,
dealloc=type_dealloc)
-@slot_function([PyObject], lltype.Void)
-def subtype_dealloc(space, obj):
- pto = obj.c_ob_type
- base = pto
- this_func_ptr = llslot(space, subtype_dealloc)
- w_obj = from_ref(space, rffi.cast(PyObject, base))
- # This wrapper is created on a specific type, call it w_A.
- # We wish to call the dealloc function from one of the base classes of w_A,
- # the first of which is not this function itself.
- # w_obj is an instance of w_A or one of its subclasses. So climb up the
- # inheritance chain until base.c_tp_dealloc is exactly this_func, and then
- # continue on up until they differ.
- #print 'subtype_dealloc, start from', rffi.charp2str(base.c_tp_name)
- while base.c_tp_dealloc != this_func_ptr:
- base = base.c_tp_base
- assert base
- #print ' ne move to', rffi.charp2str(base.c_tp_name)
- w_obj = from_ref(space, rffi.cast(PyObject, base))
- while base.c_tp_dealloc == this_func_ptr:
- base = base.c_tp_base
- assert base
- #print ' eq move to', rffi.charp2str(base.c_tp_name)
- w_obj = from_ref(space, rffi.cast(PyObject, base))
- #print ' end with', rffi.charp2str(base.c_tp_name)
- dealloc = base.c_tp_dealloc
- # XXX call tp_del if necessary
- generic_cpy_call(space, dealloc, obj)
- # XXX cpy decrefs the pto here but we do it in the base-dealloc
- # hopefully this does not clash with the memory model assumed in
- # extension modules
@slot_function([PyObject, Py_ssize_tP], lltype.Signed, error=CANNOT_FAIL)
def bf_segcount(space, w_obj, ref):
@@ -764,7 +734,9 @@
pto.c_tp_dealloc = pto.c_tp_base.c_tp_dealloc
if not pto.c_tp_dealloc:
# strange, but happens (ABCMeta)
- pto.c_tp_dealloc = llslot(space, subtype_dealloc)
+ state = space.fromcache(State)
+ d = cts.cast('destructor', state.C._PyPy_get_subtype_dealloc())
+ pto.c_tp_dealloc = d
if builder.cpyext_type_init is not None:
builder.cpyext_type_init.append((pto, w_type))
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit