Skip to content

Commit 2123df6

Browse files
committed
Don't keep a separate blockorder vec
1 parent 8f536b9 commit 2123df6

2 files changed

Lines changed: 47 additions & 49 deletions

File tree

compiler/src/compile.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl Compiler {
138138
obj_name: code_name,
139139

140140
blocks: vec![ir::Block::default()],
141-
block_order: vec![bytecode::Label(0)],
141+
current_block: bytecode::Label(0),
142142
constants: Vec::new(),
143143
name_cache: IndexSet::new(),
144144
varname_cache: IndexSet::new(),
@@ -215,7 +215,7 @@ impl Compiler {
215215
obj_name,
216216

217217
blocks: vec![ir::Block::default()],
218-
block_order: vec![bytecode::Label(0)],
218+
current_block: bytecode::Label(0),
219219
constants: Vec::new(),
220220
name_cache: IndexSet::new(),
221221
varname_cache: IndexSet::new(),
@@ -2410,7 +2410,7 @@ impl Compiler {
24102410

24112411
fn current_block(&mut self) -> &mut ir::Block {
24122412
let info = self.current_codeinfo();
2413-
&mut info.blocks[info.block_order.last().unwrap().0 as usize]
2413+
&mut info.blocks[info.current_block.0 as usize]
24142414
}
24152415

24162416
fn new_block(&mut self) -> ir::BlockIdx {
@@ -2422,13 +2422,20 @@ impl Compiler {
24222422

24232423
fn switch_to_block(&mut self, block: ir::BlockIdx) {
24242424
let code = self.current_codeinfo();
2425-
let last = code.block_order.last().unwrap();
2426-
code.blocks[last.0 as usize].done = true;
2427-
debug_assert!(
2428-
!code.blocks[block.0 as usize].done,
2429-
"switching to done block"
2425+
let prev = code.current_block;
2426+
assert_eq!(
2427+
code.blocks[block.0 as usize].next.0,
2428+
u32::MAX,
2429+
"switching to completed block"
24302430
);
2431-
code.block_order.push(block);
2431+
let prev_block = &mut code.blocks[prev.0 as usize];
2432+
assert_eq!(
2433+
prev_block.next.0,
2434+
u32::MAX,
2435+
"switching from block that's already got a next"
2436+
);
2437+
prev_block.next = block;
2438+
code.current_block = block;
24322439
}
24332440

24342441
fn set_source_location(&mut self, location: ast::Location) {

compiler/src/ir.rs

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,25 @@ use rustpython_bytecode::{CodeFlags, CodeObject, ConstantData, Instruction, Labe
33

44
pub type BlockIdx = Label;
55

6+
#[derive(Debug)]
67
pub 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)]
1216
pub struct Block {
1317
pub instructions: Vec<InstructionInfo>,
14-
pub done: bool,
18+
pub next: BlockIdx,
1519
}
1620
impl 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

Comments
 (0)