perf: live 集改 u64 位集 + 不动点缓冲复用

LiveInfo 四矩阵由逐位 Vec<bool>(1 字节/位,长度 = max_vreg+1)改为
u64 压缩位集(1 字 64 位,长度 ÷8),dataflow 不动点 out/input 缓冲
提为循环外复用(clear + 覆盖,免逐迭代逐块分配)。dce_precise /
graph 建图 / call_window 三处消费方同步改为字内位移查询,越界语义
与旧 Vec<bool>::get 一致(越界 = 不 live)。位集遍历(call_window
存活上界)按 trailing_zeros 只走实际置位,活集小则近 O(活集) 而非
O(254)。

实测(debug,start-unicode-17.0.0.js):liveness 三趟合计
~536ms → ~118ms(-78%),矩阵内存 ÷8;graph 全 node 扫描为剩余
瓶颈,另行跟进。
This commit is contained in:
2026-08-16 03:20:02 +08:00
parent 3962a329bd
commit b8611d2c4b
8 changed files with 117 additions and 82 deletions
+10 -3
View File
@@ -47,10 +47,17 @@ pub fn encode_call_window(f: &mut IRFunction, live: &LiveInfo) {
if matches!(inst.op, OpCode::CALL | OpCode::NEW_EXPRESSION | OpCode::SUPER_CALL) {
let after = &live.inst_live_after[i];
// 存活上界 = 最大存活槽号 + 1;254/255 由帧单独保存,不进窗口。
// 按 u64 位集逐字取置位(活集小,仅遍历实际存活的槽)。
let mut upper = 0u32;
for (reg, &alive) in after.iter().enumerate().take(254) {
if alive {
upper = (reg + 1) as u32;
for (word_idx, word) in after.iter().enumerate() {
let mut bits = *word;
while bits != 0 {
let bit = bits.trailing_zeros() as usize;
let reg = word_idx * 64 + bit;
if reg < 254 {
upper = (reg + 1) as u32;
}
bits &= bits - 1;
}
}
if upper > 0 {
+2 -2
View File
@@ -253,7 +253,7 @@ pub(super) fn build(
for i in 0..inst_count {
let mut at_i: Vec<u32> = Vec::new();
for &v in &node_ids {
if live.inst_live_before[i].get(v as usize).copied().unwrap_or(false) {
if oxide_liveness::bitset_get(&live.inst_live_before[i], v as usize) {
at_i.push(v);
}
}
@@ -279,7 +279,7 @@ pub(super) fn build(
if v == d {
continue;
}
if live.inst_live_after[i].get(v as usize).copied().unwrap_or(false) {
if oxide_liveness::bitset_get(&live.inst_live_after[i], v as usize) {
adj_sets.entry(d).or_default().insert(v);
adj_sets.entry(v).or_default().insert(d);
}