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

Reply via email to