From 5264f2aa272f9722015be043fd17910703eee669 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Fri, 26 Dec 2008 10:24:12 +0100 Subject: [PATCH] special keyword checking code when we know the exact number of arguments --- Cython/Compiler/Nodes.py | 41 +++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index 88a77fad..9e215f05 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -2100,9 +2100,14 @@ class DefNode(FuncDefNode): kw_only_args, argtuple_error_label, code): all_args = tuple(positional_args) + tuple(kw_only_args) max_args = len(all_args) + all_required = self.num_required_args == len(self.args) \ + and not self.star_arg and not self.starstar_arg code.putln("PyObject* values[%d] = {%s};" % ( max_args, ('0,'*max_args)[:-1])) + if all_required: + code.putln('Py_ssize_t kw_count = PyDict_Size(%s);' % + Naming.kwds_cname) # parse the tuple and check that it's not too long code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname) @@ -2120,8 +2125,13 @@ class DefNode(FuncDefNode): # parse all keyword arguments, check for duplicates, etc. if not self.num_required_kw_args: - code.putln('if (PyDict_Size(%s) > 0) {' % Naming.kwds_cname) + if all_required: + code.putln('if (kw_count > 0) {') + else: + code.putln('if (PyDict_Size(%s) > 0) {' % Naming.kwds_cname) if self.star_arg: + if self.num_required_kw_args: + code.putln('{') code.putln("const Py_ssize_t used_pos_args = (PyTuple_GET_SIZE(%s) < %d) ? PyTuple_GET_SIZE(%s) : %d;" % ( Naming.args_cname, max_positional_args, Naming.args_cname, max_positional_args)) @@ -2137,19 +2147,30 @@ class DefNode(FuncDefNode): pos_arg_count, self.name.utf8encode())) code.putln(code.error_goto(self.pos)) - if not self.num_required_kw_args: + if self.star_arg or not self.num_required_kw_args: code.putln('}') # make sure we found all required args if self.num_required_args: - last_required_arg = -1 - for i, arg in enumerate(all_args): - if not arg.default: - last_required_arg = i - use_switch = max_positional_args > 2 # switch has an overhead, too + if all_required: + # common case: we know the exact number of arguments + required_args = all_args + if len(required_args) > 1: + code.putln('if (unlikely(PyTuple_GET_SIZE(%s) + kw_count != %d)) {' % ( + Naming.args_cname, max_args)) + else: + last_required_arg = -1 + for i, arg in enumerate(all_args): + if not arg.default: + last_required_arg = i + required_args = all_args[:last_required_arg+1] + # avoid switch for the simple cases - it has an overhead, too + use_switch = max_positional_args > 2 and len(required_args) > 2 \ + and not all_required # specialised above already if use_switch: - code.putln('switch (PyTuple_GET_SIZE(%s)) {' % Naming.args_cname) - for i, arg in enumerate(all_args[:last_required_arg+1]): + code.putln('switch (PyTuple_GET_SIZE(%s)) {' % + Naming.args_cname) + for i, arg in enumerate(required_args): if use_switch and i <= max_positional_args: if self.star_arg and i == max_positional_args: code.putln('default:') @@ -2170,6 +2191,8 @@ class DefNode(FuncDefNode): code.putln('}') if use_switch: code.putln('}') + if all_required and len(required_args) > 1: + code.putln('}') # convert arg values to their final type and assign them for i, arg in enumerate(all_args): -- 2.26.2