From 29139c0a44dbc06e91f511c7c841b9e9e8a5d394 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 19 May 2022 19:33:39 +0100 Subject: [PATCH 1/3] remove compiler_check_if_end_of_block. The check can be done in compiler_use_new_implicit_block_if_needed insted (for the last instr in the block) --- Python/compile.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index c862c10a83e53c..4e149f7f2c3431 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -264,6 +264,15 @@ typedef struct basicblock_ { unsigned b_return : 1; } basicblock; + +static struct instr * +basicblock_last_instr(basicblock *b) { + if (b->b_iused) { + return &b->b_instr[b->b_iused - 1]; + } + return NULL; +} + /* fblockinfo tracks the current frame block. A frame block is used to handle loops, try/except, and try/finally. @@ -331,9 +340,6 @@ struct compiler_unit { int u_col_offset; /* the offset of the current stmt */ int u_end_lineno; /* the end line of the current stmt */ int u_end_col_offset; /* the end offset of the current stmt */ - - /* true if we need to create an implicit basicblock before the next instr */ - int u_need_new_implicit_block; }; /* This struct captures the global state of a compilation. @@ -830,7 +836,6 @@ compiler_use_next_block(struct compiler *c, basicblock *block) assert(block != NULL); c->u->u_curblock->b_next = block; c->u->u_curblock = block; - c->u->u_need_new_implicit_block = 0; return block; } @@ -1206,7 +1211,8 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg) return stack_effect(opcode, oparg, -1); } -static int is_end_of_basic_block(struct instr *instr) +static int +is_end_of_basic_block(struct instr *instr) { int opcode = instr->i_opcode; @@ -1219,7 +1225,8 @@ static int is_end_of_basic_block(struct instr *instr) static int compiler_use_new_implicit_block_if_needed(struct compiler *c) { - if (c->u->u_need_new_implicit_block) { + basicblock *b = c->u->u_curblock; + if (b->b_iused && is_end_of_basic_block(basicblock_last_instr(b))) { basicblock *b = compiler_new_block(c); if (b == NULL) { return -1; @@ -1229,14 +1236,6 @@ compiler_use_new_implicit_block_if_needed(struct compiler *c) return 0; } -static void -compiler_check_if_end_of_block(struct compiler *c, struct instr *instr) -{ - if (is_end_of_basic_block(instr)) { - c->u->u_need_new_implicit_block = 1; - } -} - /* Add an opcode with no argument. Returns 0 on failure, 1 on success. */ @@ -1269,7 +1268,6 @@ compiler_addop_line(struct compiler *c, int opcode, int line, i->i_col_offset = col_offset; i->i_end_col_offset = end_col_offset; - compiler_check_if_end_of_block(c, i); return 1; } @@ -1511,7 +1509,6 @@ compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg, i->i_col_offset = col_offset; i->i_end_col_offset = end_col_offset; - compiler_check_if_end_of_block(c, i); return 1; } @@ -1556,7 +1553,6 @@ static int add_jump_to_block(struct compiler *c, int opcode, i->i_col_offset = col_offset; i->i_end_col_offset = end_col_offset; - compiler_check_if_end_of_block(c, i); return 1; } From 302214dbcff9ca1cfa522ed7566fc47c1397a124 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 20 May 2022 10:54:25 +0100 Subject: [PATCH 2/3] refactor functions that add instructions so that they work on a basicblock rather than taking a compiler struct ptr. Rename them to basicblock_add_* --- Python/compile.c | 74 +++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 4e149f7f2c3431..3b285d77a63962 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1241,18 +1241,13 @@ compiler_use_new_implicit_block_if_needed(struct compiler *c) */ static int -compiler_addop_line(struct compiler *c, int opcode, int line, - int end_line, int col_offset, int end_col_offset) +basicblock_addop_line(basicblock *b, int opcode, int line, + int end_line, int col_offset, int end_col_offset) { assert(IS_WITHIN_OPCODE_RANGE(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(!HAS_ARG(opcode) || IS_ARTIFICIAL(opcode)); - if (compiler_use_new_implicit_block_if_needed(c) < 0) { - return -1; - } - - basicblock *b = c->u->u_curblock; int off = compiler_next_instr(b); if (off < 0) { return 0; @@ -1274,14 +1269,20 @@ compiler_addop_line(struct compiler *c, int opcode, int line, static int compiler_addop(struct compiler *c, int opcode) { - return compiler_addop_line(c, opcode, c->u->u_lineno, c->u->u_end_lineno, - c->u->u_col_offset, c->u->u_end_col_offset); + if (compiler_use_new_implicit_block_if_needed(c) < 0) { + return -1; + } + return basicblock_addop_line(c->u->u_curblock, opcode, c->u->u_lineno, c->u->u_end_lineno, + c->u->u_col_offset, c->u->u_end_col_offset); } static int compiler_addop_noline(struct compiler *c, int opcode) { - return compiler_addop_line(c, opcode, -1, 0, 0, 0); + if (compiler_use_new_implicit_block_if_needed(c) < 0) { + return -1; + } + return basicblock_addop_line(c->u->u_curblock, opcode, -1, 0, 0, 0); } @@ -1475,9 +1476,9 @@ compiler_addop_name(struct compiler *c, int opcode, PyObject *dict, */ static int -compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg, - int lineno, int end_lineno, - int col_offset, int end_col_offset) +basicblock_addop_i_line(basicblock *b, int opcode, Py_ssize_t oparg, + int lineno, int end_lineno, + int col_offset, int end_col_offset) { /* oparg value is unsigned, but a signed C int is usually used to store it in the C code (like Python/ceval.c). @@ -1492,11 +1493,6 @@ compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg, assert(HAS_ARG(opcode)); assert(0 <= oparg && oparg <= 2147483647); - if (compiler_use_new_implicit_block_if_needed(c) < 0) { - return -1; - } - - basicblock *b = c->u->u_curblock; int off = compiler_next_instr(b); if (off < 0) { return 0; @@ -1515,32 +1511,34 @@ compiler_addop_i_line(struct compiler *c, int opcode, Py_ssize_t oparg, static int compiler_addop_i(struct compiler *c, int opcode, Py_ssize_t oparg) { - return compiler_addop_i_line(c, opcode, oparg, - c->u->u_lineno, c->u->u_end_lineno, - c->u->u_col_offset, c->u->u_end_col_offset); + if (compiler_use_new_implicit_block_if_needed(c) < 0) { + return -1; + } + return basicblock_addop_i_line(c->u->u_curblock, opcode, oparg, + c->u->u_lineno, c->u->u_end_lineno, + c->u->u_col_offset, c->u->u_end_col_offset); } static int compiler_addop_i_noline(struct compiler *c, int opcode, Py_ssize_t oparg) { - return compiler_addop_i_line(c, opcode, oparg, -1, 0, 0, 0); + if (compiler_use_new_implicit_block_if_needed(c) < 0) { + return -1; + } + return basicblock_addop_i_line(c->u->u_curblock, opcode, oparg, -1, 0, 0, 0); } -static int add_jump_to_block(struct compiler *c, int opcode, - int lineno, int end_lineno, - int col_offset, int end_col_offset, - basicblock *target) +static int +basicblock_add_jump(basicblock *b, int opcode, + int lineno, int end_lineno, + int col_offset, int end_col_offset, + basicblock *target) { assert(IS_WITHIN_OPCODE_RANGE(opcode)); assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(HAS_ARG(opcode) || IS_VIRTUAL_OPCODE(opcode)); assert(target != NULL); - if (compiler_use_new_implicit_block_if_needed(c) < 0) { - return -1; - } - - basicblock *b = c->u->u_curblock; int off = compiler_next_instr(b); struct instr *i = &b->b_instr[off]; if (off < 0) { @@ -1559,15 +1557,21 @@ static int add_jump_to_block(struct compiler *c, int opcode, static int compiler_addop_j(struct compiler *c, int opcode, basicblock *b) { - return add_jump_to_block(c, opcode, c->u->u_lineno, - c->u->u_end_lineno, c->u->u_col_offset, - c->u->u_end_col_offset, b); + if (compiler_use_new_implicit_block_if_needed(c) < 0) { + return -1; + } + return basicblock_add_jump(c->u->u_curblock, opcode, c->u->u_lineno, + c->u->u_end_lineno, c->u->u_col_offset, + c->u->u_end_col_offset, b); } static int compiler_addop_j_noline(struct compiler *c, int opcode, basicblock *b) { - return add_jump_to_block(c, opcode, -1, 0, 0, 0, b); + if (compiler_use_new_implicit_block_if_needed(c) < 0) { + return -1; + } + return basicblock_add_jump(c->u->u_curblock, opcode, -1, 0, 0, 0, b); } #define ADDOP(C, OP) { \ From 4dc974675d01899bbb0b2e536ec306a2cf49b6a0 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 20 May 2022 11:33:22 +0100 Subject: [PATCH 3/3] rename compiler_next_instr --> basicblock_next_instr --- Python/compile.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 3b285d77a63962..b403f8c30ac4d8 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -395,10 +395,11 @@ typedef struct { Py_ssize_t on_top; } pattern_context; +static int basicblock_next_instr(basicblock *); + static int compiler_enter_scope(struct compiler *, identifier, int, void *, int); static void compiler_free(struct compiler *); static basicblock *compiler_new_block(struct compiler *); -static int compiler_next_instr(basicblock *); static int compiler_addop(struct compiler *, int); static int compiler_addop_i(struct compiler *, int, Py_ssize_t); static int compiler_addop_j(struct compiler *, int, basicblock *); @@ -851,7 +852,7 @@ compiler_copy_block(struct compiler *c, basicblock *block) return NULL; } for (int i = 0; i < block->b_iused; i++) { - int n = compiler_next_instr(result); + int n = basicblock_next_instr(result); if (n < 0) { return NULL; } @@ -868,7 +869,7 @@ compiler_copy_block(struct compiler *c, basicblock *block) */ static int -compiler_next_instr(basicblock *b) +basicblock_next_instr(basicblock *b) { assert(b != NULL); if (b->b_instr == NULL) { @@ -1248,7 +1249,7 @@ basicblock_addop_line(basicblock *b, int opcode, int line, assert(!IS_ASSEMBLER_OPCODE(opcode)); assert(!HAS_ARG(opcode) || IS_ARTIFICIAL(opcode)); - int off = compiler_next_instr(b); + int off = basicblock_next_instr(b); if (off < 0) { return 0; } @@ -1493,7 +1494,7 @@ basicblock_addop_i_line(basicblock *b, int opcode, Py_ssize_t oparg, assert(HAS_ARG(opcode)); assert(0 <= oparg && oparg <= 2147483647); - int off = compiler_next_instr(b); + int off = basicblock_next_instr(b); if (off < 0) { return 0; } @@ -1539,7 +1540,7 @@ basicblock_add_jump(basicblock *b, int opcode, assert(HAS_ARG(opcode) || IS_VIRTUAL_OPCODE(opcode)); assert(target != NULL); - int off = compiler_next_instr(b); + int off = basicblock_next_instr(b); struct instr *i = &b->b_instr[off]; if (off < 0) { return 0; @@ -8091,7 +8092,7 @@ build_cellfixedoffsets(struct compiler *c) static inline int insert_instruction(basicblock *block, int pos, struct instr *instr) { - if (compiler_next_instr(block) < 0) { + if (basicblock_next_instr(block) < 0) { return -1; } for (int i = block->b_iused-1; i > pos; i--) { @@ -8977,7 +8978,7 @@ extend_block(basicblock *bb) { basicblock *to_copy = last->i_target; last->i_opcode = NOP; for (int i = 0; i < to_copy->b_iused; i++) { - int index = compiler_next_instr(bb); + int index = basicblock_next_instr(bb); if (index < 0) { return -1; }