Author: Matti Picus <matti.pi...@gmail.com> Branch: call-via-pyobj Changeset: r85484:5b38ce2c4c11 Date: 2016-07-01 12:53 +0300 http://bitbucket.org/pypy/pypy/changeset/5b38ce2c4c11/
Log: proof of concept using offset-to-function instead of function diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py --- a/pypy/module/cpyext/methodobject.py +++ b/pypy/module/cpyext/methodobject.py @@ -10,9 +10,10 @@ from pypy.module.cpyext.api import ( CONST_STRING, METH_CLASS, METH_COEXIST, METH_KEYWORDS, METH_NOARGS, METH_O, METH_STATIC, METH_VARARGS, PyObject, PyObjectFields, bootstrap_function, - build_type_checkers, cpython_api, cpython_struct, generic_cpy_call) + build_type_checkers, cpython_api, cpython_struct, generic_cpy_call, + PyTypeObjectPtr) from pypy.module.cpyext.pyobject import ( - Py_DecRef, from_ref, make_ref, make_typedescr) + Py_DecRef, from_ref, make_ref, as_pyobj, make_typedescr) PyCFunction_typedef = rffi.COpaquePtr(typedef='PyCFunction') PyCFunction = lltype.Ptr(lltype.FuncType([PyObject, PyObject], PyObject)) @@ -151,13 +152,14 @@ class W_PyCWrapperObject(W_Root): def __init__(self, space, pto, method_name, wrapper_func, - wrapper_func_kwds, doc, func): + wrapper_func_kwds, doc, func, offset=-1): self.space = space self.method_name = method_name self.wrapper_func = wrapper_func self.wrapper_func_kwds = wrapper_func_kwds self.doc = doc self.func = func + self.offset = offset pyo = rffi.cast(PyObject, pto) w_type = from_ref(space, pyo) assert isinstance(w_type, W_TypeObject) @@ -172,7 +174,17 @@ raise oefmt(space.w_TypeError, "wrapper %s doesn't take any keyword arguments", self.method_name) - return self.wrapper_func(space, w_self, w_args, self.func) + if self.offset >= 0: + pto = rffi.cast(PyTypeObjectPtr, as_pyobj(space, self.w_objclass)) + pto_func_as_int = lltype.cast_ptr_to_int(pto) + self.offset + # XXX make pto_func the equivalent of this line + #lltype.cast_int_to_ptr(pto_func_as_int) + func_to_call = rffi.cast(rffi.VOIDP, pto.c_tp_as_number.c_nb_multiply) + # print '\ncalling', func_to_call, 'not', self.func + else: + # print 'calling', self.method_name,'with no offset' + func_to_call = self.func + return self.wrapper_func(space, w_self, w_args, func_to_call) def descr_method_repr(self): return self.space.wrap("<slot wrapper '%s' of '%s' objects>" % @@ -301,12 +313,6 @@ def PyDescr_NewClassMethod(space, w_type, method): return space.wrap(W_PyCClassMethodObject(space, method, w_type)) -def PyDescr_NewWrapper(space, pto, method_name, wrapper_func, - wrapper_func_kwds, doc, func): - # not exactly the API sig - return space.wrap(W_PyCWrapperObject(space, pto, method_name, - wrapper_func, wrapper_func_kwds, doc, func)) - @cpython_api([lltype.Ptr(PyMethodDef), PyObject, CONST_STRING], PyObject) def Py_FindMethod(space, table, w_obj, name_ptr): """Return a bound method object for an extension type implemented in 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 @@ -17,9 +17,9 @@ generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING, Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL, Py_TPFLAGS_HAVE_GETCHARBUFFER, build_type_checkers, StaticObjectBuilder, - PyObjectFields, Py_TPFLAGS_BASETYPE) + PyObjectFields, Py_TPFLAGS_BASETYPE, PyTypeObject, PyTypeObjectPtr) from pypy.module.cpyext.methodobject import (W_PyCClassMethodObject, - PyDescr_NewWrapper, PyCFunction_NewEx, PyCFunction_typedef, PyMethodDef, + W_PyCWrapperObject, PyCFunction_NewEx, PyCFunction_typedef, PyMethodDef, W_PyCMethodObject, W_PyCFunctionObject) from pypy.module.cpyext.modsupport import convert_method_defs from pypy.module.cpyext.pyobject import ( @@ -30,7 +30,7 @@ from pypy.module.cpyext.state import State from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne from pypy.module.cpyext.typeobjectdefs import ( - PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc, + PyGetSetDef, PyMemberDef, newfunc, PyNumberMethods, PyMappingMethods, PySequenceMethods, PyBufferProcs) from pypy.objspace.std.typeobject import W_TypeObject, find_best_base @@ -296,6 +296,7 @@ for method_name, slot_names, wrapper_func, wrapper_func_kwds, doc in slotdefs_for_wrappers: if method_name in dict_w: continue + offset = rffi.offsetof(pto._T, slot_names[0]) if len(slot_names) == 1: func = getattr(pto, slot_names[0]) else: @@ -303,14 +304,24 @@ struct = getattr(pto, slot_names[0]) if not struct: continue + offset += rffi.offsetof(struct._T, slot_names[1]) func = getattr(struct, slot_names[1]) func_voidp = rffi.cast(rffi.VOIDP, func) if not func: continue if wrapper_func is None and wrapper_func_kwds is None: continue - dict_w[method_name] = PyDescr_NewWrapper(space, pto, method_name, wrapper_func, - wrapper_func_kwds, doc, func_voidp) + name = rffi.charp2str(pto.c_tp_name) + if method_name in ('__mul__', '__rmul__') and 'array' in name: + # print '\nsetting', name, method_name, 'from', slot_names + # print ' pto is', pto + # print ' func_voidp is', func_voidp + pass + else: + offset = -1 + w_obj = W_PyCWrapperObject(space, pto, method_name, wrapper_func, + wrapper_func_kwds, doc, func_voidp, offset=offset) + dict_w[method_name] = space.wrap(w_obj) if pto.c_tp_new: add_tp_new_wrapper(space, dict_w, pto) @@ -714,6 +725,8 @@ def py_type_ready(space, pto): if pto.c_tp_flags & Py_TPFLAGS_READY: + name = rffi.charp2str(pto.c_tp_name) + print 'py_type_ready',name, 'but PyTP_FLAGS_READY is set' return type_realize(space, rffi.cast(PyObject, pto)) @@ -730,6 +743,8 @@ try: w_obj = _type_realize(space, py_obj) finally: + name = rffi.charp2str(pto.c_tp_name) + print '_type_realize done', name pto.c_tp_flags &= ~Py_TPFLAGS_READYING pto.c_tp_flags |= Py_TPFLAGS_READY return w_obj @@ -811,7 +826,9 @@ base = pto.c_tp_base base_pyo = rffi.cast(PyObject, pto.c_tp_base) if base and not base.c_tp_flags & Py_TPFLAGS_READY: - type_realize(space, rffi.cast(PyObject, base_pyo)) + name = rffi.charp2str(base.c_tp_name) + print 'realizing base while creating child', + type_realize(space, base_pyo) if base and not pto.c_ob_type: # will be filled later pto.c_ob_type = base.c_ob_type if not pto.c_tp_bases: _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit