Author: Antonio Cuni <anto.c...@gmail.com> Branch: cpyext-fast-typecheck Changeset: r94066:ba7b2efa9585 Date: 2018-03-22 13:02 +0100 http://bitbucket.org/pypy/pypy/changeset/ba7b2efa9585/
Log: WIP: modify the W_PyCWrapperObject call logic: instead of using a very generic logic which always build a tuple containing the arguments, we specify the expected arity and go through a specialized fast path 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 @@ -213,12 +213,14 @@ (self.name, self.w_objclass.getname(self.space))) - class W_PyCWrapperObject(W_Root): - def __init__(self, space, pto, method_name, wrapper_func, + _immutable_fields_ = ["arity"] + + def __init__(self, space, pto, method_name, arity, wrapper_func, wrapper_func_kwds, doc, func, offset=None): self.space = space self.method_name = method_name + self.arity = arity self.wrapper_func = wrapper_func self.wrapper_func_kwds = wrapper_func_kwds self.doc = doc @@ -229,18 +231,10 @@ assert isinstance(w_type, W_TypeObject) self.w_objclass = w_type - def descr_call(self, space, w_self, __args__): - args_w, kw_w = __args__.unpack() - w_args = space.newtuple(args_w) - w_kw = space.newdict() - for key, w_obj in kw_w.items(): - space.setitem(w_kw, space.newtext(key), w_obj) - return self.call(space, w_self, w_args, w_kw) - - def call(self, space, w_self, w_args, w_kw): + def _get_func_to_call(self): func_to_call = self.func if self.offset: - pto = as_pyobj(space, self.w_objclass) + pto = as_pyobj(self.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: @@ -254,6 +248,36 @@ assert False, "failed to convert w_type %s to PyObject" % str( self.w_objclass) assert func_to_call + return func_to_call + + def descr_call(self, space, w_self, __args__): + if self.arity == -1: + # slow, fallback logic: eventually, this should be killed + args_w, kw_w = __args__.unpack() + w_args = space.newtuple(args_w) + w_kw = space.newdict() + for key, w_obj in kw_w.items(): + space.setitem(w_kw, space.newtext(key), w_obj) + return self.call(space, w_self, w_args, w_kw) + # + # new logic + # XXX: check for keywords + length = len(__args__.arguments_w) + if length != self.arity: + raise oefmt(space.w_TypeError, "expected %d arguments, got %d", + self.arity, length) + if self.arity == 1: + return self.call_1(space, w_self, __args__) + + assert False, 'should not arrive here' + + def call_1(self, space, w_self, __args__): + func = self._get_func_to_call() + w_o = __args__.arguments_w[0] + return self.wrapper_func(space, func, w_self, w_o) + + def call(self, space, w_self, w_args, w_kw): + func_to_call = self._get_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, func_to_call, diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -84,11 +84,9 @@ check_num_args(space, w_args, 0) return generic_cpy_call(space, func_unary, w_self) -def wrap_binaryfunc(space, w_self, w_args, func): +def wrap_binaryfunc(space, func, w_self, w_x): func_binary = rffi.cast(binaryfunc, func) - check_num_args(space, w_args, 1) - args_w = space.fixedview(w_args) - return generic_cpy_call(space, func_binary, w_self, args_w[0]) + return generic_cpy_call(space, func_binary, w_self, w_x) def _get_ob_type(space, w_obj): # please ensure that w_obj stays alive 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 @@ -338,7 +338,15 @@ continue if wrapper_func is None and wrapper_func_kwds is None: continue - w_obj = W_PyCWrapperObject(space, pto, method_name, wrapper_func, + + arity = -1 + from pypy.module.cpyext.slotdefs import wrap_binaryfunc + if wrapper_func is wrap_binaryfunc: + # XXX: this is just a quick hack, we need an official way to + # specify the arity + arity = 1 + + w_obj = W_PyCWrapperObject(space, pto, method_name, arity, wrapper_func, wrapper_func_kwds, doc, func_voidp, offset=offset) dict_w[method_name] = w_obj if pto.c_tp_doc: _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit