mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
perf: LiveInfo 维度守卫改 Cow 借用,合法路径免全量复制
alloc 与 encode_call_window 在 LiveInfo 维度匹配(正常路径)时仍全量 clone 稠密 bitset 矩阵,随后只读消费。改为 Cow::Borrowed 借用原分析 结果,维度不符才 Cow::Owned 重建。零语义变化,消除每次 alloc/编码 的无谓内存复制。
This commit is contained in:
@@ -8,6 +8,8 @@
|
|||||||
//! 指令的函数同样不编码——异常 handler 的存活集不经分支/循环内调用点传播,
|
//! 指令的函数同样不编码——异常 handler 的存活集不经分支/循环内调用点传播,
|
||||||
//! 截断窗口会丢仅 handler 存活的槽(见 `encode_call_window` 内 has_try 说明)。
|
//! 截断窗口会丢仅 handler 存活的槽(见 `encode_call_window` 内 has_try 说明)。
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use oxide_bytecode::opcode::OpCode;
|
use oxide_bytecode::opcode::OpCode;
|
||||||
use oxide_ir::IRFunction;
|
use oxide_ir::IRFunction;
|
||||||
use oxide_liveness::LiveInfo;
|
use oxide_liveness::LiveInfo;
|
||||||
@@ -30,12 +32,13 @@ pub fn encode_call_window(f: &mut IRFunction, live: &LiveInfo) {
|
|||||||
.insts
|
.insts
|
||||||
.iter()
|
.iter()
|
||||||
.any(|i| matches!(i.op, OpCode::TRY_BEGIN | OpCode::TRY_FINALLY_BEGIN));
|
.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() {
|
let live = if live.inst_live_before.len() == f.insts.len() && !f.insts.is_empty() {
|
||||||
live.clone()
|
Cow::Borrowed(live)
|
||||||
} else {
|
} else {
|
||||||
let cfg = oxide_cfg::build_cfg(f);
|
let cfg = oxide_cfg::build_cfg(f);
|
||||||
oxide_liveness::liveness(f, &cfg)
|
Cow::Owned(oxide_liveness::liveness(f, &cfg))
|
||||||
};
|
};
|
||||||
// 生成器 / 异步函数体 + 含 try 的函数:调用点保持全量窗口(挂起恢复按全量
|
// 生成器 / 异步函数体 + 含 try 的函数:调用点保持全量窗口(挂起恢复按全量
|
||||||
// 寄存器快照搬移;异常 handler 存活集经截断窗口会丢值)。
|
// 寄存器快照搬移;异常 handler 存活集经截断窗口会丢值)。
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ mod rewrite;
|
|||||||
pub use alloc_map::{Alloc, AllocMap, FreshKind, FreshVreg, SpillPlan};
|
pub use alloc_map::{Alloc, AllocMap, FreshKind, FreshVreg, SpillPlan};
|
||||||
pub use call_window::encode_call_window;
|
pub use call_window::encode_call_window;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use oxide_ir::IRFunction;
|
use oxide_ir::IRFunction;
|
||||||
use oxide_liveness::LiveInfo;
|
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() {
|
if f.insts.is_empty() && f.nested.is_empty() {
|
||||||
return Ok(());
|
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() {
|
let live = if live.inst_live_before.len() == f.insts.len() && !f.insts.is_empty() {
|
||||||
live.clone()
|
Cow::Borrowed(live)
|
||||||
} else {
|
} else {
|
||||||
let cfg = oxide_cfg::build_cfg(f);
|
let cfg = oxide_cfg::build_cfg(f);
|
||||||
oxide_liveness::liveness(f, &cfg)
|
Cow::Owned(oxide_liveness::liveness(f, &cfg))
|
||||||
};
|
};
|
||||||
let map = color(f, &live)?;
|
let map = color(f, &live)?;
|
||||||
regalloc_debug!("alloc: {} vregs -> {} phys", map.map.len(), map.phys_peak);
|
regalloc_debug!("alloc: {} vregs -> {} phys", map.map.len(), map.phys_peak);
|
||||||
|
|||||||
Reference in New Issue
Block a user