feat: ShadowRealm evaluate 与 importValue 真实现落地

This commit is contained in:
2026-10-19 04:47:57 +00:00
parent d765346e37
commit ed10209764
15 changed files with 629 additions and 72 deletions
+29 -2
View File
@@ -6,14 +6,14 @@ use std::sync::{Arc, OnceLock};
use oxide_bytecode::module::CompiledModule;
use oxide_bytecode::opcode::{self, OpCode};
use oxide_runtime_api::CompilerService;
use oxide_runtime_api::{CompilerService, ModuleSourceLoader};
use oxide_types::object::PropAttributes;
use oxide_types::value::JsValue;
use super::Vm;
use crate::vm_support::FunctionFlags;
/// 缺省 no-op 编译服务:两方法均返 `Err`(错误消息指向「未安装编译服务」)。
/// 缺省 no-op 编译服务:三方法均返 `Err`(错误消息指向「未安装编译服务」)。
///
/// 供不需要动态编译的 `Vm` 实例(构造器缺省值);生产 entry points 与
/// 动态编译测试经 `set_compiler_service` 注入真实实现。
@@ -27,6 +27,12 @@ impl CompilerService for NoopCompilerService {
fn compile_eval_script(&self, _source: &str) -> Result<CompiledModule, String> {
Err("dynamic compilation unavailable: no compiler service installed".to_string())
}
fn compile_module(
&self, _source: &str, _module_path: &str, _loader: &mut dyn ModuleSourceLoader,
) -> Result<CompiledModule, String> {
Err("dynamic compilation unavailable: no compiler service installed".to_string())
}
}
impl Vm {
@@ -90,6 +96,13 @@ impl Vm {
// 子树重编号 + 追加:base = 当前代际平表长度,DFS 前序压入,push 序即新
// flat_id。make_mut 彼时平表 Arc 强引用唯一持有者是本表,原地扩展不分叉。
let table = self.current_table_mut();
// 空表(新 Vm / full_reset 后首个动态函数)补占位模块:函数对象落 index 0
// 会被 sub_module_index()==0 守卫误判为无本体函数对象。
if table.modules.is_empty() {
Arc::make_mut(&mut table.modules).insert(0, Arc::new(CompiledModule::new()));
table.immutables.insert(0, OnceLock::new());
table.si_tables.insert(0, OnceLock::new());
}
let base = table.modules.len() as u32;
let mut added = Vec::new();
rehome_subtree(&anonymous, base, &mut added);
@@ -150,6 +163,13 @@ impl Vm {
// 根模块 flat_id=0 传 base+1,重编号后落 base(避开 sub_module_index()==0
// 守卫)。make_mut 彼时平表 Arc 强引用唯一持有者是本表,原地扩展不分叉。
let table = self.current_table_mut();
// 空表(新 Vm / full_reset 后首段动态脚本)补占位模块:首个动态脚本的根
// 落 index 0 会被 sub_module_index()==0 守卫误判为无本体函数对象。
if table.modules.is_empty() {
Arc::make_mut(&mut table.modules).insert(0, Arc::new(CompiledModule::new()));
table.immutables.insert(0, OnceLock::new());
table.si_tables.insert(0, OnceLock::new());
}
let base = table.modules.len() as u32;
let mut added = Vec::new();
rehome_subtree(&module, base + 1, &mut added);
@@ -189,6 +209,13 @@ impl Vm {
// 根模块 flat_id=0 传 base+1,重编号后落 base(避开 sub_module_index()==0
// 守卫)。make_mut 彼时平表 Arc 强引用唯一持有者是本表,原地扩展不分叉。
let table = self.current_table_mut();
// 空表(新 Vm / full_reset 后首段动态脚本)补占位模块:首个动态脚本的根
// 落 index 0 会被 sub_module_index()==0 守卫误判为无本体函数对象。
if table.modules.is_empty() {
Arc::make_mut(&mut table.modules).insert(0, Arc::new(CompiledModule::new()));
table.immutables.insert(0, OnceLock::new());
table.si_tables.insert(0, OnceLock::new());
}
let base = table.modules.len() as u32;
let mut added = Vec::new();
rehome_subtree(&module, base + 1, &mut added);
+16 -1
View File
@@ -45,11 +45,13 @@ pub(crate) enum RootGroup {
DisposeStack,
EventTargets,
ModuleEvalStates,
ShadowKeepalive,
WrappedFunctionState,
}
impl RootGroup {
/// 根组总数(与变体数同源,绑定逐组计数数组的长度)。
pub const COUNT: usize = 30;
pub const COUNT: usize = 32;
}
impl Vm {
@@ -205,6 +207,19 @@ impl Vm {
for state in self.module_eval_states.values() {
f(RootGroup::ModuleEvalStates, state.namespace);
}
// WrappedFunction 保活表(影子 realm 侧):原函数是 GC 根,漏根 →
// 影子 GC 回收 → WrappedFunction 持悬垂引用。
for &value in &self.shadow_keepalive {
f(RootGroup::ShadowKeepalive, value);
}
// WrappedFunction 状态表(主 realm 侧):键(WrappedFunction 对象)是 GC 根,
// 漏根 → sweep 释放 → 调用点反查悬垂。
for &wrapped_ptr in self.wrapped_function_state.keys() {
if wrapped_ptr.is_null() {
continue;
}
f(RootGroup::WrappedFunctionState, JsValue::from_js_object(wrapped_ptr));
}
}
/// GC 根统一枚举入口:遍历的字段清单与 `for_each_value` 相同。
+15
View File
@@ -481,6 +481,21 @@ pub struct Vm {
/// Vm)。实例对象是 GC 根(`for_each_value` 遍历);影子 Vm 不跨线程,
/// 随主 Vm 整体迁移,在 `full_reset` / `Drop` 清表时统一释放。
pub(crate) shadow_realm_objects: std::collections::HashMap<u64, (JsValue, Vm)>,
/// WrappedFunction 保活表:本 Vm 的 GC 根,存放被 WrappedFunction 包装的
/// 原函数(本 Vm 堆内对象)。WrappedFunction 持有跨 realm 逻辑边,原函数
/// 须在属主 Vm 本表保活防属主 GC 回收;条目随 WrappedFunction 消亡孤儿至
/// Vm 收尾(规模有界于包装数)。
pub(crate) shadow_keepalive: std::vec::Vec<JsValue>,
/// WrappedFunction 状态表:键 = WrappedFunction 对象指针,值 =
/// (原函数属主 realm 编号,属主 Vm 保活表下标)。是 GC 根(键保活
/// WrappedFunction);值非 GC 边。主 Vm 与影子 Vm 均可持有(包装方向
/// 双向:evaluate 结果包装影子函数、包装函数实参包装主 realm 函数)。
pub(crate) wrapped_function_state: std::collections::HashMap<*mut JsObject, (u64, usize)>,
/// 属主 Vm 指针(影子 realm 侧):影子 Vm 建时指向创建它的属主 Vm,主 Vm
/// 恒空。供跨 realm 结算沿属主链上溯解析远端 realm 的属主 Vm(嵌套影子
/// realm 包装主 realm 函数场景)。与属主 Vm 同线程、同生命周期(属主 Vm
/// 侧表持影子 Vm,先于影子 Vm 存活),指针有效。
pub(crate) owner_vm: *mut Vm,
}
impl Drop for Vm {