Skip to content

Commit 9c895c2

Browse files
committed
Add label_arg{,_mut} methods
1 parent 057b5e8 commit 9c895c2

File tree

2 files changed

+51
-41
lines changed

2 files changed

+51
-41
lines changed

bytecode/src/bytecode.rs

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ impl CodeFlags {
145145
#[derive(Serialize, Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
146146
#[repr(transparent)]
147147
// XXX: if you add a new instruction that stores a Label, make sure to add it in
148-
// compile::CodeInfo::finalize_code and CodeObject::label_targets
148+
// Instruction::label_arg{,_mut}
149149
pub struct Label(pub usize);
150150
impl fmt::Display for Label {
151151
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -589,23 +589,8 @@ impl<C: Constant> CodeObject<C> {
589589
pub fn label_targets(&self) -> BTreeSet<Label> {
590590
let mut label_targets = BTreeSet::new();
591591
for instruction in &*self.instructions {
592-
match instruction {
593-
Jump { target: l }
594-
| JumpIfTrue { target: l }
595-
| JumpIfFalse { target: l }
596-
| JumpIfTrueOrPop { target: l }
597-
| JumpIfFalseOrPop { target: l }
598-
| ForIter { target: l }
599-
| SetupFinally { handler: l }
600-
| SetupExcept { handler: l }
601-
| SetupWith { end: l }
602-
| SetupAsyncWith { end: l }
603-
| SetupLoop { end: l }
604-
| Continue { target: l } => {
605-
label_targets.insert(*l);
606-
}
607-
608-
_ => {}
592+
if let Some(l) = instruction.label_arg() {
593+
label_targets.insert(*l);
609594
}
610595
}
611596
label_targets
@@ -753,6 +738,46 @@ impl<C: Constant> fmt::Display for CodeObject<C> {
753738
}
754739

755740
impl Instruction {
741+
/// Gets the label stored inside this instruction, if it exists
742+
#[inline]
743+
pub fn label_arg(&self) -> Option<&Label> {
744+
match self {
745+
Jump { target: l }
746+
| JumpIfTrue { target: l }
747+
| JumpIfFalse { target: l }
748+
| JumpIfTrueOrPop { target: l }
749+
| JumpIfFalseOrPop { target: l }
750+
| ForIter { target: l }
751+
| SetupFinally { handler: l }
752+
| SetupExcept { handler: l }
753+
| SetupWith { end: l }
754+
| SetupAsyncWith { end: l }
755+
| SetupLoop { end: l }
756+
| Continue { target: l } => Some(l),
757+
_ => None,
758+
}
759+
}
760+
761+
/// Gets a mutable reference to the label stored inside this instruction, if it exists
762+
#[inline]
763+
pub fn label_arg_mut(&mut self) -> Option<&mut Label> {
764+
match self {
765+
Jump { target: l }
766+
| JumpIfTrue { target: l }
767+
| JumpIfFalse { target: l }
768+
| JumpIfTrueOrPop { target: l }
769+
| JumpIfFalseOrPop { target: l }
770+
| ForIter { target: l }
771+
| SetupFinally { handler: l }
772+
| SetupExcept { handler: l }
773+
| SetupWith { end: l }
774+
| SetupAsyncWith { end: l }
775+
| SetupLoop { end: l }
776+
| Continue { target: l } => Some(l),
777+
_ => None,
778+
}
779+
}
780+
756781
#[allow(clippy::too_many_arguments)]
757782
fn fmt_dis<C: Constant>(
758783
&self,

compiler/src/compile.rs

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct CodeInfo {
2626
varname_cache: IndexSet<String>,
2727
cellvar_cache: IndexSet<String>,
2828
freevar_cache: IndexSet<String>,
29-
label_map: Vec<Option<Label>>,
29+
label_map: Vec<Label>,
3030
}
3131
impl CodeInfo {
3232
fn finalize_code(self) -> CodeObject {
@@ -73,27 +73,12 @@ impl CodeInfo {
7373
}
7474

7575
for instruction in &mut *code.instructions {
76-
use Instruction::*;
7776
// this is a little bit hacky, as until now the data stored inside Labels in
7877
// Instructions is just bookkeeping, but I think it's the best way to do this
79-
// XXX: any new instruction that uses a label has to be added here
80-
match instruction {
81-
Jump { target: l }
82-
| JumpIfTrue { target: l }
83-
| JumpIfFalse { target: l }
84-
| JumpIfTrueOrPop { target: l }
85-
| JumpIfFalseOrPop { target: l }
86-
| ForIter { target: l }
87-
| SetupFinally { handler: l }
88-
| SetupExcept { handler: l }
89-
| SetupWith { end: l }
90-
| SetupAsyncWith { end: l }
91-
| SetupLoop { end: l }
92-
| Continue { target: l } => {
93-
*l = label_map[l.0].expect("label never set");
94-
}
95-
96-
_ => {}
78+
if let Some(l) = instruction.label_arg_mut() {
79+
let real_label = label_map[l.0];
80+
debug_assert!(real_label.0 != usize::MAX, "label wasn't set");
81+
*l = real_label;
9782
}
9883
}
9984
code
@@ -2446,7 +2431,7 @@ impl Compiler {
24462431
fn new_label(&mut self) -> Label {
24472432
let label_map = &mut self.current_codeinfo().label_map;
24482433
let label = Label(label_map.len());
2449-
label_map.push(None);
2434+
label_map.push(Label(usize::MAX));
24502435
label
24512436
}
24522437

@@ -2458,9 +2443,9 @@ impl Compiler {
24582443
..
24592444
} = self.current_codeinfo();
24602445
let actual_label = Label(instructions.len());
2461-
let prev_val = std::mem::replace(&mut label_map[label.0], Some(actual_label));
2446+
let prev_val = std::mem::replace(&mut label_map[label.0], actual_label);
24622447
debug_assert!(
2463-
prev_val.map_or(true, |x| x == actual_label),
2448+
prev_val.0 == usize::MAX || prev_val == actual_label,
24642449
"double-set a label"
24652450
);
24662451
}

0 commit comments

Comments
 (0)