mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
These were reverted in gh-26530 (commit17c4edc
) 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
This commit is contained in:
parent
001eb520b5
commit
2ab27c4af4
23 changed files with 6044 additions and 5710 deletions
|
@ -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);
|
||||
|
|
160
Python/compile.c
160
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 (free) {
|
||||
for (i = 0; i < free; ++i) {
|
||||
if (co->co_nfreevars) {
|
||||
int i = co->co_nlocals + co->co_ncellvars;
|
||||
for (; i < co->co_nlocalsplus; ++i) {
|
||||
/* Bypass com_addop_varname because it will generate
|
||||
LOAD_DEREF but LOAD_CLOSURE is needed.
|
||||
*/
|
||||
PyObject *name = PyTuple_GET_ITEM(co->co_freevars, i);
|
||||
PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
|
||||
|
||||
/* Special case: If a class contains a method with a
|
||||
free variable that has the same name as a method,
|
||||
|
@ -2076,6 +2076,10 @@ 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",
|
||||
|
@ -2083,13 +2087,14 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags,
|
|||
reftype,
|
||||
c->u->u_name,
|
||||
co->co_name,
|
||||
co->co_freevars);
|
||||
freevars);
|
||||
Py_DECREF(freevars);
|
||||
return 0;
|
||||
}
|
||||
ADDOP_I(c, LOAD_CLOSURE, arg);
|
||||
}
|
||||
flags |= 0x08;
|
||||
ADDOP_I(c, BUILD_TUPLE, free);
|
||||
ADDOP_I(c, BUILD_TUPLE, co->co_nfreevars);
|
||||
}
|
||||
ADDOP_LOAD_CONST(c, (PyObject*)co);
|
||||
ADDOP_LOAD_CONST(c, qualname);
|
||||
|
@ -7176,6 +7181,46 @@ 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)
|
||||
|
@ -7183,36 +7228,22 @@ makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
|
|||
PyCodeObject *co = NULL;
|
||||
PyObject *names = NULL;
|
||||
PyObject *consts = NULL;
|
||||
PyObject *varnames = NULL;
|
||||
PyObject *localsplusnames = NULL;
|
||||
_PyLocalsPlusKinds localspluskinds = 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);
|
||||
varnames = dict_keys_inorder(c->u->u_varnames, 0);
|
||||
if (!names || !varnames) {
|
||||
if (!names) {
|
||||
goto error;
|
||||
}
|
||||
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;
|
||||
|
||||
if (!merge_const_one(c, &names) ||
|
||||
!merge_const_one(c, &varnames) ||
|
||||
!merge_const_one(c, &cellvars) ||
|
||||
!merge_const_one(c, &freevars))
|
||||
{
|
||||
if (!merge_const_one(c, &names)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
flags = compute_code_flags(c);
|
||||
if (flags < 0)
|
||||
int flags = compute_code_flags(c);
|
||||
if (flags < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
consts = PyList_AsTuple(constslist); /* PyCode_New requires a tuple */
|
||||
if (consts == NULL) {
|
||||
|
@ -7222,9 +7253,32 @@ makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
|
|||
goto error;
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
struct _PyCodeConstructor con = {
|
||||
.filename = c->c_filename,
|
||||
.name = c->u->u_name,
|
||||
|
@ -7237,11 +7291,10 @@ makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
|
|||
.consts = consts,
|
||||
.names = names,
|
||||
|
||||
.varnames = varnames,
|
||||
.cellvars = cellvars,
|
||||
.freevars = freevars,
|
||||
.localsplusnames = localsplusnames,
|
||||
.localspluskinds = localspluskinds,
|
||||
|
||||
.argcount = posonlyargcount + posorkeywordargcount,
|
||||
.argcount = posonlyargcount + posorkwargcount,
|
||||
.posonlyargcount = posonlyargcount,
|
||||
.kwonlyargcount = kwonlyargcount,
|
||||
|
||||
|
@ -7249,18 +7302,30 @@ 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(varnames);
|
||||
Py_XDECREF(localsplusnames);
|
||||
_PyCode_ClearLocalsPlusKinds(localspluskinds);
|
||||
Py_XDECREF(name);
|
||||
Py_XDECREF(freevars);
|
||||
Py_XDECREF(cellvars);
|
||||
return co;
|
||||
}
|
||||
|
||||
|
@ -7371,6 +7436,24 @@ 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)
|
||||
{
|
||||
|
@ -7426,6 +7509,9 @@ 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;
|
||||
|
|
|
@ -5,8 +5,7 @@ const unsigned char _Py_M__hello[] = {
|
|||
100,1,131,1,1,0,100,2,83,0,41,3,84,122,12,72,
|
||||
101,108,108,111,32,119,111,114,108,100,33,78,41,2,90,11,
|
||||
105,110,105,116,105,97,108,105,122,101,100,218,5,112,114,105,
|
||||
110,116,169,0,114,1,0,0,0,114,1,0,0,0,122,14,
|
||||
60,102,114,111,122,101,110,32,104,101,108,108,111,62,218,8,
|
||||
60,109,111,100,117,108,101,62,1,0,0,0,115,4,0,0,
|
||||
0,4,0,12,1,243,0,0,0,0,
|
||||
110,116,169,0,122,14,60,102,114,111,122,101,110,32,104,101,
|
||||
108,108,111,62,218,8,60,109,111,100,117,108,101,62,1,0,
|
||||
0,0,115,4,0,0,0,4,0,12,1,243,0,0,0,0,
|
||||
};
|
||||
|
|
3232
Python/importlib.h
generated
3232
Python/importlib.h
generated
File diff suppressed because it is too large
Load diff
5288
Python/importlib_external.h
generated
5288
Python/importlib_external.h
generated
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -518,9 +518,8 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
|||
w_object(co->co_code, p);
|
||||
w_object(co->co_consts, p);
|
||||
w_object(co->co_names, p);
|
||||
w_object(co->co_varnames, p);
|
||||
w_object(co->co_freevars, p);
|
||||
w_object(co->co_cellvars, p);
|
||||
w_object(co->co_localsplusnames, p);
|
||||
w_string(co->co_localspluskinds, co->co_nlocalsplus, p);
|
||||
w_object(co->co_filename, p);
|
||||
w_object(co->co_name, p);
|
||||
w_long(co->co_firstlineno, p);
|
||||
|
@ -1306,9 +1305,8 @@ r_object(RFILE *p)
|
|||
PyObject *code = NULL;
|
||||
PyObject *consts = NULL;
|
||||
PyObject *names = NULL;
|
||||
PyObject *varnames = NULL;
|
||||
PyObject *freevars = NULL;
|
||||
PyObject *cellvars = NULL;
|
||||
PyObject *localsplusnames = NULL;
|
||||
_PyLocalsPlusKinds localspluskinds = NULL;
|
||||
PyObject *filename = NULL;
|
||||
PyObject *name = NULL;
|
||||
int firstlineno;
|
||||
|
@ -1347,16 +1345,22 @@ r_object(RFILE *p)
|
|||
names = r_object(p);
|
||||
if (names == NULL)
|
||||
goto code_error;
|
||||
varnames = r_object(p);
|
||||
if (varnames == NULL)
|
||||
goto code_error;
|
||||
Py_ssize_t nlocals = PyTuple_GET_SIZE(varnames);
|
||||
freevars = r_object(p);
|
||||
if (freevars == NULL)
|
||||
goto code_error;
|
||||
cellvars = r_object(p);
|
||||
if (cellvars == NULL)
|
||||
localsplusnames = r_object(p);
|
||||
if (localsplusnames == NULL)
|
||||
goto code_error;
|
||||
|
||||
assert(PyTuple_GET_SIZE(localsplusnames) < INT_MAX);
|
||||
int nlocalsplus = (int)PyTuple_GET_SIZE(localsplusnames);
|
||||
if (nlocalsplus) {
|
||||
if (_PyCode_InitLocalsPlusKinds(nlocalsplus,
|
||||
&localspluskinds) < 0) {
|
||||
goto code_error;
|
||||
}
|
||||
for (int i = 0; i < nlocalsplus; i++) {
|
||||
localspluskinds[i] = r_byte(p);
|
||||
}
|
||||
}
|
||||
|
||||
filename = r_object(p);
|
||||
if (filename == NULL)
|
||||
goto code_error;
|
||||
|
@ -1375,7 +1379,8 @@ r_object(RFILE *p)
|
|||
|
||||
if (PySys_Audit("code.__new__", "OOOiiiiii",
|
||||
code, filename, name, argcount, posonlyargcount,
|
||||
kwonlyargcount, nlocals, stacksize, flags) < 0) {
|
||||
kwonlyargcount, nlocalsplus, stacksize,
|
||||
flags) < 0) {
|
||||
goto code_error;
|
||||
}
|
||||
|
||||
|
@ -1391,9 +1396,8 @@ r_object(RFILE *p)
|
|||
.consts = consts,
|
||||
.names = names,
|
||||
|
||||
.varnames = varnames,
|
||||
.cellvars = cellvars,
|
||||
.freevars = freevars,
|
||||
.localsplusnames = localsplusnames,
|
||||
.localspluskinds = localspluskinds,
|
||||
|
||||
.argcount = argcount,
|
||||
.posonlyargcount = posonlyargcount,
|
||||
|
@ -1403,22 +1407,26 @@ r_object(RFILE *p)
|
|||
|
||||
.exceptiontable = exceptiontable,
|
||||
};
|
||||
|
||||
if (_PyCode_Validate(&con) < 0) {
|
||||
goto code_error;
|
||||
}
|
||||
|
||||
v = (PyObject *)_PyCode_New(&con);
|
||||
if (v == NULL) {
|
||||
goto code_error;
|
||||
}
|
||||
|
||||
localspluskinds = NULL; // This keeps it from getting freed below.
|
||||
|
||||
v = r_ref_insert(v, idx, flag, p);
|
||||
|
||||
code_error:
|
||||
Py_XDECREF(code);
|
||||
Py_XDECREF(consts);
|
||||
Py_XDECREF(names);
|
||||
Py_XDECREF(varnames);
|
||||
Py_XDECREF(freevars);
|
||||
Py_XDECREF(cellvars);
|
||||
Py_XDECREF(localsplusnames);
|
||||
_PyCode_ClearLocalsPlusKinds(localspluskinds);
|
||||
Py_XDECREF(filename);
|
||||
Py_XDECREF(name);
|
||||
Py_XDECREF(linetable);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "pycore_frame.h"
|
||||
|
||||
#include "pycore_pyerrors.h"
|
||||
#include "pycore_code.h" // _PyCode_GetVarnames()
|
||||
|
||||
#define MAX_CANDIDATE_ITEMS 750
|
||||
#define MAX_STRING_SIZE 40
|
||||
|
@ -210,8 +211,13 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc)
|
|||
PyFrameObject *frame = traceback->tb_frame;
|
||||
assert(frame != NULL);
|
||||
PyCodeObject *code = PyFrame_GetCode(frame);
|
||||
assert(code != NULL && code->co_varnames != NULL);
|
||||
PyObject *dir = PySequence_List(code->co_varnames);
|
||||
assert(code != NULL && code->co_localsplusnames != NULL);
|
||||
PyObject *varnames = _PyCode_GetVarnames(code);
|
||||
if (varnames == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
PyObject *dir = PySequence_List(varnames);
|
||||
Py_DECREF(varnames);
|
||||
Py_DECREF(code);
|
||||
if (dir == NULL) {
|
||||
return NULL;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue