fix: 模块求值状态表补入 GC 根遍历防命名空间对象悬垂

This commit is contained in:
2026-10-14 06:18:47 +00:00
parent 05576fc406
commit 7177d43adb
4 changed files with 56 additions and 25 deletions
Generated
+21 -21
View File
@@ -1160,7 +1160,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_builtins" name = "oxide_builtins"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"chrono", "chrono",
"fast-float", "fast-float",
@@ -1185,7 +1185,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_bytecode" name = "oxide_bytecode"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"num-bigint", "num-bigint",
"oxide_log", "oxide_log",
@@ -1193,7 +1193,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_cfg" name = "oxide_cfg"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"oxide_bytecode", "oxide_bytecode",
"oxide_emit", "oxide_emit",
@@ -1204,7 +1204,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_cli" name = "oxide_cli"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"ansi_term", "ansi_term",
"bumpalo", "bumpalo",
@@ -1228,7 +1228,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_code_cache" name = "oxide_code_cache"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"lru", "lru",
"oxide_bytecode", "oxide_bytecode",
@@ -1237,7 +1237,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_compiler" name = "oxide_compiler"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"oxide_bytecode", "oxide_bytecode",
"oxide_cfg", "oxide_cfg",
@@ -1258,7 +1258,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_dce" name = "oxide_dce"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"oxide_bytecode", "oxide_bytecode",
"oxide_cfg", "oxide_cfg",
@@ -1272,7 +1272,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_emit" name = "oxide_emit"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"num-bigint", "num-bigint",
"oxc_allocator", "oxc_allocator",
@@ -1288,7 +1288,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_engine" name = "oxide_engine"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"oxide_bytecode", "oxide_bytecode",
"oxide_compiler", "oxide_compiler",
@@ -1300,7 +1300,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_fold" name = "oxide_fold"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"num-bigint", "num-bigint",
"oxide_bytecode", "oxide_bytecode",
@@ -1312,7 +1312,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_ir" name = "oxide_ir"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"oxide_bytecode", "oxide_bytecode",
"oxide_log", "oxide_log",
@@ -1321,7 +1321,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_kernel" name = "oxide_kernel"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"dashmap", "dashmap",
@@ -1335,7 +1335,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_liveness" name = "oxide_liveness"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"oxide_bytecode", "oxide_bytecode",
"oxide_cfg", "oxide_cfg",
@@ -1347,7 +1347,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_log" name = "oxide_log"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"tracing", "tracing",
"tracing-appender", "tracing-appender",
@@ -1356,11 +1356,11 @@ dependencies = [
[[package]] [[package]]
name = "oxide_net" name = "oxide_net"
version = "0.19.1" version = "0.19.3"
[[package]] [[package]]
name = "oxide_parser" name = "oxide_parser"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"oxc_allocator", "oxc_allocator",
"oxc_ast", "oxc_ast",
@@ -1375,7 +1375,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_regalloc" name = "oxide_regalloc"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"oxide_bytecode", "oxide_bytecode",
"oxide_cfg", "oxide_cfg",
@@ -1391,7 +1391,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_runtime_api" name = "oxide_runtime_api"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"num-bigint", "num-bigint",
"num-traits", "num-traits",
@@ -1404,7 +1404,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_test262" name = "oxide_test262"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"oxide_bytecode", "oxide_bytecode",
"oxide_compiler", "oxide_compiler",
@@ -1424,7 +1424,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_types" name = "oxide_types"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"dashmap", "dashmap",
@@ -1437,7 +1437,7 @@ dependencies = [
[[package]] [[package]]
name = "oxide_vm" name = "oxide_vm"
version = "0.19.1" version = "0.19.3"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"chrono", "chrono",
+1 -1
View File
@@ -25,7 +25,7 @@ members = [
] ]
[workspace.package] [workspace.package]
version = "0.19.2" version = "0.19.3"
edition = "2021" edition = "2021"
license = "MIT" license = "MIT"
rust-version = "1.80" rust-version = "1.80"
+25
View File
@@ -1233,6 +1233,31 @@ mod tests {
assert_eq!(state.error.unwrap().as_js_object_ptr(), err_ptr, "error 指针应稳定"); 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] #[test]
fn deferred_ns_read_target_falls_back_for_non_object_namespace() { fn deferred_ns_read_target_falls_back_for_non_object_namespace() {
let (mut vm, fn_val) = vm_with_function(); let (mut vm, fn_val) = vm_with_function();
+9 -3
View File
@@ -8,7 +8,7 @@ use super::frames::Completion;
use super::Vm; use super::Vm;
use crate::session_gc::SessionGc; use crate::session_gc::SessionGc;
/// GC 根组来源:`for_each_value` 枚举的 27 个根组,变体顺序与根清单 /// GC 根组来源:`for_each_value` 枚举的 29 个根组,变体顺序与根清单
/// 的枚举顺序一致。 /// 的枚举顺序一致。
/// ///
/// 变体下标是逐组计数数组(`SessionGc::root_counts`)的下标;`COUNT` 与 /// 变体下标是逐组计数数组(`SessionGc::root_counts`)的下标;`COUNT` 与
@@ -43,11 +43,12 @@ pub(crate) enum RootGroup {
WorkerObjects, WorkerObjects,
DisposeStack, DisposeStack,
EventTargets, EventTargets,
ModuleEvalStates,
} }
impl RootGroup { impl RootGroup {
/// 根组总数(与变体数同源,绑定逐组计数数组的长度)。 /// 根组总数(与变体数同源,绑定逐组计数数组的长度)。
pub const COUNT: usize = 28; pub const COUNT: usize = 29;
} }
impl Vm { impl Vm {
@@ -55,7 +56,7 @@ impl Vm {
/// 覆盖执行核心的全部 JsValue 持有点:regs/帧/各栈段/cell/在途异常与完成/ /// 覆盖执行核心的全部 JsValue 持有点:regs/帧/各栈段/cell/在途异常与完成/
/// 挂起信号/迭代器/微任务/global/Worker 对象注册表。 /// 挂起信号/迭代器/微任务/global/Worker 对象注册表。
/// ///
/// 闭包接收根组来源(`RootGroup`)与根值:组是枚举顺序中的 27 根组之一, /// 闭包接收根组来源(`RootGroup`)与根值:组是枚举顺序中的 29 根组之一,
/// 调用方按组计数(如 `SessionGc` 的逐组计数)。 /// 调用方按组计数(如 `SessionGc` 的逐组计数)。
pub(crate) fn for_each_value(&self, mut f: impl FnMut(RootGroup, JsValue)) { pub(crate) fn for_each_value(&self, mut f: impl FnMut(RootGroup, JsValue)) {
for value in &self.regs { for value in &self.regs {
@@ -193,6 +194,11 @@ impl Vm {
f(RootGroup::EventTargets, entry.callback); 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` 相同。 /// GC 根统一枚举入口:遍历的字段清单与 `for_each_value` 相同。