fix: 恢复边界镜像重载跳过 native pack 实参区

This commit is contained in:
2026-09-19 19:26:06 +00:00
parent 8cd3cf1440
commit 1d7561d07c
6 changed files with 303 additions and 12 deletions
+6 -1
View File
@@ -79,6 +79,7 @@ impl Vm {
let overflow_base = self.spill_stack.len();
let saved_overflow_base = self.native_overflow_base;
let saved_overflow_count = self.native_overflow_count;
let saved_pack_end = self.native_pack_end;
if args.len() > Self::SYNC_NATIVE_ARG_LIMIT {
self.spill_stack.extend_from_slice(&args[Self::SYNC_NATIVE_ARG_LIMIT..]);
self.native_overflow_base = overflow_base;
@@ -94,6 +95,9 @@ impl Vm {
let saved_r254 = self.regs[254];
let pack_limit = args.len().min(Self::SYNC_NATIVE_ARG_LIMIT);
let arg_regs = self.pack_sync_native_call_args(receiver, callee, &args[..pack_limit]);
// 实参区在飞期间生效:native 体内一切恢复边界的镜像重载据此跳过
// regs[0..pack_limit),防止外层 builtin 尚未读取的实参被覆写。
self.native_pack_end = pack_limit;
// SAFETY: native_fn 经 set_native_fn 以合法 NativeFn 指针设置;
// native_fn_ptr_to_fn 是 NativeFnPtr → NativeFn 的唯一强制转换点。
let func: NativeFn = unsafe { native_fn_ptr_to_fn(native_fn) };
@@ -106,6 +110,7 @@ impl Vm {
}
self.native_overflow_base = saved_overflow_base;
self.native_overflow_count = saved_overflow_count;
self.native_pack_end = saved_pack_end;
// 窗口回拷 + regs[253]/[254] 单回,缓冲归还池复用。
self.regs[..window].copy_from_slice(&saved_window);
self.regs[253] = saved_r253;
@@ -304,7 +309,7 @@ impl Vm {
self.bytecode = sub_bytecode;
self.activate_immutables(gen, sub_idx, &sub.constants);
self.cell_stack.push(Vec::with_capacity(sub.cells_needed as usize));
self.reload_builtin_mirror_slots(&sub.builtin_reg_map);
self.reload_builtin_mirror_slots(&sub.builtin_reg_map, 0);
self.active_reg_limit = sub_n_registers.max(1);
self.pc = 0;
+6
View File
@@ -268,6 +268,12 @@ pub struct Vm {
/// `restore_inline_state` 归还。热回调循环内 save/restore 反复使用同一块
/// 缓冲,只在嵌套(池已被外层取走)时新分配。
pub(crate) inline_reg_pool: Option<Vec<JsValue>>,
/// 外层 native pack 实参区上界(独占):`call_function_sync` native 分支在飞
/// 期间实参已 pack 进 `regs[0..pack_end)`,恢复边界(`restore_inline_state` /
/// `restore_frame`)的镜像重载须跳过该域——重载目标恰是外层 builtin 尚未
/// 读取的实参寄存器。0 = 无 pack 上下文;跨嵌套 native 调用存/还原
/// (与 overflow 描述符同构)。
pub(crate) native_pack_end: usize,
/// 生成器体 `dispatch()` 让出时的信号:YIELD 置 Some(让出值),恢复方(
/// generator 内嵌 dispatch 循环)取走并判定挂起。None = 正常返回/异常。
pub(crate) generator_suspended: Option<JsValue>,