Skip to content

Commit 388a620

Browse files
committed
Extract load-fast test helpers
1 parent 01d82fa commit 388a620

1 file changed

Lines changed: 53 additions & 84 deletions

File tree

‎crates/codegen/src/compile.rs‎

Lines changed: 53 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -14764,6 +14764,54 @@ def f(buffer, pos, last_char):
1476414764
})
1476514765
}
1476614766

14767+
fn non_cache_instructions(code: &CodeObject) -> impl Iterator<Item = &CodeUnit> {
14768+
code.instructions
14769+
.iter()
14770+
.filter(|unit| !matches!(unit.op, Instruction::Cache))
14771+
}
14772+
14773+
fn varname_index(code: &CodeObject, name: &str) -> usize {
14774+
code.varnames
14775+
.iter()
14776+
.position(|varname| varname.as_str() == name)
14777+
.unwrap_or_else(|| panic!("missing {name} local"))
14778+
}
14779+
14780+
fn load_fast_ops_for_var(code: &CodeObject, name: &str) -> Vec<Instruction> {
14781+
let var_idx = varname_index(code, name);
14782+
non_cache_instructions(code)
14783+
.filter_map(|unit| match unit.op {
14784+
Instruction::LoadFast { var_num } | Instruction::LoadFastBorrow { var_num } => {
14785+
let var_num = var_num.get(OpArg::new(u32::from(u8::from(unit.arg))));
14786+
(usize::from(var_num) == var_idx).then_some(unit.op)
14787+
}
14788+
_ => None,
14789+
})
14790+
.collect()
14791+
}
14792+
14793+
fn count_strong_loads_for_vars(code: &CodeObject, names: &[&str]) -> usize {
14794+
let var_indices = names
14795+
.iter()
14796+
.map(|name| varname_index(code, name))
14797+
.collect::<Vec<_>>();
14798+
non_cache_instructions(code)
14799+
.filter(|unit| match unit.op {
14800+
Instruction::LoadFast { var_num } => {
14801+
let var_num = var_num.get(OpArg::new(u32::from(u8::from(unit.arg))));
14802+
var_indices.contains(&usize::from(var_num))
14803+
}
14804+
_ => false,
14805+
})
14806+
.count()
14807+
}
14808+
14809+
fn count_strong_loads(code: &CodeObject) -> usize {
14810+
non_cache_instructions(code)
14811+
.filter(|unit| matches!(unit.op, Instruction::LoadFast { .. }))
14812+
.count()
14813+
}
14814+
1476714815
fn localsplus_name(code: &CodeObject, idx: usize) -> Option<&str> {
1476814816
if idx < code.varnames.len() {
1476914817
return Some(code.varnames[idx].as_str());
@@ -15241,23 +15289,7 @@ def f(running, errors):
1524115289
",
1524215290
);
1524315291
let f = find_code(&code, "f").expect("missing function code");
15244-
let errors_idx = f
15245-
.varnames
15246-
.iter()
15247-
.position(|name| name.as_str() == "errors")
15248-
.expect("missing errors local");
15249-
let errors_loads = f
15250-
.instructions
15251-
.iter()
15252-
.filter(|unit| !matches!(unit.op, Instruction::Cache))
15253-
.filter_map(|unit| match unit.op {
15254-
Instruction::LoadFast { var_num } | Instruction::LoadFastBorrow { var_num } => {
15255-
let var_num = var_num.get(OpArg::new(u32::from(u8::from(unit.arg))));
15256-
(usize::from(var_num) == errors_idx).then_some(unit.op)
15257-
}
15258-
_ => None,
15259-
})
15260-
.collect::<Vec<_>>();
15292+
let errors_loads = load_fast_ops_for_var(f, "errors");
1526115293
assert!(
1526215294
errors_loads
1526315295
.iter()
@@ -15284,23 +15316,7 @@ def f(self, cm, value):
1528415316
",
1528515317
);
1528615318
let f = find_code(&code, "f").expect("missing function code");
15287-
let value_idx = f
15288-
.varnames
15289-
.iter()
15290-
.position(|name| name.as_str() == "value")
15291-
.expect("missing value local");
15292-
let value_loads = f
15293-
.instructions
15294-
.iter()
15295-
.filter(|unit| !matches!(unit.op, Instruction::Cache))
15296-
.filter_map(|unit| match unit.op {
15297-
Instruction::LoadFast { var_num } | Instruction::LoadFastBorrow { var_num } => {
15298-
let var_num = var_num.get(OpArg::new(u32::from(u8::from(unit.arg))));
15299-
(usize::from(var_num) == value_idx).then_some(unit.op)
15300-
}
15301-
_ => None,
15302-
})
15303-
.collect::<Vec<_>>();
15319+
let value_loads = load_fast_ops_for_var(f, "value");
1530415320
assert!(
1530515321
value_loads
1530615322
.iter()
@@ -15336,28 +15352,7 @@ def f(test_cases):
1533615352
",
1533715353
);
1533815354
let f = find_code(&code, "f").expect("missing function code");
15339-
let src_idx = f
15340-
.varnames
15341-
.iter()
15342-
.position(|name| name.as_str() == "src")
15343-
.expect("missing src local");
15344-
let dest_idx = f
15345-
.varnames
15346-
.iter()
15347-
.position(|name| name.as_str() == "dest")
15348-
.expect("missing dest local");
15349-
let strong_src_dest_loads = f
15350-
.instructions
15351-
.iter()
15352-
.filter(|unit| !matches!(unit.op, Instruction::Cache))
15353-
.filter(|unit| match unit.op {
15354-
Instruction::LoadFast { var_num } => {
15355-
let var_num = var_num.get(OpArg::new(u32::from(u8::from(unit.arg))));
15356-
usize::from(var_num) == src_idx || usize::from(var_num) == dest_idx
15357-
}
15358-
_ => false,
15359-
})
15360-
.count();
15355+
let strong_src_dest_loads = count_strong_loads_for_vars(f, &["src", "dest"]);
1536115356
assert!(
1536215357
strong_src_dest_loads >= 2,
1536315358
"CPython codegen_try_except() emits orelse then USE_LABEL(end) before the following loop try, so optimize_load_fast() leaves fsencode arguments strong; got {strong_src_dest_loads} strong src/dest loads"
@@ -15387,28 +15382,7 @@ def f(self, f, cm):
1538715382
",
1538815383
);
1538915384
let f_code = find_code(&code, "f").expect("missing function code");
15390-
let self_idx = f_code
15391-
.varnames
15392-
.iter()
15393-
.position(|name| name.as_str() == "self")
15394-
.expect("missing self local");
15395-
let f_idx = f_code
15396-
.varnames
15397-
.iter()
15398-
.position(|name| name.as_str() == "f")
15399-
.expect("missing f local");
15400-
let strong_self_or_f_loads = f_code
15401-
.instructions
15402-
.iter()
15403-
.filter(|unit| !matches!(unit.op, Instruction::Cache))
15404-
.filter(|unit| match unit.op {
15405-
Instruction::LoadFast { var_num } => {
15406-
let var_num = var_num.get(OpArg::new(u32::from(u8::from(unit.arg))));
15407-
usize::from(var_num) == self_idx || usize::from(var_num) == f_idx
15408-
}
15409-
_ => false,
15410-
})
15411-
.count();
15385+
let strong_self_or_f_loads = count_strong_loads_for_vars(f_code, &["self", "f"]);
1541215386
assert!(
1541315387
strong_self_or_f_loads >= 2,
1541415388
"CPython codegen_try_except() emits orelse with nested with cleanup before USE_LABEL(end), so optimize_load_fast() leaves loads in the following try/else strong; got {strong_self_or_f_loads} strong self/f loads"
@@ -15432,12 +15406,7 @@ def f(self, cm):
1543215406
",
1543315407
);
1543415408
let f = find_code(&code, "f").expect("missing function code");
15435-
let strong_loads = f
15436-
.instructions
15437-
.iter()
15438-
.filter(|unit| !matches!(unit.op, Instruction::Cache))
15439-
.filter(|unit| matches!(unit.op, Instruction::LoadFast { .. }))
15440-
.count();
15409+
let strong_loads = count_strong_loads(f);
1544115410
assert!(
1544215411
strong_loads >= 3,
1544315412
"CPython codegen_try_finally() inlines a finalbody with codegen_with_inner() cleanup before the with exit label, so optimize_load_fast() leaves successor loads strong; got {strong_loads} strong loads"

0 commit comments

Comments
 (0)