Argument Clinic: Use METH_FASTCALL for positionals

Issue #29286. Use METH_FASTCALL calling convention instead of METH_VARARGS to
parse position arguments. METH_FASTCALL is faster since it avoids the creation
of a temporary tuple to pass positional arguments.
This commit is contained in:
Victor Stinner 2017-01-17 01:42:54 +01:00
parent 998c20962c
commit 0c8c3893ae
1 changed files with 33 additions and 15 deletions

View File

@ -705,16 +705,16 @@ class CLanguage(Language):
{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
""")
parser_prototype_fastcall = normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
""")
parser_prototype_varargs = normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *args)
""")
parser_prototype_fastcall = normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
""")
# parser_body_fields remembers the fields passed in to the
# previous call to parser_body. this is used for an awful hack.
parser_body_fields = ()
@ -837,18 +837,36 @@ class CLanguage(Language):
""", indent=4))
elif positional:
# positional-only, but no option groups
# we only need one call to PyArg_ParseTuple
if not new_or_init:
# positional-only, but no option groups
# we only need one call to _PyArg_ParseStack
flags = "METH_VARARGS"
parser_prototype = parser_prototype_varargs
flags = "METH_FASTCALL"
parser_prototype = parser_prototype_fastcall
parser_definition = parser_body(parser_prototype, normalize_snippet("""
if (!PyArg_ParseTuple(args, "{format_units}:{name}",
{parse_arguments})) {{
goto exit;
}}
""", indent=4))
parser_definition = parser_body(parser_prototype, normalize_snippet("""
if (!_PyArg_ParseStack(args, nargs, "{format_units}:{name}",
{parse_arguments})) {{
goto exit;
}}
if ({self_type_check}!_PyArg_NoStackKeywords("{name}", kwnames)) {{
goto exit;
}}
""", indent=4))
else:
# positional-only, but no option groups
# we only need one call to PyArg_ParseTuple
flags = "METH_VARARGS"
parser_prototype = parser_prototype_varargs
parser_definition = parser_body(parser_prototype, normalize_snippet("""
if (!PyArg_ParseTuple(args, "{format_units}:{name}",
{parse_arguments})) {{
goto exit;
}}
""", indent=4))
elif not new_or_init:
flags = "METH_FASTCALL"