Author: Antonio Cuni <[email protected]>
Branch: cpyext-jit
Changeset: r91913:25ba96ce5970
Date: 2017-07-16 15:20 +0100
http://bitbucket.org/pypy/pypy/changeset/25ba96ce5970/
Log: merge part of the cpyext-callopt branch, up to commit 9cbc8bd76297:
this should simplify and speedup the call of simple
functions/methods
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
@@ -43,8 +43,8 @@
from pypy.module.cpyext.object import _dealloc
_dealloc(space, py_obj)
-
class W_PyCFunctionObject(W_Root):
+ # TODO create a slightly different class depending on the c_ml_flags
def __init__(self, space, ml, w_self, w_module=None):
self.ml = ml
self.name = rffi.charp2str(rffi.cast(rffi.CCHARP,self.ml.c_ml_name))
@@ -57,7 +57,7 @@
w_self = self.w_self
flags = rffi.cast(lltype.Signed, self.ml.c_ml_flags)
flags &= ~(METH_CLASS | METH_STATIC | METH_COEXIST)
- if space.is_true(w_kw) and not flags & METH_KEYWORDS:
+ if not flags & METH_KEYWORDS and space.is_true(w_kw):
raise oefmt(space.w_TypeError,
"%s() takes no keyword arguments", self.name)
@@ -97,6 +97,20 @@
else:
return space.w_None
+class W_PyCFunctionObjectNoArgs(W_PyCFunctionObject):
+ def call(self, space, w_self, w_args, w_kw):
+ # Call the C function
+ if w_self is None:
+ w_self = self.w_self
+ func = self.ml.c_ml_meth
+ return generic_cpy_call(space, func, w_self, None)
+
+class W_PyCFunctionObjectSingleObject(W_PyCFunctionObject):
+ def call(self, space, w_self, w_o, w_kw):
+ if w_self is None:
+ w_self = self.w_self
+ func = self.ml.c_ml_meth
+ return generic_cpy_call(space, func, w_self, w_o)
class W_PyCMethodObject(W_PyCFunctionObject):
w_self = None
@@ -198,11 +212,22 @@
space.setitem(w_kw, space.newtext(key), w_obj)
return self.call(space, w_self, w_args, w_kw)
+def cfunction_descr_call_noargs(space, w_self):
+ # special case for calling with flags METH_NOARGS
+ self = space.interp_w(W_PyCFunctionObjectNoArgs, w_self)
+ return self.call(space, None, None, None)
+
+def cfunction_descr_call_single_object(space, w_self, w_o):
+ # special case for calling with flags METH_O
+ self = space.interp_w(W_PyCFunctionObjectSingleObject, w_self)
+ return self.call(space, None, w_o, None)
@jit.dont_look_inside
def cfunction_descr_call(space, w_self, __args__):
+ # specialize depending on the W_PyCFunctionObject
self = space.interp_w(W_PyCFunctionObject, w_self)
args_w, kw_w = __args__.unpack()
+ # XXX __args__.unpack is slow
w_args = space.newtuple(args_w)
w_kw = space.newdict()
for key, w_obj in kw_w.items():
@@ -247,6 +272,26 @@
)
W_PyCFunctionObject.typedef.acceptable_as_base_class = False
+W_PyCFunctionObjectNoArgs.typedef = TypeDef(
+ 'builtin_function_or_method', W_PyCFunctionObject.typedef,
+ __call__ = interp2app(cfunction_descr_call_noargs),
+ __doc__ = GetSetProperty(W_PyCFunctionObjectNoArgs.get_doc),
+ __module__ = interp_attrproperty_w('w_module',
cls=W_PyCFunctionObjectNoArgs),
+ __name__ = interp_attrproperty('name', cls=W_PyCFunctionObjectNoArgs,
+ wrapfn="newtext_or_none"),
+ )
+W_PyCFunctionObjectNoArgs.typedef.acceptable_as_base_class = False
+
+W_PyCFunctionObjectSingleObject.typedef = TypeDef(
+ 'builtin_function_or_method', W_PyCFunctionObject.typedef,
+ __call__ = interp2app(cfunction_descr_call_single_object),
+ __doc__ = GetSetProperty(W_PyCFunctionObjectSingleObject.get_doc),
+ __module__ = interp_attrproperty_w('w_module',
cls=W_PyCFunctionObjectSingleObject),
+ __name__ = interp_attrproperty('name', cls=W_PyCFunctionObjectSingleObject,
+ wrapfn="newtext_or_none"),
+ )
+W_PyCFunctionObjectSingleObject.typedef.acceptable_as_base_class = False
+
W_PyCMethodObject.typedef = TypeDef(
'method',
__get__ = interp2app(cmethod_descr_get),
diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py
--- a/pypy/module/cpyext/modsupport.py
+++ b/pypy/module/cpyext/modsupport.py
@@ -1,11 +1,13 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import cpython_api, cpython_struct, \
- METH_STATIC, METH_CLASS, METH_COEXIST, CANNOT_FAIL, CONST_STRING
+ METH_STATIC, METH_CLASS, METH_COEXIST, CANNOT_FAIL, CONST_STRING, \
+ METH_NOARGS, METH_O
from pypy.module.cpyext.pyobject import PyObject, as_pyobj
from pypy.interpreter.module import Module
from pypy.module.cpyext.methodobject import (
W_PyCFunctionObject, PyCFunction_NewEx, PyDescr_NewMethod,
- PyMethodDef, PyDescr_NewClassMethod, PyStaticMethod_New)
+ PyMethodDef, PyDescr_NewClassMethod, PyStaticMethod_New,
+ W_PyCFunctionObjectNoArgs, W_PyCFunctionObjectSingleObject)
from pypy.module.cpyext.pyerrors import PyErr_BadInternalCall
from pypy.module.cpyext.state import State
from pypy.interpreter.error import oefmt
@@ -79,6 +81,13 @@
space.newtext(rffi.charp2str(doc)))
return w_mod # borrowed result kept alive in PyImport_AddModule()
+def _create_pyc_function_object(space, method, w_self, w_name, flags):
+ flags &= ~(METH_CLASS | METH_STATIC | METH_COEXIST)
+ if flags == METH_NOARGS:
+ return W_PyCFunctionObjectNoArgs(space, method, w_self, w_name)
+ if flags == METH_O:
+ return W_PyCFunctionObjectSingleObject(space, method, w_self, w_name)
+ return W_PyCFunctionObject(space, method, w_self, w_name)
def convert_method_defs(space, dict_w, methods, w_type, w_self=None,
name=None):
w_name = space.newtext_or_none(name)
@@ -98,7 +107,8 @@
raise oefmt(space.w_ValueError,
"module functions cannot set METH_CLASS or "
"METH_STATIC")
- w_obj = W_PyCFunctionObject(space, method, w_self, w_name)
+ w_obj = _create_pyc_function_object(space, method, w_self,
+ w_name, flags)
else:
if methodname in dict_w and not (flags & METH_COEXIST):
continue
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit