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
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

10000
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
Implement MAKE_CELL.
  • Loading branch information
ericsnowcurrently committed Jun 7, 2021
commit e18489be9a9320908392fc6c494b67e649a6047a
12 changes: 6 additions & 6 deletions Lib/test/test_dis.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ def foo(x):
return foo

dis_nested_0 = """\
0 MAKE_CELL 0
0 MAKE_CELL 2

%3d 2 LOAD_CLOSURE 2 (y)
4 BUILD_TUPLE 1
Expand All @@ -446,7 +446,7 @@ def foo(x):

dis_nested_1 = """%s
Disassembly of <code object foo at 0x..., file "%s", line %d>:
0 MAKE_CELL 0
0 MAKE_CELL 1

%3d 2 LOAD_CLOSURE 1 (x)
4 BUILD_TUPLE 1
Expand Down Expand Up @@ -966,8 +966,8 @@ def jumpy():

Instruction = dis.Instruction
expected_opinfo_outer = [
Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval=0, argrepr='', offset=0, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval=1, argrepr='', offset=2, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_CELL', opcode=135, arg=3, argval=3, argrepr='', offset=0, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_CELL', opcode=135, arg=4, argval=4, argrepr='', offset=2, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval=(3, 4), argrepr='(3, 4)', offset=4, starts_line=2, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=136, arg=3, argval='a', argrepr='a', offset=6, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=136, arg=4, argval='b', argrepr='b', offset=8, starts_line=None, is_jump_target=False),
Expand All @@ -991,8 +991,8 @@ def jumpy():
]

expected_opinfo_f = [
Instruction(opname='MAKE_CELL', opcode=135, arg=0, argval=0, argrepr='', offset=0, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_CELL', opcode=135, arg=1, argval=1, argrepr='', offset=2, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_CELL', opcode=135, arg=3, argval=3, argrepr='', offset=0, starts_line=None, is_jump_target=False),
Instruction(opname='MAKE_CELL', opcode=135, arg=4, argval=4, argrepr='', offset=2, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CONST', opcode=100, arg=5, argval=(5, 6), argrepr='(5, 6)', offset=4, starts_line=3, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=136, arg=5, argval='a', argrepr='a', offset=6, starts_line=None, is_jump_target=False),
Instruction(opname='LOAD_CLOSURE', opcode=136, arg=6, argval='b', argrepr='b', offset=8, starts_line=None, is_jump_target=False),
Expand Down
61 changes: 53 additions & 8 deletions Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -961,15 +961,39 @@ 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 (kind & (CO_FAST_CELL | CO_FAST_FREE)) {
if (value != NULL) {
// MAKE_CELL must have executed already.
assert(PyCell_Check(value));
value = PyCell_GET(value);
}
else {
// MAKE_CELL hasn't executed yet. (This is unlikely.)
PyObject *cell = PyCell_New(NULL);
if (cell == NULL) {
PyErr_Clear();
}
else {
if (co->co_cell2arg != NULL) {
int argoffset = co->co_cell2arg[i - co->co_nlocals];
if (argoffset != CO_CELL_NOT_AN_ARG) {
// It will have been set in initialize_locals().
value = fast[argoffset];
assert(value != NULL);
Py_INCREF(value);
PyCell_SET(cell, value);
// Clear the arg slot.
Py_SETREF(fast[argoffset], NULL);
}
}
fast[i] = cell;
}
}
}
if (value == NULL) {
if (PyObject_DelItem(locals, name) != 0) {
Expand Down Expand Up @@ -1039,16 +1063,37 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
continue;
}
}
PyObject *oldvalue = fast[i];
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) {
if (oldvalue != NULL) {
// MAKE_CELL must have executed already.
assert(PyCell_Check(oldvalue));
Py_XDECREF(PyCell_GET(oldvalue));
Py_XINCREF(value);
PyCell_SET(oldvalue, value);
}
else {
// MAKE_CELL hasn't executed yet. (This is unlikely.)
PyObject *cell = PyCell_New(value);
if (cell == NULL) {
PyErr_Clear();
}
else {
fast[i] = cell;
// Clear the corresponding arg if there is one.
if (co->co_cell2arg != NULL) {
int argoffset = co->co_cell2arg[i - co->co_nlocals];
if (argoffset != CO_CELL_NOT_AN_ARG) {
// It will have been set in initialize_locals().
assert(fast[argoffset] != NULL);
Py_SETREF(fast[argoffset], NULL);
}
}
}
}
} else if (fast[i] != value) {
Py_XINCREF(value);
Py_XSETREF(fast[i], value);
Py_XSETREF(oldvalue, value);
}
Py_XDECREF(value);
}
Expand Down
54 changes: 28 additions & 26 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1835,11 +1835,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
DISPATCH();
}

case TARGET(MAKE_CELL): {
// XXX
DISPATCH();
}

/* We keep LOAD_CLOSURE so that the bytecode stays more readable. */
case TARGET(LOAD_CLOSURE):
case TARGET(LOAD_FAST): {
Expand Down Expand Up @@ -3081,6 +3076,34 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
goto error;
}

case TARGET(MAKE_CELL): {
if (GETLOCAL(oparg) != NULL) {
// A cell must have been set in PyFrame_LocalsToFast().
// (This is unlikely to happen.)
assert(PyCell_Check(GETLOCAL(oparg)));
DISPATCH();
}
PyObject *cell = PyCell_New(NULL);
if (cell == NULL) {
goto error;
}
/* If it is an arg then copy the arg into the cell. */
if (co->co_cell2arg != NULL) {
int argoffset = co->co_cell2arg[oparg - co->co_nlocals];
if (argoffset != CO_CELL_NOT_AN_ARG) {
PyObject *arg = GETLOCAL(argoffset);
// It will have been set in initialize_locals().
assert(arg != NULL);
Py_INCREF(arg);
PyCell_SET(cell, arg);
/* Clear the local copy. */
SETLOCAL(argoffset, NULL);
}
}
SETLOCAL(oparg, cell);
DISPATCH();
}

case TARGET(DELETE_DEREF): {
PyObject *cell = GETLOCAL(oparg);
PyObject *oldobj = PyCell_GET(cell);
Expand Down Expand Up @@ -5072,27 +5095,6 @@ initialize_locals(PyThreadState *tstate, PyFrameConstructor *con,
}
}


/* Allocate and initialize storage for cell vars, and copy free
vars into frame. */
for (i = 0; i < co->co_ncellvars; ++i) {
PyObject *c;
Py_ssize_t arg;
/* Possibly account for the cell variable being an argument. */
if (co->co_cell2arg != NULL &&
(arg = co->co_cell2arg[i]) != CO_CELL_NOT_AN_ARG) {
c = PyCell_New(GETLOCAL(arg));
/* Clear the local copy. */
SETLOCAL(arg, NULL);
}
else {
c = PyCell_New(NULL);
}
if (c == NULL)
goto fail;
SETLOCAL(co->co_nlocals + i, c);
}

/* Copy closure variables to free variables */
for (i = 0; i < co->co_nfreevars; ++i) {
PyObject *o = PyTuple_GET_ITEM(con->fc_closure, i);
Expand Down
1 change: 1 addition & 0 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -7474,6 +7474,7 @@ offset_derefs(basicblock *entryblock, int nlocals)
for (int i = 0; i < b->b_iused; i++) {
struct instr *inst = &b->b_instr[i];
switch(inst->i_opcode) {
case MAKE_CELL:
case LOAD_CLOSURE:
case LOAD_DEREF:
case STORE_DEREF:
Expand Down
2 changes: 1 addition & 1 deletion Python/importlib.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions Python/importlib_external.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0