feat: using 声明登记释放栈指令与 GC 根

This commit is contained in:
2026-10-09 17:55:08 +00:00
parent 0df3f9d5fd
commit b5ff2c132a
10 changed files with 88 additions and 23 deletions
+3
View File
@@ -286,6 +286,9 @@ impl Vm {
OpCode::MAKE_CELL_FRESH => {
self.dispatch_make_cell_fresh(rd, instr)?;
}
OpCode::DISPOSE_REGISTER => {
self.dispatch_dispose_register(rd, a);
}
OpCode::CELL_GET => {
self.dispatch_cell_get(rd, a, b)?;
}
+8 -3
View File
@@ -8,7 +8,7 @@ use super::frames::Completion;
use super::Vm;
use crate::session_gc::SessionGc;
/// GC 根组来源:`for_each_value` 枚举的 25 个根组,变体顺序与根清单
/// GC 根组来源:`for_each_value` 枚举的 26 个根组,变体顺序与根清单
/// 的枚举顺序一致。
///
/// 变体下标是逐组计数数组(`SessionGc::root_counts`)的下标;`COUNT` 与
@@ -40,11 +40,12 @@ pub(crate) enum RootGroup {
ForInIters,
Global,
WorkerObjects,
DisposeStack,
}
impl RootGroup {
/// 根组总数(与变体数同源,绑定逐组计数数组的长度)。
pub const COUNT: usize = 25;
pub const COUNT: usize = 26;
}
impl Vm {
@@ -52,7 +53,7 @@ impl Vm {
/// 覆盖执行核心的全部 JsValue 持有点:regs/帧/各栈段/cell/在途异常与完成/
/// 挂起信号/迭代器/微任务/global/Worker 对象注册表。
///
/// 闭包接收根组来源(`RootGroup`)与根值:组是枚举顺序中的 25 根组之一,
/// 闭包接收根组来源(`RootGroup`)与根值:组是枚举顺序中的 26 根组之一,
/// 调用方按组计数(如 `SessionGc` 的逐组计数)。
pub(crate) fn for_each_value(&self, mut f: impl FnMut(RootGroup, JsValue)) {
for value in &self.regs {
@@ -82,6 +83,10 @@ impl Vm {
for &v in &self.spill_stack {
f(RootGroup::SpillStack, v);
}
// 释放栈持 using 声明的资源值:漏根 → sweep 释放 → 释放点解引用悬垂。
for &v in &self.dispose_stack {
f(RootGroup::DisposeStack, v);
}
for cell_vec in &self.cell_stack {
for &cell_ptr in cell_vec {
if cell_ptr.is_null() {
+4
View File
@@ -230,6 +230,10 @@ pub struct Vm {
/// VM 级 spill 栈。`CallFrame.spill_offset` 定位本帧区:调用子函数时从边界后分配,
/// 帧恢复时截断到边界,子函数 spill 数据随帧丢弃。
pub(crate) spill_stack: Vec<JsValue>,
/// using/await using 声明的资源释放栈:DISPOSE_REGISTER 把资源值压入,
/// 作用域出口点逆序释放(释放点由后续指令族承担)。栈内 JsValue 是 GC 根
/// (`for_each_value` 遍历);run 边界清空,防跨 run 残留条目在下一 run 被误释放。
pub(crate) dispose_stack: Vec<JsValue>,
/// 本次 native 调用的 spill 溢出实参区:`spill_stack[base..base+count)`。
/// 实参数超过寄存器窗口(253)时,窗口外的实参转存 spill 栈(GC 根),
/// native 侧经 `VmHost::native_arg_count`/`native_arg_at` 读取。仅在一次