summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2021-05-26 19:15:40 (GMT)
committerGitHub <noreply@github.com>2021-05-26 19:15:40 (GMT)
commit6cc800d3634fdd002b986c3ffe6a3d5540f311a0 (patch)
treec6e67a6f76549102011931f2ee929b455ab40918 /Objects
parente6c815d2e34be5fdf6dbe773f0781691746d2289 (diff)
downloadcpython-6cc800d3634fdd002b986c3ffe6a3d5540f311a0.zip
cpython-6cc800d3634fdd002b986c3ffe6a3d5540f311a0.tar.gz
cpython-6cc800d3634fdd002b986c3ffe6a3d5540f311a0.tar.bz2
bpo-43693: Clean up the PyCodeObject fields. (GH-26364)
* Move up the comment about fields using in hashing/comparision. * Group the fields more clearly. * Add co_ncellvars and co_nfreevars. * Raise ValueError if nlocals != len(varnames), rather than aborting.
Diffstat (limited to 'Objects')
-rw-r--r--Objects/codeobject.c51
-rw-r--r--Objects/frameobject.c24
-rw-r--r--Objects/funcobject.c14
-rw-r--r--Objects/typeobject.c18
4 files changed, 50 insertions, 57 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 8b2cee2..65df3e3 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -164,7 +164,8 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
{
PyCodeObject *co;
Py_ssize_t *cell2arg = NULL;
- Py_ssize_t i, n_cellvars, n_varnames, total_args;
+ Py_ssize_t i, total_args;
+ int ncellvars, nfreevars;
/* Check argument types */
if (argcount < posonlyargcount || posonlyargcount < 0 ||
@@ -184,6 +185,19 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
return NULL;
}
+ /* Make sure that code is indexable with an int, this is
+ a long running assumption in ceval.c and many parts of
+ the interpreter. */
+ if (PyBytes_GET_SIZE(code) > INT_MAX) {
+ PyErr_SetString(PyExc_OverflowError, "co_code larger than INT_MAX");
+ return NULL;
+ }
+
+ if (nlocals != PyTuple_GET_SIZE(varnames)) {
+ PyErr_SetString(PyExc_ValueError, "co_nlocals != len(co_varnames)");
+ return NULL;
+ }
+
/* Ensure that strings are ready Unicode string */
if (PyUnicode_READY(name) < 0) {
return NULL;
@@ -208,46 +222,40 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
return NULL;
}
- /* Make sure that code is indexable with an int, this is
- a long running assumption in ceval.c and many parts of
- the interpreter. */
- if (PyBytes_GET_SIZE(code) > INT_MAX) {
- PyErr_SetString(PyExc_OverflowError, "co_code larger than INT_MAX");
- return NULL;
- }
-
/* Check for any inner or outer closure references */
- n_cellvars = PyTuple_GET_SIZE(cellvars);
- if (!n_cellvars && !PyTuple_GET_SIZE(freevars)) {
+ assert(PyTuple_GET_SIZE(cellvars) < INT_MAX);
+ ncellvars = (int)PyTuple_GET_SIZE(cellvars);
+ assert(PyTuple_GET_SIZE(freevars) < INT_MAX);
+ nfreevars = (int)PyTuple_GET_SIZE(freevars);
+ if (!ncellvars && !nfreevars) {
flags |= CO_NOFREE;
} else {
flags &= ~CO_NOFREE;
}
- n_varnames = PyTuple_GET_SIZE(varnames);
- if (argcount <= n_varnames && kwonlyargcount <= n_varnames) {
+ if (argcount <= nlocals && kwonlyargcount <= nlocals) {
/* Never overflows. */
total_args = (Py_ssize_t)argcount + (Py_ssize_t)kwonlyargcount +
((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
}
else {
- total_args = n_varnames + 1;
+ total_args = nlocals + 1;
}
- if (total_args > n_varnames) {
+ if (total_args > nlocals) {
PyErr_SetString(PyExc_ValueError, "code: varnames is too small");
return NULL;
}
/* Create mapping between cells and arguments if needed. */
- if (n_cellvars) {
+ if (ncellvars) {
bool used_cell2arg = false;
- cell2arg = PyMem_NEW(Py_ssize_t, n_cellvars);
+ cell2arg = PyMem_NEW(Py_ssize_t, ncellvars);
if (cell2arg == NULL) {
PyErr_NoMemory();
return NULL;
}
/* Find cells which are also arguments. */
- for (i = 0; i < n_cellvars; i++) {
+ for (i = 0; i < ncellvars; i++) {
Py_ssize_t j;
PyObject *cell = PyTuple_GET_ITEM(cellvars, i);
cell2arg[i] = CO_CELL_NOT_AN_ARG;
@@ -279,9 +287,10 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
co->co_argcount = argcount;
co->co_posonlyargcount = posonlyargcount;
co->co_kwonlyargcount = kwonlyargcount;
+ co->co_nlocalsplus = nlocals + ncellvars + nfreevars;
co->co_nlocals = nlocals;
- co->co_nlocalsplus = nlocals +
- (int)PyTuple_GET_SIZE(freevars) + (int)PyTuple_GET_SIZE(cellvars);
+ co->co_ncellvars = ncellvars;
+ co->co_nfreevars = nfreevars;
co->co_stacksize = stacksize;
co->co_flags = flags;
Py_INCREF(code);
@@ -1139,7 +1148,7 @@ code_sizeof(PyCodeObject *co, PyObject *Py_UNUSED(args))
_PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) co->co_extra;
if (co->co_cell2arg != NULL && co->co_cellvars != NULL) {
- res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(Py_ssize_t);
+ res += co->co_ncellvars * sizeof(Py_ssize_t);
}
if (co_extra != NULL) {
res += sizeof(_PyCodeObjectExtra) +
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 87c4852..1bfae90 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1023,7 +1023,6 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f)
PyObject **fast;
PyCodeObject *co;
Py_ssize_t j;
- Py_ssize_t ncells, nfreevars;
if (f == NULL) {
PyErr_BadInternalCall();
@@ -1051,10 +1050,8 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f)
if (map_to_dict(map, j, locals, fast, 0) < 0)
return -1;
}
- ncells = PyTuple_GET_SIZE(co->co_cellvars);
- nfreevars = PyTuple_GET_SIZE(co->co_freevars);
- if (ncells || nfreevars) {
- if (map_to_dict(co->co_cellvars, ncells,
+ if (co->co_ncellvars || co->co_nfreevars) {
+ if (map_to_dict(co->co_cellvars, co->co_ncellvars,
locals, fast + co->co_nlocals, 1))
return -1;
@@ -1067,8 +1064,8 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f)
into the locals dict used by the class.
*/
if (co->co_flags & CO_OPTIMIZED) {
- if (map_to_dict(co->co_freevars, nfreevars,
- locals, fast + co->co_nlocals + ncells, 1) < 0)
+ if (map_to_dict(co->co_freevars, co->co_nfreevars, locals,
+ fast + co->co_nlocals + co->co_ncellvars, 1) < 0)
return -1;
}
}
@@ -1096,7 +1093,6 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
PyObject *error_type, *error_value, *error_traceback;
PyCodeObject *co;
Py_ssize_t j;
- Py_ssize_t ncells, nfreevars;
if (f == NULL)
return;
locals = _PyFrame_Specials(f)[FRAME_SPECIALS_LOCALS_OFFSET];
@@ -1113,16 +1109,14 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
j = co->co_nlocals;
if (co->co_nlocals)
dict_to_map(co->co_varnames, j, locals, fast, 0, clear);
- ncells = PyTuple_GET_SIZE(co->co_cellvars);
- nfreevars = PyTuple_GET_SIZE(co->co_freevars);
- if (ncells || nfreevars) {
- dict_to_map(co->co_cellvars, ncells,
+ if (co->co_ncellvars || co->co_nfreevars) {
+ dict_to_map(co->co_cellvars, co->co_ncellvars,
locals, fast + co->co_nlocals, 1, clear);
/* Same test as in PyFrame_FastToLocals() above. */
if (co->co_flags & CO_OPTIMIZED) {
- dict_to_map(co->co_freevars, nfreevars,
- locals, fast + co->co_nlocals + ncells, 1,
- clear);
+ dict_to_map(co->co_freevars, co->co_nfreevars, locals,
+ fast + co->co_nlocals + co->co_ncellvars, 1,
+ clear);
}
}
PyErr_Restore(error_type, error_value, error_traceback);
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index f0b0b67..dc27215 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -279,7 +279,8 @@ func_get_code(PyFunctionObject *op, void *Py_UNUSED(ignored))
static int
func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored))
{
- Py_ssize_t nfree, nclosure;
+ Py_ssize_t nclosure;
+ int nfree;
/* Not legal to del f.func_code or to set it to anything
* other than a code object. */
@@ -294,7 +295,7 @@ func_set_code(PyFunctionObject *op, PyObject *value, void *Py_UNUSED(ignored))
return -1;
}
- nfree = PyCode_GetNumFree((PyCodeObject *)value);
+ nfree = ((PyCodeObject *)value)->co_nfreevars;
nclosure = (op->func_closure == NULL ? 0 :
PyTuple_GET_SIZE(op->func_closure));
if (nclosure != nfree) {
@@ -538,7 +539,7 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals,
/*[clinic end generated code: output=99c6d9da3a24e3be input=93611752fc2daf11]*/
{
PyFunctionObject *newfunc;
- Py_ssize_t nfree, nclosure;
+ Py_ssize_t nclosure;
if (name != Py_None && !PyUnicode_Check(name)) {
PyErr_SetString(PyExc_TypeError,
@@ -550,9 +551,8 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals,
"arg 4 (defaults) must be None or tuple");
return NULL;
}
- nfree = PyTuple_GET_SIZE(code->co_freevars);
if (!PyTuple_Check(closure)) {
- if (nfree && closure == Py_None) {
+ if (code->co_nfreevars && closure == Py_None) {
PyErr_SetString(PyExc_TypeError,
"arg 5 (closure) must be tuple");
return NULL;
@@ -566,10 +566,10 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals,
/* check that the closure is well-formed */
nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure);
- if (nfree != nclosure)
+ if (code->co_nfreevars != nclosure)
return PyErr_Format(PyExc_ValueError,
"%U requires closure of length %zd, not %zd",
- code->co_name, nfree, nclosure);
+ code->co_name, code->co_nfreevars, nclosure);
if (nclosure) {
Py_ssize_t i;
for (i = 0; i < nclosure; i++) {
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 1460085..feb25aa 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -8848,11 +8848,10 @@ super_init_without_args(PyFrameObject *f, PyCodeObject *co,
}
PyObject *obj = f->f_localsptr[0];
- Py_ssize_t i, n;
+ Py_ssize_t i;
if (obj == NULL && co->co_cell2arg) {
/* The first argument might be a cell. */
- n = PyTuple_GET_SIZE(co->co_cellvars);
- for (i = 0; i < n; i++) {
+ for (i = 0; i < co->co_ncellvars; i++) {
if (co->co_cell2arg[i] == 0) {
PyObject *cell = f->f_localsptr[co->co_nlocals + i];
assert(PyCell_Check(cell));
@@ -8867,21 +8866,12 @@ super_init_without_args(PyFrameObject *f, PyCodeObject *co,
return -1;
}
- if (co->co_freevars == NULL) {
- n = 0;
- }
- else {
- assert(PyTuple_Check(co->co_freevars));
- n = PyTuple_GET_SIZE(co->co_freevars);
- }
-
PyTypeObject *type = NULL;
- for (i = 0; i < n; i++) {
+ for (i = 0; i < co->co_nfreevars; i++) {
PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
assert(PyUnicode_Check(name));
if (_PyUnicode_EqualToASCIIId(name, &PyId___class__)) {
- Py_ssize_t index = co->co_nlocals +
- PyTuple_GET_SIZE(co->co_cellvars) + i;
+ Py_ssize_t index = co->co_nlocals + co->co_ncellvars + i;
PyObject *cell = f->f_localsptr[index];
if (cell == NULL || !PyCell_Check(cell)) {
PyErr_SetString(PyExc_RuntimeError,