From 7177d43adbc782a966851bd73953a8fe0cf414fa Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Wed, 14 Oct 2026 06:18:47 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A8=A1=E5=9D=97=E6=B1=82=E5=80=BC?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E8=A1=A8=E8=A1=A5=E5=85=A5=20GC=20=E6=A0=B9?= =?UTF-8?q?=E9=81=8D=E5=8E=86=E9=98=B2=E5=91=BD=E5=90=8D=E7=A9=BA=E9=97=B4?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E6=82=AC=E5=9E=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 42 ++++++++++++++--------------- Cargo.toml | 2 +- crates/oxide_builtins/src/module.rs | 25 +++++++++++++++++ crates/oxide_vm/src/vm/gc_hooks.rs | 12 ++++++--- 4 files changed, 56 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40f6f223..95c09f4d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.19.1" +version = "0.19.3" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.19.1" +version = "0.19.3" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.19.1" +version = "0.19.3" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.19.1" +version = "0.19.3" dependencies = [ "ansi_term", "bumpalo", @@ -1228,7 +1228,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.19.1" +version = "0.19.3" dependencies = [ "lru", "oxide_bytecode", @@ -1237,7 +1237,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.19.1" +version = "0.19.3" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1258,7 +1258,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.19.1" +version = "0.19.3" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1272,7 +1272,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.19.1" +version = "0.19.3" dependencies = [ "num-bigint", "oxc_allocator", @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.19.1" +version = "0.19.3" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1300,7 +1300,7 @@ dependencies = [ [[package]] name = "oxide_fold" -version = "0.19.1" +version = "0.19.3" dependencies = [ "num-bigint", "oxide_bytecode", @@ -1312,7 +1312,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.19.1" +version = "0.19.3" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1321,7 +1321,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.19.1" +version = "0.19.3" dependencies = [ "bumpalo", "dashmap", @@ -1335,7 +1335,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.19.1" +version = "0.19.3" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1347,7 +1347,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.19.1" +version = "0.19.3" dependencies = [ "tracing", "tracing-appender", @@ -1356,11 +1356,11 @@ dependencies = [ [[package]] name = "oxide_net" -version = "0.19.1" +version = "0.19.3" [[package]] name = "oxide_parser" -version = "0.19.1" +version = "0.19.3" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1375,7 +1375,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.19.1" +version = "0.19.3" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.19.1" +version = "0.19.3" dependencies = [ "num-bigint", "num-traits", @@ -1404,7 +1404,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.19.1" +version = "0.19.3" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1424,7 +1424,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.19.1" +version = "0.19.3" dependencies = [ "bumpalo", "dashmap", @@ -1437,7 +1437,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.19.1" +version = "0.19.3" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index af42b1df..dab1b13b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ members = [ ] [workspace.package] -version = "0.19.2" +version = "0.19.3" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_builtins/src/module.rs b/crates/oxide_builtins/src/module.rs index 36782c86..52f2d05c 100644 --- a/crates/oxide_builtins/src/module.rs +++ b/crates/oxide_builtins/src/module.rs @@ -1233,6 +1233,31 @@ mod tests { assert_eq!(state.error.unwrap().as_js_object_ptr(), err_ptr, "error 指针应稳定"); } + #[test] + fn module_eval_state_ns_survives_session_gc() { + let (mut vm, fn_val) = vm_with_function(); + // 依赖模块函数经寄存器钉为根,首收集达稳态后记录基线。 + vm.set_reg(0, fn_val); + vm.collect_session_gc(); + let baseline = vm.session_object_count(); + + // 命名空间对象为唯一新增 session 对象:per-module 求值状态表是其唯一根。 + let ns = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())); + let ns_val = JsValue::from_js_object(ns); + let ns_ptr = ns_val.as_js_object_ptr(); + vm.set_module_eval_state("p", true, ns_val); + assert_eq!(vm.session_object_count(), baseline + 1, "命名空间对象应已分配"); + + // 完整收集:若状态表边漏登,命名空间对象被回收、计数回落。 + vm.collect_session_gc(); + + assert_eq!(vm.session_object_count(), baseline + 1, "per-module 状态命名空间对象应跨收集存活(GC 边已登记)"); + // 原地 sweep 不搬移:状态表原地保留,命名空间指针稳定。 + let state = vm.get_module_eval_state("p").expect("per-module 状态应存活"); + assert!(state.evaluated, "evaluated 标志应稳定"); + assert_eq!(state.namespace.as_js_object_ptr(), ns_ptr, "命名空间指针应稳定"); + } + #[test] fn deferred_ns_read_target_falls_back_for_non_object_namespace() { let (mut vm, fn_val) = vm_with_function(); diff --git a/crates/oxide_vm/src/vm/gc_hooks.rs b/crates/oxide_vm/src/vm/gc_hooks.rs index 6655ac4d..17192283 100644 --- a/crates/oxide_vm/src/vm/gc_hooks.rs +++ b/crates/oxide_vm/src/vm/gc_hooks.rs @@ -8,7 +8,7 @@ use super::frames::Completion; use super::Vm; use crate::session_gc::SessionGc; -/// GC 根组来源:`for_each_value` 枚举的 27 个根组,变体顺序与根清单 +/// GC 根组来源:`for_each_value` 枚举的 29 个根组,变体顺序与根清单 /// 的枚举顺序一致。 /// /// 变体下标是逐组计数数组(`SessionGc::root_counts`)的下标;`COUNT` 与 @@ -43,11 +43,12 @@ pub(crate) enum RootGroup { WorkerObjects, DisposeStack, EventTargets, + ModuleEvalStates, } impl RootGroup { /// 根组总数(与变体数同源,绑定逐组计数数组的长度)。 - pub const COUNT: usize = 28; + pub const COUNT: usize = 29; } impl Vm { @@ -55,7 +56,7 @@ impl Vm { /// 覆盖执行核心的全部 JsValue 持有点:regs/帧/各栈段/cell/在途异常与完成/ /// 挂起信号/迭代器/微任务/global/Worker 对象注册表。 /// - /// 闭包接收根组来源(`RootGroup`)与根值:组是枚举顺序中的 27 根组之一, + /// 闭包接收根组来源(`RootGroup`)与根值:组是枚举顺序中的 29 根组之一, /// 调用方按组计数(如 `SessionGc` 的逐组计数)。 pub(crate) fn for_each_value(&self, mut f: impl FnMut(RootGroup, JsValue)) { for value in &self.regs { @@ -193,6 +194,11 @@ impl Vm { f(RootGroup::EventTargets, entry.callback); } } + // per-module 求值状态表持命名空间对象与 capability promise:漏根 → + // session GC 回收 → 后续读点(缓存命名空间取回 / 再查)解引用悬垂。 + for state in self.module_eval_states.values() { + f(RootGroup::ModuleEvalStates, state.namespace); + } } /// GC 根统一枚举入口:遍历的字段清单与 `for_each_value` 相同。