diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2021-06-07 12:22:26 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-07 12:22:26 -0600 |
commit | 2ab27c4af4ddf7528e1375e77c787c7fbb09b5e6 (patch) | |
tree | d3983e5282f575560cb7449fae4785447fdfff14 /Python/ceval.c | |
parent | 001eb520b5757294dc455c900d94b7b153de6cdd (diff) | |
download | cpython-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.c | 78 |
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); |