mirror of https://github.com/python/cpython
bpo-43693: Add _PyCode_New(). (gh-26375)
This is an internal-only API that helps us manage the many values used to create a code object. https://bugs.python.org/issue43693
This commit is contained in:
parent
318adeba78
commit
9f494d4929
|
@ -64,7 +64,7 @@ struct PyCodeObject {
|
|||
|
||||
/* These fields are set with computed values on new code objects. */
|
||||
|
||||
Py_ssize_t *co_cell2arg; /* Maps cell vars which are arguments. */
|
||||
int *co_cell2arg; /* Maps cell vars which are arguments. */
|
||||
// These are redundant but offer some performance benefit.
|
||||
int co_nlocalsplus; /* number of local + cell + free variables */
|
||||
int co_nlocals; /* number of local variables */
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
PyObject *ptr; /* Cached pointer (borrowed reference) */
|
||||
uint64_t globals_ver; /* ma_version of global dict */
|
||||
|
@ -24,7 +25,54 @@ struct _PyOpcache {
|
|||
char optimized;
|
||||
};
|
||||
|
||||
|
||||
struct _PyCodeConstructor {
|
||||
/* metadata */
|
||||
PyObject *filename;
|
||||
PyObject *name;
|
||||
int flags;
|
||||
|
||||
/* the code */
|
||||
PyObject *code;
|
||||
int firstlineno;
|
||||
PyObject *linetable;
|
||||
|
||||
/* used by the code */
|
||||
PyObject *consts;
|
||||
PyObject *names;
|
||||
|
||||
/* mapping frame offsets to information */
|
||||
PyObject *varnames;
|
||||
PyObject *cellvars;
|
||||
PyObject *freevars;
|
||||
|
||||
/* args (within varnames) */
|
||||
int argcount;
|
||||
int posonlyargcount;
|
||||
int kwonlyargcount;
|
||||
|
||||
/* needed to create the frame */
|
||||
int stacksize;
|
||||
|
||||
/* used by the eval loop */
|
||||
PyObject *exceptiontable;
|
||||
};
|
||||
|
||||
// Using an "arguments struct" like this is helpful for maintainability
|
||||
// in a case such as this with many parameters. It does bear a risk:
|
||||
// if the struct changes and callers are not updated properly then the
|
||||
// compiler will not catch problems (like a missing argument). This can
|
||||
// cause hard-to-debug problems. The risk is mitigated by the use of
|
||||
// check_code() in codeobject.c. However, we may decide to switch
|
||||
// back to a regular function signature. Regardless, this approach
|
||||
// wouldn't be appropriate if this weren't a strictly internal API.
|
||||
// (See the comments in https://github.com/python/cpython/pull/26258.)
|
||||
PyAPI_FUNC(int) _PyCode_Validate(struct _PyCodeConstructor *);
|
||||
PyAPI_FUNC(PyCodeObject *) _PyCode_New(struct _PyCodeConstructor *);
|
||||
|
||||
|
||||
/* Private API */
|
||||
|
||||
int _PyCode_InitOpcache(PyCodeObject *co);
|
||||
|
||||
|
||||
|
|
|
@ -80,9 +80,9 @@ class PythonValuesTestCase(unittest.TestCase):
|
|||
continue
|
||||
items.append((entry.name.decode("ascii"), entry.size))
|
||||
|
||||
expected = [("__hello__", 142),
|
||||
("__phello__", -142),
|
||||
("__phello__.spam", 142),
|
||||
expected = [("__hello__", 138),
|
||||
("__phello__", -138),
|
||||
("__phello__.spam", 138),
|
||||
]
|
||||
self.assertEqual(items, expected, "PyImport_FrozenModules example "
|
||||
"in Doc/library/ctypes.rst may be out of date")
|
||||
|
|
|
@ -354,6 +354,7 @@ _code_type = type(_write_atomic.__code__)
|
|||
# Python 3.10b1 3439 (Add ROT_N)
|
||||
# Python 3.11a1 3450 Use exception table for unwinding ("zero cost" exception handling)
|
||||
# Python 3.11a1 3451 (Add CALL_METHOD_KW)
|
||||
# Python 3.11a1 3452 (drop nlocals from marshaled code objects)
|
||||
|
||||
#
|
||||
# MAGIC must change whenever the bytecode emitted by the compiler may no
|
||||
|
@ -363,7 +364,7 @@ _code_type = type(_write_atomic.__code__)
|
|||
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
||||
# in PC/launcher.c must also be updated.
|
||||
|
||||
MAGIC_NUMBER = (3451).to_bytes(2, 'little') + b'\r\n'
|
||||
MAGIC_NUMBER = (3452).to_bytes(2, 'little') + b'\r\n'
|
||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||
|
||||
_PYCACHE = '__pycache__'
|
||||
|
|
|
@ -151,7 +151,194 @@ validate_and_copy_tuple(PyObject *tup)
|
|||
|
||||
|
||||
/******************
|
||||
* the "constructors"
|
||||
* _PyCode_New()
|
||||
******************/
|
||||
|
||||
int
|
||||
_PyCode_Validate(struct _PyCodeConstructor *con)
|
||||
{
|
||||
/* Check argument types */
|
||||
if (con->argcount < con->posonlyargcount || con->posonlyargcount < 0 ||
|
||||
con->kwonlyargcount < 0 ||
|
||||
con->stacksize < 0 || con->flags < 0 ||
|
||||
con->code == NULL || !PyBytes_Check(con->code) ||
|
||||
con->consts == NULL || !PyTuple_Check(con->consts) ||
|
||||
con->names == NULL || !PyTuple_Check(con->names) ||
|
||||
con->varnames == NULL || !PyTuple_Check(con->varnames) ||
|
||||
con->freevars == NULL || !PyTuple_Check(con->freevars) ||
|
||||
con->cellvars == NULL || !PyTuple_Check(con->cellvars) ||
|
||||
con->name == NULL || !PyUnicode_Check(con->name) ||
|
||||
con->filename == NULL || !PyUnicode_Check(con->filename) ||
|
||||
con->linetable == NULL || !PyBytes_Check(con->linetable) ||
|
||||
con->exceptiontable == NULL || !PyBytes_Check(con->exceptiontable)
|
||||
) {
|
||||
PyErr_BadInternalCall();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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(con->code) > INT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError, "co_code larger than INT_MAX");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Ensure that the co_varnames has enough names to cover the arg counts.
|
||||
* Note that totalargs = nlocals - nplainlocals. We check nplainlocals
|
||||
* here to avoid the possibility of overflow (however remote). */
|
||||
int nplainlocals = (int)PyTuple_GET_SIZE(con->varnames) -
|
||||
con->argcount -
|
||||
con->kwonlyargcount -
|
||||
((con->flags & CO_VARARGS) != 0) -
|
||||
((con->flags & CO_VARKEYWORDS) != 0);
|
||||
if (nplainlocals < 0) {
|
||||
PyErr_SetString(PyExc_ValueError, "code: varnames is too small");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
|
||||
{
|
||||
Py_INCREF(con->filename);
|
||||
co->co_filename = con->filename;
|
||||
Py_INCREF(con->name);
|
||||
co->co_name = con->name;
|
||||
co->co_flags = con->flags;
|
||||
|
||||
Py_INCREF(con->code);
|
||||
co->co_code = con->code;
|
||||
co->co_firstlineno = con->firstlineno;
|
||||
Py_INCREF(con->linetable);
|
||||
co->co_linetable = con->linetable;
|
||||
|
||||
Py_INCREF(con->consts);
|
||||
co->co_consts = con->consts;
|
||||
Py_INCREF(con->names);
|
||||
co->co_names = con->names;
|
||||
|
||||
Py_INCREF(con->varnames);
|
||||
co->co_varnames = con->varnames;
|
||||
Py_INCREF(con->cellvars);
|
||||
co->co_cellvars = con->cellvars;
|
||||
Py_INCREF(con->freevars);
|
||||
co->co_freevars = con->freevars;
|
||||
|
||||
co->co_argcount = con->argcount;
|
||||
co->co_posonlyargcount = con->posonlyargcount;
|
||||
co->co_kwonlyargcount = con->kwonlyargcount;
|
||||
|
||||
co->co_stacksize = con->stacksize;
|
||||
|
||||
Py_INCREF(con->exceptiontable);
|
||||
co->co_exceptiontable = con->exceptiontable;
|
||||
|
||||
/* derived values */
|
||||
co->co_cell2arg = NULL; // This will be set soon.
|
||||
co->co_nlocals = (int)PyTuple_GET_SIZE(con->varnames);
|
||||
co->co_ncellvars = (int)PyTuple_GET_SIZE(con->cellvars);
|
||||
co->co_nfreevars = (int)PyTuple_GET_SIZE(con->freevars);
|
||||
co->co_nlocalsplus = co->co_nlocals + co->co_ncellvars + co->co_nfreevars;
|
||||
|
||||
/* not set */
|
||||
co->co_weakreflist = NULL;
|
||||
co->co_extra = NULL;
|
||||
co->co_opcache_map = NULL;
|
||||
co->co_opcache = NULL;
|
||||
co->co_opcache_flag = 0;
|
||||
co->co_opcache_size = 0;
|
||||
}
|
||||
|
||||
/* The caller is responsible for ensuring that the given data is valid. */
|
||||
|
||||
PyCodeObject *
|
||||
_PyCode_New(struct _PyCodeConstructor *con)
|
||||
{
|
||||
/* Ensure that strings are ready Unicode string */
|
||||
if (PyUnicode_READY(con->name) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyUnicode_READY(con->filename) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (intern_strings(con->names) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (intern_string_constants(con->consts, NULL) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (intern_strings(con->varnames) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (intern_strings(con->freevars) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (intern_strings(con->cellvars) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check for any inner or outer closure references */
|
||||
int ncellvars = (int)PyTuple_GET_SIZE(con->cellvars);
|
||||
if (!ncellvars && !PyTuple_GET_SIZE(con->freevars)) {
|
||||
con->flags |= CO_NOFREE;
|
||||
} else {
|
||||
con->flags &= ~CO_NOFREE;
|
||||
}
|
||||
|
||||
PyCodeObject *co = PyObject_New(PyCodeObject, &PyCode_Type);
|
||||
if (co == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
init_code(co, con);
|
||||
|
||||
/* Create mapping between cells and arguments if needed. */
|
||||
if (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 < ncellvars; i++) {
|
||||
PyObject *cellname = PyTuple_GET_ITEM(co->co_cellvars, i);
|
||||
for (int j = 0; j < totalargs; j++) {
|
||||
PyObject *argname = PyTuple_GET_ITEM(co->co_varnames, 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, ncellvars);
|
||||
if (co->co_cell2arg == NULL) {
|
||||
Py_DECREF(co);
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
for (int k = 0; k < 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;
|
||||
}
|
||||
|
||||
|
||||
/******************
|
||||
* the legacy "constructors"
|
||||
******************/
|
||||
|
||||
PyCodeObject *
|
||||
|
@ -162,167 +349,41 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
|
|||
PyObject *filename, PyObject *name, int firstlineno,
|
||||
PyObject *linetable, PyObject *exceptiontable)
|
||||
{
|
||||
PyCodeObject *co;
|
||||
Py_ssize_t *cell2arg = NULL;
|
||||
Py_ssize_t i, total_args;
|
||||
int ncellvars, nfreevars;
|
||||
struct _PyCodeConstructor con = {
|
||||
.filename = filename,
|
||||
.name = name,
|
||||
.flags = flags,
|
||||
|
||||
/* Check argument types */
|
||||
if (argcount < posonlyargcount || posonlyargcount < 0 ||
|
||||
kwonlyargcount < 0 || nlocals < 0 ||
|
||||
stacksize < 0 || flags < 0 ||
|
||||
code == NULL || !PyBytes_Check(code) ||
|
||||
consts == NULL || !PyTuple_Check(consts) ||
|
||||
names == NULL || !PyTuple_Check(names) ||
|
||||
varnames == NULL || !PyTuple_Check(varnames) ||
|
||||
freevars == NULL || !PyTuple_Check(freevars) ||
|
||||
cellvars == NULL || !PyTuple_Check(cellvars) ||
|
||||
name == NULL || !PyUnicode_Check(name) ||
|
||||
filename == NULL || !PyUnicode_Check(filename) ||
|
||||
linetable == NULL || !PyBytes_Check(linetable) ||
|
||||
exceptiontable == NULL || !PyBytes_Check(exceptiontable)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
.code = code,
|
||||
.firstlineno = firstlineno,
|
||||
.linetable = linetable,
|
||||
|
||||
/* 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");
|
||||
.consts = consts,
|
||||
.names = names,
|
||||
|
||||
.varnames = varnames,
|
||||
.cellvars = cellvars,
|
||||
.freevars = freevars,
|
||||
|
||||
.argcount = argcount,
|
||||
.posonlyargcount = posonlyargcount,
|
||||
.kwonlyargcount = kwonlyargcount,
|
||||
|
||||
.stacksize = stacksize,
|
||||
|
||||
.exceptiontable = exceptiontable,
|
||||
};
|
||||
if (_PyCode_Validate(&con) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (nlocals != PyTuple_GET_SIZE(varnames)) {
|
||||
PyErr_SetString(PyExc_ValueError, "co_nlocals != len(co_varnames)");
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"code: co_nlocals != len(co_varnames)");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Ensure that strings are ready Unicode string */
|
||||
if (PyUnicode_READY(name) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyUnicode_READY(filename) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (intern_strings(names) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (intern_strings(varnames) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (intern_strings(freevars) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (intern_strings(cellvars) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (intern_string_constants(consts, NULL) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check for any inner or outer closure references */
|
||||
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;
|
||||
}
|
||||
|
||||
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 = nlocals + 1;
|
||||
}
|
||||
if (total_args > nlocals) {
|
||||
PyErr_SetString(PyExc_ValueError, "code: varnames is too small");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create mapping between cells and arguments if needed. */
|
||||
if (ncellvars) {
|
||||
bool used_cell2arg = false;
|
||||
cell2arg = PyMem_NEW(Py_ssize_t, ncellvars);
|
||||
if (cell2arg == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
/* Find cells which are also arguments. */
|
||||
for (i = 0; i < ncellvars; i++) {
|
||||
Py_ssize_t j;
|
||||
PyObject *cell = PyTuple_GET_ITEM(cellvars, i);
|
||||
cell2arg[i] = CO_CELL_NOT_AN_ARG;
|
||||
for (j = 0; j < total_args; j++) {
|
||||
PyObject *arg = PyTuple_GET_ITEM(varnames, j);
|
||||
int cmp = PyUnicode_Compare(cell, arg);
|
||||
if (cmp == -1 && PyErr_Occurred()) {
|
||||
PyMem_Free(cell2arg);
|
||||
return NULL;
|
||||
}
|
||||
if (cmp == 0) {
|
||||
cell2arg[i] = j;
|
||||
used_cell2arg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!used_cell2arg) {
|
||||
PyMem_Free(cell2arg);
|
||||
cell2arg = NULL;
|
||||
}
|
||||
}
|
||||
co = PyObject_New(PyCodeObject, &PyCode_Type);
|
||||
if (co == NULL) {
|
||||
if (cell2arg)
|
||||
PyMem_Free(cell2arg);
|
||||
return NULL;
|
||||
}
|
||||
co->co_argcount = argcount;
|
||||
co->co_posonlyargcount = posonlyargcount;
|
||||
co->co_kwonlyargcount = kwonlyargcount;
|
||||
co->co_nlocalsplus = nlocals + ncellvars + nfreevars;
|
||||
co->co_nlocals = nlocals;
|
||||
co->co_ncellvars = ncellvars;
|
||||
co->co_nfreevars = nfreevars;
|
||||
co->co_stacksize = stacksize;
|
||||
co->co_flags = flags;
|
||||
Py_INCREF(code);
|
||||
co->co_code = code;
|
||||
Py_INCREF(consts);
|
||||
co->co_consts = consts;
|
||||
Py_INCREF(names);
|
||||
co->co_names = names;
|
||||
Py_INCREF(varnames);
|
||||
co->co_varnames = varnames;
|
||||
Py_INCREF(freevars);
|
||||
co->co_freevars = freevars;
|
||||
Py_INCREF(cellvars);
|
||||
co->co_cellvars = cellvars;
|
||||
co->co_cell2arg = cell2arg;
|
||||
Py_INCREF(filename);
|
||||
co->co_filename = filename;
|
||||
Py_INCREF(name);
|
||||
co->co_name = name;
|
||||
co->co_firstlineno = firstlineno;
|
||||
Py_INCREF(linetable);
|
||||
co->co_linetable = linetable;
|
||||
Py_INCREF(exceptiontable);
|
||||
co->co_exceptiontable = exceptiontable;
|
||||
co->co_weakreflist = NULL;
|
||||
co->co_extra = NULL;
|
||||
|
||||
co->co_opcache_map = NULL;
|
||||
co->co_opcache = NULL;
|
||||
co->co_opcache_flag = 0;
|
||||
co->co_opcache_size = 0;
|
||||
return co;
|
||||
return _PyCode_New(&con);
|
||||
}
|
||||
|
||||
PyCodeObject *
|
||||
|
@ -342,49 +403,47 @@ PyCode_New(int argcount, int kwonlyargcount,
|
|||
PyCodeObject *
|
||||
PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
|
||||
{
|
||||
static PyObject *emptystring = NULL;
|
||||
static PyObject *nulltuple = NULL;
|
||||
PyObject *emptystring = NULL;
|
||||
PyObject *nulltuple = NULL;
|
||||
PyObject *filename_ob = NULL;
|
||||
PyObject *funcname_ob = NULL;
|
||||
PyCodeObject *result = NULL;
|
||||
|
||||
emptystring = PyBytes_FromString("");
|
||||
if (emptystring == NULL) {
|
||||
emptystring = PyBytes_FromString("");
|
||||
if (emptystring == NULL)
|
||||
goto failed;
|
||||
goto failed;
|
||||
}
|
||||
nulltuple = PyTuple_New(0);
|
||||
if (nulltuple == NULL) {
|
||||
nulltuple = PyTuple_New(0);
|
||||
if (nulltuple == NULL)
|
||||
goto failed;
|
||||
goto failed;
|
||||
}
|
||||
funcname_ob = PyUnicode_FromString(funcname);
|
||||
if (funcname_ob == NULL)
|
||||
if (funcname_ob == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
filename_ob = PyUnicode_DecodeFSDefault(filename);
|
||||
if (filename_ob == NULL)
|
||||
if (filename_ob == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
result = PyCode_NewWithPosOnlyArgs(
|
||||
0, /* argcount */
|
||||
0, /* posonlyargcount */
|
||||
0, /* kwonlyargcount */
|
||||
0, /* nlocals */
|
||||
0, /* stacksize */
|
||||
0, /* flags */
|
||||
emptystring, /* code */
|
||||
nulltuple, /* consts */
|
||||
nulltuple, /* names */
|
||||
nulltuple, /* varnames */
|
||||
nulltuple, /* freevars */
|
||||
nulltuple, /* cellvars */
|
||||
filename_ob, /* filename */
|
||||
funcname_ob, /* name */
|
||||
firstlineno, /* firstlineno */
|
||||
emptystring, /* linetable */
|
||||
emptystring /* exception table */
|
||||
);
|
||||
struct _PyCodeConstructor con = {
|
||||
.filename = filename_ob,
|
||||
.name = funcname_ob,
|
||||
.code = emptystring,
|
||||
.firstlineno = firstlineno,
|
||||
.linetable = emptystring,
|
||||
.consts = nulltuple,
|
||||
.names = nulltuple,
|
||||
.varnames = nulltuple,
|
||||
.cellvars = nulltuple,
|
||||
.freevars = nulltuple,
|
||||
.exceptiontable = emptystring,
|
||||
};
|
||||
result = _PyCode_New(&con);
|
||||
|
||||
failed:
|
||||
Py_XDECREF(emptystring);
|
||||
Py_XDECREF(nulltuple);
|
||||
Py_XDECREF(funcname_ob);
|
||||
Py_XDECREF(filename_ob);
|
||||
return result;
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
// Auto-generated by Programs/freeze_test_frozenmain.py
|
||||
unsigned char M_test_frozenmain[] = {
|
||||
227,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,7,0,0,0,64,0,0,0,115,86,0,0,0,100,0,
|
||||
100,1,108,0,90,0,100,0,100,1,108,1,90,1,101,2,
|
||||
100,2,131,1,1,0,101,2,100,3,101,0,106,3,131,2,
|
||||
1,0,101,1,160,4,161,0,100,4,25,0,90,5,100,5,
|
||||
68,0,93,14,90,6,101,2,100,6,101,6,155,0,100,7,
|
||||
101,5,101,6,25,0,155,0,157,4,131,1,1,0,113,26,
|
||||
100,1,83,0,41,8,233,0,0,0,0,78,122,18,70,114,
|
||||
111,122,101,110,32,72,101,108,108,111,32,87,111,114,108,100,
|
||||
122,8,115,121,115,46,97,114,103,118,218,6,99,111,110,102,
|
||||
105,103,41,5,90,12,112,114,111,103,114,97,109,95,110,97,
|
||||
109,101,218,10,101,120,101,99,117,116,97,98,108,101,90,15,
|
||||
117,115,101,95,101,110,118,105,114,111,110,109,101,110,116,90,
|
||||
17,99,111,110,102,105,103,117,114,101,95,99,95,115,116,100,
|
||||
105,111,90,14,98,117,102,102,101,114,101,100,95,115,116,100,
|
||||
105,111,122,7,99,111,110,102,105,103,32,122,2,58,32,41,
|
||||
7,218,3,115,121,115,90,17,95,116,101,115,116,105,110,116,
|
||||
101,114,110,97,108,99,97,112,105,218,5,112,114,105,110,116,
|
||||
218,4,97,114,103,118,90,11,103,101,116,95,99,111,110,102,
|
||||
105,103,115,114,2,0,0,0,218,3,107,101,121,169,0,114,
|
||||
8,0,0,0,114,8,0,0,0,250,18,116,101,115,116,95,
|
||||
102,114,111,122,101,110,109,97,105,110,46,112,121,218,8,60,
|
||||
109,111,100,117,108,101,62,1,0,0,0,115,16,0,0,0,
|
||||
8,3,8,1,8,2,12,1,12,1,8,1,26,7,4,249,
|
||||
243,0,0,0,0,
|
||||
227,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,
|
||||
0,64,0,0,0,115,86,0,0,0,100,0,100,1,108,0,
|
||||
90,0,100,0,100,1,108,1,90,1,101,2,100,2,131,1,
|
||||
1,0,101,2,100,3,101,0,106,3,131,2,1,0,101,1,
|
||||
160,4,161,0,100,4,25,0,90,5,100,5,68,0,93,14,
|
||||
90,6,101,2,100,6,101,6,155,0,100,7,101,5,101,6,
|
||||
25,0,155,0,157,4,131,1,1,0,113,26,100,1,83,0,
|
||||
41,8,233,0,0,0,0,78,122,18,70,114,111,122,101,110,
|
||||
32,72,101,108,108,111,32,87,111,114,108,100,122,8,115,121,
|
||||
115,46,97,114,103,118,218,6,99,111,110,102,105,103,41,5,
|
||||
90,12,112,114,111,103,114,97,109,95,110,97,109,101,218,10,
|
||||
101,120,101,99,117,116,97,98,108,101,90,15,117,115,101,95,
|
||||
101,110,118,105,114,111,110,109,101,110,116,90,17,99,111,110,
|
||||
102,105,103,117,114,101,95,99,95,115,116,100,105,111,90,14,
|
||||
98,117,102,102,101,114,101,100,95,115,116,100,105,111,122,7,
|
||||
99,111,110,102,105,103,32,122,2,58,32,41,7,218,3,115,
|
||||
121,115,90,17,95,116,101,115,116,105,110,116,101,114,110,97,
|
||||
108,99,97,112,105,218,5,112,114,105,110,116,218,4,97,114,
|
||||
103,118,90,11,103,101,116,95,99,111,110,102,105,103,115,114,
|
||||
2,0,0,0,218,3,107,101,121,169,0,114,8,0,0,0,
|
||||
114,8,0,0,0,250,18,116,101,115,116,95,102,114,111,122,
|
||||
101,110,109,97,105,110,46,112,121,218,8,60,109,111,100,117,
|
||||
108,101,62,1,0,0,0,115,16,0,0,0,8,3,8,1,
|
||||
8,2,12,1,12,1,8,1,26,7,4,249,243,0,0,0,
|
||||
0,
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "Python.h"
|
||||
#include "pycore_ast.h" // _PyAST_GetDocString()
|
||||
#include "pycore_compile.h" // _PyFuture_FromAST()
|
||||
#include "pycore_code.h" // _PyCode_New()
|
||||
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
|
||||
#include "pycore_long.h" // _PyLong_GetZero()
|
||||
#include "pycore_symtable.h" // PySTEntryObject
|
||||
|
@ -7166,16 +7167,16 @@ merge_const_one(struct compiler *c, PyObject **obj)
|
|||
}
|
||||
|
||||
static PyCodeObject *
|
||||
makecode(struct compiler *c, struct assembler *a, PyObject *consts, int maxdepth)
|
||||
makecode(struct compiler *c, struct assembler *a, PyObject *constslist,
|
||||
int maxdepth)
|
||||
{
|
||||
PyCodeObject *co = NULL;
|
||||
PyObject *names = NULL;
|
||||
PyObject *consts = NULL;
|
||||
PyObject *varnames = NULL;
|
||||
PyObject *name = NULL;
|
||||
PyObject *freevars = NULL;
|
||||
PyObject *cellvars = NULL;
|
||||
Py_ssize_t nlocals;
|
||||
int nlocals_int;
|
||||
int flags;
|
||||
int posorkeywordargcount, posonlyargcount, kwonlyargcount;
|
||||
|
||||
|
@ -7199,34 +7200,53 @@ makecode(struct compiler *c, struct assembler *a, PyObject *consts, int maxdepth
|
|||
goto error;
|
||||
}
|
||||
|
||||
nlocals = PyDict_GET_SIZE(c->u->u_varnames);
|
||||
assert(nlocals < INT_MAX);
|
||||
nlocals_int = Py_SAFE_DOWNCAST(nlocals, Py_ssize_t, int);
|
||||
|
||||
flags = compute_code_flags(c);
|
||||
if (flags < 0)
|
||||
goto error;
|
||||
|
||||
consts = PyList_AsTuple(consts); /* PyCode_New requires a tuple */
|
||||
consts = PyList_AsTuple(constslist); /* PyCode_New requires a tuple */
|
||||
if (consts == NULL) {
|
||||
goto error;
|
||||
}
|
||||
if (!merge_const_one(c, &consts)) {
|
||||
Py_DECREF(consts);
|
||||
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);
|
||||
co = PyCode_NewWithPosOnlyArgs(posonlyargcount+posorkeywordargcount,
|
||||
posonlyargcount, kwonlyargcount, nlocals_int,
|
||||
maxdepth, flags, a->a_bytecode, consts, names,
|
||||
varnames, freevars, cellvars, c->c_filename,
|
||||
c->u->u_name, c->u->u_firstlineno, a->a_lnotab, a->a_except_table);
|
||||
Py_DECREF(consts);
|
||||
struct _PyCodeConstructor con = {
|
||||
.filename = c->c_filename,
|
||||
.name = c->u->u_name,
|
||||
.flags = flags,
|
||||
|
||||
.code = a->a_bytecode,
|
||||
.firstlineno = c->u->u_firstlineno,
|
||||
.linetable = a->a_lnotab,
|
||||
|
||||
.consts = consts,
|
||||
.names = names,
|
||||
|
||||
.varnames = varnames,
|
||||
.cellvars = cellvars,
|
||||
.freevars = freevars,
|
||||
|
||||
.argcount = posonlyargcount + posorkeywordargcount,
|
||||
.posonlyargcount = posonlyargcount,
|
||||
.kwonlyargcount = kwonlyargcount,
|
||||
|
||||
.stacksize = maxdepth,
|
||||
|
||||
.exceptiontable = a->a_except_table,
|
||||
};
|
||||
if (_PyCode_Validate(&con) < 0) {
|
||||
goto error;
|
||||
}
|
||||
co = _PyCode_New(&con);
|
||||
|
||||
error:
|
||||
Py_XDECREF(names);
|
||||
Py_XDECREF(consts);
|
||||
Py_XDECREF(varnames);
|
||||
Py_XDECREF(name);
|
||||
Py_XDECREF(freevars);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/* Auto-generated by Programs/_freeze_importlib.c */
|
||||
const unsigned char _Py_M__hello[] = {
|
||||
99,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,2,0,0,0,64,0,0,0,115,16,0,0,0,100,0,
|
||||
90,0,101,1,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,
|
||||
99,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,
|
||||
0,64,0,0,0,115,16,0,0,0,100,0,90,0,101,1,
|
||||
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,
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -13,6 +13,7 @@
|
|||
#include "code.h"
|
||||
#include "marshal.h"
|
||||
#include "pycore_hashtable.h"
|
||||
#include "pycore_code.h" // _PyCode_New()
|
||||
|
||||
/*[clinic input]
|
||||
module marshal
|
||||
|
@ -512,7 +513,6 @@ w_complex_object(PyObject *v, char flag, WFILE *p)
|
|||
w_long(co->co_argcount, p);
|
||||
w_long(co->co_posonlyargcount, p);
|
||||
w_long(co->co_kwonlyargcount, p);
|
||||
w_long(co->co_nlocals, p);
|
||||
w_long(co->co_stacksize, p);
|
||||
w_long(co->co_flags, p);
|
||||
w_object(co->co_code, p);
|
||||
|
@ -1301,7 +1301,6 @@ r_object(RFILE *p)
|
|||
int argcount;
|
||||
int posonlyargcount;
|
||||
int kwonlyargcount;
|
||||
int nlocals;
|
||||
int stacksize;
|
||||
int flags;
|
||||
PyObject *code = NULL;
|
||||
|
@ -1331,9 +1330,6 @@ r_object(RFILE *p)
|
|||
goto code_error;
|
||||
}
|
||||
kwonlyargcount = (int)r_long(p);
|
||||
if (PyErr_Occurred())
|
||||
goto code_error;
|
||||
nlocals = (int)r_long(p);
|
||||
if (PyErr_Occurred())
|
||||
goto code_error;
|
||||
stacksize = (int)r_long(p);
|
||||
|
@ -1354,6 +1350,7 @@ r_object(RFILE *p)
|
|||
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;
|
||||
|
@ -1376,19 +1373,43 @@ r_object(RFILE *p)
|
|||
if (exceptiontable == NULL)
|
||||
goto code_error;
|
||||
|
||||
|
||||
if (PySys_Audit("code.__new__", "OOOiiiiii",
|
||||
code, filename, name, argcount, posonlyargcount,
|
||||
kwonlyargcount, nlocals, stacksize, flags) < 0) {
|
||||
goto code_error;
|
||||
}
|
||||
|
||||
v = (PyObject *) PyCode_NewWithPosOnlyArgs(
|
||||
argcount, posonlyargcount, kwonlyargcount,
|
||||
nlocals, stacksize, flags,
|
||||
code, consts, names, varnames,
|
||||
freevars, cellvars, filename, name,
|
||||
firstlineno, linetable, exceptiontable);
|
||||
struct _PyCodeConstructor con = {
|
||||
.filename = filename,
|
||||
.name = name,
|
||||
.flags = flags,
|
||||
|
||||
.code = code,
|
||||
.firstlineno = firstlineno,
|
||||
.linetable = linetable,
|
||||
|
||||
.consts = consts,
|
||||
.names = names,
|
||||
|
||||
.varnames = varnames,
|
||||
.cellvars = cellvars,
|
||||
.freevars = freevars,
|
||||
|
||||
.argcount = argcount,
|
||||
.posonlyargcount = posonlyargcount,
|
||||
.kwonlyargcount = kwonlyargcount,
|
||||
|
||||
.stacksize = stacksize,
|
||||
|
||||
.exceptiontable = exceptiontable,
|
||||
};
|
||||
if (_PyCode_Validate(&con) < 0) {
|
||||
goto code_error;
|
||||
}
|
||||
v = (PyObject *)_PyCode_New(&con);
|
||||
if (v == NULL) {
|
||||
goto code_error;
|
||||
}
|
||||
v = r_ref_insert(v, idx, flag, p);
|
||||
|
||||
code_error:
|
||||
|
|
Loading…
Reference in New Issue