8000 bpo-43693: Add the MAKE_CELL opcode and interleave fast locals offsets. by ericsnowcurrently · Pull Request #26396 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-43693: Add the MAKE_CELL opcode and interleave fast locals offsets. #26396

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jun 7, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix PyFrame_FastToLocals() and PyFrame_LocalsToFast() when the frame …
…has been cleared.
  • Loading branch information
ericsnowcurrently committed Jun 7, 2021
commit 9cdc8baf5c0d778a0b4b6d382aa4f23e34530b61
76 changes: 41 additions & 35 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -979,43 +979,48 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f)

PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i);
PyObject *value = fast[i];
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().
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];
}
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];
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) {
if (PyErr_ExceptionMatches(PyExc_KeyError)) {
Expand Down Expand Up @@ -1055,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;
Expand Down Expand Up @@ -1114,7 +1120,7 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
}
}
if (cell != NULL) {
PyObject *oldvalue = PyCell_GET(cell);
oldvalue = PyCell_GET(cell);
if (value != oldvalue) {
Py_XDECREF(oldvalue);
Py_XINCREF(value);
Expand Down
0