summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c159
1 files changed, 37 insertions, 122 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 1104250..03d522b 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -2047,16 +2047,16 @@ static int
compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags,
PyObject *qualname)
{
+ Py_ssize_t i, free = PyCode_GetNumFree(co);
if (qualname == NULL)
qualname = co->co_name;
- if (co->co_nfreevars) {
- int i = co->co_nlocals + co->co_ncellvars;
- for (; i < co->co_nlocalsplus; ++i) {
+ if (free) {
+ for (i = 0; i < free; ++i) {
/* Bypass com_addop_varname because it will generate
LOAD_DEREF but LOAD_CLOSURE is needed.
*/
- PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
+ PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
/* Special case: If a class contains a method with a
free variable that has the same name as a method,
@@ -2076,10 +2076,6 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags,
arg = compiler_lookup_arg(c->u->u_freevars, name);
}
if (arg == -1) {
- PyObject *freevars = _PyCode_GetFreevars(co);
- if (freevars == NULL) {
- PyErr_Clear();
- }
PyErr_Format(PyExc_SystemError,
"compiler_lookup_arg(name=%R) with reftype=%d failed in %S; "
"freevars of code %S: %R",
@@ -2087,13 +2083,13 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags,
reftype,
c->u->u_name,
co->co_name,
- freevars);
+ co->co_freevars);
return 0;
}
ADDOP_I(c, LOAD_CLOSURE, arg);
}
flags |= 0x08;
- ADDOP_I(c, BUILD_TUPLE, co->co_nfreevars);
+ ADDOP_I(c, BUILD_TUPLE, free);
}
ADDOP_LOAD_CONST(c, (PyObject*)co);
ADDOP_LOAD_CONST(c, qualname);
@@ -7180,46 +7176,6 @@ merge_const_one(struct compiler *c, PyObject **obj)
return 1;
}
-// This is in codeobject.c.
-extern void _Py_set_localsplus_info(int, PyObject *, _PyLocalsPlusKind,
- PyObject *, _PyLocalsPlusKinds);
-
-static void
-compute_localsplus_info(struct compiler *c,
- PyObject *names, _PyLocalsPlusKinds kinds)
-{
- int nlocalsplus = (int)PyTuple_GET_SIZE(names);
-
- PyObject *k, *v;
- Py_ssize_t pos = 0;
- while (PyDict_Next(c->u->u_varnames, &pos, &k, &v)) {
- int offset = (int)PyLong_AS_LONG(v);
- assert(offset >= 0);
- assert(offset < nlocalsplus);
- // For now we do not distinguish arg kinds.
- _Py_set_localsplus_info(offset, k, CO_FAST_LOCAL, names, kinds);
- }
- int nlocals = (int)PyDict_GET_SIZE(c->u->u_varnames);
-
- pos = 0;
- while (PyDict_Next(c->u->u_cellvars, &pos, &k, &v)) {
- int offset = (int)PyLong_AS_LONG(v);
- assert(offset >= 0);
- offset += nlocals;
- assert(offset < nlocalsplus);
- _Py_set_localsplus_info(offset, k, CO_FAST_CELL, names, kinds);
- }
-
- pos = 0;
- while (PyDict_Next(c->u->u_freevars, &pos, &k, &v)) {
- int offset = (int)PyLong_AS_LONG(v);
- assert(offset >= 0);
- offset += nlocals;
- assert(offset < nlocalsplus);
- _Py_set_localsplus_info(offset, k, CO_FAST_FREE, names, kinds);
- }
-}
-
static PyCodeObject *
makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
int maxdepth)
@@ -7227,23 +7183,37 @@ makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
PyCodeObject *co = NULL;
PyObject *names = NULL;
PyObject *consts = NULL;
- PyObject *localsplusnames = NULL;
- _PyLocalsPlusKinds localspluskinds = NULL;
+ PyObject *varnames = NULL;
PyObject *name = NULL;
+ PyObject *freevars = NULL;
+ PyObject *cellvars = NULL;
+ int flags;
+ int posorkeywordargcount, posonlyargcount, kwonlyargcount;
names = dict_keys_inorder(c->u->u_names, 0);
- if (!names) {
+ varnames = dict_keys_inorder(c->u->u_varnames, 0);
+ if (!names || !varnames) {
goto error;
}
- if (!merge_const_one(c, &names)) {
+ cellvars = dict_keys_inorder(c->u->u_cellvars, 0);
+ if (!cellvars)
+ goto error;
+ freevars = dict_keys_inorder(c->u->u_freevars, PyTuple_GET_SIZE(cellvars));
+ if (!freevars)
goto error;
- }
- int flags = compute_code_flags(c);
- if (flags < 0) {
+ if (!merge_const_one(c, &names) ||
+ !merge_const_one(c, &varnames) ||
+ !merge_const_one(c, &cellvars) ||
+ !merge_const_one(c, &freevars))
+ {
goto error;
}
+ flags = compute_code_flags(c);
+ if (flags < 0)
+ goto error;
+
consts = PyList_AsTuple(constslist); /* PyCode_New requires a tuple */
if (consts == NULL) {
goto error;
@@ -7252,32 +7222,9 @@ makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
goto error;
}
- assert(c->u->u_posonlyargcount < INT_MAX);
- assert(c->u->u_argcount < INT_MAX);
- assert(c->u->u_kwonlyargcount < INT_MAX);
- int posonlyargcount = (int)c->u->u_posonlyargcount;
- int posorkwargcount = (int)c->u->u_argcount;
- assert(INT_MAX - posonlyargcount - posorkwargcount > 0);
- int kwonlyargcount = (int)c->u->u_kwonlyargcount;
-
- Py_ssize_t nlocals = PyDict_GET_SIZE(c->u->u_varnames);
- Py_ssize_t ncellvars = PyDict_GET_SIZE(c->u->u_cellvars);
- Py_ssize_t nfreevars = PyDict_GET_SIZE(c->u->u_freevars);
- assert(nlocals < INT_MAX);
- assert(ncellvars < INT_MAX);
- assert(nfreevars < INT_MAX);
- assert(INT_MAX - nlocals - ncellvars - nfreevars > 0);
- int nlocalsplus = (int)nlocals + (int)ncellvars + (int)nfreevars;
-
- localsplusnames = PyTuple_New(nlocalsplus);
- if (localsplusnames == NULL) {
- goto error;
- }
- if (_PyCode_InitLocalsPlusKinds(nlocalsplus, &localspluskinds) < 0) {
- goto error;
- }
- compute_localsplus_info(c, localsplusnames, localspluskinds);
-
+ posonlyargcount = Py_SAFE_DOWNCAST(c->u->u_posonlyargcount, Py_ssize_t, int);
+ posorkeywordargcount = Py_SAFE_DOWNCAST(c->u->u_argcount, Py_ssize_t, int);
+ kwonlyargcount = Py_SAFE_DOWNCAST(c->u->u_kwonlyargcount, Py_ssize_t, int);
struct _PyCodeConstructor con = {
.filename = c->c_filename,
.name = c->u->u_name,
@@ -7290,10 +7237,11 @@ makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
.consts = consts,
.names = names,
- .localsplusnames = localsplusnames,
- .localspluskinds = localspluskinds,
+ .varnames = varnames,
+ .cellvars = cellvars,
+ .freevars = freevars,
- .argcount = posonlyargcount + posorkwargcount,
+ .argcount = posonlyargcount + posorkeywordargcount,
.posonlyargcount = posonlyargcount,
.kwonlyargcount = kwonlyargcount,
@@ -7301,30 +7249,18 @@ makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
.exceptiontable = a->a_except_table,
};
-
if (_PyCode_Validate(&con) < 0) {
goto error;
}
-
- if (!merge_const_one(c, &localsplusnames)) {
- _PyCode_ClearLocalsPlusKinds(con.localspluskinds);
- goto error;
- }
- con.localsplusnames = localsplusnames;
-
co = _PyCode_New(&con);
- if (co == NULL) {
- goto error;
- }
-
- localspluskinds = NULL; // This keeps it from getting freed below.
error:
Py_XDECREF(names);
Py_XDECREF(consts);
- Py_XDECREF(localsplusnames);
- _PyCode_ClearLocalsPlusKinds(localspluskinds);
+ Py_XDECREF(varnames);
Py_XDECREF(name);
+ Py_XDECREF(freevars);
+ Py_XDECREF(cellvars);
return co;
}
@@ -7435,24 +7371,6 @@ guarantee_lineno_for_exits(struct assembler *a, int firstlineno) {
}
}
-static void
-offset_derefs(basicblock *entryblock, int nlocals)
-{
- for (basicblock *b = entryblock; b != NULL; b = b->b_next) {
- for (int i = 0; i < b->b_iused; i++) {
- struct instr *inst = &b->b_instr[i];
- switch(inst->i_opcode) {
- case LOAD_CLOSURE:
- case LOAD_DEREF:
- case STORE_DEREF:
- case DELETE_DEREF:
- case LOAD_CLASSDEREF:
- inst->i_oparg += nlocals;
- }
- }
- }
-}
-
static PyCodeObject *
assemble(struct compiler *c, int addNone)
{
@@ -7508,9 +7426,6 @@ assemble(struct compiler *c, int addNone)
a.a_entry = entryblock;
a.a_nblocks = nblocks;
- assert(PyDict_GET_SIZE(c->u->u_varnames) < INT_MAX);
- offset_derefs(entryblock, (int)PyDict_GET_SIZE(c->u->u_varnames));
-
consts = consts_dict_keys_inorder(c->u->u_consts);
if (consts == NULL) {
goto error;