mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
refactor: AsyncGeneratorState 收敛到 SuspendedFrame(save/restore/GC 遍历/string 边/深拷贝)
This commit is contained in:
@@ -16,15 +16,14 @@ use std::collections::VecDeque;
|
||||
use std::sync::Arc;
|
||||
|
||||
use oxide_builtins::iterator::make_iter_result;
|
||||
use oxide_bytecode::opcode;
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_runtime_api::NativeResult;
|
||||
use oxide_types::mem::P;
|
||||
use oxide_types::object::{Cell, JsObject, NativeFnPtr, PropAttributes};
|
||||
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::generator::{DelegateOutcome, GeneratorResumeMode};
|
||||
use crate::vm::{CallFrame, Completion, ForInIter, FrameContinuation, TryHandler, Vm};
|
||||
use crate::vm::Vm;
|
||||
|
||||
/// 异步生成器执行阶段。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -67,32 +66,8 @@ pub(crate) struct AsyncGeneratorState {
|
||||
pub queue: VecDeque<AsyncGenRequest>,
|
||||
/// 正在处理的请求:yield 让出 / await 挂起 / 完成时结算。
|
||||
pub current: Option<AsyncGenRequest>,
|
||||
// ── 挂起时的执行上下文(与生成器同构) ──
|
||||
pub regs: Box<[JsValue; 256]>,
|
||||
pub pc: usize,
|
||||
pub bytecode: Vec<opcode::Instr>,
|
||||
/// 异步生成器模块 flat_id(恢复时重激活 immutables)。
|
||||
pub sub_idx: u32,
|
||||
pub active_reg_limit: u8,
|
||||
pub root_reg_limit: u8,
|
||||
/// 异步生成器帧(压入时由 push_bytecode_frame 构造,挂起时弹出存此)。
|
||||
pub frame: Option<CallFrame>,
|
||||
pub spill_stack: Vec<JsValue>,
|
||||
pub save_stack: Vec<JsValue>,
|
||||
pub cell_stack: Vec<Vec<*mut Cell>>,
|
||||
pub try_stack: Vec<TryHandler>,
|
||||
pub for_in_iters: Vec<*mut ForInIter<'static>>,
|
||||
pub for_of_iters: Vec<JsValue>,
|
||||
pub last_for_of_result: JsValue,
|
||||
/// `yield*` 委托中的内层迭代器:Some = 挂起在委托点,恢复时转发 next/return/throw。
|
||||
pub delegated_iterator: Option<JsValue>,
|
||||
pub saved_bytecode_stack: Vec<Vec<opcode::Instr>>,
|
||||
pub saved_immutables_stack: Vec<*const [JsValue]>,
|
||||
/// 在途异常/完成(throw 穿越 finally 挂起时保留,恢复后继续展开)。
|
||||
pub exception_value: Option<JsValue>,
|
||||
pub pending_exception: Option<JsValue>,
|
||||
pub pending_error_kind: Option<&'static str>,
|
||||
pub pending_completion: Option<Completion>,
|
||||
/// 挂起时的执行上下文(regs/pc/bytecode/各栈段/迭代器/在途异常)。
|
||||
pub suspended: crate::suspended::SuspendedFrame,
|
||||
}
|
||||
|
||||
/// 恢复闭包上区分 reject 角色的属性名(await 恢复闭包定位用)。
|
||||
@@ -123,27 +98,7 @@ impl Vm {
|
||||
result: JsValue::undefined(),
|
||||
queue: VecDeque::new(),
|
||||
current: None,
|
||||
regs: Box::new([JsValue::undefined(); 256]),
|
||||
pc: 0,
|
||||
bytecode: Vec::new(),
|
||||
sub_idx: 0,
|
||||
active_reg_limit: 0,
|
||||
root_reg_limit: 0,
|
||||
frame: None,
|
||||
spill_stack: Vec::new(),
|
||||
save_stack: Vec::new(),
|
||||
cell_stack: Vec::new(),
|
||||
try_stack: Vec::new(),
|
||||
for_in_iters: Vec::new(),
|
||||
for_of_iters: Vec::new(),
|
||||
last_for_of_result: JsValue::undefined(),
|
||||
delegated_iterator: None,
|
||||
saved_bytecode_stack: Vec::new(),
|
||||
saved_immutables_stack: Vec::new(),
|
||||
exception_value: None,
|
||||
pending_exception: None,
|
||||
pending_error_kind: None,
|
||||
pending_completion: None,
|
||||
suspended: crate::suspended::SuspendedFrame::new_empty(),
|
||||
});
|
||||
obj_ref.set_native_data(Box::into_raw(state) as *mut u8);
|
||||
self.gc_state.track_epoch_object(obj);
|
||||
@@ -186,33 +141,10 @@ impl Vm {
|
||||
self.native_call_depth += 1;
|
||||
|
||||
// 压入异步生成器帧(New)。
|
||||
self.regs = [JsValue::undefined(); 256];
|
||||
self.pc = 0;
|
||||
self.bytecode = Vec::new();
|
||||
self.active_reg_limit = 1;
|
||||
self.root_reg_limit = 1;
|
||||
self.try_stack.clear();
|
||||
self.iters.for_in_iters.clear();
|
||||
self.iters.for_of_iters.clear();
|
||||
self.iters.last_for_of_result = JsValue::undefined();
|
||||
self.spill_stack.clear();
|
||||
self.save_stack.clear();
|
||||
self.saved_bytecode_stack.clear();
|
||||
self.saved_immutables_stack.clear();
|
||||
self.cell_stack.clear();
|
||||
self.inline_callee = None;
|
||||
let callee = unsafe { (*state_ptr).callee };
|
||||
let this_value = unsafe { (*state_ptr).this_value };
|
||||
let args = unsafe { std::mem::take(&mut (*state_ptr).args) };
|
||||
let push_res = self.push_bytecode_frame(
|
||||
callee,
|
||||
this_value,
|
||||
&args,
|
||||
None,
|
||||
None,
|
||||
JsValue::undefined(),
|
||||
FrameContinuation::None,
|
||||
);
|
||||
let push_res = self.prepare_execution_initial(callee, this_value, &args);
|
||||
unsafe { (*state_ptr).args = args };
|
||||
if let Err(e) = push_res {
|
||||
self.restore_inline_state(saved);
|
||||
@@ -373,13 +305,9 @@ impl Vm {
|
||||
|
||||
{
|
||||
let state = unsafe { &mut *state_ptr };
|
||||
self.regs = *state.regs;
|
||||
self.pc = state.pc;
|
||||
self.bytecode = std::mem::take(&mut state.bytecode);
|
||||
let subs = Arc::clone(&self.sub_modules);
|
||||
if (state.sub_idx as usize) < subs.len() {
|
||||
self.activate_immutables(state.sub_idx as usize, &subs[state.sub_idx as usize].constants);
|
||||
} else {
|
||||
let restore_res = state.suspended.restore_into(self, &subs);
|
||||
if restore_res.is_err() {
|
||||
// 挂起状态跨 run:sub_modules 已重建,无法恢复(与生成器同限制)。
|
||||
self.async_gen_dispatch = prev_agd;
|
||||
self.async_gen_context = prev_gen_ctx;
|
||||
@@ -390,27 +318,6 @@ impl Vm {
|
||||
self.restore_inline_state(saved);
|
||||
return Err("async generator suspended across runs is no longer valid".into());
|
||||
}
|
||||
self.active_reg_limit = state.active_reg_limit;
|
||||
self.root_reg_limit = state.root_reg_limit;
|
||||
self.frames.clear();
|
||||
if let Some(frame) = state.frame.take() {
|
||||
self.frames.push(frame);
|
||||
}
|
||||
self.spill_stack = std::mem::take(&mut state.spill_stack);
|
||||
self.save_stack = std::mem::take(&mut state.save_stack);
|
||||
self.cell_stack = std::mem::take(&mut state.cell_stack);
|
||||
self.try_stack = std::mem::take(&mut state.try_stack);
|
||||
self.iters.for_in_iters = std::mem::take(&mut state.for_in_iters);
|
||||
self.iters.for_of_iters = std::mem::take(&mut state.for_of_iters);
|
||||
self.iters.last_for_of_result = state.last_for_of_result;
|
||||
self.delegated_iterator = state.delegated_iterator.take();
|
||||
self.saved_bytecode_stack = std::mem::take(&mut state.saved_bytecode_stack);
|
||||
self.saved_immutables_stack = std::mem::take(&mut state.saved_immutables_stack);
|
||||
self.exception_value = state.exception_value.take();
|
||||
self.pending_exception = state.pending_exception.take();
|
||||
self.pending_error_kind = state.pending_error_kind.take();
|
||||
self.pending_completion = state.pending_completion.take();
|
||||
self.inline_callee = None;
|
||||
state.phase = AsyncGenPhase::Running;
|
||||
}
|
||||
|
||||
@@ -637,39 +544,11 @@ impl Vm {
|
||||
|
||||
/// 把当前 VM 执行状态(异步生成器 body 刚在嵌套 dispatch 中让出)快照进状态盒。
|
||||
///
|
||||
/// 异步生成器帧弹出存 `frame`,其余栈段整段搬入(嵌套循环期间这些栈只含
|
||||
/// 异步生成器数据)。请求队列与当前请求保留在状态盒中不动。
|
||||
/// 异步生成器帧弹出存 `suspended.frame`,其余栈段整段搬入(嵌套循环期间这些栈
|
||||
/// 只含异步生成器数据)。请求队列与当前请求保留在状态盒中不动。
|
||||
fn snapshot_async_generator(&mut self, state_ptr: *mut AsyncGeneratorState) -> Result<(), String> {
|
||||
let state = unsafe { &mut *state_ptr };
|
||||
let frame = self
|
||||
.frames
|
||||
.pop()
|
||||
.ok_or_else(|| "async generator frame missing on yield".to_string())?;
|
||||
state.frame = Some(frame);
|
||||
state.regs = Box::new(self.regs);
|
||||
state.pc = self.pc;
|
||||
state.bytecode = std::mem::take(&mut self.bytecode);
|
||||
state.sub_idx = if state.callee.is_object() {
|
||||
unsafe { (*state.callee.as_js_object_ptr()).sub_module_index() }
|
||||
} else {
|
||||
0
|
||||
};
|
||||
state.active_reg_limit = self.active_reg_limit;
|
||||
state.root_reg_limit = self.root_reg_limit;
|
||||
state.spill_stack = std::mem::take(&mut self.spill_stack);
|
||||
state.save_stack = std::mem::take(&mut self.save_stack);
|
||||
state.cell_stack = std::mem::take(&mut self.cell_stack);
|
||||
state.try_stack = std::mem::take(&mut self.try_stack);
|
||||
state.for_in_iters = std::mem::take(&mut self.iters.for_in_iters);
|
||||
state.for_of_iters = std::mem::take(&mut self.iters.for_of_iters);
|
||||
state.last_for_of_result = self.iters.last_for_of_result;
|
||||
state.delegated_iterator = self.delegated_iterator.take();
|
||||
state.saved_bytecode_stack = std::mem::take(&mut self.saved_bytecode_stack);
|
||||
state.saved_immutables_stack = std::mem::take(&mut self.saved_immutables_stack);
|
||||
state.exception_value = self.exception_value.take();
|
||||
state.pending_exception = self.pending_exception.take();
|
||||
state.pending_error_kind = self.pending_error_kind.take();
|
||||
state.pending_completion = self.pending_completion.take();
|
||||
state.suspended.save_from(self, state.callee)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -973,35 +852,48 @@ pub(crate) fn async_generator_native_edges(obj: &JsObject) -> Vec<JsValue> {
|
||||
push(req.resolve, &mut edges);
|
||||
push(req.reject, &mut edges);
|
||||
}
|
||||
edges.extend(state.regs.iter().copied().filter(|v| v.is_object()));
|
||||
if let Some(frame) = &state.frame {
|
||||
push(frame.saved_this, &mut edges);
|
||||
push(frame.saved_new_target, &mut edges);
|
||||
push(frame.callee, &mut edges);
|
||||
if let Some(ct) = frame.constructed_this {
|
||||
push(ct, &mut edges);
|
||||
state.suspended.for_each_value(|v| {
|
||||
if v.is_object() {
|
||||
edges.push(v);
|
||||
}
|
||||
}
|
||||
edges.extend(state.spill_stack.iter().copied().filter(|v| v.is_object()));
|
||||
edges.extend(state.save_stack.iter().copied().filter(|v| v.is_object()));
|
||||
for cells in &state.cell_stack {
|
||||
for &cell_ptr in cells {
|
||||
if cell_ptr.is_null() {
|
||||
continue;
|
||||
}
|
||||
// SAFETY: cell 由 session_epoch 分配,本 session 内指针有效。
|
||||
let cell = unsafe { &*cell_ptr };
|
||||
push(cell.value, &mut edges);
|
||||
}
|
||||
}
|
||||
edges.extend(state.for_of_iters.iter().copied().filter(|v| v.is_object()));
|
||||
push(state.last_for_of_result, &mut edges);
|
||||
if let Some(iter) = state.delegated_iterator {
|
||||
push(iter, &mut edges);
|
||||
}
|
||||
});
|
||||
edges
|
||||
}
|
||||
|
||||
/// 异步生成器状态内所有 session 字符串的扁平列表(GC mark 字符串边)。
|
||||
pub(crate) fn async_generator_native_string_edges(obj: &JsObject) -> Vec<*mut oxide_types::object::JsString> {
|
||||
let Some(state) = async_gen_state_mut(obj) else {
|
||||
return Vec::new();
|
||||
};
|
||||
let mut out = Vec::new();
|
||||
let push_str = |v: JsValue, out: &mut Vec<*mut oxide_types::object::JsString>| {
|
||||
if v.is_string() {
|
||||
out.push(v.as_string_ptr_mut());
|
||||
}
|
||||
};
|
||||
push_str(state.callee, &mut out);
|
||||
for &v in &state.args {
|
||||
push_str(v, &mut out);
|
||||
}
|
||||
push_str(state.result, &mut out);
|
||||
for req in state.queue.iter() {
|
||||
push_str(req.promise, &mut out);
|
||||
push_str(req.resolve, &mut out);
|
||||
push_str(req.reject, &mut out);
|
||||
}
|
||||
if let Some(req) = &state.current {
|
||||
push_str(req.promise, &mut out);
|
||||
push_str(req.resolve, &mut out);
|
||||
push_str(req.reject, &mut out);
|
||||
}
|
||||
state.suspended.for_each_value(|v| {
|
||||
if v.is_string() {
|
||||
out.push(v.as_string_ptr_mut());
|
||||
}
|
||||
});
|
||||
out
|
||||
}
|
||||
|
||||
/// 用转发函数重写状态快照中的所有 JsValue(session GC 移动式清扫 / promote 用)。
|
||||
pub(crate) fn rewrite_async_generator_native(obj: &JsObject, mut rewrite: impl FnMut(JsValue) -> JsValue) {
|
||||
let Some(state) = async_gen_state_mut(obj) else {
|
||||
@@ -1022,36 +914,7 @@ pub(crate) fn rewrite_async_generator_native(obj: &JsObject, mut rewrite: impl F
|
||||
req.resolve = rewrite(req.resolve);
|
||||
req.reject = rewrite(req.reject);
|
||||
}
|
||||
for v in state.regs.iter_mut() {
|
||||
*v = rewrite(*v);
|
||||
}
|
||||
if let Some(frame) = &mut state.frame {
|
||||
frame.saved_this = rewrite(frame.saved_this);
|
||||
frame.saved_new_target = rewrite(frame.saved_new_target);
|
||||
frame.callee = rewrite(frame.callee);
|
||||
frame.constructed_this = frame.constructed_this.map(&mut rewrite);
|
||||
}
|
||||
for v in &mut state.spill_stack {
|
||||
*v = rewrite(*v);
|
||||
}
|
||||
for v in &mut state.save_stack {
|
||||
*v = rewrite(*v);
|
||||
}
|
||||
for cells in &mut state.cell_stack {
|
||||
for &mut cell_ptr in cells.iter_mut() {
|
||||
if cell_ptr.is_null() {
|
||||
continue;
|
||||
}
|
||||
// SAFETY: cell 由 session_epoch 分配,本 session 内指针有效。
|
||||
let cell = unsafe { &mut *cell_ptr };
|
||||
cell.value = rewrite(cell.value);
|
||||
}
|
||||
}
|
||||
for v in &mut state.for_of_iters {
|
||||
*v = rewrite(*v);
|
||||
}
|
||||
state.last_for_of_result = rewrite(state.last_for_of_result);
|
||||
state.delegated_iterator = state.delegated_iterator.map(&mut rewrite);
|
||||
state.suspended.rewrite_values(rewrite);
|
||||
}
|
||||
|
||||
/// 深拷贝状态盒到新对象(promote / sweep 用):新对象持独立 Box,源盒可安全释放。
|
||||
@@ -1083,48 +946,7 @@ pub(crate) fn clone_async_generator_native_with_rewrite(
|
||||
resolve: rewrite(req.resolve),
|
||||
reject: rewrite(req.reject),
|
||||
}),
|
||||
regs: Box::new({
|
||||
let mut regs = [JsValue::undefined(); 256];
|
||||
for (i, v) in state.regs.iter().enumerate() {
|
||||
regs[i] = rewrite(*v);
|
||||
}
|
||||
regs
|
||||
}),
|
||||
pc: state.pc,
|
||||
bytecode: state.bytecode.clone(),
|
||||
sub_idx: state.sub_idx,
|
||||
active_reg_limit: state.active_reg_limit,
|
||||
root_reg_limit: state.root_reg_limit,
|
||||
frame: state.frame.as_ref().map(|f| CallFrame {
|
||||
return_addr: f.return_addr,
|
||||
function_name: f.function_name,
|
||||
caller_reg_limit: f.caller_reg_limit,
|
||||
saved_reg_offset: f.saved_reg_offset,
|
||||
spill_offset: f.spill_offset,
|
||||
arguments_base: f.arguments_base,
|
||||
arguments_count: f.arguments_count,
|
||||
saved_this: rewrite(f.saved_this),
|
||||
saved_new_target: rewrite(f.saved_new_target),
|
||||
callee: rewrite(f.callee),
|
||||
construct_result_reg: f.construct_result_reg,
|
||||
constructed_this: f.constructed_this.map(&mut rewrite),
|
||||
is_derived_constructor: f.is_derived_constructor,
|
||||
continuation: f.continuation,
|
||||
}),
|
||||
spill_stack: state.spill_stack.iter().copied().map(&mut rewrite).collect(),
|
||||
save_stack: state.save_stack.iter().copied().map(&mut rewrite).collect(),
|
||||
cell_stack: state.cell_stack.clone(),
|
||||
try_stack: state.try_stack.clone(),
|
||||
for_in_iters: state.for_in_iters.clone(),
|
||||
for_of_iters: state.for_of_iters.iter().copied().map(&mut rewrite).collect(),
|
||||
last_for_of_result: rewrite(state.last_for_of_result),
|
||||
delegated_iterator: state.delegated_iterator.map(&mut rewrite),
|
||||
saved_bytecode_stack: state.saved_bytecode_stack.clone(),
|
||||
saved_immutables_stack: state.saved_immutables_stack.clone(),
|
||||
exception_value: state.exception_value.map(&mut rewrite),
|
||||
pending_exception: state.pending_exception.map(&mut rewrite),
|
||||
pending_error_kind: state.pending_error_kind,
|
||||
pending_completion: state.pending_completion,
|
||||
suspended: state.suspended.clone_with_rewrite(rewrite),
|
||||
};
|
||||
new.set_native_data(Box::into_raw(Box::new(cloned)) as *mut u8);
|
||||
}
|
||||
@@ -1141,8 +963,6 @@ pub(crate) fn drop_async_generator_native(obj: &JsObject) -> u64 {
|
||||
// SAFETY: 指针来自 create_async_generator_object 的 Box::into_raw,只在 GC 回收时释放一次。
|
||||
let state = unsafe { Box::from_raw(ptr) };
|
||||
std::mem::size_of::<AsyncGeneratorState>() as u64
|
||||
+ state.bytecode.len() as u64 * std::mem::size_of::<u32>() as u64
|
||||
+ state.spill_stack.capacity() as u64 * std::mem::size_of::<JsValue>() as u64
|
||||
+ state.save_stack.capacity() as u64 * std::mem::size_of::<JsValue>() as u64
|
||||
+ state.suspended.heap_bytes()
|
||||
+ state.args.capacity() as u64 * std::mem::size_of::<JsValue>() as u64
|
||||
}
|
||||
|
||||
@@ -174,10 +174,8 @@ impl SessionGc {
|
||||
}
|
||||
}
|
||||
if obj.is_async_generator_obj() {
|
||||
for value in crate::async_generator::async_generator_native_edges(obj) {
|
||||
if value.is_string() {
|
||||
live.insert(value.as_string_ptr_mut());
|
||||
}
|
||||
for ptr in crate::async_generator::async_generator_native_string_edges(obj) {
|
||||
live.insert(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user