Bytecode for calling function with keyword arguments

Currently the call of function with keyword arguments (say `f(a, b, x=c, y=d)`) is compiled to following bytecode: 0 LOAD_NAME 0 (f) 3 LOAD_NAME 1 (a) 6 LOAD_NAME 2 (b) 9 LOAD_CONST 0 ('x') 12 LOAD_NAME 3 (c) 15 LOAD_CONST 1 ('y') 18 LOAD_NAME 4 (d) 21 CALL_FUNCTION 514 (2 positional, 2 keyword pair) For every positional argument its value is pushed on the stack, and for every keyword argument its name and its value are pushed on the stack. But keyword arguments are always constant strings! We can reorder the stack, and push keyword argument values and names separately. And we can save all keyword argument names for this call in a constant tuple and load it by one bytecode command. 0 LOAD_NAME 0 (f) 3 LOAD_NAME 1 (a) 6 LOAD_NAME 2 (b) 9 LOAD_NAME 3 (c) 12 LOAD_NAME 4 (d) 15 LOAD_CONST 0 (('x', 'y')) 18 CALL_FUNCTION2 2 Benefits: 1. We save one command for every keyword parameter after the first. This saves bytecode size and execution time. 2. Since the number of keyword arguments is obtained from tuple's size, new CALL_FUNCTION opcode needs only the number of positional arguments. It's argument is simpler and needs less bits (important for wordcode). Disadvantages: 1. Increases the number of constants.

On Fri, Apr 22, 2016 at 1:52 AM, Serhiy Storchaka <storchaka@gmail.com> wrote:
What about calls that don't include any keyword arguments? Currently, no pushing is done. Will you have two opcodes, one if there are kwargs and one if there are not? Also: How does this interact with **dict calls? ChrisA

On 21.04.16 19:00, Chris Angelico wrote:
Yes, we need either two opcodes, or a falg in the argument. I prefer the first approach to keep the argument short and simple.
Also: How does this interact with **dict calls?
For now we have separate opcode for calls with **kwargs. We will have corresponding opcode with new way to provide keyword arguments. Instead of 4 current opcodes we will need at most 8 new opcodes. May be less, because calls with *args or **kwargs is less performance critical, we can pack arguments in a tuple and a dict by separate opcodes and call a function just with a tuple and a dict.

On 21.04.16 20:28, Serhiy Storchaka wrote:
Actually I think we need only 3 opcodes: one general and two specialized for common cases. 1. Call with fixed number of positional arguments. This covers about 90% of calls. 2. Call with fixed number of positional and keyword arguments. This covers about 10% of calls. 3. Call with variable number of positional and/or keyword arguments packed in a tuple and a dict. Only 0.5% of calls need this. Since *args and **kwargs can be now used multiple times in the call, there are opcodes for packing arguments: BUILD_LIST_UNPACK and BUILD_MAP_UNPACK_WITH_CALL.

With WPython I've solved this scenario with only a new opcode, LOAD_CONSTS, which basically unpacks the (constant) tuple into the stack. So, you don't need new opcodes for new function calls, and LOAD_CONSTS is only used when needed. Regards, Cesare 2016-04-21 17:52 GMT+02:00 Serhiy Storchaka <storchaka@gmail.com>:
participants (4)
-
Cesare Di Mauro
-
Chris Angelico
-
Niki Spahiev
-
Serhiy Storchaka