diff --git a/Cargo.lock b/Cargo.lock index efa42b58..09b75a0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.18.3" +version = "0.18.4" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.18.3" +version = "0.18.4" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.18.3" +version = "0.18.4" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.18.3" +version = "0.18.4" dependencies = [ "ansi_term", "bumpalo", @@ -1228,7 +1228,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.18.3" +version = "0.18.4" dependencies = [ "lru", "oxide_bytecode", @@ -1237,7 +1237,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.18.3" +version = "0.18.4" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1258,7 +1258,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.18.3" +version = "0.18.4" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1272,7 +1272,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.18.3" +version = "0.18.4" dependencies = [ "num-bigint", "oxc_allocator", @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.18.3" +version = "0.18.4" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1300,7 +1300,7 @@ dependencies = [ [[package]] name = "oxide_fold" -version = "0.18.3" +version = "0.18.4" dependencies = [ "num-bigint", "oxide_bytecode", @@ -1312,7 +1312,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.18.3" +version = "0.18.4" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1321,7 +1321,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.18.3" +version = "0.18.4" dependencies = [ "bumpalo", "dashmap", @@ -1335,7 +1335,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.18.3" +version = "0.18.4" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1347,7 +1347,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.18.3" +version = "0.18.4" dependencies = [ "tracing", "tracing-appender", @@ -1356,11 +1356,11 @@ dependencies = [ [[package]] name = "oxide_net" -version = "0.18.3" +version = "0.18.4" [[package]] name = "oxide_parser" -version = "0.18.3" +version = "0.18.4" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1375,7 +1375,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.18.3" +version = "0.18.4" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.18.3" +version = "0.18.4" dependencies = [ "num-bigint", "num-traits", @@ -1404,7 +1404,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.18.3" +version = "0.18.4" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1424,7 +1424,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.18.3" +version = "0.18.4" dependencies = [ "bumpalo", "dashmap", @@ -1437,7 +1437,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.18.3" +version = "0.18.4" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 75da6729..bd702447 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ members = [ ] [workspace.package] -version = "0.18.3" +version = "0.18.4" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_vm/src/dispatch/call.rs b/crates/oxide_vm/src/dispatch/call.rs index 6f4a9592..dfeb87fc 100644 --- a/crates/oxide_vm/src/dispatch/call.rs +++ b/crates/oxide_vm/src/dispatch/call.rs @@ -625,10 +625,11 @@ impl Vm { self.raise_error_kind("ReferenceError", "super() called more than once")?; return Ok(true); } - let Some(derived_this) = frame.constructed_this else { + if !frame.has_constructed_this { self.raise_error_kind("ReferenceError", "super() without derived this")?; return Ok(true); - }; + } + let derived_this = frame.constructed_this; let callee = frame.callee; let new_target = self.regs[255]; @@ -1197,10 +1198,11 @@ impl Vm { self.raise_error_kind("ReferenceError", "super() called more than once")?; return Ok(true); } - let Some(derived_this) = frame.constructed_this else { + if !frame.has_constructed_this { self.raise_error_kind("ReferenceError", "super() without derived this")?; return Ok(true); - }; + } + let derived_this = frame.constructed_this; let callee = frame.callee; let new_target = self.regs[255]; diff --git a/crates/oxide_vm/src/session_gc/tests.rs b/crates/oxide_vm/src/session_gc/tests.rs index 41556adf..ef6b9c86 100644 --- a/crates/oxide_vm/src/session_gc/tests.rs +++ b/crates/oxide_vm/src/session_gc/tests.rs @@ -102,7 +102,8 @@ fn gc_roots_contains_registers_frames_and_root_roots() { arguments_obj: JsValue::undefined(), construct_result_reg: None, strict: false, - constructed_this: Some(JsValue::from_js_object(child_session)), + constructed_this: JsValue::from_js_object(child_session), + has_constructed_this: true, is_derived_constructor: false, super_called: false, continuation: FrameContinuation::None, diff --git a/crates/oxide_vm/src/suspended.rs b/crates/oxide_vm/src/suspended.rs index ab3ec78d..8a1c9295 100644 --- a/crates/oxide_vm/src/suspended.rs +++ b/crates/oxide_vm/src/suspended.rs @@ -191,8 +191,8 @@ impl SuspendedFrame { f(frame.saved_new_target); f(frame.callee); f(frame.arguments_obj); - if let Some(ct) = frame.constructed_this { - f(ct); + if frame.has_constructed_this { + f(frame.constructed_this); } } for v in &self.spill_stack { @@ -307,7 +307,8 @@ mod tests { callee: tag, arguments_obj: JsValue::undefined(), construct_result_reg: None, - constructed_this: Some(tag), + constructed_this: tag, + has_constructed_this: true, is_derived_constructor: false, super_called: false, strict: false, diff --git a/crates/oxide_vm/src/vm/call.rs b/crates/oxide_vm/src/vm/call.rs index f156f210..79e301b6 100644 --- a/crates/oxide_vm/src/vm/call.rs +++ b/crates/oxide_vm/src/vm/call.rs @@ -381,7 +381,8 @@ impl Vm { callee, arguments_obj: JsValue::undefined(), construct_result_reg: construct.result_reg, - constructed_this: construct.constructed_this, + constructed_this: construct.constructed_this.unwrap_or(JsValue::undefined()), + has_constructed_this: construct.constructed_this.is_some(), is_derived_constructor: obj.is_derived_constructor(), super_called: false, strict: sub_is_strict, diff --git a/crates/oxide_vm/src/vm/frames.rs b/crates/oxide_vm/src/vm/frames.rs index e4085428..15496c15 100644 --- a/crates/oxide_vm/src/vm/frames.rs +++ b/crates/oxide_vm/src/vm/frames.rs @@ -68,7 +68,13 @@ pub struct CallFrame { /// 无 mapped arguments 时为 undefined。GC 根(帧遍历期标记)。 pub arguments_obj: JsValue, pub construct_result_reg: Option, - pub constructed_this: Option, + /// derived 构造器构造出的 this 值;仅当 `has_constructed_this` 为真时有效, + /// 标志为假时该槽为 undefined。 + /// + /// 判别位并入结构体尾部 bool 组(单字节容纳四个 bool),字段本体只占 + /// 裸 JsValue 的 8 字节,帧整体比 Option 包装省 8 字节。 + pub constructed_this: JsValue, + pub has_constructed_this: bool, pub is_derived_constructor: bool, /// derived 构造帧是否已成功调用 super()(父构造器正常返回后置位)。 /// @@ -91,6 +97,18 @@ pub struct CallFrame { pub upvalues: *const [*mut Cell], } +#[cfg(test)] +mod tests { + use super::CallFrame; + + /// CallFrame 尺寸钉:constructed_this 的判别位并入尾部 bool 组后, + /// 帧固定 104 字节(Option 包装时代为 112 字节)。 + #[test] + fn call_frame_size_pinned() { + assert_eq!(std::mem::size_of::(), 104); + } +} + /// 一次 `for-in` 迭代的游标:已收集的 key 列表与当前下标。 /// /// 体是堆上 `Box`:迭代器表与挂起状态盒各独占持有体,出表/状态盒释放时 diff --git a/crates/oxide_vm/src/vm/gc_hooks.rs b/crates/oxide_vm/src/vm/gc_hooks.rs index 83e18058..6655ac4d 100644 --- a/crates/oxide_vm/src/vm/gc_hooks.rs +++ b/crates/oxide_vm/src/vm/gc_hooks.rs @@ -74,7 +74,14 @@ impl Vm { f(RootGroup::Frames, frame.saved_new_target); f(RootGroup::Frames, frame.callee); f(RootGroup::Frames, frame.arguments_obj); - f(RootGroup::Frames, frame.constructed_this.unwrap_or(JsValue::undefined())); + f( + RootGroup::Frames, + if frame.has_constructed_this { + frame.constructed_this + } else { + JsValue::undefined() + }, + ); } for &v in &self.save_stack { f(RootGroup::SaveStack, v); diff --git a/crates/oxide_vm/src/vm_dispatch_ctrl.rs b/crates/oxide_vm/src/vm_dispatch_ctrl.rs index 28270301..a2c72908 100644 --- a/crates/oxide_vm/src/vm_dispatch_ctrl.rs +++ b/crates/oxide_vm/src/vm_dispatch_ctrl.rs @@ -819,7 +819,11 @@ impl Vm { if let Some(frame) = self.frames.pop() { self.cell_stack.pop(); let construct_result_reg = frame.construct_result_reg; - let constructed_this = frame.constructed_this; + let constructed_this = if frame.has_constructed_this { + Some(frame.constructed_this) + } else { + None + }; let is_derived_constructor = frame.is_derived_constructor; let super_called = frame.super_called; let continuation = frame.continuation; diff --git a/crates/oxide_vm/src/vm_dispatch_misc.rs b/crates/oxide_vm/src/vm_dispatch_misc.rs index 1e3392e9..ea6cc2c5 100644 --- a/crates/oxide_vm/src/vm_dispatch_misc.rs +++ b/crates/oxide_vm/src/vm_dispatch_misc.rs @@ -1646,7 +1646,7 @@ mod tests { // NEW 帧契约:构造结果寄存器与 constructed_this 随帧携带 assert_eq!(frame.construct_result_reg, Some(0), "构造结果写回 regs[0]"); assert!( - frame.constructed_this.is_some_and(|v| v.is_object()), + frame.has_constructed_this && frame.constructed_this.is_object(), "基类构造路径 constructed_this 应为新对象" ); assert!(!frame.is_derived_constructor, "普通函数非 derived 构造器"); diff --git a/crates/oxide_vm/src/vm_support/tests.rs b/crates/oxide_vm/src/vm_support/tests.rs index 296e02b2..d043a45c 100644 --- a/crates/oxide_vm/src/vm_support/tests.rs +++ b/crates/oxide_vm/src/vm_support/tests.rs @@ -852,7 +852,8 @@ fn reset_clears_runtime_state_like_rerun() { arguments_obj: JsValue::undefined(), construct_result_reg: None, strict: false, - constructed_this: None, + constructed_this: JsValue::undefined(), + has_constructed_this: false, is_derived_constructor: false, super_called: false, continuation: crate::vm::FrameContinuation::None,