aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2021-06-07 12:22:26 -0600
committerGitHub <noreply@github.com>2021-06-07 12:22:26 -0600
commit2ab27c4af4ddf7528e1375e77c787c7fbb09b5e6 (patch)
treed3983e5282f575560cb7449fae4785447fdfff14 /Python/ceval.c
parent001eb520b5757294dc455c900d94b7b153de6cdd (diff)
downloadcpython-2ab27c4af4ddf7528e1375e77c787c7fbb09b5e6.tar.gz
cpython-2ab27c4af4ddf7528e1375e77c787c7fbb09b5e6.zip
bpo-43693: Un-revert commits 2c1e258 and b2bf2bc. (gh-26577)
These were reverted in gh-26530 (commit 17c4edc) due to refleaks. * 2c1e258 - Compute deref offsets in compiler (gh-25152) * b2bf2bc - Add new internal code objects fields: co_fastlocalnames and co_fastlocalkinds. (gh-26388) This change fixes the refleaks. https://bugs.python.org/issue43693
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c78
1 files changed, 32 insertions, 46 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 619eff29e18..032bc0cd871 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1446,7 +1446,7 @@ eval_frame_handle_pending(PyThreadState *tstate)
/* Local variable macros */
-#define GETLOCAL(i) (fastlocals[i])
+#define GETLOCAL(i) (localsplus[i])
/* The SETLOCAL() macro must not DECREF the local variable in-place and
then store the new value; it must copy the old value to a temporary
@@ -1577,7 +1577,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
const _Py_CODEUNIT *next_instr;
int opcode; /* Current opcode */
int oparg; /* Current opcode argument, if any */
- PyObject **fastlocals, **freevars, **specials;
+ PyObject **localsplus, **specials;
PyObject *retval = NULL; /* Return value */
_Py_atomic_int * const eval_breaker = &tstate->interp->ceval.eval_breaker;
PyCodeObject *co;
@@ -1666,9 +1666,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
names = co->co_names;
consts = co->co_consts;
- fastlocals = f->f_localsptr;
+ localsplus = f->f_localsptr;
first_instr = co->co_firstinstr;
- freevars = f->f_localsptr + co->co_nlocals;
/*
f->f_lasti refers to the index of the last instruction,
unless it's -1 in which case next_instr should be first_instr.
@@ -1836,12 +1835,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
DISPATCH();
}
+ /* We keep LOAD_CLOSURE so that the bytecode stays more readable. */
+ case TARGET(LOAD_CLOSURE):
case TARGET(LOAD_FAST): {
PyObject *value = GETLOCAL(oparg);
if (value == NULL) {
format_exc_check_arg(tstate, PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
- PyTuple_GetItem(co->co_varnames, oparg));
+ PyTuple_GetItem(co->co_localsplusnames,
+ oparg));
goto error;
}
Py_INCREF(value);
@@ -3069,13 +3071,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
format_exc_check_arg(
tstate, PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
- PyTuple_GetItem(co->co_varnames, oparg)
+ PyTuple_GetItem(co->co_localsplusnames, oparg)
);
goto error;
}
case TARGET(DELETE_DEREF): {
- PyObject *cell = freevars[oparg];
+ PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
if (oldobj != NULL) {
PyCell_SET(cell, NULL);
@@ -3086,21 +3088,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
goto error;
}
- case TARGET(LOAD_CLOSURE): {
- PyObject *cell = freevars[oparg];
- Py_INCREF(cell);
- PUSH(cell);
- DISPATCH();
- }
-
case TARGET(LOAD_CLASSDEREF): {
PyObject *name, *value, *locals = LOCALS();
- Py_ssize_t idx;
assert(locals);
- assert(oparg >= co->co_ncellvars);
- idx = oparg - co->co_ncellvars;
- assert(idx >= 0 && idx < co->co_nfreevars);
- name = PyTuple_GET_ITEM(co->co_freevars, idx);
+ assert(oparg >= 0 && oparg < co->co_nlocalsplus);
+ name = PyTuple_GET_ITEM(co->co_localsplusnames, oparg);
if (PyDict_CheckExact(locals)) {
value = PyDict_GetItemWithError(locals, name);
if (value != NULL) {
@@ -3120,7 +3112,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
}
}
if (!value) {
- PyObject *cell = freevars[oparg];
+ PyObject *cell = GETLOCAL(oparg);
value = PyCell_GET(cell);
if (value == NULL) {
format_exc_unbound(tstate, co, oparg);
@@ -3133,7 +3125,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
}
case TARGET(LOAD_DEREF): {
- PyObject *cell = freevars[oparg];
+ PyObject *cell = GETLOCAL(oparg);
PyObject *value = PyCell_GET(cell);
if (value == NULL) {
format_exc_unbound(tstate, co, oparg);
@@ -3146,7 +3138,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
case TARGET(STORE_DEREF): {
PyObject *v = POP();
- PyObject *cell = freevars[oparg];
+ PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
PyCell_SET(cell, v);
Py_XDECREF(oldobj);
@@ -4652,7 +4644,7 @@ format_missing(PyThreadState *tstate, const char *kind,
static void
missing_arguments(PyThreadState *tstate, PyCodeObject *co,
Py_ssize_t missing, Py_ssize_t defcount,
- PyObject **fastlocals, PyObject *qualname)
+ PyObject **localsplus, PyObject *qualname)
{
Py_ssize_t i, j = 0;
Py_ssize_t start, end;
@@ -4674,7 +4666,7 @@ missing_arguments(PyThreadState *tstate, PyCodeObject *co,
}
for (i = start; i < end; i++) {
if (GETLOCAL(i) == NULL) {
- PyObject *raw = PyTuple_GET_ITEM(co->co_varnames, i);
+ PyObject *raw = PyTuple_GET_ITEM(co->co_localsplusnames, i);
PyObject *name = PyObject_Repr(raw);
if (name == NULL) {
Py_DECREF(missing_names);
@@ -4691,7 +4683,7 @@ missing_arguments(PyThreadState *tstate, PyCodeObject *co,
static void
too_many_positional(PyThreadState *tstate, PyCodeObject *co,
Py_ssize_t given, PyObject *defaults,
- PyObject **fastlocals, PyObject *qualname)
+ PyObject **localsplus, PyObject *qualname)
{
int plural;
Py_ssize_t kwonly_given = 0;
@@ -4755,7 +4747,7 @@ positional_only_passed_as_keyword(PyThreadState *tstate, PyCodeObject *co,
PyObject* posonly_names = PyList_New(0);
for(int k=0; k < co->co_posonlyargcount; k++){
- PyObject* posonly_name = PyTuple_GET_ITEM(co->co_varnames, k);
+ PyObject* posonly_name = PyTuple_GET_ITEM(co->co_localsplusnames, k);
for (int k2=0; k2<kwcount; k2++){
/* Compare the pointers first and fallback to PyObject_RichCompareBool*/
@@ -4892,12 +4884,11 @@ get_exception_handler(PyCodeObject *code, int index, int *level, int *handler, i
static int
initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
- PyObject **fastlocals, PyObject *const *args,
+ PyObject **localsplus, PyObject *const *args,
Py_ssize_t argcount, PyObject *kwnames)
{
PyCodeObject *co = (PyCodeObject*)con->fc_code;
const Py_ssize_t total_args = co->co_argcount + co->co_kwonlyargcount;
- PyObject **freevars = fastlocals + co->co_nlocals;
/* Create a dictionary for keyword parameters (**kwags) */
PyObject *kwdict;
@@ -4957,7 +4948,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
/* Speed hack: do raw pointer compares. As names are
normally interned this should almost always hit. */
- co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
+ co_varnames = ((PyTupleObject *)(co->co_localsplusnames))->ob_item;
for (j = co->co_posonlyargcount; j < total_args; j++) {
PyObject *varname = co_varnames[j];
if (varname == keyword) {
@@ -5013,7 +5004,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
/* Check the number of positional arguments */
if ((argcount > co->co_argcount) && !(co->co_flags & CO_VARARGS)) {
- too_many_positional(tstate, co, argcount, con->fc_defaults, fastlocals,
+ too_many_positional(tstate, co, argcount, con->fc_defaults, localsplus,
con->fc_qualname);
goto fail;
}
@@ -5029,7 +5020,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
}
}
if (missing) {
- missing_arguments(tstate, co, missing, defcount, fastlocals,
+ missing_arguments(tstate, co, missing, defcount, localsplus,
con->fc_qualname);
goto fail;
}
@@ -5055,7 +5046,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
for (i = co->co_argcount; i < total_args; i++) {
if (GETLOCAL(i) != NULL)
continue;
- PyObject *varname = PyTuple_GET_ITEM(co->co_varnames, i);
+ PyObject *varname = PyTuple_GET_ITEM(co->co_localsplusnames, i);
if (con->fc_kwdefaults != NULL) {
PyObject *def = PyDict_GetItemWithError(con->fc_kwdefaults, varname);
if (def) {
@@ -5070,12 +5061,13 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
missing++;
}
if (missing) {
- missing_arguments(tstate, co, missing, -1, fastlocals,
+ missing_arguments(tstate, co, missing, -1, localsplus,
con->fc_qualname);
goto fail;
}
}
+
/* Allocate and initialize storage for cell vars, and copy free
vars into frame. */
for (i = 0; i < co->co_ncellvars; ++i) {
@@ -5100,7 +5092,7 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
for (i = 0; i < co->co_nfreevars; ++i) {
PyObject *o = PyTuple_GET_ITEM(con->fc_closure, i);
Py_INCREF(o);
- freevars[co->co_ncellvars + i] = o;
+ localsplus[co->co_nlocals + co->co_ncellvars + i] = o;
}
return 0;
@@ -6433,15 +6425,11 @@ format_exc_unbound(PyThreadState *tstate, PyCodeObject *co, int oparg)
/* Don't stomp existing exception */
if (_PyErr_Occurred(tstate))
return;
- if (oparg < co->co_ncellvars) {
- name = PyTuple_GET_ITEM(co->co_cellvars,
- oparg);
- format_exc_check_arg(tstate,
- PyExc_UnboundLocalError,
- UNBOUNDLOCAL_ERROR_MSG,
- name);
+ name = PyTuple_GET_ITEM(co->co_localsplusnames, oparg);
+ if (oparg < co->co_ncellvars + co->co_nlocals) {
+ format_exc_check_arg(tstate, PyExc_UnboundLocalError,
+ UNBOUNDLOCAL_ERROR_MSG, name);
} else {
- name = PyTuple_GET_ITEM(co->co_freevars, oparg - co->co_ncellvars);
format_exc_check_arg(tstate, PyExc_NameError,
UNBOUNDFREE_ERROR_MSG, name);
}
@@ -6483,16 +6471,14 @@ unicode_concatenate(PyThreadState *tstate, PyObject *v, PyObject *w,
switch (opcode) {
case STORE_FAST:
{
- PyObject **fastlocals = f->f_localsptr;
+ PyObject **localsplus = f->f_localsptr;
if (GETLOCAL(oparg) == v)
SETLOCAL(oparg, NULL);
break;
}
case STORE_DEREF:
{
- PyObject **freevars = (f->f_localsptr +
- f->f_code->co_nlocals);
- PyObject *c = freevars[oparg];
+ PyObject *c = f->f_localsptr[oparg];
if (PyCell_GET(c) == v) {
PyCell_SET(c, NULL);
Py_DECREF(v);