From ba5e5567b550c71d8915a413b0c0e6c5ce00b614 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Mon, 12 Sep 2022 14:35:55 +0100 Subject: [PATCH 1/6] add b_except_handler, calculated seprately from reachability --- Python/compile.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 777190526d2575..fd7c9a54793dec 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -270,6 +270,8 @@ typedef struct basicblock_ { unsigned b_preserve_lasti : 1; /* Used by compiler passes to mark whether they have visited a basic block. */ unsigned b_visited : 1; + /* b_except_handler is used by the cold-detection algorithm to mark exception targets */ + unsigned b_except_handler : 1; /* b_cold is true if this block is not perf critical (like an exception handler) */ unsigned b_cold : 1; /* b_warm is used by the cold-detection algorithm to mark blocks which are definitely not cold */ @@ -7296,6 +7298,23 @@ label_exception_targets(basicblock *entryblock) { return -1; } + +static int +mark_except_handlers(basicblock *entryblock) { + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + assert(!b->b_except_handler); + } + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + for (int i=0; i < b->b_iused; i++) { + struct instr *instr = &b->b_instr[i]; + if (is_block_push(instr)) { + instr->i_target->b_except_handler = 1; + } + } + } + return 0; +} + static int mark_warm(basicblock *entryblock) { basicblock **stack = make_cfg_traversal_stack(entryblock); @@ -8257,8 +8276,8 @@ static void dump_basicblock(const basicblock *b) { const char *b_return = basicblock_returns(b) ? "return " : ""; - fprintf(stderr, "%d: [%d %d %d %p] used: %d, depth: %d, offset: %d %s\n", - b->b_label, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused, + fprintf(stderr, "%d: [P=%d EP=%d EH=%d CLD=%d WRM=%d %d %p] used: %d, depth: %d, offset: %d %s\n", + b->b_label, b->b_predecessors, b->b_except_predecessors, b->b_except_handler, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused, b->b_startdepth, b->b_offset, b_return); if (b->b_instr) { int i; @@ -9361,6 +9380,10 @@ mark_reachable(basicblock *entryblock) { } } } + for (basicblock *b = entryblock; b != NULL; b = b->b_next) { + if (b->b_except_predecessors) assert(b->b_except_handler); + if (b->b_predecessors > b->b_except_predecessors) assert(!b->b_except_handler); + } PyMem_Free(stack); return 0; } @@ -9504,12 +9527,16 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache) } remove_redundant_nops(b); assert(b->b_predecessors == 0); + assert(b->b_except_predecessors == 0); } for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { if (inline_small_exit_blocks(b) < 0) { return -1; } } + if (mark_except_handlers(g->g_entryblock) < 0) { + return -1; + } if (mark_reachable(g->g_entryblock)) { return -1; } From a5bef755eb7102c93d2ed08816bb5088d8639567 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 13 Sep 2022 16:40:17 +0100 Subject: [PATCH 2/6] remove b_except_predecessors --- Python/compile.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index fd7c9a54793dec..c3dc8e369432d5 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -260,8 +260,6 @@ typedef struct basicblock_ { int b_ialloc; /* Number of predecssors that a block has. */ int b_predecessors; - /* Number of predecssors that a block has as an exception handler. */ - int b_except_predecessors; /* depth of stack upon entry of block, computed by stackdepth() */ int b_startdepth; /* instruction offset for block, computed by assemble_jump_offsets() */ @@ -7327,7 +7325,7 @@ mark_warm(basicblock *entryblock) { entryblock->b_visited = 1; while (sp > stack) { basicblock *b = *(--sp); - assert(!b->b_except_predecessors); + assert(!b->b_except_handler); b->b_warm = 1; basicblock *next = b->b_next; if (next && BB_HAS_FALLTHROUGH(b) && !next->b_visited) { @@ -7362,8 +7360,7 @@ mark_cold(basicblock *entryblock) { basicblock **sp = stack; for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - if (b->b_except_predecessors) { - assert(b->b_except_predecessors == b->b_predecessors); + if (b->b_except_handler) { assert(!b->b_warm); *sp++ = b; b->b_visited = 1; @@ -8276,8 +8273,8 @@ static void dump_basicblock(const basicblock *b) { const char *b_return = basicblock_returns(b) ? "return " : ""; - fprintf(stderr, "%d: [P=%d EP=%d EH=%d CLD=%d WRM=%d %d %p] used: %d, depth: %d, offset: %d %s\n", - b->b_label, b->b_predecessors, b->b_except_predecessors, b->b_except_handler, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused, + fprintf(stderr, "%d: [EH=%d CLD=%d WRM=%d NO_FT=%d %p] used: %d, depth: %d, offset: %d %s\n", + b->b_label, b->b_except_handler, b->b_cold, b->b_warm, BB_NO_FALLTHROUGH(b), b, b->b_iused, b->b_startdepth, b->b_offset, b_return); if (b->b_instr) { int i; @@ -9372,18 +9369,9 @@ mark_reachable(basicblock *entryblock) { *sp++ = target; } target->b_predecessors++; - if (is_block_push(instr)) { - target->b_except_predecessors++; - } - assert(target->b_except_predecessors == 0 || - target->b_except_predecessors == target->b_predecessors); } } } - for (basicblock *b = entryblock; b != NULL; b = b->b_next) { - if (b->b_except_predecessors) assert(b->b_except_handler); - if (b->b_predecessors > b->b_except_predecessors) assert(!b->b_except_handler); - } PyMem_Free(stack); return 0; } @@ -9527,7 +9515,6 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache) } remove_redundant_nops(b); assert(b->b_predecessors == 0); - assert(b->b_except_predecessors == 0); } for (basicblock *b = g->g_entryblock; b != NULL; b = b->b_next) { if (inline_small_exit_blocks(b) < 0) { From dd2b3f367bdce896ea5cead4bfd584c5251326dc Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 13 Sep 2022 22:01:18 +0100 Subject: [PATCH 3/6] move mark_except_handler to before cfg optimizations --- Python/compile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index c3dc8e369432d5..6705aab8b3cef1 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -8632,6 +8632,9 @@ assemble(struct compiler *c, int addNone) if (calculate_jump_targets(g->g_entryblock)) { goto error; } + if (mark_except_handlers(g->g_entryblock) < 0) { + goto error; + } if (optimize_cfg(g, consts, c->c_const_cache)) { goto error; } @@ -9521,9 +9524,6 @@ optimize_cfg(cfg_builder *g, PyObject *consts, PyObject *const_cache) return -1; } } - if (mark_except_handlers(g->g_entryblock) < 0) { - return -1; - } if (mark_reachable(g->g_entryblock)) { return -1; } From d5ab8121e3dea597894c3a7ff59fea013347f9e4 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 13 Sep 2022 22:48:59 +0100 Subject: [PATCH 4/6] move label_exception_targets to before cfg optimizations --- Python/compile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 6705aab8b3cef1..525b14b36c324c 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -8635,6 +8635,9 @@ assemble(struct compiler *c, int addNone) if (mark_except_handlers(g->g_entryblock) < 0) { goto error; } + if (label_exception_targets(g->g_entryblock)) { + goto error; + } if (optimize_cfg(g, consts, c->c_const_cache)) { goto error; } @@ -8653,9 +8656,6 @@ assemble(struct compiler *c, int addNone) } /* TO DO -- For 3.12, make sure that `maxdepth <= MAX_ALLOWED_STACK_USE` */ - if (label_exception_targets(g->g_entryblock)) { - goto error; - } convert_exception_handlers_to_nops(g->g_entryblock); if (push_cold_blocks_to_end(g, code_flags) < 0) { From a3b4a33b23fb6e20e7a1669faa7f96f93560bb32 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Tue, 20 Sep 2022 09:56:17 +0100 Subject: [PATCH 5/6] typo in comment Co-authored-by: Shantanu <12621235+hauntsaninja@users.noreply.github.com> --- Python/compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/compile.c b/Python/compile.c index 525b14b36c324c..d7bfb9359060ae 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -258,7 +258,7 @@ typedef struct basicblock_ { int b_iused; /* length of instruction array (b_instr) */ int b_ialloc; - /* Number of predecssors that a block has. */ + /* Number of predecessors that a block has. */ int b_predecessors; /* depth of stack upon entry of block, computed by stackdepth() */ int b_startdepth; From 280214592a46cae91cde1170070208baad96eae3 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 20 Sep 2022 10:02:52 +0100 Subject: [PATCH 6/6] asserts under #ifndef NDEBUG --- Python/compile.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Python/compile.c b/Python/compile.c index d7bfb9359060ae..1f1ef56e7b1b07 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -7299,9 +7299,11 @@ label_exception_targets(basicblock *entryblock) { static int mark_except_handlers(basicblock *entryblock) { +#ifndef NDEBUG for (basicblock *b = entryblock; b != NULL; b = b->b_next) { assert(!b->b_except_handler); } +#endif for (basicblock *b = entryblock; b != NULL; b = b->b_next) { for (int i=0; i < b->b_iused; i++) { struct instr *instr = &b->b_instr[i];