From f899538535043a0c88a9089865cf357dfbc17772 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sun, 16 Aug 2026 03:03:55 +0800 Subject: [PATCH] =?UTF-8?q?regalloc:=20LiveInfo=20=E7=BB=B4=E5=BA=A6?= =?UTF-8?q?=E5=AE=88=E5=8D=AB=E6=94=B9=20Cow=20=E5=80=9F=E7=94=A8=EF=BC=8C?= =?UTF-8?q?=E5=90=88=E6=B3=95=E8=B7=AF=E5=BE=84=E5=85=8D=E5=85=A8=E9=87=8F?= =?UTF-8?q?=E5=A4=8D=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit alloc 与 encode_call_window 在 LiveInfo 维度匹配(正常路径)时仍全量 clone 稠密 bitset 矩阵,随后只读消费。改为 Cow::Borrowed 借用原分析 结果,维度不符才 Cow::Owned 重建。零语义变化,消除每次 alloc/编码 的无谓内存复制。 --- crates/oxide_regalloc/src/call_window.rs | 9 ++++++--- crates/oxide_regalloc/src/lib.rs | 10 +++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/crates/oxide_regalloc/src/call_window.rs b/crates/oxide_regalloc/src/call_window.rs index fbb66b2..629831a 100644 --- a/crates/oxide_regalloc/src/call_window.rs +++ b/crates/oxide_regalloc/src/call_window.rs @@ -8,6 +8,8 @@ //! 指令的函数同样不编码——异常 handler 的存活集不经分支/循环内调用点传播, //! 截断窗口会丢仅 handler 存活的槽(见 `encode_call_window` 内 has_try 说明)。 +use std::borrow::Cow; + use oxide_bytecode::opcode::OpCode; use oxide_ir::IRFunction; use oxide_liveness::LiveInfo; @@ -30,12 +32,13 @@ pub fn encode_call_window(f: &mut IRFunction, live: &LiveInfo) { .insts .iter() .any(|i| matches!(i.op, OpCode::TRY_BEGIN | OpCode::TRY_FINALLY_BEGIN)); - // LiveInfo 维度守卫:与 alloc 相同纪律,过期则重算。 + // LiveInfo 维度守卫:与 alloc 相同纪律,过期则重算。维度匹配时借用而非复制 + // (LiveInfo 稠密矩阵全量 clone 只读数据无收益)。 let live = if live.inst_live_before.len() == f.insts.len() && !f.insts.is_empty() { - live.clone() + Cow::Borrowed(live) } else { let cfg = oxide_cfg::build_cfg(f); - oxide_liveness::liveness(f, &cfg) + Cow::Owned(oxide_liveness::liveness(f, &cfg)) }; // 生成器 / 异步函数体 + 含 try 的函数:调用点保持全量窗口(挂起恢复按全量 // 寄存器快照搬移;异常 handler 存活集经截断窗口会丢值)。 diff --git a/crates/oxide_regalloc/src/lib.rs b/crates/oxide_regalloc/src/lib.rs index aebe5d7..1854cf7 100644 --- a/crates/oxide_regalloc/src/lib.rs +++ b/crates/oxide_regalloc/src/lib.rs @@ -17,6 +17,8 @@ mod rewrite; pub use alloc_map::{Alloc, AllocMap, FreshKind, FreshVreg, SpillPlan}; pub use call_window::encode_call_window; +use std::borrow::Cow; + use oxide_ir::IRFunction; use oxide_liveness::LiveInfo; @@ -45,12 +47,14 @@ pub fn alloc(f: &mut IRFunction, live: &LiveInfo) -> Result<(), String> { if f.insts.is_empty() && f.nested.is_empty() { return Ok(()); } - // LiveInfo 维度守卫:删改后的过期 LiveInfo 索引错位会误删活指令 + // LiveInfo 维度守卫:删改后的过期 LiveInfo 索引错位会误删活指令。 + // 维度匹配时借用而非复制——LiveInfo 是稠密 bitset 矩阵(大函数可达数百 MB), + // 全量 clone 白白复制一次只读数据。 let live = if live.inst_live_before.len() == f.insts.len() && !f.insts.is_empty() { - live.clone() + Cow::Borrowed(live) } else { let cfg = oxide_cfg::build_cfg(f); - oxide_liveness::liveness(f, &cfg) + Cow::Owned(oxide_liveness::liveness(f, &cfg)) }; let map = color(f, &live)?; regalloc_debug!("alloc: {} vregs -> {} phys", map.map.len(), map.phys_peak);