Closed
Description
The bytecode sequence for calls has gotten better in 3.12, but I think it can still be improved in a couple of ways:
- First, we can start either pushing
NULL
or a tuple ofkwnames
onto the stack immediately before calls, rather than sometimes stashingkwnames
away in a local eval loop variable via theKW_NAMES
opcode. This should free up a register around calls, and it's nice to do anyways since it makes the bytecode more regular (and the stack is really where this sort of stuff belongs). - Once that is done, we can use the low bit of the
CALL
oparg to indicate whether or not to expectkwnames
on the stack. This should get rid of lots of newPUSH_NULL
/CALL
pairs. - Separate from the above, but still sort of related: it's a bit awkward that our method call optimization either leaves
[callable, self, args...]
or[NULL, callable, args...]
on the stack, since it means thatCALL
(and most of its specializations) have to do an awkward swap in order to load the "correct" callable. This can be simplified by always entering calls with[callable, self_or_null, args...]
on the stack, so that the callable is always in the same position.
After this is all said and done, the CALL
stack effect will look something like:
inst(CALL, (counter/1, cache/2, callable, self_or_null, args[oparg >> 1], kwnames if (oparg & 1) -- res)) {
// ...
}
Activity