summaryrefslogtreecommitdiffstats
path: root/Python/compile.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2021-06-08 22:01:34 (GMT)
committerGitHub <noreply@github.com>2021-06-08 22:01:34 (GMT)
commit3e1c7167d86a2a928cdcb659094aa10bb5550c4c (patch)
treeb3b071ff5636c7c5edd8d536b8732c6a2259a44c /Python/compile.c
parentab36b9f83424a020fbd672f218612e6f19257a32 (diff)
downloadcpython-3e1c7167d86a2a928cdcb659094aa10bb5550c4c.zip
cpython-3e1c7167d86a2a928cdcb659094aa10bb5550c4c.tar.gz
cpython-3e1c7167d86a2a928cdcb659094aa10bb5550c4c.tar.bz2
bpo-43693: Un-revert commit f3fa63e. (#26609)
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
Diffstat (limited to 'Python/compile.c')
-rw-r--r--Python/compile.c72
1 files changed, 53 insertions, 19 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 37d5105..c97938a 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1185,6 +1185,8 @@ stack_effect(int opcode, int oparg, int jump)
return -1;
/* Closures */
+ case MAKE_CELL:
+ return 0;
case LOAD_CLOSURE:
return 1;
case LOAD_DEREF:
@@ -7374,15 +7376,47 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts);
static int
ensure_exits_have_lineno(struct compiler *c);
+static inline int
+insert_instruction(basicblock *block, int pos, struct instr *instr) {
+ if (compiler_next_instr(block) < 0) {
+ return -1;
+ }
+ for (int i = block->b_iused-1; i > pos; i--) {
+ block->b_instr[i] = block->b_instr[i-1];
+ }
+ block->b_instr[pos] = *instr;
+ return 0;
+}
+
static int
-insert_generator_prefix(struct compiler *c, basicblock *entryblock) {
+insert_prefix_instructions(struct compiler *c, basicblock *entryblock) {
int flags = compute_code_flags(c);
if (flags < 0) {
return -1;
}
- int kind;
+
+ /* Set up cells for any variable that escapes, to be put in a closure. */
+ PyObject *k, *v;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(c->u->u_cellvars, &pos, &k, &v)) {
+ assert(PyLong_AS_LONG(v) < INT_MAX);
+ int cellindex = (int)PyLong_AS_LONG(v);
+ struct instr make_cell = {
+ .i_opcode = MAKE_CELL,
+ // This will get fixed in offset_derefs().
+ .i_oparg = cellindex,
+ .i_lineno = -1,
+ .i_target = NULL,
+ };
+ if (insert_instruction(entryblock, (int)(pos - 1), &make_cell) < 0) {
+ return -1;
+ }
+ }
+
+ /* Add the generator prefix instructions. */
if (flags & (CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR)) {
+ int kind;
if (flags & CO_COROUTINE) {
kind = 1;
}
@@ -7392,20 +7426,18 @@ insert_generator_prefix(struct compiler *c, basicblock *entryblock) {
else {
kind = 0;
}
+
+ struct instr gen_start = {
+ .i_opcode = GEN_START,
+ .i_oparg = kind,
+ .i_lineno = -1,
+ .i_target = NULL,
+ };
+ if (insert_instruction(entryblock, 0, &gen_start) < 0) {
+ return -1;
+ }
}
- else {
- return 0;
- }
- if (compiler_next_instr(entryblock) < 0) {
- return -1;
- }
- for (int i = entryblock->b_iused-1; i > 0; i--) {
- entryblock->b_instr[i] = entryblock->b_instr[i-1];
- }
- entryblock->b_instr[0].i_opcode = GEN_START;
- entryblock->b_instr[0].i_oparg = kind;
- entryblock->b_instr[0].i_lineno = -1;
- entryblock->b_instr[0].i_target = NULL;
+
return 0;
}
@@ -7438,12 +7470,15 @@ guarantee_lineno_for_exits(struct assembler *a, int firstlineno) {
}
static void
-offset_derefs(basicblock *entryblock, int nlocals)
+fix_cell_offsets(struct compiler *c, basicblock *entryblock)
{
+ assert(PyDict_GET_SIZE(c->u->u_varnames) < INT_MAX);
+ int nlocals = (int)PyDict_GET_SIZE(c->u->u_varnames);
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 MAKE_CELL:
case LOAD_CLOSURE:
case LOAD_DEREF:
case STORE_DEREF:
@@ -7493,7 +7528,7 @@ assemble(struct compiler *c, int addNone)
}
assert(entryblock != NULL);
- if (insert_generator_prefix(c, entryblock)) {
+ if (insert_prefix_instructions(c, entryblock)) {
goto error;
}
@@ -7510,8 +7545,7 @@ 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));
+ fix_cell_offsets(c, entryblock);
consts = consts_dict_keys_inorder(c->u->u_consts);
if (consts == NULL) {