Author: Antonio Cuni <anto.c...@gmail.com> Branch: cpyext-fast-typecheck Changeset: r94070:5ef7b9a78fc4 Date: 2018-03-22 15:04 +0100 http://bitbucket.org/pypy/pypy/changeset/5ef7b9a78fc4/
Log: WIP, refactor the previous commit: since wrap_binaryfunc has a different signature, we can no longer mix it with the others, else the annotator (correctly) complains. Solve it by writing a specialized version of the class: eventually, we will have only specialized classes, and kill the generic one 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 @@ -214,15 +214,10 @@ class W_PyCWrapperObject(W_Root): - _immutable_fields_ = ["arity"] - - def __init__(self, space, pto, method_name, arity, wrapper_func, - wrapper_func_kwds, doc, func, offset=None): + + def __init__(self, space, pto, method_name, doc, func, offset): 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 self.func = func self.offset = offset @@ -231,7 +226,10 @@ assert isinstance(w_type, W_TypeObject) self.w_objclass = w_type - def _get_func_to_call(self): + def descr_call(self, space, w_self, __args__): + return self.call(space, w_self, __args__) + + def get_func_to_call(self): func_to_call = self.func if self.offset: pto = as_pyobj(self.space, self.w_objclass) @@ -250,34 +248,51 @@ 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 + def check_args(self, __args__, arity): # XXX: check for keywords length = len(__args__.arguments_w) - if length != self.arity: + if length != 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__) + arity, length) - assert False, 'should not arrive here' + def descr_method_repr(self): + return self.space.newtext("<slot wrapper '%s' of '%s' objects>" % + (self.method_name, + self.w_objclass.name)) - def call_1(self, space, w_self, __args__): - func = self._get_func_to_call() + +class W_PyCWrapperObjectBinary(W_PyCWrapperObject): + + def __init__(self, space, pto, method_name, wrapper_func, doc, func, offset): + W_PyCWrapperObject.__init__(self, space, pto, method_name, doc, func, offset) + self.wrap_binaryfunc = wrapper_func + + def call(self, space, w_self, __args__): + self.check_args(__args__, 1) + func = self.get_func_to_call() w_o = __args__.arguments_w[0] - return self.wrapper_func(space, func, w_self, w_o) + return self.wrap_binaryfunc(space, func, w_self, w_o) - def call(self, space, w_self, w_args, w_kw): - func_to_call = self._get_func_to_call() + +class W_PyCWrapperObjectGeneric(W_PyCWrapperObject): + """ + slow generic implementation, it should die eventually + """ + + def __init__(self, space, pto, method_name, wrapper_func, + wrapper_func_kwds, doc, func, offset=None): + W_PyCWrapperObject.__init__(self, space, pto, method_name, doc, func, offset) + self.wrapper_func = wrapper_func + self.wrapper_func_kwds = wrapper_func_kwds + + def 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) + # + 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, @@ -288,10 +303,6 @@ self.method_name) return self.wrapper_func(space, w_self, w_args, func_to_call) - def descr_method_repr(self): - return self.space.newtext("<slot wrapper '%s' of '%s' objects>" % - (self.method_name, - self.w_objclass.name)) def cmethod_descr_get(space, w_function, w_obj, w_cls=None): 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 @@ -25,8 +25,9 @@ Py_TPPYPYFLAGS_FLOAT_SUBCLASS, ) from pypy.module.cpyext.methodobject import (W_PyCClassMethodObject, - W_PyCWrapperObject, PyCFunction_NewEx, PyCFunction, PyMethodDef, - W_PyCMethodObject, W_PyCFunctionObject) + PyCFunction_NewEx, PyCFunction, PyMethodDef, + W_PyCMethodObject, W_PyCFunctionObject, + W_PyCWrapperObjectGeneric, W_PyCWrapperObjectBinary) from pypy.module.cpyext.modsupport import convert_method_defs from pypy.module.cpyext.pyobject import ( PyObject, make_ref, from_ref, get_typedescr, make_typedescr, @@ -339,15 +340,16 @@ if wrapper_func is None and wrapper_func_kwds is None: continue - 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) + # specify specialization + w_obj = W_PyCWrapperObjectBinary(space, pto, method_name, wrap_binaryfunc, + doc, func_voidp, offset=offset) + else: + w_obj = W_PyCWrapperObjectGeneric(space, pto, method_name, wrapper_func, + wrapper_func_kwds, doc, + func_voidp, offset=offset) dict_w[method_name] = w_obj if pto.c_tp_doc: dict_w['__doc__'] = space.newtext( _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit