@@ -3,21 +3,25 @@ use rustpython_bytecode::{CodeFlags, CodeObject, ConstantData, Instruction, Labe
33
44pub type BlockIdx = Label ;
55
6+ #[ derive( Debug ) ]
67pub struct InstructionInfo {
78 /// If the instruction has a Label argument, it's actually a BlockIdx, not a code offset
89 pub instr : Instruction ,
910 pub location : Location ,
1011}
1112
13+ // TODO: look into using petgraph for handling blocks and stuff? it's heavier than this, but it
14+ // might enable more analysis/optimizations
15+ #[ derive( Debug ) ]
1216pub struct Block {
1317 pub instructions : Vec < InstructionInfo > ,
14- pub done : bool ,
18+ pub next : BlockIdx ,
1519}
1620impl Default for Block {
1721 fn default ( ) -> Self {
1822 Block {
1923 instructions : Vec :: new ( ) ,
20- done : false ,
24+ next : Label ( u32 :: MAX ) ,
2125 }
2226 }
2327}
@@ -32,7 +36,7 @@ pub struct CodeInfo {
3236 pub obj_name : String , // Name of the object that created this code object
3337
3438 pub blocks : Vec < Block > ,
35- pub block_order : Vec < BlockIdx > ,
39+ pub current_block : BlockIdx ,
3640 pub constants : Vec < ConstantData > ,
3741 pub name_cache : IndexSet < String > ,
3842 pub varname_cache : IndexSet < String > ,
@@ -57,37 +61,34 @@ impl CodeInfo {
5761 first_line_number,
5862 obj_name,
5963
60- mut blocks,
61- block_order ,
64+ blocks,
65+ current_block : _ ,
6266 constants,
6367 name_cache,
6468 varname_cache,
6569 cellvar_cache,
6670 freevar_cache,
6771 } = self ;
6872
69- assert ! ( block_order. len( ) == blocks. len( ) ) ;
70-
7173 let mut num_instructions = 0 ;
7274 let mut block_to_offset = vec ! [ Label ( 0 ) ; blocks. len( ) ] ;
7375
74- for idx in & block_order {
75- let idx = idx. 0 as usize ;
76- block_to_offset[ idx] = Label ( num_instructions as u32 ) ;
77- num_instructions += blocks[ idx] . instructions . len ( ) ;
76+ for ( idx, block) in iter_blocks ( & blocks) {
77+ block_to_offset[ idx. 0 as usize ] = Label ( num_instructions as u32 ) ;
78+ num_instructions += block. instructions . len ( ) ;
7879 }
7980
8081 let mut instructions = Vec :: with_capacity ( num_instructions) ;
8182 let mut locations = Vec :: with_capacity ( num_instructions) ;
8283
83- for idx in block_order {
84- let block = std :: mem :: take ( & mut blocks [ idx . 0 as usize ] ) ;
85- for mut instr in block . instructions {
86- if let Some ( l) = instr. instr . label_arg_mut ( ) {
84+ for ( _ , block ) in iter_blocks ( & blocks ) {
85+ for info in & block . instructions {
86+ let mut instr = info . instr . clone ( ) ;
87+ if let Some ( l) = instr. label_arg_mut ( ) {
8788 * l = block_to_offset[ l. 0 as usize ] ;
8889 }
89- instructions. push ( instr. instr ) ;
90- locations. push ( instr . location ) ;
90+ instructions. push ( instr) ;
91+ locations. push ( info . location ) ;
9192 }
9293 }
9394
@@ -168,10 +169,11 @@ impl CodeInfo {
168169 startdepths[ 0 ] =
169170 self . flags
170171 . intersects ( CodeFlags :: IS_GENERATOR | CodeFlags :: IS_COROUTINE ) as u32 ;
171- stack. push ( ( Label ( 0 ) , 0 ) ) ;
172- ' process_blocks: while let Some ( ( block, blockorder ) ) = stack. pop ( ) {
172+ stack. push ( Label ( 0 ) ) ;
173+ ' process_blocks: while let Some ( block) = stack. pop ( ) {
173174 let mut depth = startdepths[ block. 0 as usize ] ;
174- for i in & self . blocks [ block. 0 as usize ] . instructions {
175+ let block = & self . blocks [ block. 0 as usize ] ;
176+ for i in & block. instructions {
175177 let instr = & i. instr ;
176178 let effect = instr. stack_effect ( false ) ;
177179 let new_depth = add_ui ( depth, effect) ;
@@ -190,37 +192,21 @@ impl CodeInfo {
190192 if target_depth > maxdepth {
191193 maxdepth = target_depth
192194 }
193- stackdepth_push (
194- & mut stack,
195- & mut startdepths,
196- ( target_block, u32:: MAX ) ,
197- target_depth,
198- ) ;
195+ stackdepth_push ( & mut stack, & mut startdepths, target_block, target_depth) ;
199196 }
200197 depth = new_depth;
201198 if instr. unconditional_branch ( ) {
202199 continue ' process_blocks;
203200 }
204201 }
205- let next_blockorder = if blockorder == u32:: MAX {
206- self . block_order . iter ( ) . position ( |x| * x == block) . unwrap ( ) as u32 + 1
207- } else {
208- blockorder + 1
209- } ;
210- let next = self . block_order [ next_blockorder as usize ] ;
211- stackdepth_push ( & mut stack, & mut startdepths, ( next, next_blockorder) , depth) ;
202+ stackdepth_push ( & mut stack, & mut startdepths, block. next , depth) ;
212203 }
213204 maxdepth
214205 }
215206}
216207
217- fn stackdepth_push (
218- stack : & mut Vec < ( Label , u32 ) > ,
219- startdepths : & mut [ u32 ] ,
220- target : ( Label , u32 ) ,
221- depth : u32 ,
222- ) {
223- let block_depth = & mut startdepths[ target. 0 . 0 as usize ] ;
208+ fn stackdepth_push ( stack : & mut Vec < Label > , startdepths : & mut [ u32 ] , target : Label , depth : u32 ) {
209+ let block_depth = & mut startdepths[ target. 0 as usize ] ;
224210 if * block_depth == u32:: MAX || depth > * block_depth {
225211 * block_depth = depth;
226212 stack. push ( target) ;
@@ -234,3 +220,8 @@ fn add_ui(a: u32, b: i32) -> u32 {
234220 a + b as u32
235221 }
236222}
223+
224+ fn iter_blocks ( blocks : & [ Block ] ) -> impl Iterator < Item = ( BlockIdx , & Block ) > + ' _ {
225+ let get_idx = move |i : BlockIdx | blocks. get ( i. 0 as usize ) . map ( |b| ( i, b) ) ;
226+ std:: iter:: successors ( get_idx ( Label ( 0 ) ) , move |( _, b) | get_idx ( b. next ) ) // if b.next is u32::MAX that's the end
227+ }
0 commit comments