Author: Matti Picus <[email protected]>
Branch:
Changeset: r85642:221017a4d9f7
Date: 2016-07-09 16:20 -0400
http://bitbucket.org/pypy/pypy/changeset/221017a4d9f7/
Log: merge call-via-pyobj which uses offset-from-PyTypeObject when
calling functions
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
@@ -1,4 +1,4 @@
-from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
from pypy.interpreter.baseobjspace import W_Root
from pypy.interpreter.error import OperationError, oefmt
@@ -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,28 +152,45 @@
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=None):
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)
self.w_objclass = w_type
def call(self, space, w_self, w_args, w_kw):
+ func_to_call = self.func
+ if self.offset:
+ pto = as_pyobj(space, self.w_objclass)
+ # make ptr the equivalent of this, using the offsets
+ #func_to_call = rffi.cast(rffi.VOIDP,
ptr.c_tp_as_number.c_nb_multiply)
+ if pto:
+ cptr = rffi.cast(rffi.CCHARP, pto)
+ for o in self.offset:
+ ptr = rffi.cast(rffi.VOIDPP, rffi.ptradd(cptr, o))[0]
+ cptr = rffi.cast(rffi.CCHARP, ptr)
+ func_to_call = rffi.cast(rffi.VOIDP, cptr)
+ else:
+ # Should never happen, assert to get a traceback
+ assert False, "failed to convert w_type %s to PyObject" % str(
+ self.w_objclass)
+ assert func_to_call
if self.wrapper_func is None:
assert self.wrapper_func_kwds is not None
- return self.wrapper_func_kwds(space, w_self, w_args, self.func,
+ return self.wrapper_func_kwds(space, w_self, w_args, func_to_call,
w_kw)
if space.is_true(w_kw):
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)
+ 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 +319,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/test/array.c b/pypy/module/cpyext/test/array.c
--- a/pypy/module/cpyext/test/array.c
+++ b/pypy/module/cpyext/test/array.c
@@ -2144,6 +2144,13 @@
return array_new(type, args, NULL);
}
+static PyObject *
+switch_multiply(void)
+{
+ Arraytype.tp_as_number->nb_multiply = array_base_multiply;
+ Py_RETURN_NONE;
+};
+
PyDoc_STRVAR(module_doc,
"This module defines an object type which can efficiently represent\n\
an array of basic values: characters, integers, floating point\n\
@@ -2394,6 +2401,7 @@
/* No functions in array module. */
static PyMethodDef a_methods[] = {
{"_reconstruct", (PyCFunction)_reconstruct, METH_VARARGS, NULL},
+ {"switch_multiply", (PyCFunction)switch_multiply, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL} /* Sentinel */
};
diff --git a/pypy/module/cpyext/test/test_arraymodule.py
b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -84,3 +84,7 @@
arr = module.array('i', [2])
res = [1, 2, 3] * arr
assert res == [1, 2, 3, 1, 2, 3]
+ module.switch_multiply()
+ res = [1, 2, 3] * arr
+ assert res == [2, 4, 6]
+
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(lltype.typeOf(pto).TO, slot_names[0])]
if len(slot_names) == 1:
func = getattr(pto, slot_names[0])
else:
@@ -303,14 +304,16 @@
struct = getattr(pto, slot_names[0])
if not struct:
continue
+ offset.append(rffi.offsetof(lltype.typeOf(struct).TO,
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)
+ 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)
@@ -730,6 +733,7 @@
try:
w_obj = _type_realize(space, py_obj)
finally:
+ name = rffi.charp2str(pto.c_tp_name)
pto.c_tp_flags &= ~Py_TPFLAGS_READYING
pto.c_tp_flags |= Py_TPFLAGS_READY
return w_obj
@@ -811,7 +815,8 @@
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)
+ 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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit