Skip to content

bpo-39151: Simplify dfs in the assembler #17733

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 5 commits into from
Jun 28, 2020
Merged
Changes from all commits
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
51 changes: 18 additions & 33 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,6 @@ typedef struct basicblock_ {
/* If b_next is non-NULL, it is a pointer to the next
block reached by normal control flow. */
struct basicblock_ *b_next;
/* b_seen is used to perform a DFS of basicblocks. */
unsigned b_seen : 1;
/* b_return is true if a RETURN_VALUE opcode is inserted. */
unsigned b_return : 1;
/* depth of stack upon entry of block, computed by stackdepth() */
Expand Down Expand Up @@ -5437,7 +5435,7 @@ struct assembler {
PyObject *a_bytecode; /* string containing bytecode */
int a_offset; /* offset into bytecode */
int a_nblocks; /* number of reachable blocks */
basicblock **a_postorder; /* list of blocks in dfs postorder */
basicblock **a_reverse_postorder; /* list of blocks in dfs postorder */
PyObject *a_lnotab; /* string containing lnotab */
int a_lnotab_off; /* offset into lnotab */
int a_lineno; /* last lineno of emitted instruction */
Expand All @@ -5447,26 +5445,14 @@ struct assembler {
static void
dfs(struct compiler *c, basicblock *b, struct assembler *a, int end)
{
int i, j;

/* Get rid of recursion for normal control flow.
Since the number of blocks is limited, unused space in a_postorder
(from a_nblocks to end) can be used as a stack for still not ordered
blocks. */
for (j = end; b && !b->b_seen; b = b->b_next) {
b->b_seen = 1;
assert(a->a_nblocks < j);
a->a_postorder[--j] = b;
}
while (j < end) {
b = a->a_postorder[j++];
for (i = 0; i < b->b_iused; i++) {
struct instr *instr = &b->b_instr[i];
if (instr->i_jrel || instr->i_jabs)
dfs(c, instr->i_target, a, j);
}
assert(a->a_nblocks < j);
a->a_postorder[a->a_nblocks++] = b;
/* There is no real depth-first-search to do here because all the
* blocks are emitted in topological order already, so we just need to
* follow the b_next pointers and place them in a->a_reverse_postorder in
* reverse order and make sure that the first one starts at 0. */

for (a->a_nblocks = 0; b != NULL; b = b->b_next) {
a->a_reverse_postorder[a->a_nblocks++] = b;
}
}

Expand Down Expand Up @@ -5567,9 +5553,9 @@ assemble_init(struct assembler *a, int nblocks, int firstlineno)
PyErr_NoMemory();
return 0;
}
a->a_postorder = (basicblock **)PyObject_Malloc(
a->a_reverse_postorder = (basicblock **)PyObject_Malloc(
sizeof(basicblock *) * nblocks);
if (!a->a_postorder) {
if (!a->a_reverse_postorder) {
PyErr_NoMemory();
return 0;
}
Expand All @@ -5581,8 +5567,8 @@ assemble_free(struct assembler *a)
{
Py_XDECREF(a->a_bytecode);
Py_XDECREF(a->a_lnotab);
if (a->a_postorder)
PyObject_Free(a->a_postorder);
if (a->a_reverse_postorder)
PyObject_Free(a->a_reverse_postorder);
}

static int
Expand Down Expand Up @@ -5743,8 +5729,8 @@ assemble_jump_offsets(struct assembler *a, struct compiler *c)
Replace block pointer with position in bytecode. */
do {
totsize = 0;
for (i = a->a_nblocks - 1; i >= 0; i--) {
b = a->a_postorder[i];
for (i = 0; i < a->a_nblocks; i++) {
b = a->a_reverse_postorder[i];
bsize = blocksize(b);
b->b_offset = totsize;
totsize += bsize;
Expand Down Expand Up @@ -5999,10 +5985,9 @@ dump_instr(const struct instr *i)
static void
dump_basicblock(const basicblock *b)
{
const char *seen = b->b_seen ? "seen " : "";
const char *b_return = b->b_return ? "return " : "";
fprintf(stderr, "used: %d, depth: %d, offset: %d %s%s\n",
b->b_iused, b->b_startdepth, b->b_offset, seen, b_return);
fprintf(stderr, "used: %d, depth: %d, offset: %d %s\n",
b->b_iused, b->b_startdepth, b->b_offset, b_return);
if (b->b_instr) {
int i;
for (i = 0; i < b->b_iused; i++) {
Expand Down Expand Up @@ -6054,8 +6039,8 @@ assemble(struct compiler *c, int addNone)
assemble_jump_offsets(&a, c);

/* Emit code in reverse postorder from dfs. */
for (i = a.a_nblocks - 1; i >= 0; i--) {
b = a.a_postorder[i];
for (i = 0; i < a.a_nblocks; i++) {
b = a.a_reverse_postorder[i];
for (j = 0; j < b->b_iused; j++)
if (!assemble_emit(&a, &b->b_instr[j]))
goto error;
Expand Down