mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
refactor: 写路径契约与压帧与异步标志组收结构体并删死参
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)?;
|
||||
|
||||
@@ -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(())
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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,
|
||||
)?;
|
||||
|
||||
@@ -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 压帧成功");
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user