@@ -912,6 +912,19 @@ cfg_builder_use_label(cfg_builder *g, jump_target_label lbl)
912
912
return cfg_builder_maybe_start_new_block (g );
913
913
}
914
914
915
+ static inline int
916
+ basicblock_append_instructions (basicblock * target , basicblock * source )
917
+ {
918
+ for (int i = 0 ; i < source -> b_iused ; i ++ ) {
919
+ int n = basicblock_next_instr (target );
920
+ if (n < 0 ) {
921
+ return -1 ;
922
+ }
923
+ target -> b_instr [n ] = source -> b_instr [i ];
924
+ }
925
+ return 0 ;
926
+ }
927
+
915
928
static basicblock *
916
929
copy_basicblock (cfg_builder * g , basicblock * block )
917
930
{
@@ -923,12 +936,8 @@ copy_basicblock(cfg_builder *g, basicblock *block)
923
936
if (result == NULL ) {
924
937
return NULL ;
925
938
}
926
- for (int i = 0 ; i < block -> b_iused ; i ++ ) {
927
- int n = basicblock_next_instr (result );
928
- if (n < 0 ) {
929
- return NULL ;
930
- }
931
- result -> b_instr [n ] = block -> b_instr [i ];
939
+ if (basicblock_append_instructions (result , block ) < 0 ) {
940
+ return NULL ;
932
941
}
933
942
return result ;
934
943
}
@@ -7080,15 +7089,14 @@ stackdepth(basicblock *entryblock, int code_flags)
7080
7089
if (new_depth > maxdepth ) {
7081
7090
maxdepth = new_depth ;
7082
7091
}
7083
- assert (depth >= 0 ); /* invalid code or bug in stackdepth() */
7084
7092
if (HAS_TARGET (instr -> i_opcode )) {
7085
7093
effect = stack_effect (instr -> i_opcode , instr -> i_oparg , 1 );
7086
7094
assert (effect != PY_INVALID_STACK_EFFECT );
7087
7095
int target_depth = depth + effect ;
7096
+ assert (target_depth >= 0 ); /* invalid code or bug in stackdepth() */
7088
7097
if (target_depth > maxdepth ) {
7089
7098
maxdepth = target_depth ;
7090
7099
}
7091
- assert (target_depth >= 0 ); /* invalid code or bug in stackdepth() */
7092
7100
stackdepth_push (& sp , instr -> i_target , target_depth );
7093
7101
}
7094
7102
depth = new_depth ;
@@ -7487,6 +7495,9 @@ convert_exception_handlers_to_nops(basicblock *entryblock) {
7487
7495
}
7488
7496
}
7489
7497
}
7498
+ for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
7499
+ remove_redundant_nops (b );
7500
+ }
7490
7501
}
7491
7502
7492
7503
static inline void
@@ -7964,8 +7975,8 @@ scan_block_for_local(int target, basicblock *b, bool unsafe_to_start,
7964
7975
#undef MAYBE_PUSH
7965
7976
7966
7977
static int
7967
- add_checks_for_loads_of_unknown_variables (basicblock * entryblock ,
7968
- struct compiler * c )
7978
+ add_checks_for_loads_of_uninitialized_variables (basicblock * entryblock ,
7979
+ struct compiler * c )
7969
7980
{
7970
7981
basicblock * * stack = make_cfg_traversal_stack (entryblock );
7971
7982
if (stack == NULL ) {
@@ -8291,7 +8302,7 @@ dump_basicblock(const basicblock *b)
8291
8302
8292
8303
8293
8304
static int
8294
- calculate_jump_targets (basicblock * entryblock );
8305
+ translate_jump_labels_to_targets (basicblock * entryblock );
8295
8306
8296
8307
static int
8297
8308
optimize_cfg (cfg_builder * g , PyObject * consts , PyObject * const_cache );
@@ -8628,11 +8639,9 @@ assemble(struct compiler *c, int addNone)
8628
8639
}
8629
8640
nlocalsplus -= numdropped ;
8630
8641
8631
- consts = consts_dict_keys_inorder (c -> u -> u_consts );
8632
- if (consts == NULL ) {
8633
- goto error ;
8634
- }
8635
- if (calculate_jump_targets (g -> g_entryblock )) {
8642
+ /** Preprocessing **/
8643
+ /* Map labels to targets and mark exception handlers */
8644
+ if (translate_jump_labels_to_targets (g -> g_entryblock )) {
8636
8645
goto error ;
8637
8646
}
8638
8647
if (mark_except_handlers (g -> g_entryblock ) < 0 ) {
@@ -8641,18 +8650,31 @@ assemble(struct compiler *c, int addNone)
8641
8650
if (label_exception_targets (g -> g_entryblock )) {
8642
8651
goto error ;
8643
8652
}
8653
+
8654
+ /** Optimization **/
8655
+ consts = consts_dict_keys_inorder (c -> u -> u_consts );
8656
+ if (consts == NULL ) {
8657
+ goto error ;
8658
+ }
8644
8659
if (optimize_cfg (g , consts , c -> c_const_cache )) {
8645
8660
goto error ;
8646
8661
}
8647
- if (trim_unused_consts (g -> g_entryblock , consts ) ) {
8662
+ if (add_checks_for_loads_of_uninitialized_variables (g -> g_entryblock , c ) < 0 ) {
8648
8663
goto error ;
8649
8664
}
8665
+
8666
+ /** line numbers (TODO: move this before optimization stage) */
8650
8667
if (duplicate_exits_without_lineno (g ) < 0 ) {
8651
8668
goto error ;
8652
8669
}
8653
8670
propagate_line_numbers (g -> g_entryblock );
8654
8671
guarantee_lineno_for_exits (g -> g_entryblock , c -> u -> u_firstlineno );
8655
8672
8673
+ if (push_cold_blocks_to_end (g , code_flags ) < 0 ) {
8674
+ goto error ;
8675
+ }
8676
+
8677
+ /** Assembly **/
8656
8678
int maxdepth = stackdepth (g -> g_entryblock , code_flags );
8657
8679
if (maxdepth < 0 ) {
8658
8680
goto error ;
@@ -8661,27 +8683,19 @@ assemble(struct compiler *c, int addNone)
8661
8683
8662
8684
convert_exception_handlers_to_nops (g -> g_entryblock );
8663
8685
8664
- if (push_cold_blocks_to_end (g , code_flags ) < 0 ) {
8665
- goto error ;
8666
- }
8667
- for (basicblock * b = g -> g_entryblock ; b != NULL ; b = b -> b_next ) {
8668
- remove_redundant_nops (b );
8669
- }
8670
-
8671
8686
/* Order of basic blocks must have been determined by now */
8672
8687
if (normalize_jumps (g ) < 0 ) {
8673
8688
goto error ;
8674
8689
}
8675
8690
8676
- if (add_checks_for_loads_of_unknown_variables (g -> g_entryblock , c ) < 0 ) {
8677
- goto error ;
8678
- }
8679
-
8680
8691
assert (no_redundant_jumps (g ));
8681
8692
8682
8693
/* Can't modify the bytecode after computing jump offsets. */
8683
8694
assemble_jump_offsets (g -> g_entryblock );
8684
8695
8696
+ if (trim_unused_consts (g -> g_entryblock , consts )) {
8697
+ goto error ;
8698
+ }
8685
8699
8686
8700
/* Create assembler */
8687
8701
if (!assemble_init (& a , c -> u -> u_firstlineno ))
@@ -9265,12 +9279,8 @@ inline_small_exit_blocks(basicblock *bb) {
9265
9279
basicblock * target = last -> i_target ;
9266
9280
if (basicblock_exits_scope (target ) && target -> b_iused <= MAX_COPY_SIZE ) {
9267
9281
last -> i_opcode = NOP ;
9268
- for (int i = 0 ; i < target -> b_iused ; i ++ ) {
9269
- int index = basicblock_next_instr (bb );
9270
- if (index < 0 ) {
9271
- return -1 ;
9272
- }
9273
- bb -> b_instr [index ] = target -> b_instr [i ];
9282
+ if (basicblock_append_instructions (bb , target ) < 0 ) {
9283
+ return -1 ;
9274
9284
}
9275
9285
return 1 ;
9276
9286
}
@@ -9456,7 +9466,7 @@ propagate_line_numbers(basicblock *entryblock) {
9456
9466
9457
9467
/* Calculate the actual jump target from the target_label */
9458
9468
static int
9459
- calculate_jump_targets (basicblock * entryblock )
9469
+ translate_jump_labels_to_targets (basicblock * entryblock )
9460
9470
{
9461
9471
int max_label = -1 ;
9462
9472
for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
@@ -9599,12 +9609,14 @@ is_exit_without_lineno(basicblock *b) {
9599
9609
static int
9600
9610
duplicate_exits_without_lineno (cfg_builder * g )
9601
9611
{
9612
+ assert (no_empty_basic_blocks (g ));
9602
9613
/* Copy all exit blocks without line number that are targets of a jump.
9603
9614
*/
9604
9615
basicblock * entryblock = g -> g_entryblock ;
9605
9616
for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
9606
9617
struct instr * last = basicblock_last_instr (b );
9607
- if (last != NULL && is_jump (last )) {
9618
+ assert (last != NULL );
9619
+ if (is_jump (last )) {
9608
9620
basicblock * target = last -> i_target ;
9609
9621
if (is_exit_without_lineno (target ) && target -> b_predecessors > 1 ) {
9610
9622
basicblock * new_target = copy_basicblock (g , target );
@@ -9621,8 +9633,6 @@ duplicate_exits_without_lineno(cfg_builder *g)
9621
9633
}
9622
9634
}
9623
9635
9624
- assert (no_empty_basic_blocks (g ));
9625
-
9626
9636
/* Any remaining reachable exit blocks without line number can only be reached by
9627
9637
* fall through, and thus can only have a single predecessor */
9628
9638
for (basicblock * b = entryblock ; b != NULL ; b = b -> b_next ) {
@@ -9775,7 +9785,7 @@ _PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts)
9775
9785
if (const_cache == NULL ) {
9776
9786
goto error ;
9777
9787
}
9778
- if (calculate_jump_targets (g .g_entryblock )) {
9788
+ if (translate_jump_labels_to_targets (g .g_entryblock )) {
9779
9789
goto error ;
9780
9790
}
9781
9791
if (optimize_cfg (& g , consts , const_cache ) < 0 ) {
0 commit comments