From 582475363bee99801372789b15184e8199325917 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Fri, 9 Oct 2026 09:07:20 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20run=20=E8=A3=85=E8=BD=BD=E6=9C=9F?= =?UTF-8?q?=E5=AF=B9=E5=85=B1=E4=BA=AB=E6=A8=A1=E5=9D=97=E5=AD=97=E8=8A=82?= =?UTF-8?q?=E7=A0=81=E6=98=BE=E5=BC=8F=E5=A4=8D=E5=88=B6=EF=BC=8CCOW=20?= =?UTF-8?q?=E6=B7=B1=E6=8B=B7=E8=B4=9D=E7=A7=BB=E5=87=BA=E7=83=AD=E8=B7=AF?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 38 +++++++++++++++---------------- Cargo.toml | 2 +- crates/oxide_vm/src/vm/mod.rs | 3 ++- crates/oxide_vm/src/vm_runtime.rs | 29 +++++++++++++++++++++-- 4 files changed, 49 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55f7d293..1816f70a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.8.94" +version = "0.8.95" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.8.94" +version = "0.8.95" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.8.94" +version = "0.8.95" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.8.94" +version = "0.8.95" dependencies = [ "ansi_term", "bumpalo", @@ -1226,7 +1226,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.8.94" +version = "0.8.95" dependencies = [ "lru", "oxide_bytecode", @@ -1235,7 +1235,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.8.94" +version = "0.8.95" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1255,7 +1255,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.8.94" +version = "0.8.95" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1269,7 +1269,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.8.94" +version = "0.8.95" dependencies = [ "num-bigint", "oxc_allocator", @@ -1284,7 +1284,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.8.94" +version = "0.8.95" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1296,7 +1296,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.8.94" +version = "0.8.95" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.8.94" +version = "0.8.95" dependencies = [ "bumpalo", "dashmap", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.8.94" +version = "0.8.95" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.8.94" +version = "0.8.95" dependencies = [ "tracing", "tracing-appender", @@ -1340,7 +1340,7 @@ dependencies = [ [[package]] name = "oxide_parser" -version = "0.8.94" +version = "0.8.95" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1355,7 +1355,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.8.94" +version = "0.8.95" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1371,7 +1371,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.8.94" +version = "0.8.95" dependencies = [ "num-bigint", "num-traits", @@ -1384,7 +1384,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.8.94" +version = "0.8.95" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1402,7 +1402,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.8.94" +version = "0.8.95" dependencies = [ "bumpalo", "dashmap", @@ -1415,7 +1415,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.8.94" +version = "0.8.95" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 3bebf681..f50c6e89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ members = [ ] [workspace.package] -version = "0.8.94" +version = "0.8.95" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_vm/src/vm/mod.rs b/crates/oxide_vm/src/vm/mod.rs index 8b5eae17..0a1e8755 100644 --- a/crates/oxide_vm/src/vm/mod.rs +++ b/crates/oxide_vm/src/vm/mod.rs @@ -168,7 +168,8 @@ pub struct Vm { pub(crate) regs: [JsValue; 256], pub(crate) pc: usize, /// 当前活动字节码。以 `Arc<[Instr]>` 共享:函数调用经 `Arc::clone` 换帧(O(1)), - /// 不再逐帧深拷贝。与子模块平表源共享同一缓冲,IC 写回经 `bytecode_mut` 的 + /// 不再逐帧深拷贝。顶层装载期按引用计数条件复制(共享时显式深拷贝,独占时 + /// 零拷贝),子模块平表源保持惰性 COW,IC 写回经 `bytecode_mut` 的 /// `Arc::make_mut` 写时复制,保证独占后才改写(miss 时才深拷贝,频率低)。 pub(crate) bytecode: Arc<[opcode::Instr]>, /// 当前活动模块已转换不可变常量的只读视图(指向当前表代际的 immutables 内部)。 diff --git a/crates/oxide_vm/src/vm_runtime.rs b/crates/oxide_vm/src/vm_runtime.rs index 569cb192..d764ca58 100644 --- a/crates/oxide_vm/src/vm_runtime.rs +++ b/crates/oxide_vm/src/vm_runtime.rs @@ -664,7 +664,8 @@ impl Vm { /// 加载并执行一个已编译模块,返回模块顶层执行结果或未捕获异常消息。 /// /// 模块以 `Arc` 与调用方共享(如 CodeForge 缓存条目):平表装载只做 - /// Arc::clone,run 期零模块拷贝。内部初始化寄存器/bytecode/immutables 与 + /// Arc::clone,顶层字节码按引用计数条件复制(共享时装载期显式深拷贝, + /// 独占时零拷贝)。内部初始化寄存器/bytecode/immutables 与 /// builtin 寄存器预绑定,然后进入 dispatch 主循环;执行完成或异常展开后返回。 pub fn run(&mut self, module: &Arc) -> Result { vm_debug!("run: starting bytecode execution, {} instructions", module.bytecode.len()); @@ -696,7 +697,15 @@ impl Vm { self.active_table_gen = self.current_gen; // 顶层脚本严格模式:无帧且无 inline 时写路径的 strict/sloppy 判定来源。 self.top_level_strict = module.is_strict; - self.bytecode = Arc::clone(&module.bytecode); + // 顶层字节码按模块引用计数条件复制:模块被宿主共享(外层 Arc 计数 > 1, + // 如 CodeForge 缓存条目与调用方各持一份)时装载期显式深拷贝,把 COW 深拷贝 + // 从 dispatch 主循环热路径挪到 run 装载期(批量、可预测);模块独占(计数 1, + // 如 worker 新编译模块)保持 Arc::clone,无宿主共享缓冲需保护,复制无收益。 + if Arc::strong_count(module) > 1 { + self.bytecode = Arc::from(&module.bytecode[..]); + } else { + self.bytecode = Arc::clone(&module.bytecode); + } self.activate_immutables(self.current_gen, 0, &module.constants); self.root_reg_limit = module.n_registers.max(1); self.active_reg_limit = self.root_reg_limit; @@ -933,6 +942,22 @@ mod tests { assert_eq!(vm.bytecode.len(), module.bytecode.len()); } + #[test] + fn run_copies_bytecode_when_shared() { + // 顶层字节码装载期显式副本:共享模块(引用计数 > 1)在 run 装载期即深拷贝, + // 即使零 IC miss(无写回触发惰性 COW)Vm.bytecode 也须是私有 Arc 实例。 + // 本钉在惰性 COW 行为下必失败(无写回则不拷贝,保持与宿主同一实例)。 + let mut vm = Vm::new(); + let module = Arc::new(compile("var x = 1; x + 1")); + let shared = Arc::clone(&module); // 双 Arc 计数,模拟宿主缓存共享 + vm.run(&shared).expect("run"); + assert!( + !Arc::ptr_eq(&module.bytecode, &vm.bytecode), + "共享模块装载期须显式复制,Vm.bytecode 不得与宿主共享同一 Arc" + ); + assert_eq!(vm.bytecode.len(), module.bytecode.len()); + } + #[test] fn save_restore_inline_round_trip() { // 构造带哨兵的 VM → save → 恢复 → 断言全部字段逐字往返(含 accessor_frame_target_reg)。