diff --git a/crates/oxide_vm/src/async_generator.rs b/crates/oxide_vm/src/async_generator.rs index 6faeebe4..52672a25 100644 --- a/crates/oxide_vm/src/async_generator.rs +++ b/crates/oxide_vm/src/async_generator.rs @@ -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, /// 正在处理的请求:yield 让出 / await 挂起 / 完成时结算。 pub current: Option, - // ── 挂起时的执行上下文(与生成器同构) ── - pub regs: Box<[JsValue; 256]>, - pub pc: usize, - pub bytecode: Vec, - /// 异步生成器模块 flat_id(恢复时重激活 immutables)。 - pub sub_idx: u32, - pub active_reg_limit: u8, - pub root_reg_limit: u8, - /// 异步生成器帧(压入时由 push_bytecode_frame 构造,挂起时弹出存此)。 - pub frame: Option, - pub spill_stack: Vec, - pub save_stack: Vec, - pub cell_stack: Vec>, - pub try_stack: Vec, - pub for_in_iters: Vec<*mut ForInIter<'static>>, - pub for_of_iters: Vec, - pub last_for_of_result: JsValue, - /// `yield*` 委托中的内层迭代器:Some = 挂起在委托点,恢复时转发 next/return/throw。 - pub delegated_iterator: Option, - pub saved_bytecode_stack: Vec>, - pub saved_immutables_stack: Vec<*const [JsValue]>, - /// 在途异常/完成(throw 穿越 finally 挂起时保留,恢复后继续展开)。 - pub exception_value: Option, - pub pending_exception: Option, - pub pending_error_kind: Option<&'static str>, - pub pending_completion: Option, + /// 挂起时的执行上下文(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 { 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::() as u64 - + state.bytecode.len() as u64 * std::mem::size_of::() as u64 - + state.spill_stack.capacity() as u64 * std::mem::size_of::() as u64 - + state.save_stack.capacity() as u64 * std::mem::size_of::() as u64 + + state.suspended.heap_bytes() + state.args.capacity() as u64 * std::mem::size_of::() as u64 } diff --git a/crates/oxide_vm/src/session_gc.rs b/crates/oxide_vm/src/session_gc.rs index 6c8fd2e5..6c59a045 100644 --- a/crates/oxide_vm/src/session_gc.rs +++ b/crates/oxide_vm/src/session_gc.rs @@ -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); } } }