Skip to content

Commit

Permalink
Argument Clinic: Use METH_FASTCALL for positionals
Browse files Browse the repository at this point in the history
Issue python#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.
  • Loading branch information
vstinner committed Jan 17, 2017
1 parent 998c209 commit 0c8c389
Showing 1 changed file with 32 additions and 14 deletions.
46 changes: 32 additions & 14 deletions Tools/clinic/clinic.py
Original file line number Diff line number Diff line change
Expand Up @@ -705,14 +705,14 @@ def output_templates(self, f):
{c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs)
""")

parser_prototype_fastcall = normalize_snippet("""
parser_prototype_varargs = normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{c_basename}({self_type}{self_name}, PyObject *args)
""")

parser_prototype_varargs = normalize_snippet("""
parser_prototype_fastcall = normalize_snippet("""
static PyObject *
{c_basename}({self_type}{self_name}, PyObject *args)
{c_basename}({self_type}{self_name}, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
""")

# parser_body_fields remembers the fields passed in to the
Expand Down Expand Up @@ -837,18 +837,36 @@ def insert_keywords(s):
""", 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"
Expand Down

0 comments on commit 0c8c389

Please sign in to comment.