Commit 5264f2aa authored by Stefan Behnel's avatar Stefan Behnel

special keyword checking code when we know the exact number of arguments

parent 9256e626
......@@ -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):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment