]> granicus.if.org Git - python/commitdiff
Argument Clinic: Use METH_FASTCALL for boring positionals
authorVictor Stinner <victor.stinner@gmail.com>
Tue, 17 Jan 2017 01:35:41 +0000 (02:35 +0100)
committerVictor Stinner <victor.stinner@gmail.com>
Tue, 17 Jan 2017 01:35:41 +0000 (02:35 +0100)
Issue #29286. Use METH_FASTCALL calling convention instead of METH_VARARGS to
parse "boring" position arguments. METH_FASTCALL is faster since it avoids the
creation of a temporary tuple to pass positional arguments.

Replace PyArg_UnpackTuple() with _PyArg_UnpackStack()+_PyArg_NoStackKeywords().

Tools/clinic/clinic.py

index 7c4b388efe5bcf6715b6e399d42d28c8e33ef244..894d1c5d994bbed16d25668757469b6d430fda54 100755 (executable)
@@ -825,16 +825,32 @@ class CLanguage(Language):
             # and nothing but normal objects:
             # PyArg_UnpackTuple!
 
-            flags = "METH_VARARGS"
-            parser_prototype = parser_prototype_varargs
+            if not new_or_init:
+                flags = "METH_FASTCALL"
+                parser_prototype = parser_prototype_fastcall
 
-            parser_definition = parser_body(parser_prototype, normalize_snippet("""
-                if (!PyArg_UnpackTuple(args, "{name}",
-                    {unpack_min}, {unpack_max},
-                    {parse_arguments})) {{
-                    goto exit;
-                }}
-                """, indent=4))
+                parser_definition = parser_body(parser_prototype, normalize_snippet("""
+                    if (!_PyArg_UnpackStack(args, nargs, "{name}",
+                        {unpack_min}, {unpack_max},
+                        {parse_arguments})) {{
+                        goto exit;
+                    }}
+
+                    if ({self_type_check}!_PyArg_NoStackKeywords("{name}", kwnames)) {{
+                        goto exit;
+                    }}
+                    """, indent=4))
+            else:
+                flags = "METH_VARARGS"
+                parser_prototype = parser_prototype_varargs
+
+                parser_definition = parser_body(parser_prototype, normalize_snippet("""
+                    if (!PyArg_UnpackTuple(args, "{name}",
+                        {unpack_min}, {unpack_max},
+                        {parse_arguments})) {{
+                        goto exit;
+                    }}
+                    """, indent=4))
 
         elif positional:
             if not new_or_init: