From dc09ccc1dabcf5edffb859f56a52b1708f57d343 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Wed, 23 Sep 2026 15:38:38 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20BuiltinWorld=20=E5=A2=9E=20SharedArrayB?= =?UTF-8?q?uffer=20=E5=8E=9F=E5=9E=8B=E4=B8=8E=E6=9E=84=E9=80=A0=E5=99=A8?= =?UTF-8?q?=E6=A7=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_kernel/src/builtin/construct.rs | 15 +++++-- crates/oxide_kernel/src/builtin/rebuild.rs | 7 +++ crates/oxide_kernel/src/builtin/world.rs | 45 +++++++++++++++++++- crates/oxide_kernel/src/kernel/builtin_id.rs | 36 +++++++++++++++- crates/oxide_kernel/src/kernel/session.rs | 2 + 5 files changed, 97 insertions(+), 8 deletions(-) diff --git a/crates/oxide_kernel/src/builtin/construct.rs b/crates/oxide_kernel/src/builtin/construct.rs index 53fa33fc..aea7e458 100644 --- a/crates/oxide_kernel/src/builtin/construct.rs +++ b/crates/oxide_kernel/src/builtin/construct.rs @@ -269,11 +269,11 @@ fn set_proto_if_changed(obj: &P, proto: JsValue) { /// `[[Prototype]]` 赋值。 /// /// # 步骤 -/// 1. 35 组构造器/原型对互指(`.prototype` / `.constructor` 槽,含 +/// 1. 36 组构造器/原型对互指(`.prototype` / `.constructor` 槽,含 /// TypedArray 家族共享对),经 `wire_ctor_proto` 覆盖占位槽; -/// 2. 23 个非 TypedArray 构造器的 `[[Prototype]]` → Function.prototype +/// 2. 24 个非 TypedArray 构造器的 `[[Prototype]]` → Function.prototype /// (标准内置函数对象均继承 Function.prototype); -/// 3. 25 个非 Object 原型的 `[[Prototype]]` → Object.prototype,另含 +/// 3. 26 个非 Object 原型的 `[[Prototype]]` → Object.prototype,另含 /// Temporal 命名空间对象、Temporal.now、Console 单例与 Math/JSON /// 命名空间对象; /// 4. %IteratorPrototype% → Object.prototype,6 个集合迭代器原型 @@ -304,6 +304,7 @@ pub(crate) fn wire_builtin_world_links(world: &BuiltinWorld) { wire_ctor_proto(&world.map_constructor, &world.map_proto); wire_ctor_proto(&world.regexp_constructor, &world.regexp_proto); wire_ctor_proto(&world.array_buffer_constructor, &world.array_buffer_proto); + wire_ctor_proto(&world.shared_array_buffer_constructor, &world.shared_array_buffer_proto); wire_ctor_proto(&world.data_view_constructor, &world.data_view_proto); wire_ctor_proto(&world.int8array_constructor, &world.int8array_proto); wire_ctor_proto(&world.uint8array_constructor, &world.uint8array_proto); @@ -343,6 +344,7 @@ pub(crate) fn wire_builtin_world_links(world: &BuiltinWorld) { &world.map_constructor, &world.regexp_constructor, &world.array_buffer_constructor, + &world.shared_array_buffer_constructor, &world.data_view_constructor, &world.bigint_constructor, &world.instant_constructor, @@ -358,7 +360,7 @@ pub(crate) fn wire_builtin_world_links(world: &BuiltinWorld) { } let obj_proto_val = JsValue::from_js_object(world.object_proto.as_ptr() as *mut JsObject); - let non_object_protos: [&P; 25] = [ + let non_object_protos: [&P; 26] = [ &world.array_proto, &world.function_proto, &world.string_proto, @@ -371,6 +373,7 @@ pub(crate) fn wire_builtin_world_links(world: &BuiltinWorld) { &world.map_proto, &world.regexp_proto, &world.array_buffer_proto, + &world.shared_array_buffer_proto, &world.data_view_proto, &world.typed_array_proto, &world.instant_proto, @@ -489,6 +492,8 @@ impl BuiltinWorld { let (regexp_proto, regexp_constructor) = make_named_pair(string_forge, shape_forge, labels, "RegExp"); let (array_buffer_proto, array_buffer_constructor) = make_named_pair(string_forge, shape_forge, labels, "ArrayBuffer"); + let (shared_array_buffer_proto, shared_array_buffer_constructor) = + make_named_pair(string_forge, shape_forge, labels, "SharedArrayBuffer"); let (data_view_proto, data_view_constructor) = make_named_pair(string_forge, shape_forge, labels, "DataView"); let typed_arrays = make_typed_array_family(string_forge, shape_forge, labels, &object_proto); @@ -576,6 +581,8 @@ impl BuiltinWorld { regexp_proto, array_buffer_constructor, array_buffer_proto, + shared_array_buffer_proto, + shared_array_buffer_constructor, data_view_constructor, data_view_proto, typed_array_proto: typed_arrays.typed_array_proto, diff --git a/crates/oxide_kernel/src/builtin/rebuild.rs b/crates/oxide_kernel/src/builtin/rebuild.rs index e0b44635..68d4bc15 100644 --- a/crates/oxide_kernel/src/builtin/rebuild.rs +++ b/crates/oxide_kernel/src/builtin/rebuild.rs @@ -309,6 +309,11 @@ impl BuiltinWorld { } else { (current.array_buffer_proto.clone(), current.array_buffer_constructor.clone()) }; + let (shared_array_buffer_proto, shared_array_buffer_constructor) = if dirty.shared_array_buffer { + make_named_pair(string_forge, shape_forge, labels, "SharedArrayBuffer") + } else { + (current.shared_array_buffer_proto.clone(), current.shared_array_buffer_constructor.clone()) + }; let (data_view_proto, data_view_constructor) = if dirty.data_view { make_named_pair(string_forge, shape_forge, labels, "DataView") } else { @@ -511,6 +516,8 @@ impl BuiltinWorld { regexp_proto, array_buffer_constructor, array_buffer_proto, + shared_array_buffer_proto, + shared_array_buffer_constructor, data_view_constructor, data_view_proto, typed_array_proto: typed_arrays.typed_array_proto, diff --git a/crates/oxide_kernel/src/builtin/world.rs b/crates/oxide_kernel/src/builtin/world.rs index 431e4d6e..9a7d5bda 100644 --- a/crates/oxide_kernel/src/builtin/world.rs +++ b/crates/oxide_kernel/src/builtin/world.rs @@ -1,4 +1,4 @@ -//! 注册表职责:BuiltinWorld 结构(104 固定 P 字段 + stub 族 + Box::into_raw +//! 注册表职责:BuiltinWorld 结构(106 固定 P 字段 + stub 族 + Box::into_raw //! 登记表)、get_by_id 派发、all_p_fields 104 元组枚举(新增 P 字段四处同步 //! 约束载体)与登记表 track/find/inherit/teardown。 @@ -48,6 +48,10 @@ pub struct BuiltinWorld { pub regexp_proto: P, pub array_buffer_constructor: P, pub array_buffer_proto: P, + /// `SharedArrayBuffer.prototype` 与 `SharedArrayBuffer` 构造器:经 + /// `make_named_pair` 成对构造,方法/访问器由绑定层安装。 + pub shared_array_buffer_proto: P, + pub shared_array_buffer_constructor: P, pub data_view_constructor: P, pub data_view_proto: P, pub typed_array_proto: P, @@ -343,7 +347,7 @@ impl BuiltinWorld { /// session 收尾(`teardown_heap_data`)与选择性重建收尾(`retire_replaced`) /// 的 P 字段枚举唯一入口:`BuiltinWorld` 新增 P 字段须在此同步补一行,否则 /// 收尾时该字段属性区无法释放、重建原型槽改写/释放漏掉该字段。 - pub(crate) fn all_p_fields(&self) -> [&P; 104] { + pub(crate) fn all_p_fields(&self) -> [&P; 106] { [ &self.object_proto, &self.array_proto, @@ -380,6 +384,8 @@ impl BuiltinWorld { &self.regexp_proto, &self.array_buffer_constructor, &self.array_buffer_proto, + &self.shared_array_buffer_proto, + &self.shared_array_buffer_constructor, &self.data_view_constructor, &self.data_view_proto, &self.typed_array_proto, @@ -532,6 +538,8 @@ impl BuiltinWorld { BuiltinId::RegExpProto => &self.regexp_proto, BuiltinId::ArrayBufferConstructor => &self.array_buffer_constructor, BuiltinId::ArrayBufferProto => &self.array_buffer_proto, + BuiltinId::SharedArrayBufferProto => &self.shared_array_buffer_proto, + BuiltinId::SharedArrayBufferConstructor => &self.shared_array_buffer_constructor, BuiltinId::DataViewConstructor => &self.data_view_constructor, BuiltinId::DataViewProto => &self.data_view_proto, BuiltinId::TypedArrayProto => &self.typed_array_proto, @@ -658,4 +666,37 @@ mod tests { // 登记表并入新 world:保留 wrapper 仍须由 session 收尾统一释放。 assert!(session.builtin_world.leaked_objects.borrow().iter().any(|s| s.ptr == wrapper)); } + + /// SAB 家族脏线冒烟:仅 SAB 对世代漂移 → 选择性重置只判 SAB 家族脏, + /// ArrayBuffer 家族指针原样保留(钉 dirty_since_snapshot 家族线接线)。 + #[test] + fn sab_family_selective_rebuild() { + use crate::kernel::{KernelConfig, KernelCore, KernelSession}; + let core = KernelCore::new(KernelConfig::minimal()); + let mut session = KernelSession::new(&core); + let old_world = std::sync::Arc::clone(&session.builtin_world); + let sab_proto = old_world.shared_array_buffer_proto.as_ptr() as *mut JsObject; + let sab_ctor = old_world.shared_array_buffer_constructor.as_ptr() as *mut JsObject; + let ab_proto = old_world.array_buffer_proto.as_ptr() as *mut JsObject; + + unsafe { + (&mut *sab_proto).bump_generation(); + (&mut *sab_ctor).bump_generation(); + } + let dirty = session.selective_reset(&core); + assert!(dirty.shared_array_buffer); + assert!(!dirty.array_buffer); + assert!(!dirty.data_view); + + // 脏家族换新对象对,未脏家族指针原样保留。 + assert!(!std::ptr::eq( + sab_proto, + session.builtin_world.shared_array_buffer_proto.as_ptr() as *mut JsObject + )); + assert!(!std::ptr::eq( + sab_ctor, + session.builtin_world.shared_array_buffer_constructor.as_ptr() as *mut JsObject + )); + assert!(std::ptr::eq(ab_proto, session.builtin_world.array_buffer_proto.as_ptr() as *mut JsObject)); + } } diff --git a/crates/oxide_kernel/src/kernel/builtin_id.rs b/crates/oxide_kernel/src/kernel/builtin_id.rs index 6f94e4a1..05b2c32c 100644 --- a/crates/oxide_kernel/src/kernel/builtin_id.rs +++ b/crates/oxide_kernel/src/kernel/builtin_id.rs @@ -1,4 +1,4 @@ -//! 内置对象 id 枚举(`BuiltinId` 94 变体 + `ALL` 顺序钉表)、世代快照 +//! 内置对象 id 枚举(`BuiltinId` 96 变体 + `ALL` 顺序钉表)、世代快照 //! (`BuiltinSnapshot`)与按家族划分的脏标记位集(`BuiltinDirtySet`); //! `NUM_BUILTINS` 文档承载"新增 BuiltinWorld 字段须同步"四处约束注记。 @@ -11,7 +11,7 @@ use crate::builtin::BuiltinWorld; /// 维护注意:每个新增的 `BuiltinWorld` 对象字段都必须加到这里以及 /// `KernelSession::dirty_since_snapshot()`,以便选择性重置重建正确的 /// builtin 家族。 -pub const NUM_BUILTINS: usize = 94; +pub const NUM_BUILTINS: usize = 96; /// 内置对象枚举 id,与 `BuiltinWorld` 中的存储槽一一对应。 /// @@ -115,6 +115,8 @@ pub enum BuiltinId { PlainMonthDayProto = 91, PlainYearMonthConstructor = 92, PlainYearMonthProto = 93, + SharedArrayBufferProto = 94, + SharedArrayBufferConstructor = 95, } impl BuiltinId { @@ -216,6 +218,8 @@ impl BuiltinId { BuiltinId::PlainMonthDayProto, BuiltinId::PlainYearMonthConstructor, BuiltinId::PlainYearMonthProto, + BuiltinId::SharedArrayBufferProto, + BuiltinId::SharedArrayBufferConstructor, ]; } @@ -283,6 +287,7 @@ pub struct BuiltinDirtySet { pub map: bool, pub regexp: bool, pub array_buffer: bool, + pub shared_array_buffer: bool, pub data_view: bool, pub typed_array_family: bool, pub temporal: bool, @@ -314,6 +319,7 @@ impl BuiltinDirtySet { map: true, regexp: true, array_buffer: true, + shared_array_buffer: true, data_view: true, typed_array_family: true, temporal: true, @@ -340,6 +346,7 @@ impl BuiltinDirtySet { || self.map || self.regexp || self.array_buffer + || self.shared_array_buffer || self.data_view || self.typed_array_family || self.temporal @@ -352,3 +359,28 @@ impl BuiltinDirtySet { self.any_builtin_dirty() || self.global } } + +#[cfg(test)] +mod tests { + use super::*; + + /// 槽对齐面:表尾追加 SAB 家族后总槽数 96,既有 94 个判别值零位移, + /// 快照数组随 NUM_BUILTINS 自动扩维、逐槽对齐。 + #[test] + fn builtin_snapshot_all_slots_aligned() { + assert_eq!(NUM_BUILTINS, 96); + assert_eq!(BuiltinId::ALL.len(), NUM_BUILTINS); + // 前 94 项判别值 0-93 逐项不变(尾追加零位移)。 + for i in 0..94usize { + assert_eq!(BuiltinId::ALL[i] as usize, i); + } + assert_eq!(BuiltinId::ALL[94], BuiltinId::SharedArrayBufferProto); + assert_eq!(BuiltinId::ALL[95], BuiltinId::SharedArrayBufferConstructor); + + // 快照经 session 全量构造路径采集,generations 数组维度 = 槽数。 + use crate::kernel::{KernelConfig, KernelCore, KernelSession}; + let core = KernelCore::new(KernelConfig::minimal()); + let session = KernelSession::new(&core); + assert_eq!(session.builtin_snapshot.generations.len(), NUM_BUILTINS); + } +} diff --git a/crates/oxide_kernel/src/kernel/session.rs b/crates/oxide_kernel/src/kernel/session.rs index dc0aee9c..e8d97e9d 100644 --- a/crates/oxide_kernel/src/kernel/session.rs +++ b/crates/oxide_kernel/src/kernel/session.rs @@ -157,6 +157,8 @@ impl KernelSession { || gen(BuiltinId::RegExpProto) != snap(BuiltinId::RegExpProto), array_buffer: gen(BuiltinId::ArrayBufferConstructor) != snap(BuiltinId::ArrayBufferConstructor) || gen(BuiltinId::ArrayBufferProto) != snap(BuiltinId::ArrayBufferProto), + shared_array_buffer: gen(BuiltinId::SharedArrayBufferProto) != snap(BuiltinId::SharedArrayBufferProto) + || gen(BuiltinId::SharedArrayBufferConstructor) != snap(BuiltinId::SharedArrayBufferConstructor), data_view: gen(BuiltinId::DataViewConstructor) != snap(BuiltinId::DataViewConstructor) || gen(BuiltinId::DataViewProto) != snap(BuiltinId::DataViewProto), typed_array_family: gen(BuiltinId::TypedArrayProto) != snap(BuiltinId::TypedArrayProto)