@@ -812,6 +812,28 @@ compiler_use_next_block(struct compiler *c, basicblock *block)
812812 return block ;
813813}
814814
815+ static basicblock *
816+ compiler_copy_block (struct compiler * c , basicblock * block )
817+ {
818+ /* Cannot copy a block if it has a fallthrough, since
819+ * a block can only have one fallthrough predecessor.
820+ */
821+ assert (block -> b_nofallthrough );
822+ basicblock * result = compiler_next_block (c );
823+ if (result == NULL ) {
824+ return NULL ;
825+ }
826+ for (int i = 0 ; i < block -> b_iused ; i ++ ) {
827+ int n = compiler_next_instr (result );
828+ if (n < 0 ) {
829+ return NULL ;
830+ }
831+ result -> b_instr [n ] = block -> b_instr [i ];
832+ }
833+ result -> b_exit = block -> b_exit ;
834+ return result ;
835+ }
836+
815837/* Returns the offset of the next instruction in the current block's
816838 b_instr array. Resizes the b_instr as necessary.
817839 Returns -1 on failure.
@@ -2732,12 +2754,13 @@ compiler_if(struct compiler *c, stmt_ty s)
27322754static int
27332755compiler_for (struct compiler * c , stmt_ty s )
27342756{
2735- basicblock * start , * cleanup , * end ;
2757+ basicblock * start , * body , * cleanup , * end ;
27362758
27372759 start = compiler_new_block (c );
2760+ body = compiler_new_block (c );
27382761 cleanup = compiler_new_block (c );
27392762 end = compiler_new_block (c );
2740- if (start == NULL || end == NULL || cleanup == NULL ) {
2763+ if (start == NULL || body == NULL || end == NULL || cleanup == NULL ) {
27412764 return 0 ;
27422765 }
27432766 if (!compiler_push_fblock (c , FOR_LOOP , start , end , NULL )) {
@@ -2747,6 +2770,7 @@ compiler_for(struct compiler *c, stmt_ty s)
27472770 ADDOP (c , GET_ITER );
27482771 compiler_use_next_block (c , start );
27492772 ADDOP_JUMP (c , FOR_ITER , cleanup );
2773+ compiler_use_next_block (c , body );
27502774 VISIT (c , expr , s -> v .For .target );
27512775 VISIT_SEQ (c , stmt , s -> v .For .body );
27522776 ADDOP_JUMP (c , JUMP_ABSOLUTE , start );
@@ -5929,9 +5953,16 @@ dump_basicblock(const basicblock *b)
59295953}
59305954#endif
59315955
5956+
5957+ static int
5958+ normalize_basic_block (basicblock * bb );
5959+
59325960static int
59335961optimize_cfg (struct assembler * a , PyObject * consts );
59345962
5963+ static int
5964+ ensure_exits_have_lineno (struct compiler * c );
5965+
59355966static PyCodeObject *
59365967assemble (struct compiler * c , int addNone )
59375968{
@@ -5952,6 +5983,16 @@ assemble(struct compiler *c, int addNone)
59525983 ADDOP (c , RETURN_VALUE );
59535984 }
59545985
5986+ for (basicblock * b = c -> u -> u_blocks ; b != NULL ; b = b -> b_list ) {
5987+ if (normalize_basic_block (b )) {
5988+ goto error ;
5989+ }
5990+ }
5991+
5992+ if (ensure_exits_have_lineno (c )) {
5993+ goto error ;
5994+ }
5995+
59555996 nblocks = 0 ;
59565997 entryblock = NULL ;
59575998 for (b = c -> u -> u_blocks ; b != NULL ; b = b -> b_list ) {
@@ -5966,6 +6007,7 @@ assemble(struct compiler *c, int addNone)
59666007 else
59676008 c -> u -> u_firstlineno = 1 ;
59686009 }
6010+
59696011 if (!assemble_init (& a , nblocks , c -> u -> u_firstlineno ))
59706012 goto error ;
59716013 a .a_entry = entryblock ;
@@ -6338,7 +6380,6 @@ clean_basic_block(basicblock *bb) {
63386380 bb -> b_iused = dest ;
63396381}
63406382
6341-
63426383static int
63436384normalize_basic_block (basicblock * bb ) {
63446385 /* Mark blocks as exit and/or nofallthrough.
@@ -6349,7 +6390,8 @@ normalize_basic_block(basicblock *bb) {
63496390 case RAISE_VARARGS :
63506391 case RERAISE :
63516392 bb -> b_exit = 1 ;
6352- /* fall through */
6393+ bb -> b_nofallthrough = 1 ;
6394+ break ;
63536395 case JUMP_ABSOLUTE :
63546396 case JUMP_FORWARD :
63556397 bb -> b_nofallthrough = 1 ;
@@ -6358,16 +6400,21 @@ normalize_basic_block(basicblock *bb) {
63586400 case POP_JUMP_IF_TRUE :
63596401 case JUMP_IF_FALSE_OR_POP :
63606402 case JUMP_IF_TRUE_OR_POP :
6403+ case FOR_ITER :
63616404 if (i != bb -> b_iused - 1 ) {
63626405 PyErr_SetString (PyExc_SystemError , "malformed control flow graph." );
63636406 return -1 ;
63646407 }
6408+ /* Skip over empty basic blocks. */
6409+ while (bb -> b_instr [i ].i_target -> b_iused == 0 ) {
6410+ bb -> b_instr [i ].i_target = bb -> b_instr [i ].i_target -> b_next ;
6411+ }
6412+
63656413 }
63666414 }
63676415 return 0 ;
63686416}
63696417
6370-
63716418static int
63726419mark_reachable (struct assembler * a ) {
63736420 basicblock * * stack , * * sp ;
@@ -6398,8 +6445,27 @@ mark_reachable(struct assembler *a) {
63986445 return 0 ;
63996446}
64006447
6448+ /* If an instruction has no line number, but it's predecessor in the BB does,
6449+ * then copy the line number. This reduces the size of the line number table,
6450+ * but has no impact on the generated line number events.
6451+ */
6452+ static void
6453+ minimize_lineno_table (struct assembler * a ) {
6454+ for (basicblock * b = a -> a_entry ; b != NULL ; b = b -> b_next ) {
6455+ int prev_lineno = -1 ;
6456+ for (int i = 0 ; i < b -> b_iused ; i ++ ) {
6457+ if (b -> b_instr [i ].i_lineno < 0 ) {
6458+ b -> b_instr [i ].i_lineno = prev_lineno ;
6459+ }
6460+ else {
6461+ prev_lineno = b -> b_instr [i ].i_lineno ;
6462+ }
6463+ }
6464+
6465+ }
6466+ }
64016467
6402- /* Perform basic peephole optimizations on a control flow graph.
6468+ /* Perform optimizations on a control flow graph.
64036469 The consts object should still be in list form to allow new constants
64046470 to be appended.
64056471
@@ -6411,11 +6477,6 @@ mark_reachable(struct assembler *a) {
64116477static int
64126478optimize_cfg (struct assembler * a , PyObject * consts )
64136479{
6414- for (basicblock * b = a -> a_entry ; b != NULL ; b = b -> b_next ) {
6415- if (normalize_basic_block (b )) {
6416- return -1 ;
6417- }
6418- }
64196480 for (basicblock * b = a -> a_entry ; b != NULL ; b = b -> b_next ) {
64206481 if (optimize_basic_block (b , consts )) {
64216482 return -1 ;
@@ -6432,9 +6493,63 @@ optimize_cfg(struct assembler *a, PyObject *consts)
64326493 b -> b_iused = 0 ;
64336494 }
64346495 }
6496+ minimize_lineno_table (a );
6497+ return 0 ;
6498+ }
6499+
6500+ static inline int
6501+ is_exit_without_lineno (basicblock * b ) {
6502+ return b -> b_exit && b -> b_instr [0 ].i_lineno < 0 ;
6503+ }
6504+
6505+ /* PEP 626 mandates that the f_lineno of a frame is correct
6506+ * after a frame terminates. It would be prohibitively expensive
6507+ * to continuously update the f_lineno field at runtime,
6508+ * so we make sure that all exiting instruction (raises and returns)
6509+ * have a valid line number, allowing us to compute f_lineno lazily.
6510+ * We can do this by duplicating the exit blocks without line number
6511+ * so that none have more than one predecessor. We can then safely
6512+ * copy the line number from the sole predecessor block.
6513+ */
6514+ static int
6515+ ensure_exits_have_lineno (struct compiler * c )
6516+ {
6517+ /* Copy all exit blocks without line number that are targets of a jump.
6518+ */
6519+ for (basicblock * b = c -> u -> u_blocks ; b != NULL ; b = b -> b_list ) {
6520+ if (b -> b_iused > 0 && is_jump (& b -> b_instr [b -> b_iused - 1 ])) {
6521+ switch (b -> b_instr [b -> b_iused - 1 ].i_opcode ) {
6522+ /* Note: Only actual jumps, not exception handlers */
6523+ case SETUP_ASYNC_WITH :
6524+ case SETUP_WITH :
6525+ case SETUP_FINALLY :
6526+ continue ;
6527+ }
6528+ basicblock * target = b -> b_instr [b -> b_iused - 1 ].i_target ;
6529+ if (is_exit_without_lineno (target )) {
6530+ basicblock * new_target = compiler_copy_block (c , target );
6531+ if (new_target == NULL ) {
6532+ return -1 ;
6533+ }
6534+ new_target -> b_instr [0 ].i_lineno = b -> b_instr [b -> b_iused - 1 ].i_lineno ;
6535+ b -> b_instr [b -> b_iused - 1 ].i_target = new_target ;
6536+ }
6537+ }
6538+ }
6539+ /* Any remaining reachable exit blocks without line number can only be reached by
6540+ * fall through, and thus can only have a single predecessor */
6541+ for (basicblock * b = c -> u -> u_blocks ; b != NULL ; b = b -> b_list ) {
6542+ if (!b -> b_nofallthrough && b -> b_next && b -> b_iused > 0 ) {
6543+ if (is_exit_without_lineno (b -> b_next )) {
6544+ assert (b -> b_next -> b_iused > 0 );
6545+ b -> b_next -> b_instr [0 ].i_lineno = b -> b_instr [b -> b_iused - 1 ].i_lineno ;
6546+ }
6547+ }
6548+ }
64356549 return 0 ;
64366550}
64376551
6552+
64386553/* Retained for API compatibility.
64396554 * Optimization is now done in optimize_cfg */
64406555
0 commit comments