(original) (raw)
changeset: 106178:de90f3d06bc9 user: Victor Stinner victor.stinner@gmail.com date: Tue Jan 17 01:42:54 2017 +0100 files: Tools/clinic/clinic.py description: 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. diff -r 38ab8572fde2 -r de90f3d06bc9 Tools/clinic/clinic.py --- a/Tools/clinic/clinic.py Tue Jan 17 01:57:29 2017 +0100 +++ b/Tools/clinic/clinic.py Tue Jan 17 01:42:54 2017 +0100 @@ -705,16 +705,16 @@ {c_basename}({self_type}{self_name}, PyObject *args, PyObject *kwargs) """) + 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_prototype_varargs = normalize_snippet(""" - static PyObject * - {c_basename}({self_type}{self_name}, PyObject *args) - """) - # 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 @@ """, indent=4)) elif positional: - # 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)) + if not new_or_init: + # positional-only, but no option groups + # we only need one call to _PyArg_ParseStack + + flags = "METH_FASTCALL" + parser_prototype = parser_prototype_fastcall + + 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" /victor.stinner@gmail.com