mirror of
https://github.com/python/cpython.git
synced 2025-11-25 04:34:37 +00:00
This was reverted in GH-26596 (commit 6d518bb) due to some bad memory accesses.
* Add the MAKE_CELL opcode. (gh-26396)
The memory accesses have been fixed.
https://bugs.python.org/issue43693
This commit is contained in:
parent
ab36b9f834
commit
3e1c7167d8
16 changed files with 4470 additions and 4234 deletions
|
|
@ -918,6 +918,19 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code,
|
|||
return f;
|
||||
}
|
||||
|
||||
int
|
||||
_PyFrame_OpAlreadyRan(PyFrameObject *f, int opcode, int oparg)
|
||||
{
|
||||
const _Py_CODEUNIT *code =
|
||||
(const _Py_CODEUNIT *)PyBytes_AS_STRING(f->f_code->co_code);
|
||||
for (int i = 0; i < f->f_lasti; i++) {
|
||||
if (_Py_OPCODE(code[i]) == opcode && _Py_OPARG(code[i]) == oparg) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
PyFrame_FastToLocalsWithError(PyFrameObject *f)
|
||||
{
|
||||
|
|
@ -961,15 +974,52 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f)
|
|||
former here and will later use the cell for the variable.
|
||||
*/
|
||||
if (kind & CO_FAST_LOCAL && kind & CO_FAST_CELL) {
|
||||
assert(fast[i] == NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
|
||||
PyObject *value = fast[i];
|
||||
if (kind & (CO_FAST_CELL | CO_FAST_FREE) && value != NULL) {
|
||||
assert(PyCell_Check(value));
|
||||
value = PyCell_GET(value);
|
||||
if (f->f_state != FRAME_CLEARED) {
|
||||
int cellargoffset = CO_CELL_NOT_AN_ARG;
|
||||
if (co->co_cell2arg != NULL) {
|
||||
cellargoffset = co->co_cell2arg[i - co->co_nlocals];
|
||||
}
|
||||
if (kind & CO_FAST_FREE) {
|
||||
// The cell was set by _PyEval_MakeFrameVector() from
|
||||
// the function's closure.
|
||||
assert(value != NULL && PyCell_Check(value));
|
||||
value = PyCell_GET(value);
|
||||
}
|
||||
else if (kind & CO_FAST_CELL) {
|
||||
// Note that no *_DEREF ops can happen before MAKE_CELL
|
||||
// executes. So there's no need to duplicate the work
|
||||
// that MAKE_CELL would otherwise do later, if it hasn't
|
||||
// run yet.
|
||||
if (value != NULL) {
|
||||
if (PyCell_Check(value) &&
|
||||
_PyFrame_OpAlreadyRan(f, MAKE_CELL, i)) {
|
||||
// (likely) MAKE_CELL must have executed already.
|
||||
value = PyCell_GET(value);
|
||||
}
|
||||
// (unlikely) Otherwise it must be an initial value set
|
||||
// by an earlier call to PyFrame_FastToLocals().
|
||||
}
|
||||
else {
|
||||
// (unlikely) MAKE_CELL hasn't executed yet.
|
||||
if (cellargoffset != CO_CELL_NOT_AN_ARG) {
|
||||
// It is an arg that escapes into an inner
|
||||
// function so we use the initial value that
|
||||
// was already set by _PyEval_MakeFrameVector().
|
||||
// Normally the arg value would always be set.
|
||||
// However, it can be NULL if it was deleted via
|
||||
// PyFrame_LocalsToFast().
|
||||
value = fast[cellargoffset];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
assert(value == NULL);
|
||||
}
|
||||
if (value == NULL) {
|
||||
if (PyObject_DelItem(locals, name) != 0) {
|
||||
|
|
@ -1010,8 +1060,9 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
|
|||
PyObject **fast;
|
||||
PyObject *error_type, *error_value, *error_traceback;
|
||||
PyCodeObject *co;
|
||||
if (f == NULL)
|
||||
if (f == NULL || f->f_state == FRAME_CLEARED) {
|
||||
return;
|
||||
}
|
||||
locals = _PyFrame_Specials(f)[FRAME_SPECIALS_LOCALS_OFFSET];
|
||||
if (locals == NULL)
|
||||
return;
|
||||
|
|
@ -1039,16 +1090,68 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if (kind & (CO_FAST_CELL | CO_FAST_FREE)) {
|
||||
assert(PyCell_Check(fast[i]));
|
||||
if (PyCell_GET(fast[i]) != value) {
|
||||
if (PyCell_Set(fast[i], value) < 0) {
|
||||
PyErr_Clear();
|
||||
}
|
||||
PyObject *oldvalue = fast[i];
|
||||
int cellargoffset = CO_CELL_NOT_AN_ARG;
|
||||
if (kind & CO_FAST_CELL && co->co_cell2arg != NULL) {
|
||||
assert(i >= co->co_nlocals);
|
||||
cellargoffset = co->co_cell2arg[i - co->co_nlocals];
|
||||
}
|
||||
PyObject *cell = NULL;
|
||||
if (kind == CO_FAST_FREE) {
|
||||
// The cell was set by _PyEval_MakeFrameVector() from
|
||||
// the function's closure.
|
||||
assert(oldvalue != NULL && PyCell_Check(oldvalue));
|
||||
cell = oldvalue;
|
||||
}
|
||||
else if (kind & CO_FAST_CELL && oldvalue != NULL) {
|
||||
if (cellargoffset != CO_CELL_NOT_AN_ARG) {
|
||||
// (likely) MAKE_CELL must have executed already.
|
||||
// It's the cell for an arg.
|
||||
assert(PyCell_Check(oldvalue));
|
||||
cell = oldvalue;
|
||||
}
|
||||
else {
|
||||
if (PyCell_Check(oldvalue) &&
|
||||
_PyFrame_OpAlreadyRan(f, MAKE_CELL, i)) {
|
||||
// (likely) MAKE_CELL must have executed already.
|
||||
cell = oldvalue;
|
||||
}
|
||||
// (unlikely) Otherwise, it must have been set to some
|
||||
// initial value by an earlier call to PyFrame_LocalsToFast().
|
||||
}
|
||||
}
|
||||
if (cell != NULL) {
|
||||
oldvalue = PyCell_GET(cell);
|
||||
if (value != oldvalue) {
|
||||
Py_XDECREF(oldvalue);
|
||||
Py_XINCREF(value);
|
||||
PyCell_SET(cell, value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int offset = i;
|
||||
if (kind & CO_FAST_CELL) {
|
||||
// (unlikely) MAKE_CELL hasn't executed yet.
|
||||
// Note that there is no need to create the cell that
|
||||
// MAKE_CELL would otherwise create later, since no
|
||||
// *_DEREF ops can happen before MAKE_CELL has run.
|
||||
if (cellargoffset != CO_CELL_NOT_AN_ARG) {
|
||||
// It's the cell for an arg.
|
||||
// Replace the initial value that was set by
|
||||
// _PyEval_MakeFrameVector().
|
||||
// Normally the arg value would always be set.
|
||||
// However, it can be NULL if it was deleted
|
||||
// via an earlier PyFrame_LocalsToFast() call.
|
||||
offset = cellargoffset;
|
||||
oldvalue = fast[offset];
|
||||
}
|
||||
// Otherwise set an initial value for MAKE_CELL to use
|
||||
// when it runs later.
|
||||
}
|
||||
if (value != oldvalue) {
|
||||
Py_XINCREF(value);
|
||||
Py_XSETREF(fast[offset], value);
|
||||
}
|
||||
} else if (fast[i] != value) {
|
||||
Py_XINCREF(value);
|
||||
Py_XSETREF(fast[i], value);
|
||||
}
|
||||
Py_XDECREF(value);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue