Issue #27095: Simplified MAKE_FUNCTION and removed MAKE_CLOSURE opcodes.

Patch by Demur Rumed.
This commit is contained in:
Serhiy Storchaka 2016-06-12 17:36:24 +03:00
parent 5697c4b641
commit 64204de04c
13 changed files with 4100 additions and 4160 deletions

View file

@ -3325,116 +3325,36 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
DISPATCH();
}
TARGET(MAKE_CLOSURE)
TARGET(MAKE_FUNCTION) {
int posdefaults = oparg & 0xff;
int kwdefaults = (oparg>>8) & 0xff;
int num_annotations = (oparg >> 16) & 0x7fff;
PyObject *qualname = POP();
PyObject *codeobj = POP();
PyFunctionObject *func = (PyFunctionObject *)
PyFunction_NewWithQualName(codeobj, f->f_globals, qualname);
PyObject *qualname = POP(); /* qualname */
PyObject *code = POP(); /* code object */
PyObject *func = PyFunction_NewWithQualName(code, f->f_globals, qualname);
Py_DECREF(code);
Py_DECREF(codeobj);
Py_DECREF(qualname);
if (func == NULL)
if (func == NULL) {
goto error;
if (opcode == MAKE_CLOSURE) {
PyObject *closure = POP();
if (PyFunction_SetClosure(func, closure) != 0) {
/* Can't happen unless bytecode is corrupt. */
Py_DECREF(func);
Py_DECREF(closure);
goto error;
}
Py_DECREF(closure);
}
if (num_annotations > 0) {
Py_ssize_t name_ix;
PyObject *names = POP(); /* names of args with annotations */
PyObject *anns = PyDict_New();
if (anns == NULL) {
Py_DECREF(func);
Py_DECREF(names);
goto error;
}
name_ix = PyTuple_Size(names);
assert(num_annotations == name_ix+1);
while (name_ix > 0) {
PyObject *name, *value;
int err;
--name_ix;
name = PyTuple_GET_ITEM(names, name_ix);
value = POP();
err = PyDict_SetItem(anns, name, value);
Py_DECREF(value);
if (err != 0) {
Py_DECREF(anns);
Py_DECREF(func);
Py_DECREF(names);
goto error;
}
}
Py_DECREF(names);
if (PyFunction_SetAnnotations(func, anns) != 0) {
/* Can't happen unless
PyFunction_SetAnnotations changes. */
Py_DECREF(anns);
Py_DECREF(func);
goto error;
}
Py_DECREF(anns);
if (oparg & 0x08) {
assert(PyTuple_CheckExact(TOP()));
func ->func_closure = POP();
}
if (oparg & 0x04) {
assert(PyDict_CheckExact(TOP()));
func->func_annotations = POP();
}
if (oparg & 0x02) {
assert(PyDict_CheckExact(TOP()));
func->func_kwdefaults = POP();
}
if (oparg & 0x01) {
assert(PyTuple_CheckExact(TOP()));
func->func_defaults = POP();
}
/* XXX Maybe this should be a separate opcode? */
if (kwdefaults > 0) {
PyObject *defs = PyDict_New();
if (defs == NULL) {
Py_DECREF(func);
goto error;
}
while (--kwdefaults >= 0) {
PyObject *v = POP(); /* default value */
PyObject *key = POP(); /* kw only arg name */
int err = PyDict_SetItem(defs, key, v);
Py_DECREF(v);
Py_DECREF(key);
if (err != 0) {
Py_DECREF(defs);
Py_DECREF(func);
goto error;
}
}
if (PyFunction_SetKwDefaults(func, defs) != 0) {
/* Can't happen unless
PyFunction_SetKwDefaults changes. */
Py_DECREF(func);
Py_DECREF(defs);
goto error;
}
Py_DECREF(defs);
}
if (posdefaults > 0) {
PyObject *defs = PyTuple_New(posdefaults);
if (defs == NULL) {
Py_DECREF(func);
goto error;
}
while (--posdefaults >= 0)
PyTuple_SET_ITEM(defs, posdefaults, POP());
if (PyFunction_SetDefaults(func, defs) != 0) {
/* Can't happen unless
PyFunction_SetDefaults changes. */
Py_DECREF(defs);
Py_DECREF(func);
goto error;
}
Py_DECREF(defs);
}
PUSH(func);
PUSH((PyObject *)func);
DISPATCH();
}