diff --git a/Cargo.lock b/Cargo.lock index a029afa3..0043f86b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.8.71" +version = "0.8.72" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.8.71" +version = "0.8.72" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.8.71" +version = "0.8.72" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.8.71" +version = "0.8.72" dependencies = [ "ansi_term", "bumpalo", @@ -1226,7 +1226,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.8.71" +version = "0.8.72" dependencies = [ "lru", "oxide_bytecode", @@ -1235,7 +1235,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.8.71" +version = "0.8.72" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1255,7 +1255,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.8.71" +version = "0.8.72" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1269,7 +1269,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.8.71" +version = "0.8.72" dependencies = [ "num-bigint", "oxc_allocator", @@ -1284,7 +1284,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.8.71" +version = "0.8.72" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1296,7 +1296,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.8.71" +version = "0.8.72" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1305,7 +1305,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.8.71" +version = "0.8.72" dependencies = [ "bumpalo", "dashmap", @@ -1319,7 +1319,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.8.71" +version = "0.8.72" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1331,7 +1331,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.8.71" +version = "0.8.72" dependencies = [ "tracing", "tracing-appender", @@ -1340,7 +1340,7 @@ dependencies = [ [[package]] name = "oxide_parser" -version = "0.8.71" +version = "0.8.72" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1355,7 +1355,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.8.71" +version = "0.8.72" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1371,7 +1371,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.8.71" +version = "0.8.72" dependencies = [ "num-bigint", "num-traits", @@ -1384,7 +1384,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.8.71" +version = "0.8.72" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1402,7 +1402,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.8.71" +version = "0.8.72" dependencies = [ "bumpalo", "dashmap", @@ -1415,7 +1415,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.8.71" +version = "0.8.72" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 3108b79a..9491f039 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ members = [ ] [workspace.package] -version = "0.8.71" +version = "0.8.72" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_runtime_api/src/host.rs b/crates/oxide_runtime_api/src/host.rs index d77326a1..98d785ed 100644 --- a/crates/oxide_runtime_api/src/host.rs +++ b/crates/oxide_runtime_api/src/host.rs @@ -1,11 +1,107 @@ //! `VmHost` trait:builtins 依赖的 `Vm` 能力集合,trait 面向泛型而非对象安全。 +use std::ffi::c_void; use std::sync::Arc; use oxide_kernel::kernel::{KernelCore, KernelSession}; +use oxide_types::mem::P; use oxide_types::object::{Cell, JsObject, PropAttributes}; use oxide_types::value::JsValue; +/// shape 节点只读投影:shape forge 节点字段的中立镜像(免跨 crate 引用具体类型)。 +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct ShapeNode { + /// shape 整数标识。 + pub id: u32, + /// 本节点新增的属性名(字符串键 si;`u32::MAX` 为哨兵,表示无属性)。 + pub property_name: u32, + /// 父 shape id(根节点为 `None`)。 + pub parent: Option, + /// 根到本 shape 的非哨兵属性数。 + pub depth: u32, +} + +/// 内建对象种类:session builtin world 中 builtins 读取的原型与构造器槽位。 +/// +/// 变体与 builtin world 字段一一对应,仅覆盖 builtins 实际读取的槽位; +/// 新增内建读取面时在此追加变体(尾操作,零位移)。 +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum ProtoKind { + // 基础原型 + ObjectProto, + ArrayProto, + FunctionProto, + StringProto, + NumberProto, + BooleanProto, + SymbolProto, + BigIntProto, + // 错误族原型 + ErrorProto, + TypeErrorProto, + ReferenceErrorProto, + RangeErrorProto, + SyntaxErrorProto, + UriErrorProto, + EvalErrorProto, + SuppressedErrorProto, + // 集合 / 正则 / 日期原型 + DateProto, + SetProto, + MapProto, + RegExpProto, + // 缓冲与视图原型 + ArrayBufferProto, + SharedArrayBufferProto, + DataViewProto, + TypedArrayProto, + Int8ArrayProto, + Uint8ArrayProto, + Uint8ClampedArrayProto, + Int16ArrayProto, + Uint16ArrayProto, + Int32ArrayProto, + Uint32ArrayProto, + Float32ArrayProto, + Float64ArrayProto, + BigInt64ArrayProto, + BigUint64ArrayProto, + // Temporal 原型 + InstantProto, + PlainDateProto, + PlainTimeProto, + DurationProto, + ZonedDateTimeProto, + PlainDateTimeProto, + PlainMonthDayProto, + PlainYearMonthProto, + // 迭代器原型 + IteratorProto, + ArrayIteratorProto, + MapIteratorProto, + SetIteratorProto, + StringIteratorProto, + RegExpStringIteratorProto, + IteratorHelperProto, + DisposableStackProto, + AsyncDisposableStackProto, + // 构造器 + RegExpConstructor, + ArrayBufferConstructor, + SharedArrayBufferConstructor, + Int8ArrayConstructor, + Uint8ArrayConstructor, + Uint8ClampedArrayConstructor, + Int16ArrayConstructor, + Uint16ArrayConstructor, + Int32ArrayConstructor, + Uint32ArrayConstructor, + Float32ArrayConstructor, + Float64ArrayConstructor, + BigInt64ArrayConstructor, + BigUint64ArrayConstructor, +} + /// builtins 依赖的 `Vm` 能力集合。 /// /// 方法签名是 `Vm` 上同名固有方法的逐字节拷贝;`impl VmHost for Vm` 委托给 @@ -116,6 +212,29 @@ pub trait VmHost { /// 在单表达式内消费,不跨 `borrow_mut` 长存。 fn session(&self) -> std::cell::Ref<'_, KernelSession>; + // 内核能力面(perm interner / shape forge / builtin world / global object) + /// intern 字符串键,返回其 si(perm interner,零分配共享键空间)。 + fn perm_intern(&self, s: &str) -> u32; + /// 由 si 反查字符串键文本(si 非已登记字符串键时为 `None`)。 + fn perm_lookup(&self, si: u32) -> Option<&str>; + /// shape 转换:在 `parent` 上追加属性 `prop_si` 返回新 shape id; + /// 相同 (parent, prop_si) 组合恒返回同一 id。 + fn make_shape(&self, parent: u32, prop_si: u32) -> u32; + /// 查 shape `shape_id` 中属性 `prop_si` 的槽位(该 shape 链上无此属性为 `None`)。 + fn lookup_position(&self, shape_id: u32, prop_si: u32) -> Option; + /// 读 shape 节点(id 非有效 shape 为 `None`)。 + fn get_shape(&self, id: u32) -> Option; + /// perm interner 裸指针(调用方解引用读键空间;interner 随 VM 存活)。 + fn perm_interner_ptr(&self) -> *const c_void; + /// shape forge 裸指针(调用方解引用读 shape 链;forge 随 VM 存活)。 + fn shape_forge_ptr(&self) -> *const c_void; + /// 读当前 session builtin world 的内建对象指针(原型 / 构造器)。 + fn builtin_proto(&self, kind: ProtoKind) -> *mut JsObject; + /// 读 String 默认迭代器裸指针(绑定层未捕获时为 null 指针)。 + fn string_default_iterator(&self) -> *const JsObject; + /// 读当前 session 全局对象(引用计数持久指针,跨调用存活)。 + fn global_object(&self) -> P; + // 属性解析 fn property_key_si(&mut self, val: JsValue) -> u32; /// ToPropertyKey 完整路径:键值 → 内部属性键 si。对象经 ToPrimitive(string diff --git a/crates/oxide_runtime_api/src/lib.rs b/crates/oxide_runtime_api/src/lib.rs index 01dbac22..6ef5b59a 100644 --- a/crates/oxide_runtime_api/src/lib.rs +++ b/crates/oxide_runtime_api/src/lib.rs @@ -29,5 +29,5 @@ pub use coercion::{ ToPrimitiveHint, }; pub use compiler_service::CompilerService; -pub use host::VmHost; +pub use host::{ProtoKind, ShapeNode, VmHost}; pub use native_result::NativeResult; diff --git a/crates/oxide_vm/src/vm/vmhost.rs b/crates/oxide_vm/src/vm/vmhost.rs index bbd73f20..801bb05c 100644 --- a/crates/oxide_vm/src/vm/vmhost.rs +++ b/crates/oxide_vm/src/vm/vmhost.rs @@ -1,8 +1,11 @@ //! `oxide_runtime_api::VmHost` 委托实现:宿主接口各项委托到 `Vm` 同名固有方法。 +use std::ffi::c_void; use std::sync::Arc; use oxide_kernel::kernel::{KernelCore, KernelSession}; +use oxide_runtime_api::{ProtoKind, ShapeNode}; +use oxide_types::mem::P; use oxide_types::object::{Cell, JsObject, PropAttributes}; use oxide_types::value::JsValue; @@ -48,6 +51,114 @@ impl oxide_runtime_api::VmHost for Vm { fn session(&self) -> std::cell::Ref<'_, KernelSession> { self.session() } + fn perm_intern(&self, s: &str) -> u32 { + self.kernel_core.perm_interner().intern(s).0 + } + fn perm_lookup(&self, si: u32) -> Option<&str> { + self.kernel_core.perm_interner().lookup(si) + } + fn make_shape(&self, parent: u32, prop_si: u32) -> u32 { + self.kernel_core.shape_forge().make_shape(parent, prop_si) + } + fn lookup_position(&self, shape_id: u32, prop_si: u32) -> Option { + self.kernel_core.shape_forge().lookup_position(shape_id, prop_si) + } + fn get_shape(&self, id: u32) -> Option { + self.kernel_core.shape_forge().get_shape(id).map(|s| ShapeNode { + id: s.id, + property_name: s.property_name, + parent: s.parent, + depth: s.depth, + }) + } + fn perm_interner_ptr(&self) -> *const c_void { + Arc::as_ptr(self.kernel_core.perm_interner()) as *const c_void + } + fn shape_forge_ptr(&self) -> *const c_void { + Arc::as_ptr(self.kernel_core.shape_forge()) as *const c_void + } + fn builtin_proto(&self, kind: ProtoKind) -> *mut JsObject { + // session 守卫存活至方法返回:world 借用不跨语句长存。 + let session = self.session(); + let world = session.builtin_world(); + let p = match kind { + ProtoKind::ObjectProto => &world.object_proto, + ProtoKind::ArrayProto => &world.array_proto, + ProtoKind::FunctionProto => &world.function_proto, + ProtoKind::StringProto => &world.string_proto, + ProtoKind::NumberProto => &world.number_proto, + ProtoKind::BooleanProto => &world.boolean_proto, + ProtoKind::SymbolProto => &world.symbol_proto, + ProtoKind::BigIntProto => &world.bigint_proto, + ProtoKind::ErrorProto => &world.error_proto, + ProtoKind::TypeErrorProto => &world.type_error_proto, + ProtoKind::ReferenceErrorProto => &world.reference_error_proto, + ProtoKind::RangeErrorProto => &world.range_error_proto, + ProtoKind::SyntaxErrorProto => &world.syntax_error_proto, + ProtoKind::UriErrorProto => &world.uri_error_proto, + ProtoKind::EvalErrorProto => &world.eval_error_proto, + ProtoKind::SuppressedErrorProto => &world.suppressed_error_proto, + ProtoKind::DateProto => &world.date_proto, + ProtoKind::SetProto => &world.set_proto, + ProtoKind::MapProto => &world.map_proto, + ProtoKind::RegExpProto => &world.regexp_proto, + ProtoKind::ArrayBufferProto => &world.array_buffer_proto, + ProtoKind::SharedArrayBufferProto => &world.shared_array_buffer_proto, + ProtoKind::DataViewProto => &world.data_view_proto, + ProtoKind::TypedArrayProto => &world.typed_array_proto, + ProtoKind::Int8ArrayProto => &world.int8array_proto, + ProtoKind::Uint8ArrayProto => &world.uint8array_proto, + ProtoKind::Uint8ClampedArrayProto => &world.uint8clampedarray_proto, + ProtoKind::Int16ArrayProto => &world.int16array_proto, + ProtoKind::Uint16ArrayProto => &world.uint16array_proto, + ProtoKind::Int32ArrayProto => &world.int32array_proto, + ProtoKind::Uint32ArrayProto => &world.uint32array_proto, + ProtoKind::Float32ArrayProto => &world.float32array_proto, + ProtoKind::Float64ArrayProto => &world.float64array_proto, + ProtoKind::BigInt64ArrayProto => &world.bigint64array_proto, + ProtoKind::BigUint64ArrayProto => &world.biguint64array_proto, + ProtoKind::InstantProto => &world.instant_proto, + ProtoKind::PlainDateProto => &world.plain_date_proto, + ProtoKind::PlainTimeProto => &world.plain_time_proto, + ProtoKind::DurationProto => &world.duration_proto, + ProtoKind::ZonedDateTimeProto => &world.zoned_date_time_proto, + ProtoKind::PlainDateTimeProto => &world.plain_date_time_proto, + ProtoKind::PlainMonthDayProto => &world.plain_month_day_proto, + ProtoKind::PlainYearMonthProto => &world.plain_year_month_proto, + ProtoKind::IteratorProto => &world.iterator_proto, + ProtoKind::ArrayIteratorProto => &world.array_iterator_proto, + ProtoKind::MapIteratorProto => &world.map_iterator_proto, + ProtoKind::SetIteratorProto => &world.set_iterator_proto, + ProtoKind::StringIteratorProto => &world.string_iterator_proto, + ProtoKind::RegExpStringIteratorProto => &world.regexp_string_iterator_proto, + ProtoKind::IteratorHelperProto => &world.iterator_helper_proto, + ProtoKind::DisposableStackProto => &world.disposable_stack_proto, + ProtoKind::AsyncDisposableStackProto => &world.async_disposable_stack_proto, + ProtoKind::RegExpConstructor => &world.regexp_constructor, + ProtoKind::ArrayBufferConstructor => &world.array_buffer_constructor, + ProtoKind::SharedArrayBufferConstructor => &world.shared_array_buffer_constructor, + ProtoKind::Int8ArrayConstructor => &world.int8array_constructor, + ProtoKind::Uint8ArrayConstructor => &world.uint8array_constructor, + ProtoKind::Uint8ClampedArrayConstructor => &world.uint8clampedarray_constructor, + ProtoKind::Int16ArrayConstructor => &world.int16array_constructor, + ProtoKind::Uint16ArrayConstructor => &world.uint16array_constructor, + ProtoKind::Int32ArrayConstructor => &world.int32array_constructor, + ProtoKind::Uint32ArrayConstructor => &world.uint32array_constructor, + ProtoKind::Float32ArrayConstructor => &world.float32array_constructor, + ProtoKind::Float64ArrayConstructor => &world.float64array_constructor, + ProtoKind::BigInt64ArrayConstructor => &world.bigint64array_constructor, + ProtoKind::BigUint64ArrayConstructor => &world.biguint64array_constructor, + }; + P::as_ptr(p) as *mut JsObject + } + fn string_default_iterator(&self) -> *const JsObject { + let session = self.session(); + session.builtin_world().string_default_iterator.get() + } + fn global_object(&self) -> P { + let session = self.session(); + session.global_object().clone() + } fn pc(&self) -> usize { self.pc }