[Python-Dev] MAKE_FUNCTION simplification
Nikita Nemkin
nikita at nemkin.ru
Thu Apr 14 05:04:34 EDT 2016
MAKE_FUNCTION opcode is complex due to the way it receives
input arguments:
1) default args, individually;
2) default kwonly args, individual name-value pairs;
3) a tuple of parameter names (single constant);
4) annotation values, individually;
5) code object;
6) qualname.
The counts for 1,2,4 are packed into oparg bitfields, making oparg large.
My suggestion is to pre-package 1-4 before calling MAKE_FUNCTION,
i.e. explicitly emit BUILD_TUPLE for defaults args and BUILD_MAPs
for keyword defaults and annotations.
Then, MAKE_FUNCTION will become a dramatically simpler
5 argument opcode, taking
1) default args tuple (optional);
2) default keyword only args dict (optional);
3) annotations dict (optional);
4) code object;
5) qualname.
These arguments correspond exactly to __annotations__, __kwdefaults__,
__defaults__, __code__ and __qualname__ attributes.
For optional args, oparg bits should indicate individual arg presence.
(This also saves None checks in opcode implementation.)
If we add another optional argument (and oparg bit) for __closure__
attribute, then separate MAKE_CLOSURE opcode becomes unnecessary.
Default args tuple is likely to be a constant and can be packaged whole,
compensating for the extra size of explicit BUILD_* instructions.
Compare the current implementation:
https://github.com/python/cpython/blob/master/Python/ceval.c#L3262
with this provisional implementation (untested):
TARGET(MAKE_FUNCTION) {
PyObject *qualname = POP();
PyObject *codeobj = POP();
PyFunctionObject *func;
func = (PyFunctionObject *)PyFunction_NewWithQualName(
codeobj, f->f_globals, qualname);
Py_DECREF(codeobj);
Py_DECREF(qualname);
if (func == NULL)
goto error;
/* NB: Py_None is not an acceptable value for these. */
if (oparg & 0x08)
func->func_closure = POP();
if (oparg & 0x04)
func->func_annotations = POP();
if (oparg & 0x02)
func->func_kwdefaults = POP();
if (oparg & 0x01)
func->func_defaults = POP();
PUSH((PyObject *)func);
DISPATCH();
}
compile.c also gets a bit simpler, but not much.
What do you think?
More information about the Python-Dev
mailing list