@@ -7061,7 +7061,6 @@ struct assembler {
70617061 PyObject * a_except_table ; /* bytes containing exception table */
70627062 basicblock * a_entry ;
70637063 int a_offset ; /* offset into bytecode */
7064- int a_nblocks ; /* number of reachable blocks */
70657064 int a_except_table_off ; /* offset into exception table */
70667065 int a_prevlineno ; /* lineno of last emitted line in line table */
70677066 int a_prev_end_lineno ; /* end_lineno of last emitted line in line table */
@@ -7074,6 +7073,20 @@ struct assembler {
70747073 int a_location_off ; /* offset of last written location info frame */
70757074};
70767075
7076+ static basicblock * *
7077+ make_cfg_traversal_stack (basicblock * entry ) {
7078+ int nblocks = 0 ;
7079+ for (basicblock * b = entry ; b != NULL ; b = b -> b_next ) {
7080+ b -> b_visited = 0 ;
7081+ nblocks ++ ;
7082+ }
7083+ basicblock * * stack = (basicblock * * )PyMem_Malloc (sizeof (basicblock * ) * nblocks );
7084+ if (!stack ) {
7085+ PyErr_NoMemory ();
7086+ }
7087+ return stack ;
7088+ }
7089+
70777090Py_LOCAL_INLINE (void )
70787091stackdepth_push (basicblock * * * sp , basicblock * b , int depth )
70797092{
@@ -7089,31 +7102,26 @@ stackdepth_push(basicblock ***sp, basicblock *b, int depth)
70897102 * cycles in the flow graph have no net effect on the stack depth.
70907103 */
70917104static int
7092- stackdepth (struct compiler * c )
7105+ stackdepth (struct compiler * c , basicblock * entry )
70937106{
7094- basicblock * b , * entryblock = NULL ;
7095- basicblock * * stack , * * sp ;
7096- int nblocks = 0 , maxdepth = 0 ;
7097- for (b = c -> u -> u_blocks ; b != NULL ; b = b -> b_list ) {
7107+ for (basicblock * b = entry ; b != NULL ; b = b -> b_next ) {
70987108 b -> b_startdepth = INT_MIN ;
7099- entryblock = b ;
7100- nblocks ++ ;
71017109 }
7102- assert (entryblock != NULL );
7103- stack = (basicblock * * )PyObject_Malloc (sizeof (basicblock * ) * nblocks );
7110+ basicblock * * stack = make_cfg_traversal_stack (entry );
71047111 if (!stack ) {
7105- PyErr_NoMemory ();
71067112 return -1 ;
71077113 }
71087114
7109- sp = stack ;
7115+ int maxdepth = 0 ;
7116+ basicblock * * sp = stack ;
71107117 if (c -> u -> u_ste -> ste_generator || c -> u -> u_ste -> ste_coroutine ) {
7111- stackdepth_push (& sp , entryblock , 1 );
7118+ stackdepth_push (& sp , entry , 1 );
71127119 } else {
7113- stackdepth_push (& sp , entryblock , 0 );
7120+ stackdepth_push (& sp , entry , 0 );
71147121 }
7122+
71157123 while (sp != stack ) {
7116- b = * -- sp ;
7124+ basicblock * b = * -- sp ;
71177125 int depth = b -> b_startdepth ;
71187126 assert (depth >= 0 );
71197127 basicblock * next = b -> b_next ;
@@ -7159,7 +7167,7 @@ stackdepth(struct compiler *c)
71597167 stackdepth_push (& sp , next , depth );
71607168 }
71617169 }
7162- PyObject_Free (stack );
7170+ PyMem_Free (stack );
71637171 return maxdepth ;
71647172}
71657173
@@ -7264,14 +7272,8 @@ copy_except_stack(ExceptStack *stack) {
72647272
72657273static int
72667274label_exception_targets (basicblock * entry ) {
7267- int nblocks = 0 ;
7268- for (basicblock * b = entry ; b != NULL ; b = b -> b_next ) {
7269- b -> b_visited = 0 ;
7270- nblocks ++ ;
7271- }
7272- basicblock * * todo_stack = PyMem_Malloc (sizeof (basicblock * )* nblocks );
7275+ basicblock * * todo_stack = make_cfg_traversal_stack (entry );
72737276 if (todo_stack == NULL ) {
7274- PyErr_NoMemory ();
72757277 return -1 ;
72767278 }
72777279 ExceptStack * except_stack = make_except_stack ();
@@ -8051,7 +8053,7 @@ static int
80518053optimize_cfg (struct compiler * c , struct assembler * a , PyObject * consts );
80528054
80538055static int
8054- trim_unused_consts (struct compiler * c , struct assembler * a , PyObject * consts );
8056+ trim_unused_consts (struct assembler * a , PyObject * consts );
80558057
80568058/* Duplicates exit BBs, so that line numbers can be propagated to them */
80578059static int
@@ -8347,7 +8349,6 @@ assemble(struct compiler *c, int addNone)
83478349 if (!assemble_init (& a , nblocks , c -> u -> u_firstlineno ))
83488350 goto error ;
83498351 a .a_entry = entryblock ;
8350- a .a_nblocks = nblocks ;
83518352
83528353 int numdropped = fix_cell_offsets (c , entryblock , cellfixedoffsets );
83538354 PyMem_Free (cellfixedoffsets ); // At this point we're done with it.
@@ -8368,12 +8369,12 @@ assemble(struct compiler *c, int addNone)
83688369 if (duplicate_exits_without_lineno (c )) {
83698370 return NULL ;
83708371 }
8371- if (trim_unused_consts (c , & a , consts )) {
8372+ if (trim_unused_consts (& a , consts )) {
83728373 goto error ;
83738374 }
83748375 propagate_line_numbers (& a );
83758376 guarantee_lineno_for_exits (& a , c -> u -> u_firstlineno );
8376- int maxdepth = stackdepth (c );
8377+ int maxdepth = stackdepth (c , entryblock );
83778378 if (maxdepth < 0 ) {
83788379 goto error ;
83798380 }
@@ -9081,17 +9082,19 @@ normalize_basic_block(basicblock *bb) {
90819082
90829083static int
90839084mark_reachable (struct assembler * a ) {
9084- basicblock * * stack , * * sp ;
9085- sp = stack = (basicblock * * )PyObject_Malloc (sizeof (basicblock * ) * a -> a_nblocks );
9085+ basicblock * * stack = make_cfg_traversal_stack (a -> a_entry );
90869086 if (stack == NULL ) {
90879087 return -1 ;
90889088 }
9089+ basicblock * * sp = stack ;
90899090 a -> a_entry -> b_predecessors = 1 ;
90909091 * sp ++ = a -> a_entry ;
90919092 while (sp > stack ) {
90929093 basicblock * b = * (-- sp );
9094+ b -> b_visited = 1 ;
90939095 if (b -> b_next && !b -> b_nofallthrough ) {
9094- if (b -> b_next -> b_predecessors == 0 ) {
9096+ if (!b -> b_next -> b_visited ) {
9097+ assert (b -> b_next -> b_predecessors == 0 );
90959098 * sp ++ = b -> b_next ;
90969099 }
90979100 b -> b_next -> b_predecessors ++ ;
@@ -9101,14 +9104,15 @@ mark_reachable(struct assembler *a) {
91019104 struct instr * instr = & b -> b_instr [i ];
91029105 if (is_jump (instr ) || is_block_push (instr )) {
91039106 target = instr -> i_target ;
9104- if (target -> b_predecessors == 0 ) {
9107+ if (!target -> b_visited ) {
9108+ assert (target -> b_predecessors == 0 || target == b -> b_next );
91059109 * sp ++ = target ;
91069110 }
91079111 target -> b_predecessors ++ ;
91089112 }
91099113 }
91109114 }
9111- PyObject_Free (stack );
9115+ PyMem_Free (stack );
91129116 return 0 ;
91139117}
91149118
@@ -9128,12 +9132,15 @@ eliminate_empty_basic_blocks(basicblock *entry) {
91289132 if (b -> b_iused == 0 ) {
91299133 continue ;
91309134 }
9131- if (is_jump (& b -> b_instr [b -> b_iused - 1 ])) {
9132- basicblock * target = b -> b_instr [b -> b_iused - 1 ].i_target ;
9133- while (target -> b_iused == 0 ) {
9134- target = target -> b_next ;
9135+ for (int i = 0 ; i < b -> b_iused ; i ++ ) {
9136+ struct instr * instr = & b -> b_instr [i ];
9137+ if (is_jump (instr ) || is_block_push (instr )) {
9138+ basicblock * target = instr -> i_target ;
9139+ while (target -> b_iused == 0 ) {
9140+ target = target -> b_next ;
9141+ }
9142+ instr -> i_target = target ;
91359143 }
9136- b -> b_instr [b -> b_iused - 1 ].i_target = target ;
91379144 }
91389145 }
91399146}
@@ -9253,7 +9260,7 @@ optimize_cfg(struct compiler *c, struct assembler *a, PyObject *consts)
92539260
92549261// Remove trailing unused constants.
92559262static int
9256- trim_unused_consts (struct compiler * c , struct assembler * a , PyObject * consts )
9263+ trim_unused_consts (struct assembler * a , PyObject * consts )
92579264{
92589265 assert (PyList_CheckExact (consts ));
92599266
0 commit comments