refactor: 写路径契约与压帧与异步标志组收结构体并删死参

This commit is contained in:
2026-10-12 19:12:11 +00:00
parent 2dc5e1fb9e
commit 05b9b280cf
16 changed files with 339 additions and 274 deletions
Generated
+21 -21
View File
@@ -1160,7 +1160,7 @@ dependencies = [
[[package]]
name = "oxide_builtins"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"chrono",
"fast-float",
@@ -1185,7 +1185,7 @@ dependencies = [
[[package]]
name = "oxide_bytecode"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"num-bigint",
"oxide_log",
@@ -1193,7 +1193,7 @@ dependencies = [
[[package]]
name = "oxide_cfg"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"oxide_bytecode",
"oxide_emit",
@@ -1204,7 +1204,7 @@ dependencies = [
[[package]]
name = "oxide_cli"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"ansi_term",
"bumpalo",
@@ -1228,7 +1228,7 @@ dependencies = [
[[package]]
name = "oxide_code_cache"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"lru",
"oxide_bytecode",
@@ -1237,7 +1237,7 @@ dependencies = [
[[package]]
name = "oxide_compiler"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1258,7 +1258,7 @@ dependencies = [
[[package]]
name = "oxide_dce"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1272,7 +1272,7 @@ dependencies = [
[[package]]
name = "oxide_emit"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"num-bigint",
"oxc_allocator",
@@ -1288,7 +1288,7 @@ dependencies = [
[[package]]
name = "oxide_engine"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1300,7 +1300,7 @@ dependencies = [
[[package]]
name = "oxide_fold"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"num-bigint",
"oxide_bytecode",
@@ -1312,7 +1312,7 @@ dependencies = [
[[package]]
name = "oxide_ir"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"oxide_bytecode",
"oxide_log",
@@ -1321,7 +1321,7 @@ dependencies = [
[[package]]
name = "oxide_kernel"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"bumpalo",
"dashmap",
@@ -1335,7 +1335,7 @@ dependencies = [
[[package]]
name = "oxide_liveness"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1347,7 +1347,7 @@ dependencies = [
[[package]]
name = "oxide_log"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"tracing",
"tracing-appender",
@@ -1356,11 +1356,11 @@ dependencies = [
[[package]]
name = "oxide_net"
version = "0.17.5"
version = "0.17.6"
[[package]]
name = "oxide_parser"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1375,7 +1375,7 @@ dependencies = [
[[package]]
name = "oxide_regalloc"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"oxide_bytecode",
"oxide_cfg",
@@ -1391,7 +1391,7 @@ dependencies = [
[[package]]
name = "oxide_runtime_api"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"num-bigint",
"num-traits",
@@ -1404,7 +1404,7 @@ dependencies = [
[[package]]
name = "oxide_test262"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"oxide_bytecode",
"oxide_compiler",
@@ -1424,7 +1424,7 @@ dependencies = [
[[package]]
name = "oxide_types"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"bumpalo",
"dashmap",
@@ -1437,7 +1437,7 @@ dependencies = [
[[package]]
name = "oxide_vm"
version = "0.17.5"
version = "0.17.6"
dependencies = [
"bumpalo",
"chrono",
+1 -1
View File
@@ -25,7 +25,7 @@ members = [
]
[workspace.package]
version = "0.17.5"
version = "0.17.6"
edition = "2021"
license = "MIT"
rust-version = "1.80"
+2 -6
View File
@@ -90,7 +90,7 @@ pub(super) fn run(f: &mut IRFunction, map: &AllocMap) {
}
// 重写 inst 本体(含调用点参数连续性 MOV)
let (rewritten, arg_movs) = rewrite_inst(f, inst, map, &slot_color, i);
let (rewritten, arg_movs) = rewrite_inst(inst, map, &slot_color);
// 发射顺序:UNSPILLs(按 vreg 升序)→ RMW UNSPILL → 连续性 MOVs → 指令 → SPILLs
for &(vreg, color) in &use_unspills {
@@ -133,9 +133,7 @@ pub(super) fn run(f: &mut IRFunction, map: &AllocMap) {
}
/// 重写单条指令:槽位映射 + 调用点参数连续性 MOV 补位。返回 (重写后指令, 参数 MOV 列表)。
fn rewrite_inst(
f: &IRFunction, inst: &Inst, map: &AllocMap, slot_color: &BTreeMap<u32, u32>, i: usize,
) -> (Inst, Vec<(u32, u32)>) {
fn rewrite_inst(inst: &Inst, map: &AllocMap, slot_color: &BTreeMap<u32, u32>) -> (Inst, Vec<(u32, u32)>) {
let raw_nargs = inst.ext.first().copied().unwrap_or(0);
let nargs = raw_nargs;
let first_arg = match inst.op {
@@ -172,7 +170,6 @@ fn rewrite_inst(
}
}
}
let _ = i;
// 槽位重写
let rewrite = |o: Operand| -> Operand {
@@ -275,7 +272,6 @@ fn rewrite_inst(
_ => {}
}
}
let _ = f;
// 防御:imm16 编码位的操作数必须是 Imm/None,不得是 Reg——
// 上面的 Reg 重写会改号,若该槽被改写,VM 侧按 imm16 读取会拿到错误值。
match inst.op {
+79 -89
View File
@@ -70,6 +70,20 @@ pub(crate) const ASYNC_ESCAPE_PROMISE_PROP: &str = "__oxide_async_escape_promise
/// 异步释放结算闭包上存释放方法 promise 的属性名(陈旧防御校验用)。
pub(crate) const ASYNC_DISPOSE_PROMISE_PROP: &str = "__oxide_async_dispose_promise__";
/// 异步 dispatch 标志组:异步上下文、异步生成器上下文与三个 dispatch 标志
/// (生成器 / 异步 / 异步生成器)。
///
/// 按值传递的 Copy 结构体,字段数五;保存点把整组 VM 标志合成一个结构体
/// 字面量,恢复方整体接参,避免 4 至 5 个保存值散参搬运。
#[derive(Clone, Copy)]
pub(crate) struct AsyncDispatchFlags {
pub(crate) ctx: Option<JsValue>,
pub(crate) gen_ctx: Option<JsValue>,
pub(crate) gd: bool,
pub(crate) ad: bool,
pub(crate) agd: bool,
}
impl Vm {
/// 调用异步函数返回的 capability promise:创建上下文对象 + 状态盒,立即压帧
/// 同步执行 body 到第一个 AWAIT/RETURN/异常,返回 pending promise。
@@ -126,10 +140,13 @@ impl Vm {
let state_ptr = self.async_state_ptr(ctx_val);
let saved = self.save_inline_state(256);
self.async_suspended = false;
let prev_ctx = self.async_context.take();
let prev_dispatch = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_gen_dispatch = self.async_gen_dispatch;
let prev = AsyncDispatchFlags {
ctx: self.async_context.take(),
gen_ctx: self.async_gen_context.take(),
gd: self.generator_dispatch,
ad: self.async_dispatch,
agd: self.async_gen_dispatch,
};
self.async_dispatch = true;
// 普通异步函数执行期间 AWAIT 走普通异步恢复路径:屏蔽外层异步生成器上下文。
self.async_gen_dispatch = false;
@@ -142,7 +159,7 @@ impl Vm {
let push_res = self.prepare_execution_initial(callee, this_value, &args);
unsafe { (*state_ptr).args = args };
if let Err(e) = push_res {
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err(e);
@@ -150,7 +167,7 @@ impl Vm {
unsafe { (*state_ptr).phase = AsyncPhase::Running };
let result = self.dispatch();
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
if std::mem::take(&mut self.async_suspended) {
@@ -189,10 +206,13 @@ impl Vm {
let state_ptr = self.async_state_ptr(ctx_val);
let saved = self.save_inline_state(256);
self.async_suspended = false;
let prev_ctx = self.async_context.take();
let prev_dispatch = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_gen_dispatch = self.async_gen_dispatch;
let prev = AsyncDispatchFlags {
ctx: self.async_context.take(),
gen_ctx: self.async_gen_context.take(),
gd: self.generator_dispatch,
ad: self.async_dispatch,
agd: self.async_gen_dispatch,
};
self.async_dispatch = true;
// 普通异步函数执行期间 AWAIT 走普通异步恢复路径:屏蔽外层异步生成器上下文。
self.async_gen_dispatch = false;
@@ -204,7 +224,7 @@ impl Vm {
let restore_res = state.suspended.restore_into(self, state.callee);
if restore_res.is_err() {
// callee 记录的表代际已被回收(跨 run 且无存活函数引用),无法恢复。
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err("async function suspended across runs is no longer valid".into());
@@ -218,7 +238,7 @@ impl Vm {
self.pending_error_kind = Some(self.thrown_error_kind(exc));
if self.unwind().is_err() {
// 异常逃逸出异步帧(无 catch/finally):结算为 reject。
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
let thrown = self.last_uncaught_value.take().unwrap_or(exc);
self.finish_async(state_ptr, Err(thrown))?;
@@ -230,7 +250,7 @@ impl Vm {
}
let result = self.dispatch();
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
if std::mem::take(&mut self.async_suspended) {
@@ -259,14 +279,14 @@ impl Vm {
}
/// 恢复嵌套 dispatch 覆盖的 async 上下文标志(含外层异步生成器上下文)。
fn restore_async_flags(
&mut self, prev_ctx: Option<JsValue>, prev_dispatch: bool, prev_gen_ctx: Option<JsValue>,
prev_gen_dispatch: bool,
) {
self.async_dispatch = prev_dispatch;
self.async_context = prev_ctx;
self.async_gen_dispatch = prev_gen_dispatch;
self.async_gen_context = prev_gen_ctx;
///
/// 注意:`gd` 位(`generator_dispatch`)不写回——普通异步函数执行期间
/// 生成器 dispatch 标志不被本路径覆盖,与保存点只存四字段同口径。
fn restore_async_flags(&mut self, prev: AsyncDispatchFlags) {
self.async_dispatch = prev.ad;
self.async_context = prev.ctx;
self.async_gen_dispatch = prev.agd;
self.async_gen_context = prev.gen_ctx;
}
/// 结算异步函数:正常结束 resolve capability,异常结束 reject capability。
@@ -437,10 +457,13 @@ impl Vm {
let saved = self.save_inline_state(256);
// 清上一轮多层关闭残留的挂起信号(多层逐层结算每轮清零,防陈旧信号误消费)。
self.async_suspended = false;
let prev_ctx = self.async_context.take();
let prev_dispatch = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_gen_dispatch = self.async_gen_dispatch;
let prev = AsyncDispatchFlags {
ctx: self.async_context.take(),
gen_ctx: self.async_gen_context.take(),
gd: self.generator_dispatch,
ad: self.async_dispatch,
agd: self.async_gen_dispatch,
};
self.async_dispatch = true;
self.async_gen_dispatch = false;
self.async_context = Some(ctx);
@@ -454,14 +477,14 @@ impl Vm {
Some(p) if p.close_promise == promise
);
if is_stale {
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
let restore_res = state.suspended.restore_into(self, state.callee);
if restore_res.is_err() {
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err("async function suspended across runs is no longer valid".into());
@@ -486,7 +509,7 @@ impl Vm {
Ok(true) => {
self.async_suspended = false;
self.snapshot_async(unsafe { &mut *state_ptr })?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
@@ -504,7 +527,7 @@ impl Vm {
if self.unwind().is_err() {
let exc = self.last_uncaught_value.take().unwrap_or(value);
self.finish_async(state_ptr, Err(exc))?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
@@ -513,7 +536,7 @@ impl Vm {
// 处理器体内再挂起(await):快照新状态后退出。
if std::mem::take(&mut self.async_suspended) {
self.snapshot_async(unsafe { &mut *state_ptr })?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
@@ -528,7 +551,7 @@ impl Vm {
self.finish_async(state_ptr, Err(exc))?;
}
}
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
@@ -548,7 +571,7 @@ impl Vm {
// 完成跳转后 body 继续执行到下一个 await/return/异常。
if std::mem::take(&mut self.async_suspended) {
self.snapshot_async(unsafe { &mut *state_ptr })?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
@@ -565,7 +588,7 @@ impl Vm {
}
}
}
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
Ok(())
@@ -574,13 +597,12 @@ impl Vm {
/// 续 dispatch 并结算:运行 body 到下一个 AWAIT/RETURN/异常,挂起则快照新状态,
/// 完成/异常则结算 capability。恢复调用方状态。
fn dispatch_and_finish_async(
&mut self, state_ptr: *mut AsyncState, saved: Box<InlineSyncState>, prev_ctx: Option<JsValue>,
prev_dispatch: bool, prev_gen_ctx: Option<JsValue>, prev_gen_dispatch: bool,
&mut self, state_ptr: *mut AsyncState, saved: Box<InlineSyncState>, prev: AsyncDispatchFlags,
) -> Result<(), String> {
let result = self.dispatch();
if std::mem::take(&mut self.async_suspended) {
self.snapshot_async(unsafe { &mut *state_ptr })?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
@@ -595,7 +617,7 @@ impl Vm {
self.finish_async(state_ptr, Err(exc))?;
}
}
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
Ok(())
@@ -621,10 +643,13 @@ impl Vm {
let saved = self.save_inline_state(256);
// 清上一轮残留的挂起信号(防陈旧信号误消费)。
self.async_suspended = false;
let prev_ctx = self.async_context.take();
let prev_dispatch = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_gen_dispatch = self.async_gen_dispatch;
let prev = AsyncDispatchFlags {
ctx: self.async_context.take(),
gen_ctx: self.async_gen_context.take(),
gd: self.generator_dispatch,
ad: self.async_dispatch,
agd: self.async_gen_dispatch,
};
self.async_dispatch = true;
self.async_gen_dispatch = false;
self.async_context = Some(ctx);
@@ -638,14 +663,14 @@ impl Vm {
Some(p) if p.dispose_promise == promise
);
if is_stale {
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
let restore_res = state.suspended.restore_into(self, state.callee);
if restore_res.is_err() {
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err("async function suspended across runs is no longer valid".into());
@@ -658,7 +683,7 @@ impl Vm {
Some(p) => (p.mark, p.completion, p.kind),
// 陈旧防御已早退,正常路径此处必为 Some;防御性兜底。
None => {
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
@@ -675,7 +700,7 @@ impl Vm {
// 从水位续释放循环(复用批量释放核心);再挂起则重新登记 + 快照 + 返回。
if matches!(self.dispose_above_core(mark, kind, completion)?, DisposePhase::Suspended) {
self.snapshot_async(unsafe { &mut *state_ptr })?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
@@ -688,19 +713,12 @@ impl Vm {
if self.exception_value.is_some() && self.unwind().is_err() {
let exc = self.last_uncaught_value.take().unwrap_or(JsValue::undefined());
self.finish_async(state_ptr, Err(exc))?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
self.dispatch_and_finish_async(
state_ptr,
saved,
prev_ctx,
prev_dispatch,
prev_gen_ctx,
prev_gen_dispatch,
)
self.dispatch_and_finish_async(state_ptr, saved, prev)
}
DisposeResumeKind::Unwind(handler) => {
// 重压 handler 再入 unwind(handler 已弹出,不重压则 catch/finally 丢失)。
@@ -710,19 +728,12 @@ impl Vm {
if self.unwind().is_err() {
let exc = self.last_uncaught_value.take().unwrap_or(JsValue::undefined());
self.finish_async(state_ptr, Err(exc))?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
self.dispatch_and_finish_async(
state_ptr,
saved,
prev_ctx,
prev_dispatch,
prev_gen_ctx,
prev_gen_dispatch,
)
self.dispatch_and_finish_async(state_ptr, saved, prev)
}
DisposeResumeKind::Escape(completion_val) => {
if self.exception_value.is_some() {
@@ -730,19 +741,12 @@ impl Vm {
if self.unwind().is_err() {
let exc = self.last_uncaught_value.take().unwrap_or(JsValue::undefined());
self.finish_async(state_ptr, Err(exc))?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
self.dispatch_and_finish_async(
state_ptr,
saved,
prev_ctx,
prev_dispatch,
prev_gen_ctx,
prev_gen_dispatch,
)
self.dispatch_and_finish_async(state_ptr, saved, prev)
} else {
// 无合并错误:执行完成。
match completion_val {
@@ -750,30 +754,16 @@ impl Vm {
let result = self.do_return(ret_val)?;
if let Some(result) = result {
self.finish_async(state_ptr, Ok(result))?;
self.restore_async_flags(prev_ctx, prev_dispatch, prev_gen_ctx, prev_gen_dispatch);
self.restore_async_flags(prev);
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Ok(());
}
self.dispatch_and_finish_async(
state_ptr,
saved,
prev_ctx,
prev_dispatch,
prev_gen_ctx,
prev_gen_dispatch,
)
self.dispatch_and_finish_async(state_ptr, saved, prev)
}
Completion::Break { target_pc, .. } | Completion::Continue { target_pc, .. } => {
self.pc = target_pc;
self.dispatch_and_finish_async(
state_ptr,
saved,
prev_ctx,
prev_dispatch,
prev_gen_ctx,
prev_gen_dispatch,
)
self.dispatch_and_finish_async(state_ptr, saved, prev)
}
}
}
+61 -57
View File
@@ -20,6 +20,7 @@ use oxide_runtime_api::{NativeResult, VmHost};
use oxide_types::object::{Cell, JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
use crate::async_func::AsyncDispatchFlags;
use crate::generator::{DelegateOutcome, GeneratorResumeMode};
use crate::vm::{Completion, DisposeResumeKind, Vm};
use crate::vm_dispatch_misc::DisposePhase;
@@ -320,11 +321,13 @@ impl Vm {
let saved = self.save_inline_state(256);
self.generator_suspended = None;
self.async_gen_suspended = false;
let prev_ctx = self.async_context.take();
let prev_gd = self.generator_dispatch;
let prev_ad = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_agd = self.async_gen_dispatch;
let prev = AsyncDispatchFlags {
ctx: self.async_context.take(),
gen_ctx: self.async_gen_context.take(),
gd: self.generator_dispatch,
ad: self.async_dispatch,
agd: self.async_gen_dispatch,
};
self.generator_dispatch = true;
self.async_dispatch = true;
self.async_gen_dispatch = true;
@@ -337,11 +340,11 @@ impl Vm {
let restore_res = state.suspended.restore_into(self, state.callee);
if restore_res.is_err() {
// callee 记录的表代际已被回收(跨 run 且无存活函数引用),无法恢复。
self.async_gen_dispatch = prev_agd;
self.async_gen_context = prev_gen_ctx;
self.generator_dispatch = prev_gd;
self.async_dispatch = prev_ad;
self.async_context = prev_ctx;
self.async_gen_dispatch = prev.agd;
self.async_gen_context = prev.gen_ctx;
self.generator_dispatch = prev.gd;
self.async_dispatch = prev.ad;
self.async_context = prev.ctx;
self.native_call_depth -= 1;
self.restore_inline_state(saved);
return Err("async generator suspended across runs is no longer valid".into());
@@ -369,7 +372,7 @@ impl Vm {
.last_uncaught_value
.take()
.unwrap_or_else(|| oxide_builtins::error::create_from_text(self, &e));
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_exc(state_ptr, saved, gen_val, exc);
}
Ok(DelegateOutcome::Suspend { .. }) => {
@@ -378,7 +381,7 @@ impl Vm {
// dispatch 之前返回,调度标志须在此恢复(dispatch 后的恢复不会执行)。
unsafe { (*state_ptr).phase = AsyncGenPhase::AwaitSuspended };
self.snapshot_async_generator(state_ptr)?;
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.restore_inline_state(saved);
return Ok(());
}
@@ -390,7 +393,7 @@ impl Vm {
// (return 请求值经 Await 步挂起结算),此臂仅作穷尽防御。
let completed = self.complete_generator_return(value);
if let Some(completed) = completed? {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_ok(state_ptr, saved, gen_val, completed);
}
// 进入 finally 穿越:继续 dispatch。
@@ -415,14 +418,14 @@ impl Vm {
self.pending_error_kind = Some(self.thrown_error_kind(exc));
if self.unwind().is_err() {
let thrown = self.last_uncaught_value.take().unwrap_or(exc);
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_exc(state_ptr, saved, gen_val, thrown);
}
}
GeneratorResumeMode::Return(value) => {
let completed = self.complete_generator_return(value);
if let Some(completed) = completed? {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_ok(state_ptr, saved, gen_val, completed);
}
// 进入 finally 穿越:继续 dispatch。
@@ -432,7 +435,7 @@ impl Vm {
}
let result = self.dispatch();
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.post_dispatch_async_gen(state_ptr, saved, gen_val, result)
}
@@ -605,15 +608,12 @@ impl Vm {
}
/// 恢复嵌套 dispatch 覆盖的 VM 标志(dispatch 前提前返回的路径用)。
fn restore_async_gen_flags(
&mut self, prev_ctx: Option<JsValue>, prev_gen_ctx: Option<JsValue>, prev_gd: bool, prev_ad: bool,
prev_agd: bool,
) {
self.async_gen_dispatch = prev_agd;
self.async_gen_context = prev_gen_ctx;
self.generator_dispatch = prev_gd;
self.async_dispatch = prev_ad;
self.async_context = prev_ctx;
fn restore_async_gen_flags(&mut self, prev: AsyncDispatchFlags) {
self.async_gen_dispatch = prev.agd;
self.async_gen_context = prev.gen_ctx;
self.generator_dispatch = prev.gd;
self.async_dispatch = prev.ad;
self.async_context = prev.ctx;
self.native_call_depth -= 1;
}
@@ -842,11 +842,13 @@ impl Vm {
// 清上一轮多层关闭残留的挂起信号(多层逐层结算每轮清零,防陈旧信号误消费)。
self.generator_suspended = None;
self.async_gen_suspended = false;
let prev_ctx = self.async_context.take();
let prev_gd = self.generator_dispatch;
let prev_ad = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_agd = self.async_gen_dispatch;
let prev = AsyncDispatchFlags {
ctx: self.async_context.take(),
gen_ctx: self.async_gen_context.take(),
gd: self.generator_dispatch,
ad: self.async_dispatch,
agd: self.async_gen_dispatch,
};
self.generator_dispatch = true;
self.async_dispatch = true;
self.async_gen_dispatch = true;
@@ -862,13 +864,13 @@ impl Vm {
Some(p) if p.close_promise == promise
);
if is_stale {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.restore_inline_state(saved);
return Ok(());
}
let restore_res = state.suspended.restore_into(self, state.callee);
if restore_res.is_err() {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.restore_inline_state(saved);
return Err("async generator suspended across runs is no longer valid".into());
}
@@ -880,7 +882,7 @@ impl Vm {
Some(p) => (p.completion, p.remaining),
// 陈旧防御已早退,正常路径此处必为 Some;防御性兜底。
None => {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.restore_inline_state(saved);
return Ok(());
}
@@ -897,7 +899,7 @@ impl Vm {
self.async_gen_suspended = false;
unsafe { (*state_ptr).phase = AsyncGenPhase::AwaitSuspended };
self.snapshot_async_generator(state_ptr)?;
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.restore_inline_state(saved);
return Ok(());
}
@@ -913,11 +915,11 @@ impl Vm {
self.pending_error_kind = Some(self.thrown_error_kind(value));
if self.unwind().is_err() {
let exc = self.last_uncaught_value.take().unwrap_or(value);
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_exc(state_ptr, saved, ctx, exc);
}
let result = self.dispatch();
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.post_dispatch_async_gen(state_ptr, saved, ctx, result);
}
@@ -926,18 +928,18 @@ impl Vm {
Completion::Return { value: ret_val, .. } => {
let result = self.do_return(ret_val)?;
if let Some(result) = result {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_ok(state_ptr, saved, ctx, result);
}
// 嵌套帧未弹空:续 dispatch。
let result = self.dispatch();
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.post_dispatch_async_gen(state_ptr, saved, ctx, result)
}
Completion::Break { target_pc, .. } | Completion::Continue { target_pc, .. } => {
self.pc = target_pc;
let result = self.dispatch();
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.post_dispatch_async_gen(state_ptr, saved, ctx, result)
}
}
@@ -964,11 +966,13 @@ impl Vm {
// 清上一轮残留的挂起信号(防陈旧信号误消费)。
self.generator_suspended = None;
self.async_gen_suspended = false;
let prev_ctx = self.async_context.take();
let prev_gd = self.generator_dispatch;
let prev_ad = self.async_dispatch;
let prev_gen_ctx = self.async_gen_context.take();
let prev_agd = self.async_gen_dispatch;
let prev = AsyncDispatchFlags {
ctx: self.async_context.take(),
gen_ctx: self.async_gen_context.take(),
gd: self.generator_dispatch,
ad: self.async_dispatch,
agd: self.async_gen_dispatch,
};
self.generator_dispatch = true;
self.async_dispatch = true;
self.async_gen_dispatch = true;
@@ -984,13 +988,13 @@ impl Vm {
Some(p) if p.dispose_promise == promise
);
if is_stale {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.restore_inline_state(saved);
return Ok(());
}
let restore_res = state.suspended.restore_into(self, state.callee);
if restore_res.is_err() {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.restore_inline_state(saved);
return Err("async generator suspended across runs is no longer valid".into());
}
@@ -1002,7 +1006,7 @@ impl Vm {
Some(p) => (p.mark, p.completion, p.kind),
// 陈旧防御已早退,正常路径此处必为 Some;防御性兜底。
None => {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.restore_inline_state(saved);
return Ok(());
}
@@ -1019,7 +1023,7 @@ impl Vm {
if matches!(self.dispose_above_core(mark, kind, completion)?, DisposePhase::Suspended) {
unsafe { (*state_ptr).phase = AsyncGenPhase::AwaitSuspended };
self.snapshot_async_generator(state_ptr)?;
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.restore_inline_state(saved);
return Ok(());
}
@@ -1030,11 +1034,11 @@ impl Vm {
// 有合并错误则展开(无处理器则 reject 当前请求),否则续行。
if self.exception_value.is_some() && self.unwind().is_err() {
let exc = self.last_uncaught_value.take().unwrap_or(JsValue::undefined());
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_exc(state_ptr, saved, ctx, exc);
}
let result = self.dispatch();
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.post_dispatch_async_gen(state_ptr, saved, ctx, result)
}
DisposeResumeKind::Unwind(handler) => {
@@ -1044,11 +1048,11 @@ impl Vm {
}
if self.unwind().is_err() {
let exc = self.last_uncaught_value.take().unwrap_or(JsValue::undefined());
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_exc(state_ptr, saved, ctx, exc);
}
let result = self.dispatch();
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.post_dispatch_async_gen(state_ptr, saved, ctx, result)
}
DisposeResumeKind::Escape(completion_val) => {
@@ -1056,11 +1060,11 @@ impl Vm {
// 有合并错误:丢弃完成值,展开到外围处理器(无处理器则 reject)。
if self.unwind().is_err() {
let exc = self.last_uncaught_value.take().unwrap_or(JsValue::undefined());
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_exc(state_ptr, saved, ctx, exc);
}
let result = self.dispatch();
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.post_dispatch_async_gen(state_ptr, saved, ctx, result)
} else {
// 无合并错误:执行完成。
@@ -1068,18 +1072,18 @@ impl Vm {
Completion::Return { value: ret_val, .. } => {
let result = self.do_return(ret_val)?;
if let Some(result) = result {
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
return self.finish_async_gen_ok(state_ptr, saved, ctx, result);
}
// 嵌套帧未弹空:续 dispatch。
let result = self.dispatch();
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.post_dispatch_async_gen(state_ptr, saved, ctx, result)
}
Completion::Break { target_pc, .. } | Completion::Continue { target_pc, .. } => {
self.pc = target_pc;
let result = self.dispatch();
self.restore_async_gen_flags(prev_ctx, prev_gen_ctx, prev_gd, prev_ad, prev_agd);
self.restore_async_gen_flags(prev);
self.post_dispatch_async_gen(state_ptr, saved, ctx, result)
}
}
+8 -20
View File
@@ -1,5 +1,6 @@
use crate::native::NativeFn;
use crate::vm::{native_fn_ptr_to_fn, FrameArgs, FrameContinuation, Vm};
use crate::vm::{native_fn_ptr_to_fn, ConstructArgs, FrameArgs, FrameContinuation, Vm};
use crate::vm_support::FunctionFlags;
use crate::{vm_debug, vm_trace};
use oxide_builtins::iterator::make_iterator_for_value;
use oxide_builtins::{builtins_debug, builtins_trace};
@@ -156,9 +157,7 @@ impl Vm {
callee,
this,
FrameArgs::Slice(&args),
None,
None,
JsValue::undefined(),
ConstructArgs::none(),
FrameContinuation::None,
0,
)
@@ -197,10 +196,7 @@ impl Vm {
let result = self.create_function_object(
sub_idx,
self.active_table_gen,
is_arrow,
is_class_constructor,
is_derived_constructor,
needs_home_object,
FunctionFlags::new(is_arrow, is_class_constructor, is_derived_constructor),
);
// 箭头函数词法继承 super 上下文:home object 从外层函数(当前 callee)
// 继承。类方法由 SET_HOME_OBJECT 显式挂接,不经此路径。
@@ -724,9 +720,7 @@ impl Vm {
first: first_arg_reg,
count: arg_count,
},
Some(254),
Some(derived_this),
new_target,
ConstructArgs::new(254, derived_this, new_target),
FrameContinuation::None,
call_window,
)?;
@@ -1026,9 +1020,7 @@ impl Vm {
callee,
this_value,
FrameArgs::Slice(&args),
None,
None,
JsValue::undefined(),
ConstructArgs::none(),
FrameContinuation::None,
0,
)?;
@@ -1175,9 +1167,7 @@ impl Vm {
constructor,
this_value,
FrameArgs::Slice(&args),
Some(rd as u8),
Some(new_obj_val),
constructor,
ConstructArgs::new(rd as u8, new_obj_val, constructor),
FrameContinuation::None,
0,
)?;
@@ -1285,9 +1275,7 @@ impl Vm {
super_ctor,
derived_this,
FrameArgs::Slice(&args),
Some(254),
Some(derived_this),
new_target,
ConstructArgs::new(254, derived_this, new_target),
FrameContinuation::None,
0,
)?;
+9 -1
View File
@@ -7,6 +7,7 @@ use oxide_types::value::JsValue;
use crate::ic_helper::{self, ic_get_hit, ic_set_hit, VIRTUAL_LENGTH_SLOT};
use crate::vm::{Vm, MAX_PROTO_CHAIN_DEPTH};
use crate::vm_props::SetContract;
#[cold]
fn prop_cache_miss() {}
@@ -526,7 +527,14 @@ impl Vm {
self.ordinary_set_dispatch(obj, prop_name_si, value, receiver, self.current_strict())?;
return Ok(());
}
self.create_named_prop_fast(obj, prop_name_si, value, receiver, ic_pc, true, self.current_strict())?;
self.create_named_prop_fast(
obj,
prop_name_si,
value,
receiver,
ic_pc,
SetContract::dispatch(self.current_strict()),
)?;
}
Ok(())
+2 -4
View File
@@ -9,7 +9,7 @@ use oxide_runtime_api::NativeResult;
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
use oxide_types::value::JsValue;
use crate::vm::{FrameArgs, FrameContinuation, Vm};
use crate::vm::{ConstructArgs, FrameArgs, FrameContinuation, Vm};
use super::aggregate::{
promise_static_all, promise_static_all_keyed, promise_static_all_settled, promise_static_all_settled_keyed,
@@ -233,9 +233,7 @@ impl Vm {
ctor,
this_value,
FrameArgs::Slice(args),
Some(0),
Some(new_obj_val),
new_target,
ConstructArgs::new(0, new_obj_val, new_target),
FrameContinuation::None,
0,
)
+39 -12
View File
@@ -12,6 +12,29 @@ use super::{native_fn_ptr_to_fn, Vm};
use crate::native::NativeFn;
use crate::{vm_debug, vm_trace};
/// 压帧构造三元组:构造结果寄存器、构造出的 this、new.target。
///
/// 按值传递的 Copy 结构体,字段数三;非构造调用方统一传 `none()`,
/// 构造调用方传 `new(...)` 三值,避免三元组散参样板。
#[derive(Clone, Copy)]
pub(crate) struct ConstructArgs {
result_reg: Option<u8>,
constructed_this: Option<JsValue>,
new_target: JsValue,
}
impl ConstructArgs {
/// 非构造调用:无结果寄存器、无构造 this,new.target 为 undefined。
pub(crate) fn none() -> Self {
Self { result_reg: None, constructed_this: None, new_target: JsValue::undefined() }
}
/// 构造调用:携带结果寄存器、构造 this 与 new.target。
pub(crate) fn new(result_reg: u8, constructed_this: JsValue, new_target: JsValue) -> Self {
Self { result_reg: Some(result_reg), constructed_this: Some(constructed_this), new_target }
}
}
impl Vm {
fn pack_sync_native_call_args(&mut self, receiver: JsValue, callee: JsValue, args: &[JsValue]) -> Vec<u8> {
self.regs[253] = receiver;
@@ -219,10 +242,14 @@ impl Vm {
/// # 副作用
/// - 压入调用帧与各类保存栈,改写 pc / bytecode / 活动寄存器上限与镜像槽;
/// `continuation` 决定返回后的续行方式。
#[expect(clippy::too_many_arguments)]
pub(crate) fn push_bytecode_frame(
&mut self, callee: JsValue, this_value: JsValue, args: FrameArgs, construct_result_reg: Option<u8>,
constructed_this: Option<JsValue>, new_target: JsValue, continuation: FrameContinuation, call_window: u8,
&mut self,
callee: JsValue,
this_value: JsValue,
args: FrameArgs,
construct: ConstructArgs,
continuation: FrameContinuation,
call_window: u8,
) -> Result<(), String> {
vm_trace!(
"push_bytecode_frame: depth={}, args={}, continuation={:?}",
@@ -312,7 +339,7 @@ impl Vm {
} else {
oxide_runtime_api::to_object(this_value, self)?
};
self.regs[255] = new_target;
self.regs[255] = construct.new_target;
self.saved_bytecode_stack.push(std::mem::take(&mut self.bytecode));
self.saved_immutables_stack.push(self.active_immutables);
@@ -350,8 +377,8 @@ impl Vm {
saved_new_target,
callee,
arguments_obj: JsValue::undefined(),
construct_result_reg,
constructed_this,
construct_result_reg: construct.result_reg,
constructed_this: construct.constructed_this,
is_derived_constructor: obj.is_derived_constructor(),
super_called: false,
strict: sub_is_strict,
@@ -382,6 +409,8 @@ mod tests {
use oxide_runtime_api::VmHost;
use oxide_types::object::NativeFnPtr;
use crate::vm_support::FunctionFlags;
fn native_return_last_arg(vm: &mut Vm, args: &[u8]) -> NativeResult {
let reg = *args.last().expect("receiver + args");
NativeResult::Ok(vm.reg(reg))
@@ -510,7 +539,7 @@ mod tests {
vm.active_reg_limit = 254;
vm.regs[253] = JsValue::int(42);
let callee = vm.create_function_object(1, vm.current_gen, false, false, false, false);
let callee = vm.create_function_object(1, vm.current_gen, FunctionFlags::none());
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
let result = vm
.call_bytecode_function_inline(callee, callee_obj, JsValue::undefined(), &[])
@@ -534,7 +563,7 @@ mod tests {
vm.regs[253] = JsValue::int(7);
vm.regs[254] = JsValue::int(8);
let inner_callee = vm.create_function_object(1, vm.current_gen, false, false, false, false);
let inner_callee = vm.create_function_object(1, vm.current_gen, FunctionFlags::none());
let outer_native = native_function(&mut vm, native_nested_inline_254);
let result = vm
.call_function_sync(outer_native, JsValue::int(99), &[inner_callee])
@@ -563,14 +592,12 @@ mod tests {
vm.regs[1] = JsValue::int(10);
vm.regs[2] = JsValue::int(20);
let callee = vm.create_function_object(1, vm.current_gen, false, false, false, false);
let callee = vm.create_function_object(1, vm.current_gen, FunctionFlags::none());
vm.push_bytecode_frame(
callee,
JsValue::undefined(),
super::FrameArgs::RegRange { first: 1, count: 2 },
None,
None,
JsValue::undefined(),
ConstructArgs::none(),
super::FrameContinuation::None,
0,
)
+4 -3
View File
@@ -11,6 +11,7 @@ use oxide_types::object::PropAttributes;
use oxide_types::value::JsValue;
use super::Vm;
use crate::vm_support::FunctionFlags;
/// 缺省 no-op 编译服务:两方法均返 `Err`(错误消息指向「未安装编译服务」)。
///
@@ -97,7 +98,7 @@ impl Vm {
table.immutables.resize(table.modules.len(), OnceLock::new());
table.si_tables.resize(table.modules.len(), OnceLock::new());
let func_val = self.create_function_object(base, self.current_gen, false, false, false, false);
let func_val = self.create_function_object(base, self.current_gen, FunctionFlags::none());
let func_obj = unsafe { &mut *func_val.as_js_object_ptr() };
let length_si = self.kernel_core.perm_interner().intern("length").0;
let name_si = self.kernel_core.perm_interner().intern("name").0;
@@ -156,7 +157,7 @@ impl Vm {
// 平表变长后同步扩容常量缓存与 si 侧表,否则激活新模块常量时越界 panic。
table.immutables.resize(table.modules.len(), OnceLock::new());
table.si_tables.resize(table.modules.len(), OnceLock::new());
Ok(self.create_function_object(base, self.current_gen, false, false, false, false))
Ok(self.create_function_object(base, self.current_gen, FunctionFlags::none()))
}
/// 动态编译脚本(普通脚本模式):顶层 var/function 声明落全局对象
@@ -195,7 +196,7 @@ impl Vm {
// 平表变长后同步扩容常量缓存与 si 侧表,否则激活新模块常量时越界 panic。
table.immutables.resize(table.modules.len(), OnceLock::new());
table.si_tables.resize(table.modules.len(), OnceLock::new());
Ok(self.create_function_object(base, self.current_gen, false, false, false, false))
Ok(self.create_function_object(base, self.current_gen, FunctionFlags::none()))
}
}
+1
View File
@@ -37,6 +37,7 @@ mod props;
mod tables;
mod vmhost;
pub(crate) use call::ConstructArgs;
pub(crate) use dynamic::NoopCompilerService;
pub(crate) use frames::FrameArgs;
pub use frames::{CallFrame, Completion, ForInIter, FrameContinuation, TryHandler};
+2 -4
View File
@@ -1,4 +1,4 @@
use crate::vm::{Completion, FrameArgs, FrameContinuation, PendingAsyncEscape, TryHandler, Vm};
use crate::vm::{Completion, ConstructArgs, FrameArgs, FrameContinuation, PendingAsyncEscape, TryHandler, Vm};
use crate::vm_dispatch_misc::DisposePhase;
use crate::vm_trace;
use oxide_bytecode::opcode;
@@ -91,9 +91,7 @@ impl Vm {
first: first_arg_reg,
count: arg_count,
},
None,
None,
JsValue::undefined(),
ConstructArgs::none(),
FrameContinuation::None,
call_window,
)?;
+6 -9
View File
@@ -1,6 +1,6 @@
use crate::vm::{
Completion, DisposeResumeKind, ForInIter, FrameArgs, FrameContinuation, PendingAsyncDispose, TryHandler, Vm,
MAX_PROTO_CHAIN_DEPTH,
Completion, ConstructArgs, DisposeResumeKind, ForInIter, FrameArgs, FrameContinuation, PendingAsyncDispose,
TryHandler, Vm, MAX_PROTO_CHAIN_DEPTH,
};
use crate::vm_trace;
use oxide_builtins::iterator::is_callable;
@@ -200,9 +200,7 @@ impl Vm {
first: first_arg_reg,
count: arg_count,
},
Some(rd as u8),
Some(new_obj_val),
constructor,
ConstructArgs::new(rd as u8, new_obj_val, constructor),
FrameContinuation::None,
call_window,
)?;
@@ -346,9 +344,7 @@ impl Vm {
target_val,
this_value,
FrameArgs::Slice(&call_args),
Some(rd as u8),
Some(new_obj_val),
target_val,
ConstructArgs::new(rd as u8, new_obj_val, target_val),
FrameContinuation::None,
call_window,
)?;
@@ -1586,6 +1582,7 @@ mod tests {
use oxide_bytecode::opcode;
use crate::vm_state::ForOfEntry;
use crate::vm_support::FunctionFlags;
#[test]
fn for_of_close_pops_iterator_stack() {
@@ -1634,7 +1631,7 @@ mod tests {
// 调用方实参区 regs[1..3):arg0=10, arg1=20;regs[2] 同时是 callee 形参槽(param_base=2)
vm.regs[1] = JsValue::int(10);
vm.regs[2] = JsValue::int(20);
vm.regs[5] = vm.create_function_object(1, vm.current_gen, false, false, false, false);
vm.regs[5] = vm.create_function_object(1, vm.current_gen, FunctionFlags::none());
vm.dispatch_new_expression(0, 5, 1).expect("NEW 压帧成功");
+46 -33
View File
@@ -1,4 +1,4 @@
use crate::vm::{FrameArgs, FrameContinuation, Vm, MAX_PROTO_CHAIN_DEPTH};
use crate::vm::{ConstructArgs, FrameArgs, FrameContinuation, Vm, MAX_PROTO_CHAIN_DEPTH};
use crate::{ic_trace, vm_trace};
use oxide_kernel::prop_forge::PropTemplate;
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
@@ -8,6 +8,34 @@ use oxide_types::arguments_map::ArgumentsMapState;
use oxide_types::object::{JsObject, PropAttributes, PropMetaEntry};
use oxide_types::value::JsValue;
/// 写路径三布尔调用契约:帧化(setter 压帧)、严格性、builtin 入口。
///
/// 按值传递的 Copy 结构体,字段数三;三个入口薄包装各给一个关联构造器,
/// 调用点整体传值,避免三布尔散参。
#[derive(Clone, Copy)]
pub(crate) struct SetContract {
use_frame_push: bool,
strict: bool,
builtin: bool,
}
impl SetContract {
/// 字节码入口(ordinary_set / member 写):不帧化、非 builtin,严格性由调用点给。
pub(crate) const fn bytecode(strict: bool) -> Self {
Self { use_frame_push: false, strict, builtin: false }
}
/// builtin 入口(ordinary_set_builtin):不帧化、builtin,严格性由调用点给。
pub(crate) const fn builtin(strict: bool) -> Self {
Self { use_frame_push: false, strict, builtin: true }
}
/// 分发入口(ordinary_set_dispatch / IC 写):帧化、非 builtin,严格性由调用点给。
pub(crate) const fn dispatch(strict: bool) -> Self {
Self { use_frame_push: true, strict, builtin: false }
}
}
impl Vm {
/// 判定 mapped arguments 映射是否存活:创建帧仍在帧栈上且帧身份匹配。
///
@@ -229,9 +257,7 @@ impl Vm {
getter,
receiver,
FrameArgs::Slice(&[]),
None,
None,
JsValue::undefined(),
ConstructArgs::none(),
FrameContinuation::AccessorGet { target_reg },
0,
)?;
@@ -356,7 +382,7 @@ impl Vm {
pub(crate) fn ordinary_set(
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, strict: bool,
) -> Result<(), String> {
self.ordinary_set_inner(obj, prop_name_si, val, receiver, false, strict, false)
self.ordinary_set_inner(obj, prop_name_si, val, receiver, SetContract::bytecode(strict))
}
/// builtin 内部写入口:失败一律返回格式化 `Err` 由调用边界恢复为异常对象,
@@ -365,24 +391,22 @@ impl Vm {
pub(crate) fn ordinary_set_builtin(
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, strict: bool,
) -> Result<(), String> {
self.ordinary_set_inner(obj, prop_name_si, val, receiver, false, strict, true)
self.ordinary_set_inner(obj, prop_name_si, val, receiver, SetContract::builtin(strict))
}
/// 分发期入口:值直接落位。
pub(crate) fn ordinary_set_dispatch(
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, strict: bool,
) -> Result<(), String> {
self.ordinary_set_inner(obj, prop_name_si, val, receiver, true, strict, false)
self.ordinary_set_inner(obj, prop_name_si, val, receiver, SetContract::dispatch(strict))
}
#[expect(
clippy::too_many_arguments,
reason = "写路径须透传 receiver、帧化与 builtin 三组调用契约标志"
)]
fn ordinary_set_inner(
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, use_frame_push: bool,
strict: bool, builtin: bool,
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, contract: SetContract,
) -> Result<(), String> {
let strict = contract.strict;
let builtin = contract.builtin;
let use_frame_push = contract.use_frame_push;
vm_trace!(
"ordinary_set_inner: shape={} prop_si={} frame_push={}",
obj.shape_id(),
@@ -448,16 +472,7 @@ impl Vm {
if (index as usize) >= live {
return Ok(());
}
return self.set_to_receiver(
obj,
prop_name_si,
val,
receiver,
index as usize,
use_frame_push,
strict,
builtin,
);
return self.set_to_receiver(prop_name_si, val, receiver, index as usize, builtin);
}
oxide_builtins::typed_array::TaIndexGate::NumericInvalid => {
// 强转(副作用/抛错先触发)后按 live 复判落位;receiver
@@ -681,10 +696,8 @@ impl Vm {
///
/// # 副作用
/// - 可能写 receiver 的 buffer / 属性存储;强转副作用与自写臂同。
#[allow(clippy::too_many_arguments)]
fn set_to_receiver(
&mut self, _ta_obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, index: usize,
_use_frame_push: bool, _strict: bool, builtin: bool,
&mut self, prop_name_si: u32, val: JsValue, receiver: JsValue, index: usize, builtin: bool,
) -> Result<(), String> {
let receiver_ptr = receiver.as_js_object_ptr();
if receiver_ptr.is_null() {
@@ -767,9 +780,7 @@ impl Vm {
setter,
receiver,
FrameArgs::Slice(&[val]),
None,
None,
JsValue::undefined(),
ConstructArgs::none(),
FrameContinuation::AccessorSet,
0,
)?;
@@ -877,7 +888,7 @@ impl Vm {
// 元素区写),与 dispatch_ic_set_prop 对称,防快路径建影子槽破坏数组语义。
self.ordinary_set(obj, prop_name_si, val, receiver, strict)?;
} else {
self.create_named_prop_fast(obj, prop_name_si, val, receiver, ext_pc, false, strict)?;
self.create_named_prop_fast(obj, prop_name_si, val, receiver, ext_pc, SetContract::bytecode(strict))?;
}
Ok(())
}
@@ -888,13 +899,15 @@ impl Vm {
/// # 边界与前提
/// - 调用方已确认属性不存在于 shape 链(lookup_position miss)。
/// - 数组 length / 数组与 TA 整数索引键不进入本路径(调用方先分流到 ordinary_set)。
/// - `use_frame_push` 与 ordinary_set* 入口一致(member 写 false / IC_SET 分发 true)。
/// - `contract` 与 ordinary_set* 入口一致(member 写 bytecode / IC_SET 分发 dispatch);
/// builtin 位恒 false,本路径不消费。
/// - `strict` 为写方的严格模式:原型链只读/无 setter/不可扩展时严格抛错、sloppy 静默 no-op。
#[allow(clippy::too_many_arguments)]
pub(crate) fn create_named_prop_fast(
&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, ext_pc: usize,
use_frame_push: bool, strict: bool,
contract: SetContract,
) -> Result<(), String> {
let strict = contract.strict;
let use_frame_push = contract.use_frame_push;
// 原型链同名 accessor 须触发 setter、只读 data 须报错(与 ordinary_set 一致),
// 命中时不得创建 own 属性(规范 [[Set]] shadow 语义)。
if let Some(meta) = self.inherited_property_meta(obj, prop_name_si) {
+2 -4
View File
@@ -4,7 +4,7 @@ use std::sync::{Arc, OnceLock};
use oxide_bytecode::module::CompiledModule;
use oxide_bytecode::opcode::OpCode;
use crate::vm::{CallFrame, FrameArgs, FrameContinuation, InlineSyncState, TableGen, Vm};
use crate::vm::{CallFrame, ConstructArgs, FrameArgs, FrameContinuation, InlineSyncState, TableGen, Vm};
use crate::vm_dispatch_misc::DisposePhase;
use crate::{vm_debug, vm_info, vm_trace, vm_warn};
use oxide_types::object::{Cell, JsObject};
@@ -383,9 +383,7 @@ impl Vm {
callee,
this_value,
FrameArgs::Slice(args),
None,
None,
JsValue::undefined(),
ConstructArgs::none(),
FrameContinuation::None,
0,
)
+56 -10
View File
@@ -26,6 +26,56 @@ fn gc_pressure_mode_from_env() -> bool {
std::env::var_os("OXIDE_GC_PRESSURE").is_some()
}
/// 函数种类标志位集合:箭头、类构造器、派生构造器,压缩在单个 `u8` 中。
///
/// 位定义:bit0 = arrow,bit1 = class_constructor,bit2 = derived_constructor。
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct FunctionFlags(pub u8);
impl FunctionFlags {
/// 箭头函数标志位(bit0)。
pub(crate) const ARROW: u8 = 0b001;
/// 类构造器标志位(bit1)。
pub(crate) const CLASS_CONSTRUCTOR: u8 = 0b010;
/// 派生构造器标志位(bit2)。
pub(crate) const DERIVED_CONSTRUCTOR: u8 = 0b100;
/// 无标志(普通函数)。
pub(crate) const fn none() -> Self {
Self(0)
}
/// 由三个布尔标志构造位集。
pub(crate) const fn new(is_arrow: bool, is_class_constructor: bool, is_derived_constructor: bool) -> Self {
let mut bits = 0;
if is_arrow {
bits |= Self::ARROW;
}
if is_class_constructor {
bits |= Self::CLASS_CONSTRUCTOR;
}
if is_derived_constructor {
bits |= Self::DERIVED_CONSTRUCTOR;
}
Self(bits)
}
/// 是否箭头函数。
pub(crate) const fn is_arrow(self) -> bool {
self.0 & Self::ARROW != 0
}
/// 是否类构造器。
pub(crate) const fn is_class_constructor(self) -> bool {
self.0 & Self::CLASS_CONSTRUCTOR != 0
}
/// 是否派生构造器。
pub(crate) const fn is_derived_constructor(self) -> bool {
self.0 & Self::DERIVED_CONSTRUCTOR != 0
}
}
impl Vm {
/// Cons(rope)节点保留的单元阈值:拼接总长(UTF-16 单元数)≤ 该值时
/// 急切扁平。小链的"链接 + 首次消费扁平化"双重分配高于直接拷贝,直接
@@ -756,16 +806,13 @@ impl Vm {
}
/// 为 BytecodeFunc 常量创建函数 JsObject。
/// 当 `is_arrow` 为 true 时,捕获当前 `this`(regs[254]),供调用时词法 this 绑定。
/// 箭头标志置位时,捕获当前 `this`(regs[254]),供调用时词法 this 绑定。
///
/// # 边界与前提
/// - `gen` 为函数对象所属表代际:`sub_idx` 的口径与对象头的 `table_gen`
/// 盖写均以它为准(闭包创建传执行帧代际,动态构造传当前代际——动态扩表
/// 追加进当前代际平表)。
pub(crate) fn create_function_object(
&mut self, sub_idx: u32, gen: u32, is_arrow: bool, is_class_constructor: bool, is_derived_constructor: bool,
needs_home_object: bool,
) -> JsValue {
pub(crate) fn create_function_object(&mut self, sub_idx: u32, gen: u32, flags: FunctionFlags) -> JsValue {
// 生成器函数对象:原型为 %GeneratorFunction.prototype%(constructor 链解析到
// "GeneratorFunction"),且不像普通函数那样拥有 `prototype` 属性。
// 标志按函数对象所属代际平表解析:跨 run 调用时执行帧代际可异于当前代际,
@@ -790,10 +837,9 @@ impl Vm {
// 记录创建期表代际:调用点按 (table_gen, sub_module_index) 解析子模块
// 平表,跨 run 换表后存活函数仍命中原表(注册表按代际保活)。
obj.set_table_gen(gen);
obj.set_class_constructor(is_class_constructor);
obj.set_derived_constructor(is_derived_constructor);
let _ = needs_home_object;
if is_arrow {
obj.set_class_constructor(flags.is_class_constructor());
obj.set_derived_constructor(flags.is_derived_constructor());
if flags.is_arrow() {
obj.set_arrow(true);
obj.set_captured_this(self.regs[254]);
}
@@ -803,7 +849,7 @@ impl Vm {
let obj_ptr = self.alloc_session_object(obj);
let func_val = JsValue::object(obj_ptr as *mut u8);
if !is_arrow && !(is_async && !is_generator) {
if !flags.is_arrow() && !(is_async && !is_generator) {
// 原型对象自身的 [[Prototype]]:生成器为 %GeneratorPrototype%,普通函数为 Object.prototype。
// 纯异步函数(非生成器)无 `prototype` 属性:规范不为其建 prototype 子对象。
let proto_of_proto = if is_async_generator {