From f1d2f7cb478a5226cbca33417d54e0f5efff9ff4 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Fri, 11 Sep 2026 22:24:17 +0000 Subject: [PATCH] =?UTF-8?q?test:=20=E9=A1=B6=E5=B1=82=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=85=B1=E4=BA=AB=E6=8A=A4=E6=A0=8F=E9=92=89=E2=80=94=E2=80=94?= =?UTF-8?q?=E5=B9=B3=E8=A1=A8=E9=A1=B6=E5=B1=82=E4=B8=8E=E5=AE=BF=E4=B8=BB?= =?UTF-8?q?=20Arc=20=E5=90=8C=E4=B8=80=E5=AE=9E=E4=BE=8B=EF=BC=88=E5=90=AB?= =?UTF-8?q?=20full=5Freset=20=E5=90=8E=E4=BA=8C=E6=AC=A1=20run=EF=BC=89?= =?UTF-8?q?=EF=BC=8Crun=20=E5=90=8E=E5=AE=BF=E4=B8=BB=E7=BC=93=E5=86=B2=20?= =?UTF-8?q?IC=20=E6=89=A9=E5=B1=95=E5=AD=97=E6=81=92=E9=9B=B6=E4=B8=94=20V?= =?UTF-8?q?m.bytecode=20=E4=B8=BA=20COW=20=E7=A7=81=E6=9C=89=E6=8B=B7?= =?UTF-8?q?=E8=B4=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_vm/src/vm_runtime.rs | 43 +++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/crates/oxide_vm/src/vm_runtime.rs b/crates/oxide_vm/src/vm_runtime.rs index a4dd8a05..04214705 100644 --- a/crates/oxide_vm/src/vm_runtime.rs +++ b/crates/oxide_vm/src/vm_runtime.rs @@ -637,6 +637,49 @@ mod tests { use crate::vm::Completion; use oxide_types::value::JsValue; + fn compile(source: &str) -> oxide_bytecode::module::CompiledModule { + let allocator = oxide_parser::Allocator::default(); + let program = oxide_parser::parse(&allocator, source).expect("parse"); + oxide_compiler::compiler::Compiler::new().compile(&program).expect("compile") + } + + #[test] + fn top_level_module_entry_shares_host_arc() { + // 顶层平表条目 = 宿主模块 Arc 同一实例:run 期零模块克隆, + // 克隆会产出不同 Arc,本钉在此情形必失败。 + let mut vm = Vm::new(); + let module = Arc::new(compile("var o = { a: 1 }; o.a + o.a")); + vm.run(&module).expect("run1"); + assert!(Arc::ptr_eq(&vm.sub_modules[0], &module), "顶层条目须与宿主 Arc 同一实例"); + vm.full_reset(); + vm.run(&module).expect("run2"); + assert!(Arc::ptr_eq(&vm.sub_modules[0], &module), "full_reset 后二次 run 仍共享"); + } + + #[test] + fn top_level_run_keeps_host_bytecode_ic_words_zero() { + // 宿主侧 bytecode 的 IC 扩展字在 run 后恒零:IC 写回只发生在 + // Vm.bytecode 的 COW 私有拷贝上——dispatch 期平表与 Vm.bytecode 双持 + // 共享缓冲(refcount ≥ 2),make_mut 必先深拷贝再写,宿主共享缓冲 + // 结构上不可写。 + let mut vm = Vm::new(); + let module = Arc::new(compile("var o = { a: 1 }; o.a + o.a")); + vm.run(&module).expect("run"); + assert!(vm.ic_miss_count() > 0, "源含属性读取,应发生 IC miss 与写回"); + // 以 clear_ic_caches 的扫描口径作 oracle:IC 扩展字若已全零,清零是 no-op。 + let original: Vec = module.bytecode.to_vec(); + let mut probe = original.clone(); + crate::ic_helper::clear_ic_caches(&mut probe); + assert_eq!(probe, original, "宿主侧 IC 扩展字须全零"); + // 写回未落宿主缓冲:run 末 Vm.bytecode 是 COW 私有拷贝(不同分配), + // 而非宿主共享缓冲本身。 + assert!( + !Arc::ptr_eq(&module.bytecode, &vm.bytecode), + "Vm.bytecode 须为 COW 私有拷贝,写回不得落宿主缓冲" + ); + assert_eq!(vm.bytecode.len(), module.bytecode.len()); + } + #[test] fn save_restore_inline_round_trip() { // 构造带哨兵的 VM → save → 恢复 → 断言全部字段逐字往返(含 accessor_frame_target_reg)。