diff --git a/crates/oxide_bytecode/src/module.rs b/crates/oxide_bytecode/src/module.rs index ad17194..d70a75c 100644 --- a/crates/oxide_bytecode/src/module.rs +++ b/crates/oxide_bytecode/src/module.rs @@ -5,6 +5,7 @@ //! 或由其它模块克隆复制。`Display` 输出可读的反汇编文本,供调试用。 use std::fmt; +use std::sync::Arc; use crate::opcode::{self, OpCode}; @@ -47,7 +48,7 @@ pub struct UpvalueCapture { /// - `is_class_constructor` / `is_derived_constructor` / `needs_home_object` — 类相关; /// - `upvalue_captures` / `cells_needed` — 闭包捕获描述。 pub struct CompiledModule { - pub bytecode: Vec, + pub bytecode: Arc<[opcode::Instr]>, pub constants: Vec, pub n_registers: u8, pub n_args: u8, @@ -83,7 +84,7 @@ impl CompiledModule { /// 构造空模块:空字节码、空常量池、零寄存器与全部标志默认关闭。 pub fn new() -> Self { Self { - bytecode: Vec::new(), + bytecode: Arc::from(Vec::new()), constants: Vec::new(), n_registers: 0, n_args: 0, diff --git a/crates/oxide_code_cache/src/lib.rs b/crates/oxide_code_cache/src/lib.rs index d018a91..a5dc6ee 100644 --- a/crates/oxide_code_cache/src/lib.rs +++ b/crates/oxide_code_cache/src/lib.rs @@ -168,12 +168,12 @@ mod tests { fn cache_hit_debug_verifies_bytecode() { let forge = forge(16); let mut m1 = CompiledModule::new(); - m1.bytecode = vec![1, 2, 3]; + m1.bytecode = Arc::from(vec![1, 2, 3]); forge.insert(42, m1); let _ = forge .get_or_insert_with(42, || { let mut m = CompiledModule::new(); - m.bytecode = vec![4, 5, 6]; + m.bytecode = Arc::from(vec![4, 5, 6]); Ok(m) }) .unwrap(); @@ -183,12 +183,12 @@ mod tests { fn cache_hit_returns_cached_not_recompiled() { let forge = forge(16); let mut m = CompiledModule::new(); - m.bytecode = vec![1, 2, 3]; + m.bytecode = Arc::from(vec![1, 2, 3]); let cached = forge.insert(99, m); let result = forge .get_or_insert_with(99, || { let mut m = CompiledModule::new(); - m.bytecode = vec![1, 2, 3]; + m.bytecode = Arc::from(vec![1, 2, 3]); Ok(m) }) .unwrap(); diff --git a/crates/oxide_compiler/src/flatten.rs b/crates/oxide_compiler/src/flatten.rs index b84f1da..ac34048 100644 --- a/crates/oxide_compiler/src/flatten.rs +++ b/crates/oxide_compiler/src/flatten.rs @@ -6,6 +6,8 @@ //! imm16 重写为对应子模块的 `flat_id`。运行时以 `flat_id` 为平表下标,闭包自足, //! 不再依赖调用上下文。 +use std::sync::Arc; + use oxide_bytecode::module::CompiledModule; use oxide_bytecode::opcode::{self, OpCode}; @@ -20,7 +22,7 @@ fn assign_ids(module: &mut CompiledModule, next_id: &mut u32) { sub.flat_id = *next_id; *next_id += 1; } - for instr in &mut module.bytecode { + for instr in Arc::make_mut(&mut module.bytecode).iter_mut() { if opcode::opcode(*instr) == OpCode::CREATE_CLOSURE { let rel = opcode::imm16(*instr) as usize; // rel 应为 1-based 子模块下标;0 表示无引用(异常输入),按未解析处理。 @@ -51,10 +53,10 @@ mod tests { #[test] fn flatten_assigns_global_ids_and_rewrites_closures() { let mut leaf = CompiledModule::new(); - leaf.bytecode = vec![opcode::encode(OpCode::CREATE_CLOSURE, 1, 1, 0)]; + leaf.bytecode = Arc::from(vec![opcode::encode(OpCode::CREATE_CLOSURE, 1, 1, 0)]); let mut mid = CompiledModule::new(); mid.sub_modules = vec![leaf]; - mid.bytecode = vec![opcode::encode(OpCode::CREATE_CLOSURE, 2, 1, 0)]; + mid.bytecode = Arc::from(vec![opcode::encode(OpCode::CREATE_CLOSURE, 2, 1, 0)]); let mut top = module_with_closure(vec![mid]); flatten_submodules(&mut top); diff --git a/crates/oxide_ir/src/lower.rs b/crates/oxide_ir/src/lower.rs index 332e2dc..ab0ace2 100644 --- a/crates/oxide_ir/src/lower.rs +++ b/crates/oxide_ir/src/lower.rs @@ -4,6 +4,8 @@ //! label 用前缀和:`label_pos` 记 Inst 下标,平铺时维护 inst→instr 映射, //! 跳转 offset 以 Instr(含 ext 字)为单位。 +use std::sync::Arc; + use oxide_bytecode::module::CompiledModule; use oxide_bytecode::opcode::{self, OpCode}; @@ -75,7 +77,7 @@ pub fn lower(f: &IRFunction) -> Result { } Ok(CompiledModule { - bytecode: instrs, + bytecode: Arc::from(instrs), constants: f.constants.clone(), n_registers: f.n_registers as u8, n_args: f.param_layout.count as u8, diff --git a/crates/oxide_vm/src/dispatch/call.rs b/crates/oxide_vm/src/dispatch/call.rs index 47a18e6..5ea548f 100644 --- a/crates/oxide_vm/src/dispatch/call.rs +++ b/crates/oxide_vm/src/dispatch/call.rs @@ -482,7 +482,7 @@ impl Vm { return Err(self.error_message_text("RangeError", "Maximum call stack size exceeded")); } - let sub_bytecode = self.sub_modules[sub_idx].bytecode.clone(); + let sub_bytecode = Arc::clone(&self.sub_modules[sub_idx].bytecode); let sub_n_args = self.sub_modules[sub_idx].n_args as usize; let sub_n_registers = self.sub_modules[sub_idx].n_registers; let sub_param_base = self.sub_modules[sub_idx].param_base as usize; diff --git a/crates/oxide_vm/src/dispatch/property.rs b/crates/oxide_vm/src/dispatch/property.rs index fdf6707..c6d1bea 100644 --- a/crates/oxide_vm/src/dispatch/property.rs +++ b/crates/oxide_vm/src/dispatch/property.rs @@ -305,6 +305,7 @@ impl Vm { let obj = unsafe { &*obj_ptr }; let prop_name_si = self.property_key_si(self.regs[b]); let (cached_shape_id, cached_slot, cached_depth) = ic_helper::read_ic_entry(&self.bytecode, &mut self.pc); + let ic_pc = self.pc; if obj.has_prop_meta() { let val = self.ordinary_get_with_target(obj, prop_name_si, val, a as u8)?; if self.accessor_frame_target_reg.take().is_none() { @@ -322,7 +323,7 @@ impl Vm { prop_cache_miss(); if template.prop_name == prop_name_si { if template.position < obj.prop_vec_len() as u32 { - ic_helper::write_ic_back(&mut self.bytecode, self.pc, obj.shape_id(), template.position, 0); + ic_helper::write_ic_back(self.bytecode_mut(), ic_pc, obj.shape_id(), template.position, 0); ic_debug!( "IC_GET propforge hit shape={} prop={} slot={}", obj.shape_id(), @@ -345,7 +346,7 @@ impl Vm { // 先试自身属性(快路径,depth=0)。 if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) { if !obj.is_accessor_meta(pos) { - ic_helper::write_ic_back(&mut self.bytecode, self.pc, obj.shape_id(), pos, 0); + ic_helper::write_ic_back(self.bytecode_mut(), ic_pc, obj.shape_id(), pos, 0); ic_debug!("IC_GET write-back own shape={} slot={}", obj.shape_id(), pos); } } else { @@ -356,7 +357,7 @@ impl Vm { let co_ref = unsafe { &*cursor }; if let Some(pos) = self.kernel_core.shape_forge().lookup_position(co_ref.shape_id(), prop_name_si) { if !co_ref.is_accessor_meta(pos) { - ic_helper::write_ic_back(&mut self.bytecode, self.pc, co_ref.shape_id(), pos, depth); + ic_helper::write_ic_back(self.bytecode_mut(), ic_pc, co_ref.shape_id(), pos, depth); ic_debug!( "IC_GET write-back proto shape={} slot={} depth={}", co_ref.shape_id(), @@ -399,6 +400,7 @@ impl Vm { } let (cached_shape_id, cached_slot, cached_depth) = ic_helper::read_ic_entry(&self.bytecode, &mut self.pc); + let ic_pc = self.pc; let value = self.promote_if_needed_for_write_ptr(obj_ptr, self.regs[a]); let receiver = self.regs[rd]; let obj = unsafe { &mut *obj_ptr }; @@ -414,7 +416,7 @@ impl Vm { self.profiling.record_ic_miss(); prop_cache_miss(); obj.set_prop_shape(pos, value); - ic_helper::write_ic_back(&mut self.bytecode, self.pc, obj.shape_id(), pos, 0); + ic_helper::write_ic_back(self.bytecode_mut(), ic_pc, obj.shape_id(), pos, 0); ic_debug!("IC_SET write-back shape={} slot={}", obj.shape_id(), pos); } else { self.profiling.record_ic_miss(); @@ -423,7 +425,7 @@ impl Vm { self.ordinary_set_dispatch(obj, prop_name_si, value, receiver)?; if old_shape != obj.shape_id() { if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) { - ic_helper::write_ic_back(&mut self.bytecode, self.pc, obj.shape_id(), pos, 0); + ic_helper::write_ic_back(self.bytecode_mut(), ic_pc, obj.shape_id(), pos, 0); ic_debug!("IC_SET write-back shape={} slot={}", obj.shape_id(), pos); self.kernel_core.prop_forge().upsert( obj.shape_id(), diff --git a/crates/oxide_vm/src/suspended.rs b/crates/oxide_vm/src/suspended.rs index 1902d92..9d59812 100644 --- a/crates/oxide_vm/src/suspended.rs +++ b/crates/oxide_vm/src/suspended.rs @@ -18,7 +18,7 @@ use crate::vm::{CallFrame, Completion, ForInIter, TryHandler, Vm}; pub(crate) struct SuspendedFrame { pub regs: Box<[JsValue; 256]>, pub pc: usize, - pub bytecode: Vec, + pub bytecode: Arc<[opcode::Instr]>, /// 模块 flat_id(恢复时经 sub_modules 重激活 immutables;跨 run 失效据此报错)。 pub sub_idx: u32, pub active_reg_limit: u8, @@ -34,7 +34,7 @@ pub(crate) struct SuspendedFrame { pub last_for_of_result: JsValue, /// `yield*` 委托中的内层迭代器;异步函数恒为 None。 pub delegated_iterator: Option, - pub saved_bytecode_stack: Vec>, + pub saved_bytecode_stack: Vec>, pub saved_immutables_stack: Vec<*const [JsValue]>, pub exception_value: Option, pub pending_exception: Option, @@ -47,7 +47,7 @@ impl SuspendedFrame { pub fn new_empty() -> Self { SuspendedFrame { regs: Box::new([JsValue::undefined(); 256]), pc: 0, - bytecode: Vec::new(), + bytecode: Arc::default(), sub_idx: 0, active_reg_limit: 0, root_reg_limit: 0, @@ -349,7 +349,7 @@ mod tests { frame.regs[0] = JsValue::float(1.0); frame.regs[7] = JsValue::float(2.0); frame.pc = 11; - frame.bytecode = vec![0u32]; + frame.bytecode = Arc::from(vec![0u32]); frame.sub_idx = 3; frame.active_reg_limit = 4; frame.root_reg_limit = 5; @@ -367,7 +367,7 @@ mod tests { frame.for_of_iters.push(JsValue::float(6.0)); frame.last_for_of_result = JsValue::float(7.0); frame.delegated_iterator = Some(JsValue::float(8.0)); - frame.saved_bytecode_stack.push(vec![0u32]); + frame.saved_bytecode_stack.push(Arc::from(vec![0u32])); frame.saved_immutables_stack.push(std::ptr::slice_from_raw_parts(std::ptr::null(), 0)); frame.exception_value = Some(JsValue::float(9.0)); frame.pending_exception = Some(JsValue::float(10.0)); diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index 614078d..64885bf 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -197,7 +197,7 @@ impl Completion { pub(crate) struct InlineSyncState { pub(crate) regs: Box<[JsValue; 256]>, pub(crate) pc: usize, - pub(crate) bytecode: Vec, + pub(crate) bytecode: Arc<[opcode::Instr]>, pub(crate) active_immutables: *const [JsValue], pub(crate) active_reg_limit: u8, pub(crate) root_reg_limit: u8, @@ -210,7 +210,7 @@ pub(crate) struct InlineSyncState { pub(crate) for_in_iters: Vec<*mut ForInIter<'static>>, pub(crate) for_of_iters: Vec, pub(crate) last_for_of_result: JsValue, - pub(crate) saved_bytecode_stack: Vec>, + pub(crate) saved_bytecode_stack: Vec>, pub(crate) saved_immutables_stack: Vec<*const [JsValue]>, pub(crate) save_stack: Vec, pub(crate) spill_stack: Vec, @@ -229,7 +229,10 @@ pub(crate) struct InlineSyncState { pub struct Vm { pub(crate) regs: [JsValue; 256], pub(crate) pc: usize, - pub(crate) bytecode: Vec, + /// 当前活动字节码。以 `Arc<[Instr]>` 共享:函数调用经 `Arc::clone` 换帧(O(1)), + /// 不再逐帧深拷贝。与 sub_modules 源共享同一缓冲,IC 写回经 `bytecode_mut` 的 + /// `Arc::make_mut` 写时复制,保证独占后才改写(miss 时才深拷贝,频率低)。 + pub(crate) bytecode: Arc<[opcode::Instr]>, /// 每次 run 转换一次的不可变常量缓存。下标 0 = 顶层模块,sub_idx+1 = sub_modules[sub_idx]。 /// 每个 `OnceLock` 保存该模块常量本次运行中只转换一次的 `JsValue` 结果,每次 `run()` 重建。 /// 不可变常量是标量 + perm 字符串,只读,不作为 GC 根。 @@ -267,7 +270,8 @@ pub struct Vm { /// 全局扁平模块表:下标 = 模块 `flat_id`(顶层 0,子模块 flatten 后全局唯一)。 /// 闭包 `sub_module_index` 即 flat_id,逃逸闭包也能自足解析。 pub(crate) sub_modules: Arc>, - pub(crate) saved_bytecode_stack: Vec>, + /// 帧切换时暂存调用方字节码的 Arc 栈(与 `bytecode` 同共享语义)。 + pub(crate) saved_bytecode_stack: Vec>, pub(crate) saved_immutables_stack: Vec<*const [JsValue]>, /// 共享寄存器保存栈。每个活动 `CallFrame` 在 push 时把调用方活跃寄存器 /// (`regs[..caller_reg_limit]`)按 `saved_reg_offset` 存到这里;恢复时复制回 @@ -521,6 +525,13 @@ impl Vm { self.active_immutables = vec.as_slice() as *const [JsValue]; } + /// 当前活动字节码的可变访问入口。bytecode 以 `Arc<[Instr]>` 与 sub_modules 源共享, + /// IC 写回经 `Arc::make_mut` 保证独占:独占时零拷贝原地写,共享时先深拷贝再写 + /// (IC miss 才触发,频率低)。所有写操作必须经此方法,防止共享缓冲被多实例污染。 + pub(crate) fn bytecode_mut(&mut self) -> &mut [opcode::Instr] { + Arc::make_mut(&mut self.bytecode) + } + /// GC 根收集的统一遍历(对象与字符串都产出)。与 `rewrite_values` 字段一一对应。 /// 覆盖执行核心的全部 JsValue 持有点:regs/帧/各栈段/cell/在途异常与完成/ /// 挂起信号/迭代器/微任务/global。新增执行字段必须同时登记在此与 @@ -1036,7 +1047,7 @@ impl Vm { return self.raise_error_kind("RangeError", "Maximum call stack size exceeded"); } - let sub_bytecode = self.sub_modules[sub_idx].bytecode.clone(); + let sub_bytecode = Arc::clone(&self.sub_modules[sub_idx].bytecode); let sub_n_args = self.sub_modules[sub_idx].n_args as usize; let sub_n_registers = self.sub_modules[sub_idx].n_registers; let sub_param_base = self.sub_modules[sub_idx].param_base as usize; @@ -1902,7 +1913,7 @@ impl Vm { /// 原子树 flat_id 自 1 连续,因此拷贝顺序即新 id 顺序,`out` 下标对齐平表槽位。 fn rehome_subtree(module: &CompiledModule, base: u32, out: &mut Vec) { let new_id = base + module.flat_id - 1; - let mut bytecode = module.bytecode.clone(); + let mut bytecode = module.bytecode.to_vec(); for instr in &mut bytecode { if opcode::opcode(*instr) == OpCode::CREATE_CLOSURE { let old = opcode::imm16(*instr) as u32; @@ -1916,7 +1927,7 @@ fn rehome_subtree(module: &CompiledModule, base: u32, out: &mut Vec>()); vm.iters.for_of_iters.push(JsValue::undefined()); vm.saved_bytecode_stack - .push(vec![opcode::encode(opcode::OpCode::HALT, 0, 0, 0)]); + .push(Arc::from(vec![opcode::encode(opcode::OpCode::HALT, 0, 0, 0)])); vm.saved_immutables_stack .push(std::ptr::slice_from_raw_parts(std::ptr::null(), 0)); vm.try_stack.push(TryHandler { @@ -2071,10 +2083,10 @@ mod tests { #[test] fn for_of_close_pops_iterator_stack() { let module = CompiledModule { - bytecode: vec![ + bytecode: Arc::from(vec![ opcode::encode(opcode::OpCode::FOR_OF_CLOSE, 0, 0, 0), opcode::encode(opcode::OpCode::HALT, 0, 0, 0), - ], + ]), n_registers: 1, ..CompiledModule::new() }; @@ -2089,9 +2101,9 @@ mod tests { #[test] fn write_ic_back_updates_three_extension_words() { let mut vm = Vm::new(); - vm.bytecode = vec![0, 0, 0]; + vm.bytecode = Arc::from(vec![0, 0, 0]); vm.pc = 3; - crate::ic_helper::write_ic_back(&mut vm.bytecode, vm.pc, 0x1234_5678, 7, 0); + crate::ic_helper::write_ic_back(Arc::make_mut(&mut vm.bytecode), vm.pc, 0x1234_5678, 7, 0); assert_eq!(vm.bytecode[0], 0x0034_5678); assert_eq!(vm.bytecode[1], 7); assert_eq!(vm.bytecode[2], 0); @@ -2100,9 +2112,9 @@ mod tests { #[test] fn write_ic_back_stores_proto_depth() { let mut vm = Vm::new(); - vm.bytecode = vec![0, 0, 0]; + vm.bytecode = Arc::from(vec![0, 0, 0]); vm.pc = 3; - crate::ic_helper::write_ic_back(&mut vm.bytecode, vm.pc, 0xAAAA_BBBB, 42, 2); + crate::ic_helper::write_ic_back(Arc::make_mut(&mut vm.bytecode), vm.pc, 0xAAAA_BBBB, 42, 2); assert_eq!(vm.bytecode[0], 0x00AA_BBBB); assert_eq!(vm.bytecode[1], 42); assert_eq!(vm.bytecode[2], 2); @@ -2111,10 +2123,10 @@ mod tests { #[test] fn unimplemented_profile_opcode_fails_explicitly() { let module = CompiledModule { - bytecode: vec![ + bytecode: Arc::from(vec![ opcode::encode(opcode::OpCode::PROFILE_SHAPE, 0, 0, 0), opcode::encode(opcode::OpCode::HALT, 0, 0, 0), - ], + ]), n_registers: 1, ..CompiledModule::new() }; diff --git a/crates/oxide_vm/src/vm_dispatch_misc.rs b/crates/oxide_vm/src/vm_dispatch_misc.rs index 21d3569..4085f63 100644 --- a/crates/oxide_vm/src/vm_dispatch_misc.rs +++ b/crates/oxide_vm/src/vm_dispatch_misc.rs @@ -109,7 +109,7 @@ impl Vm { } let new_obj_val = JsValue::object(new_obj as *mut u8); - let sub_bytecode = self.sub_modules[sub_idx].bytecode.clone(); + let sub_bytecode = Arc::clone(&self.sub_modules[sub_idx].bytecode); let sub_n_args = self.sub_modules[sub_idx].n_args as usize; let sub_n_registers = self.sub_modules[sub_idx].n_registers; let sub_param_base = self.sub_modules[sub_idx].param_base as usize; diff --git a/crates/oxide_vm/src/vm_props.rs b/crates/oxide_vm/src/vm_props.rs index 6ac9a42..8c9e38e 100644 --- a/crates/oxide_vm/src/vm_props.rs +++ b/crates/oxide_vm/src/vm_props.rs @@ -278,6 +278,7 @@ impl Vm { let ext1 = self.bytecode[self.pc + 1]; let ext2 = self.bytecode[self.pc + 2]; self.pc += 3; + let ic_pc = self.pc; if obj.has_prop_meta() { return self.ordinary_get(obj, prop_name_si, receiver); } @@ -291,7 +292,7 @@ impl Vm { if template.prop_name != prop_name_si { self.proto_chain_ic_get(obj, prop_name_si, receiver)? } else if template.position < obj.prop_vec_len() as u32 { - crate::ic_helper::write_ic_back(&mut self.bytecode, self.pc, obj.shape_id(), template.position, 0); + crate::ic_helper::write_ic_back(self.bytecode_mut(), ic_pc, obj.shape_id(), template.position, 0); obj.get_prop_shape(template.position) } else { self.proto_chain_ic_get(obj, prop_name_si, receiver)? @@ -304,11 +305,12 @@ impl Vm { /// 执行 ordinary_get 并把 IC 按原型链深度写回。 fn proto_chain_ic_get(&mut self, obj: &JsObject, prop_name_si: u32, receiver: JsValue) -> Result { + let ic_pc = self.pc; let resolved = self.ordinary_get(obj, prop_name_si, receiver)?; // 快路径:自身属性(depth=0)。 if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) { if !obj.is_accessor_meta(pos) { - crate::ic_helper::write_ic_back(&mut self.bytecode, self.pc, obj.shape_id(), pos, 0); + crate::ic_helper::write_ic_back(self.bytecode_mut(), ic_pc, obj.shape_id(), pos, 0); } return Ok(resolved); } @@ -319,7 +321,7 @@ impl Vm { let co = unsafe { &*cursor }; if let Some(pos) = self.kernel_core.shape_forge().lookup_position(co.shape_id(), prop_name_si) { if !co.is_accessor_meta(pos) { - crate::ic_helper::write_ic_back(&mut self.bytecode, self.pc, co.shape_id(), pos, depth); + crate::ic_helper::write_ic_back(self.bytecode_mut(), ic_pc, co.shape_id(), pos, depth); } break; } @@ -336,6 +338,7 @@ impl Vm { &mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue, receiver: JsValue, ) -> Result<(), String> { ic_trace!("set_member_prop: shape_id={} prop_name_si={}", obj.shape_id(), prop_name_si); + let ic_pc = self.pc; let val = self.promote_if_needed_for_write_ptr(obj as *mut JsObject, val); if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) { if obj.has_prop_meta() { @@ -343,7 +346,7 @@ impl Vm { return Ok(()); } obj.set_prop_shape(pos, val); - crate::ic_helper::write_ic_back(&mut self.bytecode, self.pc, obj.shape_id(), pos, 0); + crate::ic_helper::write_ic_back(self.bytecode_mut(), ic_pc, obj.shape_id(), pos, 0); } else { self.ordinary_set(obj, prop_name_si, val, receiver)?; } diff --git a/crates/oxide_vm/src/vm_runtime.rs b/crates/oxide_vm/src/vm_runtime.rs index 78b0220..abfe7c9 100644 --- a/crates/oxide_vm/src/vm_runtime.rs +++ b/crates/oxide_vm/src/vm_runtime.rs @@ -156,7 +156,7 @@ impl Vm { ) -> Result<(), String> { self.regs = [JsValue::undefined(); 256]; self.pc = 0; - self.bytecode = Vec::new(); + self.bytecode = Arc::default(); self.active_reg_limit = 1; self.root_reg_limit = 1; self.try_stack.clear(); @@ -222,7 +222,7 @@ impl Vm { self.regs = [JsValue::undefined(); 256]; self.pc = 0; - self.bytecode = sub.bytecode.clone(); + self.bytecode = Arc::clone(&sub.bytecode); self.activate_immutables(sub_idx, &sub.constants); self.active_reg_limit = sub.n_registers.max(1); self.root_reg_limit = self.active_reg_limit; @@ -300,7 +300,7 @@ impl Vm { vm_info!("rerun: clearing IC caches"); self.clear_execution_state(); self.active_reg_limit = self.root_reg_limit; - crate::ic_helper::clear_ic_caches(&mut self.bytecode); + crate::ic_helper::clear_ic_caches(self.bytecode_mut()); self.dispatch() } @@ -315,7 +315,7 @@ impl Vm { self.cell_stack.push(Vec::new()); self.sub_modules = Arc::new(collect_flat_modules(module)); self.immutables_cache = (0..self.sub_modules.len()).map(|_| OnceLock::new()).collect(); - self.bytecode = module.bytecode.clone(); + self.bytecode = Arc::clone(&module.bytecode); self.activate_immutables(0, &module.constants); self.root_reg_limit = module.n_registers.max(1); self.active_reg_limit = self.root_reg_limit; diff --git a/crates/oxide_vm/src/vm_support.rs b/crates/oxide_vm/src/vm_support.rs index b3512fd..169f1af 100644 --- a/crates/oxide_vm/src/vm_support.rs +++ b/crates/oxide_vm/src/vm_support.rs @@ -25,7 +25,7 @@ impl Vm { let mut vm = Self { regs: [JsValue::undefined(); 256], pc: 0, - bytecode: Vec::new(), + bytecode: Arc::default(), immutables_cache: Vec::new(), active_immutables: std::ptr::slice_from_raw_parts(std::ptr::null(), 0), frames: smallvec::SmallVec::new(), @@ -118,7 +118,7 @@ impl Vm { let mut vm = Self { regs: [JsValue::undefined(); 256], pc: 0, - bytecode: Vec::new(), + bytecode: Arc::default(), immutables_cache: Vec::new(), active_immutables: std::ptr::slice_from_raw_parts(std::ptr::null(), 0), frames: smallvec::SmallVec::new(), @@ -266,7 +266,7 @@ impl Vm { fn clear_full_reset_state(&mut self) { self.clear_execution_state(); - self.bytecode.clear(); + self.bytecode = Arc::default(); self.immutables_cache.clear(); self.active_immutables = std::ptr::slice_from_raw_parts(std::ptr::null(), 0); self.free_epoch_object_heap_data(); @@ -334,7 +334,7 @@ impl Vm { pub fn reset(&mut self) { self.clear_execution_state(); self.maybe_collect_session_gc(); - self.bytecode.clear(); + self.bytecode = Arc::default(); self.immutables_cache.clear(); self.active_immutables = std::ptr::slice_from_raw_parts(std::ptr::null(), 0); self.free_epoch_object_heap_data();