aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects/codeobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/codeobject.c')
-rw-r--r--Objects/codeobject.c110
1 files changed, 36 insertions, 74 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index e054c43a1cf..11a83d4a512 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -162,43 +162,28 @@ _Py_set_localsplus_info(int offset, PyObject *name, _PyLocalsPlusKind kind,
Py_INCREF(name);
PyTuple_SET_ITEM(names, offset, name);
kinds[offset] = kind;
-
- if (kind == CO_FAST_CELL) {
- // Cells can overlap with args, so mark those cases.
- int nlocalsplus = (int)PyTuple_GET_SIZE(names);
- for (int i = 0; i < nlocalsplus; i++) {
- _PyLocalsPlusKind kind = kinds[i];
- if (kind && !(kind & CO_FAST_LOCAL)) {
- // We've moved past the locals.
- break;
- }
- PyObject *varname = PyTuple_GET_ITEM(names, i);
- int cmp = PyUnicode_Compare(name, varname);
- if (cmp == 0) {
- kinds[i] |= CO_FAST_CELL;
- break;
- }
- assert(cmp > 0 || !PyErr_Occurred());
- }
- }
}
static void
get_localsplus_counts(PyObject *names, _PyLocalsPlusKinds kinds,
- int *pnlocals, int *pncellvars,
+ int *pnlocals, int *pnplaincellvars, int *pncellvars,
int *pnfreevars)
{
int nlocals = 0;
+ int nplaincellvars = 0;
int ncellvars = 0;
int nfreevars = 0;
- int nlocalsplus = Py_SAFE_DOWNCAST(PyTuple_GET_SIZE(names),
- Py_ssize_t, int);
+ Py_ssize_t nlocalsplus = PyTuple_GET_SIZE(names);
for (int i = 0; i < nlocalsplus; i++) {
if (kinds[i] & CO_FAST_LOCAL) {
nlocals += 1;
+ if (kinds[i] & CO_FAST_CELL) {
+ ncellvars += 1;
+ }
}
else if (kinds[i] & CO_FAST_CELL) {
ncellvars += 1;
+ nplaincellvars += 1;
}
else if (kinds[i] & CO_FAST_FREE) {
nfreevars += 1;
@@ -207,6 +192,9 @@ get_localsplus_counts(PyObject *names, _PyLocalsPlusKinds kinds,
if (pnlocals != NULL) {
*pnlocals = nlocals;
}
+ if (pnplaincellvars != NULL) {
+ *pnplaincellvars = nplaincellvars;
+ }
if (pncellvars != NULL) {
*pncellvars = ncellvars;
}
@@ -227,10 +215,6 @@ get_localsplus_names(PyCodeObject *co, _PyLocalsPlusKind kind, int num)
if ((co->co_localspluskinds[offset] & kind) == 0) {
continue;
}
- // For now there may be duplicates, which we ignore.
- if (kind == CO_FAST_CELL && co->co_localspluskinds[offset] != kind) {
- continue;
- }
assert(index < num);
PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, offset);
Py_INCREF(name);
@@ -283,7 +267,7 @@ _PyCode_Validate(struct _PyCodeConstructor *con)
* here to avoid the possibility of overflow (however remote). */
int nlocals;
get_localsplus_counts(con->localsplusnames, con->localspluskinds,
- &nlocals, NULL, NULL);
+ &nlocals, NULL, NULL, NULL);
int nplainlocals = nlocals -
con->argcount -
con->kwonlyargcount -
@@ -301,9 +285,9 @@ static void
init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
{
int nlocalsplus = (int)PyTuple_GET_SIZE(con->localsplusnames);
- int nlocals, ncellvars, nfreevars;
+ int nlocals, nplaincellvars, ncellvars, nfreevars;
get_localsplus_counts(con->localsplusnames, con->localspluskinds,
- &nlocals, &ncellvars, &nfreevars);
+ &nlocals, &nplaincellvars, &ncellvars, &nfreevars);
Py_INCREF(con->filename);
co->co_filename = con->filename;
@@ -338,9 +322,9 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
co->co_exceptiontable = con->exceptiontable;
/* derived values */
- co->co_cell2arg = NULL; // This will be set soon.
co->co_nlocalsplus = nlocalsplus;
co->co_nlocals = nlocals;
+ co->co_nplaincellvars = nplaincellvars;
co->co_ncellvars = ncellvars;
co->co_nfreevars = nfreevars;
co->co_varnames = NULL;
@@ -392,44 +376,6 @@ _PyCode_New(struct _PyCodeConstructor *con)
co->co_flags &= ~CO_NOFREE;
}
- /* Create mapping between cells and arguments if needed. */
- if (co->co_ncellvars) {
- int totalargs = co->co_argcount +
- co->co_kwonlyargcount +
- ((co->co_flags & CO_VARARGS) != 0) +
- ((co->co_flags & CO_VARKEYWORDS) != 0);
- assert(totalargs <= co->co_nlocals);
- /* Find cells which are also arguments. */
- for (int i = 0; i < co->co_ncellvars; i++) {
- PyObject *cellname = PyTuple_GET_ITEM(co->co_localsplusnames,
- i + co->co_nlocals);
- for (int j = 0; j < totalargs; j++) {
- PyObject *argname = PyTuple_GET_ITEM(co->co_localsplusnames, j);
- int cmp = PyUnicode_Compare(cellname, argname);
- if (cmp == -1 && PyErr_Occurred()) {
- Py_DECREF(co);
- return NULL;
- }
- if (cmp == 0) {
- if (co->co_cell2arg == NULL) {
- co->co_cell2arg = PyMem_NEW(int, co->co_ncellvars);
- if (co->co_cell2arg == NULL) {
- Py_DECREF(co);
- PyErr_NoMemory();
- return NULL;
- }
- for (int k = 0; k < co->co_ncellvars; k++) {
- co->co_cell2arg[k] = CO_CELL_NOT_AN_ARG;
- }
- }
- co->co_cell2arg[i] = j;
- // Go to the next cell name.
- break;
- }
- }
- }
- }
-
return co;
}
@@ -478,6 +424,23 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
}
for (int i = 0; i < ncellvars; i++, offset++) {
PyObject *name = PyTuple_GET_ITEM(cellvars, i);
+ int argoffset = -1;
+ for (int j = 0; j < nvarnames; j++) {
+ int cmp = PyUnicode_Compare(PyTuple_GET_ITEM(varnames, j),
+ name);
+ assert(!PyErr_Occurred());
+ if (cmp == 0) {
+ argoffset = j;
+ break;
+ }
+ }
+ if (argoffset >= 0) {
+ // Merge the localsplus indices.
+ nlocalsplus -= 1;
+ offset -= 1;
+ localspluskinds[argoffset] |= CO_FAST_CELL;
+ continue;
+ }
_Py_set_localsplus_info(offset, name, CO_FAST_CELL,
localsplusnames, localspluskinds);
}
@@ -486,6 +449,11 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
_Py_set_localsplus_info(offset, name, CO_FAST_FREE,
localsplusnames, localspluskinds);
}
+ // If any cells were args then nlocalsplus will have shrunk.
+ // We don't bother resizing localspluskinds.
+ if (_PyTuple_Resize(&localsplusnames, nlocalsplus) < 0) {
+ goto error;
+ }
struct _PyCodeConstructor con = {
.filename = filename,
@@ -1182,8 +1150,6 @@ code_dealloc(PyCodeObject *co)
Py_XDECREF(co->co_name);
Py_XDECREF(co->co_linetable);
Py_XDECREF(co->co_exceptiontable);
- if (co->co_cell2arg != NULL)
- PyMem_Free(co->co_cell2arg);
if (co->co_weakreflist != NULL)
PyObject_ClearWeakRefs((PyObject*)co);
if (co->co_quickened) {
@@ -1377,10 +1343,6 @@ code_sizeof(PyCodeObject *co, PyObject *Py_UNUSED(args))
(co_extra->ce_size-1) * sizeof(co_extra->ce_extras[0]);
}
- if (co->co_cell2arg != NULL && co->co_cellvars != NULL) {
- res += co->co_ncellvars * sizeof(Py_ssize_t);
- }
-
if (co->co_quickened != NULL) {
Py_ssize_t count = co->co_quickened[0].entry.zero.cache_count;
count += (PyBytes_GET_SIZE(co->co_code)+sizeof(SpecializedCacheEntry)-1)/