mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 11:11:11 +08:00
feat: await using 释放挂起跨微任务续行并合并 SuppressedError
This commit is contained in:
@@ -118,6 +118,14 @@ impl Vm {
|
||||
}
|
||||
loop {
|
||||
steps += 1;
|
||||
// 异步释放挂起:unwind 经 dispose_above 挂起时须让内嵌 dispatch 返回
|
||||
// (挂起信号由 register_dispose_suspend 置位,此处统一消费,覆盖 THROW
|
||||
// 与各错误处理器路径;AWAIT/BREAK/CONTINUE/RETURN/DISPOSE_POP 各臂已
|
||||
// 就地返回,此处为兜底)。
|
||||
if self.async_suspended || self.async_gen_suspended {
|
||||
self.profiling.set_instruction_count(steps);
|
||||
return Ok(JsValue::undefined());
|
||||
}
|
||||
// 执行期 GC 安全点:仅在顶层 dispatch(native_call_depth == 0)
|
||||
// 的指令边界触发——嵌套 dispatch(builtin 经 call_function_sync 重入
|
||||
// 执行 JS 回调、generator/async 恢复)期间,调用方寄存器窗口副本存于
|
||||
@@ -294,6 +302,12 @@ impl Vm {
|
||||
}
|
||||
OpCode::DISPOSE_POP => {
|
||||
self.dispatch_dispose_pop()?;
|
||||
// `await using` 释放的异步挂起:挂起时须像 AWAIT 一样让内嵌
|
||||
// dispatch 返回,由恢复方快照状态。
|
||||
if self.async_suspended || self.async_gen_suspended {
|
||||
self.profiling.set_instruction_count(steps);
|
||||
return Ok(JsValue::undefined());
|
||||
}
|
||||
}
|
||||
OpCode::CELL_GET => {
|
||||
self.dispatch_cell_get(rd, a, b)?;
|
||||
|
||||
@@ -8,7 +8,7 @@ use super::frames::Completion;
|
||||
use super::Vm;
|
||||
use crate::session_gc::SessionGc;
|
||||
|
||||
/// GC 根组来源:`for_each_value` 枚举的 26 个根组,变体顺序与根清单
|
||||
/// GC 根组来源:`for_each_value` 枚举的 27 个根组,变体顺序与根清单
|
||||
/// 的枚举顺序一致。
|
||||
///
|
||||
/// 变体下标是逐组计数数组(`SessionGc::root_counts`)的下标;`COUNT` 与
|
||||
@@ -31,6 +31,7 @@ pub(crate) enum RootGroup {
|
||||
AsyncContext,
|
||||
AsyncGenContext,
|
||||
PendingAsyncEscape,
|
||||
PendingAsyncDispose,
|
||||
InlineCallee,
|
||||
TemplateObjects,
|
||||
NumberToStringCache,
|
||||
@@ -45,7 +46,7 @@ pub(crate) enum RootGroup {
|
||||
|
||||
impl RootGroup {
|
||||
/// 根组总数(与变体数同源,绑定逐组计数数组的长度)。
|
||||
pub const COUNT: usize = 26;
|
||||
pub const COUNT: usize = 27;
|
||||
}
|
||||
|
||||
impl Vm {
|
||||
@@ -53,7 +54,7 @@ impl Vm {
|
||||
/// 覆盖执行核心的全部 JsValue 持有点:regs/帧/各栈段/cell/在途异常与完成/
|
||||
/// 挂起信号/迭代器/微任务/global/Worker 对象注册表。
|
||||
///
|
||||
/// 闭包接收根组来源(`RootGroup`)与根值:组是枚举顺序中的 26 根组之一,
|
||||
/// 闭包接收根组来源(`RootGroup`)与根值:组是枚举顺序中的 27 根组之一,
|
||||
/// 调用方按组计数(如 `SessionGc` 的逐组计数)。
|
||||
pub(crate) fn for_each_value(&self, mut f: impl FnMut(RootGroup, JsValue)) {
|
||||
for value in &self.regs {
|
||||
@@ -121,6 +122,16 @@ impl Vm {
|
||||
f(RootGroup::PendingAsyncEscape, v);
|
||||
}
|
||||
}
|
||||
// 在途异步释放的 promise/合并错误/完成值都是 GC 根。
|
||||
if let Some(pend) = &self.pending_async_dispose {
|
||||
f(RootGroup::PendingAsyncDispose, pend.dispose_promise);
|
||||
if let Some(v) = pend.completion {
|
||||
f(RootGroup::PendingAsyncDispose, v);
|
||||
}
|
||||
if let super::DisposeResumeKind::Escape(Completion::Return { value, .. }) = pend.kind {
|
||||
f(RootGroup::PendingAsyncDispose, value);
|
||||
}
|
||||
}
|
||||
f(RootGroup::InlineCallee, self.inline_callee.unwrap_or(JsValue::undefined()));
|
||||
// 标签模板对象缓存:命中的模板对象是 GC 根(未根 → sweep 搬移/回收悬垂)。
|
||||
for &cached in self.template_objects.values() {
|
||||
|
||||
@@ -159,6 +159,31 @@ pub(crate) struct PendingAsyncEscape {
|
||||
pub(crate) remaining: Vec<JsValue>,
|
||||
}
|
||||
|
||||
/// `await using` 资源释放的异步挂起在途状态:释放方法的 promise 挂起等待结算,
|
||||
/// 结算闭包(微任务)恢复挂起帧后继续释放剩余条目并执行完成。
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct PendingAsyncDispose {
|
||||
/// 正在等待的释放方法 promise(结算闭包陈旧防御校验用)。
|
||||
pub(crate) dispose_promise: JsValue,
|
||||
/// 作用域水位:恢复后继续释放水位以上条目(LIFO)。
|
||||
pub(crate) mark: usize,
|
||||
/// 在途合并错误(SuppressedError 链跨挂起累积)。
|
||||
pub(crate) completion: Option<JsValue>,
|
||||
/// 释放循环结束后的恢复动作类别。
|
||||
pub(crate) kind: DisposeResumeKind,
|
||||
}
|
||||
|
||||
/// 释放循环结束后的恢复动作类别(三穿越点)。
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub(crate) enum DisposeResumeKind {
|
||||
/// 作用域出口正常完成:有合并错误则展开,否则续行。
|
||||
Pop,
|
||||
/// 异常穿越:handler 已弹出,恢复时重压后再入 unwind。
|
||||
Unwind(Option<TryHandler>),
|
||||
/// return/break/continue 穿越:有合并错误则丢弃完成值并展开,否则执行完成。
|
||||
Escape(Completion),
|
||||
}
|
||||
|
||||
/// 基于寄存器的 JS 虚拟机:持有执行状态、寄存器文件、调用栈与 session 内存。
|
||||
///
|
||||
/// 执行入口为 [`Vm::run`](见 `vm_runtime` 模块);内存模型为统一入口分配 +
|
||||
@@ -268,6 +293,9 @@ pub struct Vm {
|
||||
/// 逃出 for-await-of 的异步关闭在途状态:return() 的 promise 挂起等待结算,
|
||||
/// 结算闭包(微任务)恢复挂起帧后继续关闭剩余条目并执行完成。
|
||||
pub(crate) pending_async_escape: Option<PendingAsyncEscape>,
|
||||
/// `await using` 资源释放的异步挂起在途状态:释放方法的 promise 挂起等待
|
||||
/// 结算,结算闭包(微任务)恢复挂起帧后继续释放剩余条目并执行完成。
|
||||
pub(crate) pending_async_dispose: Option<PendingAsyncDispose>,
|
||||
pub(crate) root_reg_limit: u8,
|
||||
pub(crate) active_reg_limit: u8,
|
||||
pub(crate) native_call_depth: usize,
|
||||
|
||||
Reference in New Issue
Block a user