Visitar URL original
gh-87092: refactor assemble() to a number of separate functions, which do not need the compiler struct by iritkatriel · Pull Request #102562 · python/cpython · GitHub
Skip to content
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
extract optimize_code_unit() out of assemble()
  • Loading branch information
iritkatriel committed Mar 9, 2023
commit dbf22d19693310f74951f388529bd70431aba2f2
125 changes: 58 additions & 67 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,14 @@ instr_sequence_to_cfg(instr_sequence *seq, cfg_builder *g) {
instruction *instr = &seq->s_instrs[i];
RETURN_IF_ERROR(cfg_builder_addop(g, instr->i_opcode, instr->i_oparg, instr->i_loc));
}
int nblocks = 0;
for (basicblock *b = g->g_block_list; b != NULL; b = b->b_list) {
nblocks++;
}
if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) {
PyErr_NoMemory();
return ERROR;
}
return SUCCESS;
}

Expand Down Expand Up @@ -937,6 +945,7 @@ dictbytype(PyObject *src, int scope_type, int flag, Py_ssize_t offset)
static bool
cfg_builder_check(cfg_builder *g)
{
assert(g->g_entryblock->b_iused > 0);
for (basicblock *block = g->g_block_list; block != NULL; block = block->b_list) {
assert(!_PyMem_IsPtrFreed(block));
if (block->b_instr != NULL) {
Expand Down Expand Up @@ -8636,6 +8645,40 @@ add_return_at_end(struct compiler *c, int addNone)
return SUCCESS;
}

static int
optimize_code_unit(struct compiler_unit *u, cfg_builder *g, PyObject *consts,
PyObject *const_cache, int code_flags)
{
assert(cfg_builder_check(g));
/** Preprocessing **/
/* Set firstlineno if it wasn't explicitly set. */
if (!u->u_firstlineno) {
if (g->g_entryblock->b_instr && g->g_entryblock->b_instr->i_loc.lineno) {
u->u_firstlineno = g->g_entryblock->b_instr->i_loc.lineno;
}
else {
u->u_firstlineno = 1;
}
}
/* Map labels to targets and mark exception handlers */
RETURN_IF_ERROR(translate_jump_labels_to_targets(g->g_entryblock));
RETURN_IF_ERROR(mark_except_handlers(g->g_entryblock));
RETURN_IF_ERROR(label_exception_targets(g->g_entryblock));

/** Optimization **/
RETURN_IF_ERROR(optimize_cfg(g, consts, const_cache));
RETURN_IF_ERROR(remove_unused_consts(g->g_entryblock, consts));
RETURN_IF_ERROR(add_checks_for_loads_of_uninitialized_variables(g->g_entryblock, u));

/** line numbers */
RETURN_IF_ERROR(duplicate_exits_without_lineno(g));
propagate_line_numbers(g->g_entryblock);
guarantee_lineno_for_exits(g->g_entryblock, u->u_firstlineno);

RETURN_IF_ERROR(push_cold_blocks_to_end(g, code_flags));
return SUCCESS;
}

static PyCodeObject *
assemble(struct compiler *c, int addNone)
{
Expand All @@ -8644,9 +8687,6 @@ assemble(struct compiler *c, int addNone)
PyObject *filename = c->c_filename;

PyCodeObject *co = NULL;
PyObject *consts = NULL;
cfg_builder g_;
cfg_builder *g = &g_;
struct assembler a;
memset(&a, 0, sizeof(struct assembler));

Expand All @@ -8659,100 +8699,51 @@ assemble(struct compiler *c, int addNone)
return NULL;
}

/** Preprocessing **/
if (instr_sequence_to_cfg(INSTR_SEQUENCE(c), g) < 0) {
goto error;
}
assert(cfg_builder_check(g));

int nblocks = 0;
for (basicblock *b = g->g_block_list; b != NULL; b = b->b_list) {
nblocks++;
}
if ((size_t)nblocks > SIZE_MAX / sizeof(basicblock *)) {
PyErr_NoMemory();
goto error;
}

/* Set firstlineno if it wasn't explicitly set. */
if (!u->u_firstlineno) {
if (g->g_entryblock->b_instr && g->g_entryblock->b_instr->i_loc.lineno) {
u->u_firstlineno = g->g_entryblock->b_instr->i_loc.lineno;
}
else {
u->u_firstlineno = 1;
}
}

/* Map labels to targets and mark exception handlers */
if (translate_jump_labels_to_targets(g->g_entryblock) < 0) {
goto error;
}
if (mark_except_handlers(g->g_entryblock) < 0) {
goto error;
}
if (label_exception_targets(g->g_entryblock)) {
goto error;
}

/** Optimization **/
consts = consts_dict_keys_inorder(u->u_consts);
PyObject *consts = consts_dict_keys_inorder(u->u_consts);
if (consts == NULL) {
goto error;
}
if (optimize_cfg(g, consts, const_cache)) {
goto error;
}
if (remove_unused_consts(g->g_entryblock, consts) < 0) {
goto error;
}
if (add_checks_for_loads_of_uninitialized_variables(g->g_entryblock, u) < 0) {
goto error;
}

/** line numbers (TODO: move this before optimization stage) */
if (duplicate_exits_without_lineno(g) < 0) {
cfg_builder g;
if (instr_sequence_to_cfg(INSTR_SEQUENCE(c), &g) < 0) {
goto error;
}
propagate_line_numbers(g->g_entryblock);
guarantee_lineno_for_exits(g->g_entryblock, u->u_firstlineno);

if (push_cold_blocks_to_end(g, code_flags) < 0) {
if (optimize_code_unit(u, &g, consts, const_cache, code_flags) < 0) {
goto error;
}

/** Assembly **/

int nlocalsplus = prepare_localsplus(u, g, code_flags);
int nlocalsplus = prepare_localsplus(u, &g, code_flags);
if (nlocalsplus < 0) {
goto error;
}

int maxdepth = stackdepth(g->g_entryblock, code_flags);
int maxdepth = stackdepth(g.g_entryblock, code_flags);
if (maxdepth < 0) {
goto error;
}
/* TO DO -- For 3.12, make sure that `maxdepth <= MAX_ALLOWED_STACK_USE` */

convert_exception_handlers_to_nops(g->g_entryblock);
convert_exception_handlers_to_nops(g.g_entryblock);

/* Order of basic blocks must have been determined by now */
if (normalize_jumps(g) < 0) {
if (normalize_jumps(&g) < 0) {
goto error;
}
assert(no_redundant_jumps(g));
assert(opcode_metadata_is_sane(g));
assert(no_redundant_jumps(&g));
assert(opcode_metadata_is_sane(&g));

/* Can't modify the bytecode after computing jump offsets. */
assemble_jump_offsets(g->g_entryblock);
assemble_jump_offsets(g.g_entryblock);

/* Create assembler */
if (assemble_init(&a, u->u_firstlineno) < 0) {
goto error;
}

/* Emit code. */
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
for (basicblock *b = g.g_entryblock; b != NULL; b = b->b_next) {
for (int j = 0; j < b->b_iused; j++) {
if (assemble_emit(&a, &b->b_instr[j]) < 0) {
goto error;
Expand All @@ -8764,7 +8755,7 @@ assemble(struct compiler *c, int addNone)
a.a_lineno = u->u_firstlineno;
location loc = NO_LOCATION;
int size = 0;
for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) {
for (basicblock *b = g.g_entryblock; b != NULL; b = b->b_next) {
for (int j = 0; j < b->b_iused; j++) {
if (!same_location(loc, b->b_instr[j].i_loc)) {
if (assemble_emit_location(&a, loc, size)) {
Expand All @@ -8780,7 +8771,7 @@ assemble(struct compiler *c, int addNone)
goto error;
}

if (assemble_exception_table(&a, g->g_entryblock) < 0) {
if (assemble_exception_table(&a, g.g_entryblock) < 0) {
goto error;
}
if (_PyBytes_Resize(&a.a_except_table, a.a_except_table_off) < 0) {
Expand All @@ -8807,7 +8798,7 @@ assemble(struct compiler *c, int addNone)
co = makecode(u, &a, const_cache, consts, maxdepth, nlocalsplus, code_flags, filename);
error:
Py_XDECREF(consts);
cfg_builder_fini(g);
cfg_builder_fini(&g);
assemble_free(&a);
return co;
}
Expand Down