mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 02:31:13 +08:00
refactor: kernel 会话段拆出独立 session 模块并收口
This commit is contained in:
@@ -1,263 +1,11 @@
|
||||
#![allow(clippy::arc_with_non_send_sync)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_types::mem::P;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::builtin::BuiltinWorld;
|
||||
use crate::shape_forge::EMPTY_SHAPE_ID;
|
||||
|
||||
mod builtin_id;
|
||||
mod config;
|
||||
mod core;
|
||||
mod session;
|
||||
|
||||
pub use builtin_id::{BuiltinDirtySet, BuiltinId, BuiltinSnapshot, NUM_BUILTINS};
|
||||
pub use config::KernelConfig;
|
||||
pub use core::KernelCore;
|
||||
|
||||
/// 每会话可变状态:内置原型对象与全局对象。
|
||||
/// 在 full_reset() 时重建,实现 JS 执行之间的完全隔离。
|
||||
pub struct KernelSession {
|
||||
pub builtin_world: Arc<BuiltinWorld>,
|
||||
pub global_object: P<JsObject>,
|
||||
pub builtin_snapshot: BuiltinSnapshot,
|
||||
}
|
||||
|
||||
impl KernelSession {
|
||||
fn new_global_object(core: &KernelCore) -> P<JsObject> {
|
||||
let mut global_obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
|
||||
let si_nan = core.perm_interner.intern("NaN").0;
|
||||
let si_undef = core.perm_interner.intern("undefined").0;
|
||||
let si_infinity = core.perm_interner.intern("Infinity").0;
|
||||
|
||||
// 全局三常量描述符:{ writable:false, enumerable:false, configurable:false }。
|
||||
// e:false 是枚举面守卫(Object.keys / for-in 由 enumerable 决定);
|
||||
// c:false 是 delete / defineProperty 可观察的规范值(delete globalThis.undefined
|
||||
// 返回 false、属性不可删,后续声明/定义均不得 reconfigure)。
|
||||
let nan_shape = core.shape_forge.make_shape(EMPTY_SHAPE_ID, si_nan);
|
||||
global_obj.set_shape_id(nan_shape);
|
||||
global_obj.ensure_hash_props().push(JsValue::float(f64::NAN));
|
||||
global_obj.set_data_meta(
|
||||
global_obj.prop_vec_len().saturating_sub(1) as u32,
|
||||
oxide_types::object::PropAttributes::new(false, false, false),
|
||||
);
|
||||
|
||||
let undef_shape = core.shape_forge.make_shape(nan_shape, si_undef);
|
||||
global_obj.set_shape_id(undef_shape);
|
||||
global_obj.ensure_hash_props().push(JsValue::undefined());
|
||||
global_obj.set_data_meta(
|
||||
global_obj.prop_vec_len().saturating_sub(1) as u32,
|
||||
oxide_types::object::PropAttributes::new(false, false, false),
|
||||
);
|
||||
|
||||
let inf_shape = core.shape_forge.make_shape(undef_shape, si_infinity);
|
||||
global_obj.set_shape_id(inf_shape);
|
||||
global_obj.ensure_hash_props().push(JsValue::float(f64::INFINITY));
|
||||
global_obj.set_data_meta(
|
||||
global_obj.prop_vec_len().saturating_sub(1) as u32,
|
||||
oxide_types::object::PropAttributes::new(false, false, false),
|
||||
);
|
||||
|
||||
P::new(global_obj)
|
||||
}
|
||||
|
||||
/// 从 KernelCore 构建一个全新 session。所有 string/shape intern 调用在
|
||||
/// 第二次及后续调用时命中缓存——净开销 < 0.5 ms。
|
||||
pub fn new(core: &KernelCore) -> Self {
|
||||
let builtin_world = Arc::new(BuiltinWorld::new(&core.perm_interner, &core.shape_forge));
|
||||
let global_object = Self::new_global_object(core);
|
||||
let builtin_snapshot = BuiltinSnapshot::new(&builtin_world, &global_object);
|
||||
|
||||
Self {
|
||||
builtin_world,
|
||||
global_object,
|
||||
builtin_snapshot,
|
||||
}
|
||||
}
|
||||
|
||||
/// 只读访问当前 session 的 builtin world。
|
||||
pub fn builtin_world(&self) -> &Arc<BuiltinWorld> {
|
||||
&self.builtin_world
|
||||
}
|
||||
|
||||
/// 只读访问当前 session 的 global object。
|
||||
pub fn global_object(&self) -> &P<JsObject> {
|
||||
&self.global_object
|
||||
}
|
||||
|
||||
/// 重新采集内置对象世代快照,作为下一次脏检查的基准。
|
||||
pub fn record_snapshot(&mut self) {
|
||||
self.builtin_snapshot = BuiltinSnapshot::new(&self.builtin_world, &self.global_object);
|
||||
}
|
||||
|
||||
/// 对比当前世代与最近快照,返回各 builtin 家族是否被污染。
|
||||
pub fn dirty_since_snapshot(&self) -> BuiltinDirtySet {
|
||||
let world = self.builtin_world.as_ref();
|
||||
let snapshot = &self.builtin_snapshot;
|
||||
let stub_generations_dirty = world
|
||||
.stub_objects
|
||||
.iter()
|
||||
.zip(snapshot.stub_object_generations.iter())
|
||||
.any(|(obj, generation)| BuiltinSnapshot::gen(obj) != *generation);
|
||||
let gen = |id: BuiltinId| BuiltinSnapshot::gen(world.get_by_id(id));
|
||||
let snap = |id: BuiltinId| snapshot.generations[id as usize];
|
||||
|
||||
BuiltinDirtySet {
|
||||
object: gen(BuiltinId::ObjectProto) != snap(BuiltinId::ObjectProto)
|
||||
|| gen(BuiltinId::ObjectConstructor) != snap(BuiltinId::ObjectConstructor),
|
||||
array: gen(BuiltinId::ArrayProto) != snap(BuiltinId::ArrayProto)
|
||||
|| gen(BuiltinId::ArrayConstructor) != snap(BuiltinId::ArrayConstructor),
|
||||
function: gen(BuiltinId::FunctionProto) != snap(BuiltinId::FunctionProto)
|
||||
|| gen(BuiltinId::FunctionConstructor) != snap(BuiltinId::FunctionConstructor),
|
||||
string: gen(BuiltinId::StringProto) != snap(BuiltinId::StringProto)
|
||||
|| gen(BuiltinId::StringConstructor) != snap(BuiltinId::StringConstructor),
|
||||
number: gen(BuiltinId::NumberProto) != snap(BuiltinId::NumberProto)
|
||||
|| gen(BuiltinId::NumberConstructor) != snap(BuiltinId::NumberConstructor),
|
||||
boolean: gen(BuiltinId::BooleanProto) != snap(BuiltinId::BooleanProto)
|
||||
|| gen(BuiltinId::BooleanConstructor) != snap(BuiltinId::BooleanConstructor),
|
||||
error_family: gen(BuiltinId::ErrorProto) != snap(BuiltinId::ErrorProto)
|
||||
|| gen(BuiltinId::ErrorConstructor) != snap(BuiltinId::ErrorConstructor)
|
||||
|| gen(BuiltinId::TypeErrorProto) != snap(BuiltinId::TypeErrorProto)
|
||||
|| gen(BuiltinId::ReferenceErrorProto) != snap(BuiltinId::ReferenceErrorProto)
|
||||
|| gen(BuiltinId::RangeErrorProto) != snap(BuiltinId::RangeErrorProto)
|
||||
|| gen(BuiltinId::SyntaxErrorProto) != snap(BuiltinId::SyntaxErrorProto)
|
||||
|| gen(BuiltinId::UriErrorProto) != snap(BuiltinId::UriErrorProto)
|
||||
|| gen(BuiltinId::EvalErrorProto) != snap(BuiltinId::EvalErrorProto)
|
||||
|| gen(BuiltinId::SuppressedErrorProto) != snap(BuiltinId::SuppressedErrorProto),
|
||||
symbol_family: gen(BuiltinId::SymbolProto) != snap(BuiltinId::SymbolProto)
|
||||
|| gen(BuiltinId::SymbolConstructor) != snap(BuiltinId::SymbolConstructor)
|
||||
|| gen(BuiltinId::SymMatch) != snap(BuiltinId::SymMatch)
|
||||
|| gen(BuiltinId::SymReplace) != snap(BuiltinId::SymReplace)
|
||||
|| gen(BuiltinId::SymSearch) != snap(BuiltinId::SymSearch)
|
||||
|| gen(BuiltinId::SymSplit) != snap(BuiltinId::SymSplit)
|
||||
|| gen(BuiltinId::SymIterator) != snap(BuiltinId::SymIterator)
|
||||
|| gen(BuiltinId::SymToPrimitive) != snap(BuiltinId::SymToPrimitive)
|
||||
|| gen(BuiltinId::SymHasInstance) != snap(BuiltinId::SymHasInstance)
|
||||
|| gen(BuiltinId::SymMatchAll) != snap(BuiltinId::SymMatchAll)
|
||||
|| gen(BuiltinId::SymAsyncIterator) != snap(BuiltinId::SymAsyncIterator)
|
||||
|| gen(BuiltinId::SymToStringTag) != snap(BuiltinId::SymToStringTag)
|
||||
|| gen(BuiltinId::SymSpecies) != snap(BuiltinId::SymSpecies)
|
||||
|| gen(BuiltinId::SymAsyncDispose) != snap(BuiltinId::SymAsyncDispose)
|
||||
|| gen(BuiltinId::SymDispose) != snap(BuiltinId::SymDispose),
|
||||
math: gen(BuiltinId::MathObject) != snap(BuiltinId::MathObject),
|
||||
json: gen(BuiltinId::JsonObject) != snap(BuiltinId::JsonObject),
|
||||
date: gen(BuiltinId::DateConstructor) != snap(BuiltinId::DateConstructor)
|
||||
|| gen(BuiltinId::DateProto) != snap(BuiltinId::DateProto),
|
||||
set: gen(BuiltinId::SetConstructor) != snap(BuiltinId::SetConstructor)
|
||||
|| gen(BuiltinId::SetProto) != snap(BuiltinId::SetProto),
|
||||
map: gen(BuiltinId::MapConstructor) != snap(BuiltinId::MapConstructor)
|
||||
|| gen(BuiltinId::MapProto) != snap(BuiltinId::MapProto),
|
||||
regexp: gen(BuiltinId::RegExpConstructor) != snap(BuiltinId::RegExpConstructor)
|
||||
|| gen(BuiltinId::RegExpProto) != snap(BuiltinId::RegExpProto),
|
||||
array_buffer: gen(BuiltinId::ArrayBufferConstructor) != snap(BuiltinId::ArrayBufferConstructor)
|
||||
|| gen(BuiltinId::ArrayBufferProto) != snap(BuiltinId::ArrayBufferProto),
|
||||
data_view: gen(BuiltinId::DataViewConstructor) != snap(BuiltinId::DataViewConstructor)
|
||||
|| gen(BuiltinId::DataViewProto) != snap(BuiltinId::DataViewProto),
|
||||
typed_array_family: gen(BuiltinId::TypedArrayProto) != snap(BuiltinId::TypedArrayProto)
|
||||
|| gen(BuiltinId::Int8ArrayConstructor) != snap(BuiltinId::Int8ArrayConstructor)
|
||||
|| gen(BuiltinId::Int8ArrayProto) != snap(BuiltinId::Int8ArrayProto)
|
||||
|| gen(BuiltinId::Uint8ArrayConstructor) != snap(BuiltinId::Uint8ArrayConstructor)
|
||||
|| gen(BuiltinId::Uint8ArrayProto) != snap(BuiltinId::Uint8ArrayProto)
|
||||
|| gen(BuiltinId::Uint8ClampedArrayConstructor) != snap(BuiltinId::Uint8ClampedArrayConstructor)
|
||||
|| gen(BuiltinId::Uint8ClampedArrayProto) != snap(BuiltinId::Uint8ClampedArrayProto)
|
||||
|| gen(BuiltinId::Int16ArrayConstructor) != snap(BuiltinId::Int16ArrayConstructor)
|
||||
|| gen(BuiltinId::Int16ArrayProto) != snap(BuiltinId::Int16ArrayProto)
|
||||
|| gen(BuiltinId::Uint16ArrayConstructor) != snap(BuiltinId::Uint16ArrayConstructor)
|
||||
|| gen(BuiltinId::Uint16ArrayProto) != snap(BuiltinId::Uint16ArrayProto)
|
||||
|| gen(BuiltinId::Int32ArrayConstructor) != snap(BuiltinId::Int32ArrayConstructor)
|
||||
|| gen(BuiltinId::Int32ArrayProto) != snap(BuiltinId::Int32ArrayProto)
|
||||
|| gen(BuiltinId::Uint32ArrayConstructor) != snap(BuiltinId::Uint32ArrayConstructor)
|
||||
|| gen(BuiltinId::Uint32ArrayProto) != snap(BuiltinId::Uint32ArrayProto)
|
||||
|| gen(BuiltinId::Float32ArrayConstructor) != snap(BuiltinId::Float32ArrayConstructor)
|
||||
|| gen(BuiltinId::Float32ArrayProto) != snap(BuiltinId::Float32ArrayProto)
|
||||
|| gen(BuiltinId::Float64ArrayConstructor) != snap(BuiltinId::Float64ArrayConstructor)
|
||||
|| gen(BuiltinId::Float64ArrayProto) != snap(BuiltinId::Float64ArrayProto)
|
||||
|| gen(BuiltinId::BigInt64ArrayConstructor) != snap(BuiltinId::BigInt64ArrayConstructor)
|
||||
|| gen(BuiltinId::BigInt64ArrayProto) != snap(BuiltinId::BigInt64ArrayProto)
|
||||
|| gen(BuiltinId::BigUint64ArrayConstructor) != snap(BuiltinId::BigUint64ArrayConstructor)
|
||||
|| gen(BuiltinId::BigUint64ArrayProto) != snap(BuiltinId::BigUint64ArrayProto),
|
||||
temporal: gen(BuiltinId::TemporalObject) != snap(BuiltinId::TemporalObject)
|
||||
|| gen(BuiltinId::TemporalNowObject) != snap(BuiltinId::TemporalNowObject)
|
||||
|| gen(BuiltinId::InstantConstructor) != snap(BuiltinId::InstantConstructor)
|
||||
|| gen(BuiltinId::InstantProto) != snap(BuiltinId::InstantProto)
|
||||
|| gen(BuiltinId::PlainDateConstructor) != snap(BuiltinId::PlainDateConstructor)
|
||||
|| gen(BuiltinId::PlainDateProto) != snap(BuiltinId::PlainDateProto)
|
||||
|| gen(BuiltinId::PlainTimeConstructor) != snap(BuiltinId::PlainTimeConstructor)
|
||||
|| gen(BuiltinId::PlainTimeProto) != snap(BuiltinId::PlainTimeProto)
|
||||
|| gen(BuiltinId::DurationConstructor) != snap(BuiltinId::DurationConstructor)
|
||||
|| gen(BuiltinId::DurationProto) != snap(BuiltinId::DurationProto)
|
||||
|| gen(BuiltinId::ZonedDateTimeConstructor) != snap(BuiltinId::ZonedDateTimeConstructor)
|
||||
|| gen(BuiltinId::ZonedDateTimeProto) != snap(BuiltinId::ZonedDateTimeProto)
|
||||
|| gen(BuiltinId::PlainDateTimeConstructor) != snap(BuiltinId::PlainDateTimeConstructor)
|
||||
|| gen(BuiltinId::PlainDateTimeProto) != snap(BuiltinId::PlainDateTimeProto)
|
||||
|| gen(BuiltinId::PlainMonthDayConstructor) != snap(BuiltinId::PlainMonthDayConstructor)
|
||||
|| gen(BuiltinId::PlainMonthDayProto) != snap(BuiltinId::PlainMonthDayProto)
|
||||
|| gen(BuiltinId::PlainYearMonthConstructor) != snap(BuiltinId::PlainYearMonthConstructor)
|
||||
|| gen(BuiltinId::PlainYearMonthProto) != snap(BuiltinId::PlainYearMonthProto),
|
||||
stubs: world.stub_objects.len() != snapshot.stub_objects_len
|
||||
|| stub_generations_dirty
|
||||
|| gen(BuiltinId::BigIntConstructor) != snap(BuiltinId::BigIntConstructor)
|
||||
|| gen(BuiltinId::BigIntProto) != snap(BuiltinId::BigIntProto),
|
||||
global: BuiltinSnapshot::gen(&self.global_object) != snapshot.global_object_generation,
|
||||
console: gen(BuiltinId::Console) != snap(BuiltinId::Console),
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否自上次快照以来存在任何污染。
|
||||
pub fn is_dirty_since_snapshot(&self) -> bool {
|
||||
self.dirty_since_snapshot().any()
|
||||
}
|
||||
|
||||
/// 收尾释放 session 拥有的手工堆数据:builtin world(方法 wrapper 登记表 +
|
||||
/// 全部 P 对象属性区)与 global 对象属性区。对象本体随 Arc 引用归零释放。
|
||||
///
|
||||
/// # 注意事项
|
||||
/// 幂等(登记表按值取走、属性区释放后置空),session 生命周期内可安全重入;
|
||||
/// 仅应在 session 真正终止时调用——选择性重置换出的旧 world/global 不走本路径。
|
||||
pub fn teardown_builtins(&mut self) {
|
||||
self.builtin_world.teardown_heap_data();
|
||||
// SAFETY: global 归本 session 所有,收尾时恰好释放其属性区一次。
|
||||
let global = unsafe { &mut *(self.global_object.as_ptr() as *mut JsObject) };
|
||||
global.release_raw_heap();
|
||||
}
|
||||
|
||||
/// 选择性重置:只重建被污染的对象(global 或相应 builtin 家族),并返回脏集合。
|
||||
///
|
||||
/// 相比全量重建,可保留未污染的内置对象指针与世代,减少隔离成本。
|
||||
pub fn selective_reset(&mut self, core: &Arc<KernelCore>) -> BuiltinDirtySet {
|
||||
let dirty = self.dirty_since_snapshot();
|
||||
if dirty.global {
|
||||
// 旧 global 的属性区在替换前释放,避免随旧引用永久泄漏。
|
||||
let old_global = unsafe { &mut *(self.global_object.as_ptr() as *mut JsObject) };
|
||||
old_global.release_raw_heap();
|
||||
self.global_object = Self::new_global_object(core);
|
||||
}
|
||||
if dirty.any_builtin_dirty() {
|
||||
let old_world = self.builtin_world.clone();
|
||||
let new_world = BuiltinWorld::rebuild_with_dirty(
|
||||
&old_world,
|
||||
core.perm_interner.as_ref(),
|
||||
core.shape_forge.as_ref(),
|
||||
&dirty,
|
||||
);
|
||||
// 旧 world 的登记表并入新 world:存活 wrapper(未污染家族别名)仍须在
|
||||
// session 收尾统一释放;已弃 wrapper 随之恰好释放一次,不二次持有。
|
||||
new_world.inherit_leaked_objects(&old_world);
|
||||
// 重建收尾:保留对象(登记表 wrapper + 共用保留 P 字段)proto 槽
|
||||
// 重指新指针,随后被替换旧对象属性区恰好释放一次(含保活钉住
|
||||
// 对的属性区,本体钉保留);重指须先于释放、先于换出完成。
|
||||
new_world.retire_replaced(&old_world);
|
||||
self.builtin_world = Arc::new(new_world);
|
||||
}
|
||||
dirty
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for KernelSession {
|
||||
fn drop(&mut self) {
|
||||
self.teardown_builtins();
|
||||
}
|
||||
}
|
||||
pub use session::KernelSession;
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
//! 每会话可变状态:内置原型对象(BuiltinWorld)与全局对象,full_reset 时
|
||||
//! 重建;世代快照 + 家族位脏集合计算,selective_reset 只重建脏家族。
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_types::mem::P;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::builtin::BuiltinWorld;
|
||||
use crate::shape_forge::EMPTY_SHAPE_ID;
|
||||
|
||||
use super::{BuiltinDirtySet, BuiltinId, BuiltinSnapshot, KernelCore};
|
||||
/// 每会话可变状态:内置原型对象与全局对象。
|
||||
/// 在 full_reset() 时重建,实现 JS 执行之间的完全隔离。
|
||||
pub struct KernelSession {
|
||||
pub builtin_world: Arc<BuiltinWorld>,
|
||||
pub global_object: P<JsObject>,
|
||||
pub builtin_snapshot: BuiltinSnapshot,
|
||||
}
|
||||
|
||||
impl KernelSession {
|
||||
fn new_global_object(core: &KernelCore) -> P<JsObject> {
|
||||
let mut global_obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
|
||||
let si_nan = core.perm_interner.intern("NaN").0;
|
||||
let si_undef = core.perm_interner.intern("undefined").0;
|
||||
let si_infinity = core.perm_interner.intern("Infinity").0;
|
||||
|
||||
// 全局三常量描述符:{ writable:false, enumerable:false, configurable:false }。
|
||||
// e:false 是枚举面守卫(Object.keys / for-in 由 enumerable 决定);
|
||||
// c:false 是 delete / defineProperty 可观察的规范值(delete globalThis.undefined
|
||||
// 返回 false、属性不可删,后续声明/定义均不得 reconfigure)。
|
||||
let nan_shape = core.shape_forge.make_shape(EMPTY_SHAPE_ID, si_nan);
|
||||
global_obj.set_shape_id(nan_shape);
|
||||
global_obj.ensure_hash_props().push(JsValue::float(f64::NAN));
|
||||
global_obj.set_data_meta(
|
||||
global_obj.prop_vec_len().saturating_sub(1) as u32,
|
||||
oxide_types::object::PropAttributes::new(false, false, false),
|
||||
);
|
||||
|
||||
let undef_shape = core.shape_forge.make_shape(nan_shape, si_undef);
|
||||
global_obj.set_shape_id(undef_shape);
|
||||
global_obj.ensure_hash_props().push(JsValue::undefined());
|
||||
global_obj.set_data_meta(
|
||||
global_obj.prop_vec_len().saturating_sub(1) as u32,
|
||||
oxide_types::object::PropAttributes::new(false, false, false),
|
||||
);
|
||||
|
||||
let inf_shape = core.shape_forge.make_shape(undef_shape, si_infinity);
|
||||
global_obj.set_shape_id(inf_shape);
|
||||
global_obj.ensure_hash_props().push(JsValue::float(f64::INFINITY));
|
||||
global_obj.set_data_meta(
|
||||
global_obj.prop_vec_len().saturating_sub(1) as u32,
|
||||
oxide_types::object::PropAttributes::new(false, false, false),
|
||||
);
|
||||
|
||||
P::new(global_obj)
|
||||
}
|
||||
|
||||
/// 从 KernelCore 构建一个全新 session。所有 string/shape intern 调用在
|
||||
/// 第二次及后续调用时命中缓存——净开销 < 0.5 ms。
|
||||
pub fn new(core: &KernelCore) -> Self {
|
||||
let builtin_world = Arc::new(BuiltinWorld::new(&core.perm_interner, &core.shape_forge));
|
||||
let global_object = Self::new_global_object(core);
|
||||
let builtin_snapshot = BuiltinSnapshot::new(&builtin_world, &global_object);
|
||||
|
||||
Self {
|
||||
builtin_world,
|
||||
global_object,
|
||||
builtin_snapshot,
|
||||
}
|
||||
}
|
||||
|
||||
/// 只读访问当前 session 的 builtin world。
|
||||
pub fn builtin_world(&self) -> &Arc<BuiltinWorld> {
|
||||
&self.builtin_world
|
||||
}
|
||||
|
||||
/// 只读访问当前 session 的 global object。
|
||||
pub fn global_object(&self) -> &P<JsObject> {
|
||||
&self.global_object
|
||||
}
|
||||
|
||||
/// 重新采集内置对象世代快照,作为下一次脏检查的基准。
|
||||
pub fn record_snapshot(&mut self) {
|
||||
self.builtin_snapshot = BuiltinSnapshot::new(&self.builtin_world, &self.global_object);
|
||||
}
|
||||
|
||||
/// 对比当前世代与最近快照,返回各 builtin 家族是否被污染。
|
||||
pub fn dirty_since_snapshot(&self) -> BuiltinDirtySet {
|
||||
let world = self.builtin_world.as_ref();
|
||||
let snapshot = &self.builtin_snapshot;
|
||||
let stub_generations_dirty = world
|
||||
.stub_objects
|
||||
.iter()
|
||||
.zip(snapshot.stub_object_generations.iter())
|
||||
.any(|(obj, generation)| BuiltinSnapshot::gen(obj) != *generation);
|
||||
let gen = |id: BuiltinId| BuiltinSnapshot::gen(world.get_by_id(id));
|
||||
let snap = |id: BuiltinId| snapshot.generations[id as usize];
|
||||
|
||||
BuiltinDirtySet {
|
||||
object: gen(BuiltinId::ObjectProto) != snap(BuiltinId::ObjectProto)
|
||||
|| gen(BuiltinId::ObjectConstructor) != snap(BuiltinId::ObjectConstructor),
|
||||
array: gen(BuiltinId::ArrayProto) != snap(BuiltinId::ArrayProto)
|
||||
|| gen(BuiltinId::ArrayConstructor) != snap(BuiltinId::ArrayConstructor),
|
||||
function: gen(BuiltinId::FunctionProto) != snap(BuiltinId::FunctionProto)
|
||||
|| gen(BuiltinId::FunctionConstructor) != snap(BuiltinId::FunctionConstructor),
|
||||
string: gen(BuiltinId::StringProto) != snap(BuiltinId::StringProto)
|
||||
|| gen(BuiltinId::StringConstructor) != snap(BuiltinId::StringConstructor),
|
||||
number: gen(BuiltinId::NumberProto) != snap(BuiltinId::NumberProto)
|
||||
|| gen(BuiltinId::NumberConstructor) != snap(BuiltinId::NumberConstructor),
|
||||
boolean: gen(BuiltinId::BooleanProto) != snap(BuiltinId::BooleanProto)
|
||||
|| gen(BuiltinId::BooleanConstructor) != snap(BuiltinId::BooleanConstructor),
|
||||
error_family: gen(BuiltinId::ErrorProto) != snap(BuiltinId::ErrorProto)
|
||||
|| gen(BuiltinId::ErrorConstructor) != snap(BuiltinId::ErrorConstructor)
|
||||
|| gen(BuiltinId::TypeErrorProto) != snap(BuiltinId::TypeErrorProto)
|
||||
|| gen(BuiltinId::ReferenceErrorProto) != snap(BuiltinId::ReferenceErrorProto)
|
||||
|| gen(BuiltinId::RangeErrorProto) != snap(BuiltinId::RangeErrorProto)
|
||||
|| gen(BuiltinId::SyntaxErrorProto) != snap(BuiltinId::SyntaxErrorProto)
|
||||
|| gen(BuiltinId::UriErrorProto) != snap(BuiltinId::UriErrorProto)
|
||||
|| gen(BuiltinId::EvalErrorProto) != snap(BuiltinId::EvalErrorProto)
|
||||
|| gen(BuiltinId::SuppressedErrorProto) != snap(BuiltinId::SuppressedErrorProto),
|
||||
symbol_family: gen(BuiltinId::SymbolProto) != snap(BuiltinId::SymbolProto)
|
||||
|| gen(BuiltinId::SymbolConstructor) != snap(BuiltinId::SymbolConstructor)
|
||||
|| gen(BuiltinId::SymMatch) != snap(BuiltinId::SymMatch)
|
||||
|| gen(BuiltinId::SymReplace) != snap(BuiltinId::SymReplace)
|
||||
|| gen(BuiltinId::SymSearch) != snap(BuiltinId::SymSearch)
|
||||
|| gen(BuiltinId::SymSplit) != snap(BuiltinId::SymSplit)
|
||||
|| gen(BuiltinId::SymIterator) != snap(BuiltinId::SymIterator)
|
||||
|| gen(BuiltinId::SymToPrimitive) != snap(BuiltinId::SymToPrimitive)
|
||||
|| gen(BuiltinId::SymHasInstance) != snap(BuiltinId::SymHasInstance)
|
||||
|| gen(BuiltinId::SymMatchAll) != snap(BuiltinId::SymMatchAll)
|
||||
|| gen(BuiltinId::SymAsyncIterator) != snap(BuiltinId::SymAsyncIterator)
|
||||
|| gen(BuiltinId::SymToStringTag) != snap(BuiltinId::SymToStringTag)
|
||||
|| gen(BuiltinId::SymSpecies) != snap(BuiltinId::SymSpecies)
|
||||
|| gen(BuiltinId::SymAsyncDispose) != snap(BuiltinId::SymAsyncDispose)
|
||||
|| gen(BuiltinId::SymDispose) != snap(BuiltinId::SymDispose),
|
||||
math: gen(BuiltinId::MathObject) != snap(BuiltinId::MathObject),
|
||||
json: gen(BuiltinId::JsonObject) != snap(BuiltinId::JsonObject),
|
||||
date: gen(BuiltinId::DateConstructor) != snap(BuiltinId::DateConstructor)
|
||||
|| gen(BuiltinId::DateProto) != snap(BuiltinId::DateProto),
|
||||
set: gen(BuiltinId::SetConstructor) != snap(BuiltinId::SetConstructor)
|
||||
|| gen(BuiltinId::SetProto) != snap(BuiltinId::SetProto),
|
||||
map: gen(BuiltinId::MapConstructor) != snap(BuiltinId::MapConstructor)
|
||||
|| gen(BuiltinId::MapProto) != snap(BuiltinId::MapProto),
|
||||
regexp: gen(BuiltinId::RegExpConstructor) != snap(BuiltinId::RegExpConstructor)
|
||||
|| gen(BuiltinId::RegExpProto) != snap(BuiltinId::RegExpProto),
|
||||
array_buffer: gen(BuiltinId::ArrayBufferConstructor) != snap(BuiltinId::ArrayBufferConstructor)
|
||||
|| gen(BuiltinId::ArrayBufferProto) != snap(BuiltinId::ArrayBufferProto),
|
||||
data_view: gen(BuiltinId::DataViewConstructor) != snap(BuiltinId::DataViewConstructor)
|
||||
|| gen(BuiltinId::DataViewProto) != snap(BuiltinId::DataViewProto),
|
||||
typed_array_family: gen(BuiltinId::TypedArrayProto) != snap(BuiltinId::TypedArrayProto)
|
||||
|| gen(BuiltinId::Int8ArrayConstructor) != snap(BuiltinId::Int8ArrayConstructor)
|
||||
|| gen(BuiltinId::Int8ArrayProto) != snap(BuiltinId::Int8ArrayProto)
|
||||
|| gen(BuiltinId::Uint8ArrayConstructor) != snap(BuiltinId::Uint8ArrayConstructor)
|
||||
|| gen(BuiltinId::Uint8ArrayProto) != snap(BuiltinId::Uint8ArrayProto)
|
||||
|| gen(BuiltinId::Uint8ClampedArrayConstructor) != snap(BuiltinId::Uint8ClampedArrayConstructor)
|
||||
|| gen(BuiltinId::Uint8ClampedArrayProto) != snap(BuiltinId::Uint8ClampedArrayProto)
|
||||
|| gen(BuiltinId::Int16ArrayConstructor) != snap(BuiltinId::Int16ArrayConstructor)
|
||||
|| gen(BuiltinId::Int16ArrayProto) != snap(BuiltinId::Int16ArrayProto)
|
||||
|| gen(BuiltinId::Uint16ArrayConstructor) != snap(BuiltinId::Uint16ArrayConstructor)
|
||||
|| gen(BuiltinId::Uint16ArrayProto) != snap(BuiltinId::Uint16ArrayProto)
|
||||
|| gen(BuiltinId::Int32ArrayConstructor) != snap(BuiltinId::Int32ArrayConstructor)
|
||||
|| gen(BuiltinId::Int32ArrayProto) != snap(BuiltinId::Int32ArrayProto)
|
||||
|| gen(BuiltinId::Uint32ArrayConstructor) != snap(BuiltinId::Uint32ArrayConstructor)
|
||||
|| gen(BuiltinId::Uint32ArrayProto) != snap(BuiltinId::Uint32ArrayProto)
|
||||
|| gen(BuiltinId::Float32ArrayConstructor) != snap(BuiltinId::Float32ArrayConstructor)
|
||||
|| gen(BuiltinId::Float32ArrayProto) != snap(BuiltinId::Float32ArrayProto)
|
||||
|| gen(BuiltinId::Float64ArrayConstructor) != snap(BuiltinId::Float64ArrayConstructor)
|
||||
|| gen(BuiltinId::Float64ArrayProto) != snap(BuiltinId::Float64ArrayProto)
|
||||
|| gen(BuiltinId::BigInt64ArrayConstructor) != snap(BuiltinId::BigInt64ArrayConstructor)
|
||||
|| gen(BuiltinId::BigInt64ArrayProto) != snap(BuiltinId::BigInt64ArrayProto)
|
||||
|| gen(BuiltinId::BigUint64ArrayConstructor) != snap(BuiltinId::BigUint64ArrayConstructor)
|
||||
|| gen(BuiltinId::BigUint64ArrayProto) != snap(BuiltinId::BigUint64ArrayProto),
|
||||
temporal: gen(BuiltinId::TemporalObject) != snap(BuiltinId::TemporalObject)
|
||||
|| gen(BuiltinId::TemporalNowObject) != snap(BuiltinId::TemporalNowObject)
|
||||
|| gen(BuiltinId::InstantConstructor) != snap(BuiltinId::InstantConstructor)
|
||||
|| gen(BuiltinId::InstantProto) != snap(BuiltinId::InstantProto)
|
||||
|| gen(BuiltinId::PlainDateConstructor) != snap(BuiltinId::PlainDateConstructor)
|
||||
|| gen(BuiltinId::PlainDateProto) != snap(BuiltinId::PlainDateProto)
|
||||
|| gen(BuiltinId::PlainTimeConstructor) != snap(BuiltinId::PlainTimeConstructor)
|
||||
|| gen(BuiltinId::PlainTimeProto) != snap(BuiltinId::PlainTimeProto)
|
||||
|| gen(BuiltinId::DurationConstructor) != snap(BuiltinId::DurationConstructor)
|
||||
|| gen(BuiltinId::DurationProto) != snap(BuiltinId::DurationProto)
|
||||
|| gen(BuiltinId::ZonedDateTimeConstructor) != snap(BuiltinId::ZonedDateTimeConstructor)
|
||||
|| gen(BuiltinId::ZonedDateTimeProto) != snap(BuiltinId::ZonedDateTimeProto)
|
||||
|| gen(BuiltinId::PlainDateTimeConstructor) != snap(BuiltinId::PlainDateTimeConstructor)
|
||||
|| gen(BuiltinId::PlainDateTimeProto) != snap(BuiltinId::PlainDateTimeProto)
|
||||
|| gen(BuiltinId::PlainMonthDayConstructor) != snap(BuiltinId::PlainMonthDayConstructor)
|
||||
|| gen(BuiltinId::PlainMonthDayProto) != snap(BuiltinId::PlainMonthDayProto)
|
||||
|| gen(BuiltinId::PlainYearMonthConstructor) != snap(BuiltinId::PlainYearMonthConstructor)
|
||||
|| gen(BuiltinId::PlainYearMonthProto) != snap(BuiltinId::PlainYearMonthProto),
|
||||
stubs: world.stub_objects.len() != snapshot.stub_objects_len
|
||||
|| stub_generations_dirty
|
||||
|| gen(BuiltinId::BigIntConstructor) != snap(BuiltinId::BigIntConstructor)
|
||||
|| gen(BuiltinId::BigIntProto) != snap(BuiltinId::BigIntProto),
|
||||
global: BuiltinSnapshot::gen(&self.global_object) != snapshot.global_object_generation,
|
||||
console: gen(BuiltinId::Console) != snap(BuiltinId::Console),
|
||||
}
|
||||
}
|
||||
|
||||
/// 是否自上次快照以来存在任何污染。
|
||||
pub fn is_dirty_since_snapshot(&self) -> bool {
|
||||
self.dirty_since_snapshot().any()
|
||||
}
|
||||
|
||||
/// 收尾释放 session 拥有的手工堆数据:builtin world(方法 wrapper 登记表 +
|
||||
/// 全部 P 对象属性区)与 global 对象属性区。对象本体随 Arc 引用归零释放。
|
||||
///
|
||||
/// # 注意事项
|
||||
/// 幂等(登记表按值取走、属性区释放后置空),session 生命周期内可安全重入;
|
||||
/// 仅应在 session 真正终止时调用——选择性重置换出的旧 world/global 不走本路径。
|
||||
pub fn teardown_builtins(&mut self) {
|
||||
self.builtin_world.teardown_heap_data();
|
||||
// SAFETY: global 归本 session 所有,收尾时恰好释放其属性区一次。
|
||||
let global = unsafe { &mut *(self.global_object.as_ptr() as *mut JsObject) };
|
||||
global.release_raw_heap();
|
||||
}
|
||||
|
||||
/// 选择性重置:只重建被污染的对象(global 或相应 builtin 家族),并返回脏集合。
|
||||
///
|
||||
/// 相比全量重建,可保留未污染的内置对象指针与世代,减少隔离成本。
|
||||
pub fn selective_reset(&mut self, core: &Arc<KernelCore>) -> BuiltinDirtySet {
|
||||
let dirty = self.dirty_since_snapshot();
|
||||
if dirty.global {
|
||||
// 旧 global 的属性区在替换前释放,避免随旧引用永久泄漏。
|
||||
let old_global = unsafe { &mut *(self.global_object.as_ptr() as *mut JsObject) };
|
||||
old_global.release_raw_heap();
|
||||
self.global_object = Self::new_global_object(core);
|
||||
}
|
||||
if dirty.any_builtin_dirty() {
|
||||
let old_world = self.builtin_world.clone();
|
||||
let new_world = BuiltinWorld::rebuild_with_dirty(
|
||||
&old_world,
|
||||
core.perm_interner.as_ref(),
|
||||
core.shape_forge.as_ref(),
|
||||
&dirty,
|
||||
);
|
||||
// 旧 world 的登记表并入新 world:存活 wrapper(未污染家族别名)仍须在
|
||||
// session 收尾统一释放;已弃 wrapper 随之恰好释放一次,不二次持有。
|
||||
new_world.inherit_leaked_objects(&old_world);
|
||||
// 重建收尾:保留对象(登记表 wrapper + 共用保留 P 字段)proto 槽
|
||||
// 重指新指针,随后被替换旧对象属性区恰好释放一次(含保活钉住
|
||||
// 对的属性区,本体钉保留);重指须先于释放、先于换出完成。
|
||||
new_world.retire_replaced(&old_world);
|
||||
self.builtin_world = Arc::new(new_world);
|
||||
}
|
||||
dirty
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for KernelSession {
|
||||
fn drop(&mut self) {
|
||||
self.teardown_builtins();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user