mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 19:21:11 +08:00
fix: 恢复边界镜像重载跳过 native pack 实参区
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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>,
|
||||
|
||||
@@ -271,10 +271,11 @@ impl Vm {
|
||||
}
|
||||
|
||||
/// 重载活动帧模块(`active_flat_id`)的 builtin 镜像槽:先按值取出名集再
|
||||
/// 写寄存器,避免借用交叉。帧恢复 / 重执行边界调用。
|
||||
pub(crate) fn reload_active_module_mirror_slots(&mut self) {
|
||||
/// 写寄存器,避免借用交叉。帧恢复 / 重执行边界调用;`pack_end` 为外层
|
||||
/// native pack 实参区上界(独占),落域镜像槽跳过。
|
||||
pub(crate) fn reload_active_module_mirror_slots(&mut self, pack_end: usize) {
|
||||
let map = self.active_module().map(|m| m.builtin_reg_map.clone()).unwrap_or_default();
|
||||
self.reload_builtin_mirror_slots(&map);
|
||||
self.reload_builtin_mirror_slots(&map, pack_end);
|
||||
}
|
||||
|
||||
/// 从全局对象 A 侧重载模块 builtin 名集的镜像槽:属性在位取原始存储值,
|
||||
@@ -283,14 +284,19 @@ impl Vm {
|
||||
/// # 边界与前提
|
||||
/// - 缺位臂语义为"写 undefined",各入口(run / 帧 / inline / 恢复)统一,
|
||||
/// 使成员形删除后的裸读与入口预载看到同一值。
|
||||
/// - `pack_end` 为 native pack 实参区上界(独占):落 [0, pack_end) 的镜像
|
||||
/// 槽跳过,实参值只存在于寄存器、无刷新源,窗口拷回负责其还原。
|
||||
/// # 副作用
|
||||
/// - 只写镜像槽寄存器(槽下标受编译期登记约束)。
|
||||
pub(crate) fn reload_builtin_mirror_slots(&mut self, map: &[(String, u32)]) {
|
||||
pub(crate) fn reload_builtin_mirror_slots(&mut self, map: &[(String, u32)], pack_end: usize) {
|
||||
if map.is_empty() {
|
||||
return;
|
||||
}
|
||||
let global = self.session.global_object();
|
||||
for (name, reg) in map {
|
||||
if (*reg as usize) < pack_end {
|
||||
continue;
|
||||
}
|
||||
let si = self.kernel_core.perm_interner().intern(name.as_str()).0;
|
||||
let val = self
|
||||
.kernel_core
|
||||
|
||||
@@ -332,8 +332,9 @@ impl Vm {
|
||||
let _window_regs: Vec<JsValue> = Vec::new();
|
||||
inline_core_fields!(vm, saved, inline_restore, _window_regs);
|
||||
// 窗口回拷已复活调用方陈旧镜像槽:重载调用方模块的 builtin 名集
|
||||
// (active_flat_id 已随宏回写还原到调用方)。
|
||||
vm.reload_active_module_mirror_slots();
|
||||
// (active_flat_id 已随宏回写还原到调用方);外层 native pack 实参区
|
||||
// 在飞时跳过该域,实参值由窗口拷回还原、不在此刷新。
|
||||
vm.reload_active_module_mirror_slots(vm.native_pack_end);
|
||||
}
|
||||
|
||||
/// 首次执行的 VM 就绪:清空执行核心(regs/pc/bytecode/各栈段/迭代器/内联态),
|
||||
@@ -486,7 +487,7 @@ impl Vm {
|
||||
receiver
|
||||
};
|
||||
self.regs[255] = JsValue::undefined();
|
||||
self.reload_builtin_mirror_slots(&sub.builtin_reg_map);
|
||||
self.reload_builtin_mirror_slots(&sub.builtin_reg_map, 0);
|
||||
let _ = callee;
|
||||
|
||||
vm_trace!(
|
||||
@@ -556,8 +557,9 @@ impl Vm {
|
||||
self.active_reg_limit = frame.caller_active_reg_limit;
|
||||
self.pc = frame.return_addr;
|
||||
// 窗口回拷已复活调用方陈旧镜像槽:重载调用方模块的 builtin 名集
|
||||
// (active_flat_id 已随保存栈弹回还原到调用方)。
|
||||
self.reload_active_module_mirror_slots();
|
||||
// (active_flat_id 已随保存栈弹回还原到调用方);外层 native pack
|
||||
// 实参区在飞时跳过该域,实参值由窗口拷回还原、不在此刷新。
|
||||
self.reload_active_module_mirror_slots(self.native_pack_end);
|
||||
}
|
||||
|
||||
/// 重新执行当前已加载的 bytecode:清空执行状态并重置 IC 缓存后再次 dispatch。
|
||||
@@ -572,7 +574,7 @@ impl Vm {
|
||||
self.active_reg_limit = self.root_reg_limit;
|
||||
self.regs[254] = self.top_level_this;
|
||||
// 寄存器文件清空后镜像槽须重载(与 run 入口同语义),否则裸读回陈旧值。
|
||||
self.reload_active_module_mirror_slots();
|
||||
self.reload_active_module_mirror_slots(0);
|
||||
crate::ic_helper::clear_ic_caches(self.bytecode_mut());
|
||||
self.dispatch()
|
||||
}
|
||||
@@ -644,7 +646,7 @@ impl Vm {
|
||||
self.root_reg_limit = module.n_registers.max(1);
|
||||
self.active_reg_limit = self.root_reg_limit;
|
||||
|
||||
self.reload_builtin_mirror_slots(&module.builtin_reg_map);
|
||||
self.reload_builtin_mirror_slots(&module.builtin_reg_map, 0);
|
||||
|
||||
// 顶层 this:脚本为全局对象(ECMA-262 全局执行上下文);
|
||||
// ES module 顶层环境 GetThisBinding 返回 undefined。记录到
|
||||
|
||||
@@ -104,6 +104,7 @@ impl Vm {
|
||||
top_level_strict: false,
|
||||
top_level_this: JsValue::undefined(),
|
||||
inline_reg_pool: None,
|
||||
native_pack_end: 0,
|
||||
generator_suspended: None,
|
||||
delegated_iterator: None,
|
||||
generator_dispatch: false,
|
||||
@@ -234,6 +235,7 @@ impl Vm {
|
||||
top_level_strict: false,
|
||||
top_level_this: JsValue::undefined(),
|
||||
inline_reg_pool: None,
|
||||
native_pack_end: 0,
|
||||
generator_suspended: None,
|
||||
delegated_iterator: None,
|
||||
generator_dispatch: false,
|
||||
|
||||
Reference in New Issue
Block a user