diff --git a/crates/oxide_vm/src/dispatch/call.rs b/crates/oxide_vm/src/dispatch/call.rs index a3fe5bf6..477e087b 100644 --- a/crates/oxide_vm/src/dispatch/call.rs +++ b/crates/oxide_vm/src/dispatch/call.rs @@ -413,9 +413,12 @@ impl Vm { } } - self.sub_module_stack.push(Arc::clone(&self.sub_modules)); let callee_subs = &subs[sub_idx].sub_modules; - if !callee_subs.is_empty() { + if callee_subs.is_empty() { + self.sub_module_stack.push((Arc::clone(&self.sub_modules), None)); + } else { + self.sub_module_stack + .push((Arc::clone(&self.sub_modules), Some(std::mem::take(&mut self.immutables_cache)))); self.sub_modules = Arc::new(callee_subs.clone()); self.immutables_cache = (0..=callee_subs.len()).map(|_| OnceLock::new()).collect(); } diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index 174c5624..7d6cf846 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -220,7 +220,7 @@ pub struct Vm { pub(crate) iters: IterState, /// 分组保存 inline cache 与指令计数器。 pub(crate) profiling: ProfilingState, - pub(crate) sub_module_stack: Vec>>, + pub(crate) sub_module_stack: Vec<(Arc>, Option>>>)>, pub(crate) cell_stack: Vec>, pub(crate) temp_immutables: Vec>, /// 可复用字符串缓冲区,避免每次 `+` 拼接都分配。 @@ -811,10 +811,14 @@ impl Vm { } } - self.sub_module_stack.push(Arc::clone(&self.sub_modules)); let callee_subs = &subs[sub_idx].sub_modules; - if !callee_subs.is_empty() { + if callee_subs.is_empty() { + self.sub_module_stack.push((Arc::clone(&self.sub_modules), None)); + } else { + self.sub_module_stack + .push((Arc::clone(&self.sub_modules), Some(std::mem::take(&mut self.immutables_cache)))); self.sub_modules = Arc::new(callee_subs.clone()); + self.immutables_cache = (0..=callee_subs.len()).map(|_| OnceLock::new()).collect(); } self.active_reg_limit = sub_n_registers.max(1); diff --git a/crates/oxide_vm/src/vm_dispatch_misc.rs b/crates/oxide_vm/src/vm_dispatch_misc.rs index c1f35593..b0310d25 100644 --- a/crates/oxide_vm/src/vm_dispatch_misc.rs +++ b/crates/oxide_vm/src/vm_dispatch_misc.rs @@ -143,6 +143,7 @@ impl Vm { self.bytecode = sub_bytecode; let subs = Arc::clone(&self.sub_modules); self.activate_immutables(sub_idx + 1, &subs[sub_idx].constants); + self.cell_stack.push(Vec::with_capacity(subs[sub_idx].cells_needed as usize)); for (name, reg) in &self.sub_modules[sub_idx].builtin_reg_map { let si = self.kernel_core.perm_interner().intern(name.as_str()).0; diff --git a/crates/oxide_vm/src/vm_runtime.rs b/crates/oxide_vm/src/vm_runtime.rs index 0d4c2266..d4652776 100644 --- a/crates/oxide_vm/src/vm_runtime.rs +++ b/crates/oxide_vm/src/vm_runtime.rs @@ -130,8 +130,11 @@ impl Vm { if let Some(saved_imm) = self.saved_immutables_stack.pop() { self.active_immutables = saved_imm; } - if let Some(saved_subs) = self.sub_module_stack.pop() { + if let Some((saved_subs, saved_cache)) = self.sub_module_stack.pop() { self.sub_modules = saved_subs; + if let Some(saved_cache) = saved_cache { + self.immutables_cache = saved_cache; + } } self.temp_immutables.pop(); let offset = frame.saved_reg_offset as usize; @@ -189,6 +192,7 @@ impl Vm { while let Some(handler) = self.try_stack.pop() { while self.frames.len() > handler.frame_depth { if let Some(frame) = self.frames.pop() { + self.cell_stack.pop(); self.restore_frame(frame); } } @@ -213,6 +217,7 @@ impl Vm { } self.close_for_of_above(0); while let Some(frame) = self.frames.pop() { + self.cell_stack.pop(); self.restore_frame(frame); } let exc = self.exception_value.take().unwrap_or(JsValue::undefined()); diff --git a/crates/oxide_vm/src/vm_support.rs b/crates/oxide_vm/src/vm_support.rs index 03ab9483..74be700a 100644 --- a/crates/oxide_vm/src/vm_support.rs +++ b/crates/oxide_vm/src/vm_support.rs @@ -211,6 +211,7 @@ impl Vm { self.regs = [JsValue::undefined(); 256]; self.pc = 0; self.frames.clear(); + self.sub_module_stack.clear(); self.iters.reset(); self.saved_bytecode_stack.clear(); self.saved_immutables_stack.clear();