diff --git a/crates/oxide_bytecode/src/module.rs b/crates/oxide_bytecode/src/module.rs index d70a75c..543d0df 100644 --- a/crates/oxide_bytecode/src/module.rs +++ b/crates/oxide_bytecode/src/module.rs @@ -43,7 +43,7 @@ pub struct UpvalueCapture { /// - `bytecode` / `constants` — 指令序列与常量池; /// - `n_registers` / `n_args` / `param_base` — 寄存器窗口布局; /// - `builtin_reg_map` — 内置对象到寄存器的预绑定; -/// - `sub_modules` — 嵌套函数(闭包体)的编译产物; +/// - `sub_modules` — 嵌套函数(闭包体)的编译产物(`Arc` 共享,避免每次 run 深拷贝模块树); /// - `is_arrow` / `captured_this_const_idx` — 箭头函数词法 `this`; /// - `is_class_constructor` / `is_derived_constructor` / `needs_home_object` — 类相关; /// - `upvalue_captures` / `cells_needed` — 闭包捕获描述。 @@ -54,7 +54,7 @@ pub struct CompiledModule { pub n_args: u8, pub param_base: u8, pub builtin_reg_map: Vec<(String, u32)>, - pub sub_modules: Vec, + pub sub_modules: Vec>, /// 是否为箭头函数体(箭头函数从外围作用域词法捕获 `this`)。 pub is_arrow: bool, /// 捕获 `this` 的 JsValue 在常量池中的下标;0 表示未捕获,使用标准 this 绑定。 diff --git a/crates/oxide_compiler/src/flatten.rs b/crates/oxide_compiler/src/flatten.rs index ac34048..e991646 100644 --- a/crates/oxide_compiler/src/flatten.rs +++ b/crates/oxide_compiler/src/flatten.rs @@ -19,7 +19,8 @@ pub fn flatten_submodules(module: &mut CompiledModule) { fn assign_ids(module: &mut CompiledModule, next_id: &mut u32) { for sub in &mut module.sub_modules { - sub.flat_id = *next_id; + // 子模块以 Arc 共享;flatten 在编译末端跑(refcount 1),make_mut 无拷贝。 + Arc::make_mut(sub).flat_id = *next_id; *next_id += 1; } for instr in Arc::make_mut(&mut module.bytecode).iter_mut() { @@ -36,7 +37,7 @@ fn assign_ids(module: &mut CompiledModule, next_id: &mut u32) { } } for sub in &mut module.sub_modules { - assign_ids(sub, next_id); + assign_ids(Arc::make_mut(sub), next_id); } } @@ -44,7 +45,7 @@ fn assign_ids(module: &mut CompiledModule, next_id: &mut u32) { mod tests { use super::*; - fn module_with_closure(nested: Vec) -> CompiledModule { + fn module_with_closure(nested: Vec>) -> CompiledModule { let mut m = CompiledModule::new(); m.sub_modules = nested; m @@ -55,9 +56,9 @@ mod tests { let mut leaf = CompiledModule::new(); leaf.bytecode = Arc::from(vec![opcode::encode(OpCode::CREATE_CLOSURE, 1, 1, 0)]); let mut mid = CompiledModule::new(); - mid.sub_modules = vec![leaf]; + mid.sub_modules = vec![Arc::new(leaf)]; mid.bytecode = Arc::from(vec![opcode::encode(OpCode::CREATE_CLOSURE, 2, 1, 0)]); - let mut top = module_with_closure(vec![mid]); + let mut top = module_with_closure(vec![Arc::new(mid)]); flatten_submodules(&mut top); diff --git a/crates/oxide_ir/src/lower.rs b/crates/oxide_ir/src/lower.rs index ab0ace2..bbfacb4 100644 --- a/crates/oxide_ir/src/lower.rs +++ b/crates/oxide_ir/src/lower.rs @@ -73,7 +73,7 @@ pub fn lower(f: &IRFunction) -> Result { let mut sub_modules = Vec::with_capacity(f.nested.len()); for nested in &f.nested { - sub_modules.push(lower(nested)?); + sub_modules.push(Arc::new(lower(nested)?)); } Ok(CompiledModule { diff --git a/crates/oxide_vm/src/suspended.rs b/crates/oxide_vm/src/suspended.rs index 9d59812..e39525e 100644 --- a/crates/oxide_vm/src/suspended.rs +++ b/crates/oxide_vm/src/suspended.rs @@ -112,7 +112,7 @@ impl SuspendedFrame { /// # 边界 /// `sub_idx >= sub_modules.len()`(挂起状态跨 run)返回 Err,调用方须按各自 /// 路径回滚并报错(保持现有三处行为)。 - pub fn restore_into(&mut self, vm: &mut Vm, sub_modules: &Arc>) -> Result<(), String> { + pub fn restore_into(&mut self, vm: &mut Vm, sub_modules: &Arc>>) -> Result<(), String> { vm.regs = *self.regs; vm.pc = self.pc; vm.bytecode = std::mem::take(&mut self.bytecode); diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index 64885bf..6646d82 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -269,7 +269,9 @@ pub struct Vm { pub math_rng_state: u64, /// 全局扁平模块表:下标 = 模块 `flat_id`(顶层 0,子模块 flatten 后全局唯一)。 /// 闭包 `sub_module_index` 即 flat_id,逃逸闭包也能自足解析。 - pub(crate) sub_modules: Arc>, + /// 条目为 `Arc`,与调用方模块树共享(`run()` 只做 Arc::clone, + /// 不再每次深拷贝整棵子树)。 + pub(crate) sub_modules: Arc>>, /// 帧切换时暂存调用方字节码的 Arc 栈(与 `bytecode` 同共享语义)。 pub(crate) saved_bytecode_stack: Vec>, pub(crate) saved_immutables_stack: Vec<*const [JsValue]>, @@ -1911,7 +1913,7 @@ impl Vm { /// 把 flatten 后的子模块子树重编号到平表偏移 `base`:DFS 前序拷贝进 `out`, /// 新 flat_id = base + (old - 1),子树内每条 `CREATE_CLOSURE` 的 imm16 同步重写。 /// 原子树 flat_id 自 1 连续,因此拷贝顺序即新 id 顺序,`out` 下标对齐平表槽位。 -fn rehome_subtree(module: &CompiledModule, base: u32, out: &mut Vec) { +fn rehome_subtree(module: &CompiledModule, base: u32, out: &mut Vec>) { let new_id = base + module.flat_id - 1; let mut bytecode = module.bytecode.to_vec(); for instr in &mut bytecode { @@ -1929,7 +1931,7 @@ fn rehome_subtree(module: &CompiledModule, base: u32, out: &mut Vec Vec { - let mut out: Vec> = Vec::new(); - place_flat(module, &mut out); +/// +/// 子模块节点以 `Arc` 与调用方模块树共享:只做 Arc::clone(O(1) 引用计数), +/// 不再深拷贝 constants/upvalue_captures 等。顶层模块本身以浅拷贝包 Arc—— +/// 其自有 constants 仍逐 run 复制,但整棵子树零深拷贝。 +fn collect_flat_modules(module: &CompiledModule) -> Vec> { + let mut out: Vec>> = Vec::new(); + let top = Arc::new(module.clone()); + place_flat(&top, &mut out); out.into_iter().map(|m| m.expect("flat_id slot must be filled")).collect() } -fn place_flat(module: &CompiledModule, out: &mut Vec>) { +fn place_flat(module: &Arc, out: &mut Vec>>) { let idx = module.flat_id as usize; if idx >= out.len() { out.resize(idx + 1, None); } - out[idx] = Some(module.clone()); + out[idx] = Some(Arc::clone(module)); for sub in &module.sub_modules { place_flat(sub, out); }