From 72b22016e32267f1e5d69a357d6c48aeeb0b262d Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Mon, 8 Jun 2026 23:31:45 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=BB=9F=E4=B8=80=20IC=20=E6=89=A9?= =?UTF-8?q?=E5=B1=95=E5=AD=97=E5=9B=9E=E5=86=99=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_vm/src/vm.rs | 71 +++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 36 deletions(-) diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index d345b9bc..e23ee291 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -110,9 +110,7 @@ macro_rules! member_read_prop { .resolve_property($obj, $prop_name_si) .unwrap_or(JsValue::undefined()) } else if let Some(ptr) = $self.template_prop_ptr($obj, &template) { - $self.bytecode[$self.pc - 3] = $obj.shape_id() & 0x00FF_FFFF; - $self.bytecode[$self.pc - 2] = ptr as u32; - $self.bytecode[$self.pc - 1] = (ptr as u64 >> 32) as u32; + $self.write_ic_back($obj.shape_id(), ptr); unsafe { *ptr } } else { $self @@ -126,9 +124,7 @@ macro_rules! member_read_prop { .lookup_position($obj.shape_id(), $prop_name_si) { if let Some(ptr) = $obj.prop_ptr_at(pos) { - $self.bytecode[$self.pc - 3] = $obj.shape_id() & 0x00FF_FFFF; - $self.bytecode[$self.pc - 2] = ptr as u32; - $self.bytecode[$self.pc - 1] = (ptr as u64 >> 32) as u32; + $self.write_ic_back($obj.shape_id(), ptr); } } val @@ -515,9 +511,7 @@ impl Vm { obj.set_prop_at(pos, val); // IC write-back: 3 extension words (shape_id + ptr_lo + ptr_hi) if let Some(ptr) = obj.prop_ptr_at(pos) { - self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(obj.shape_id(), ptr); } } else { let new_shape_id = self @@ -528,9 +522,7 @@ impl Vm { let new_pos = obj.push_prop(val); obj.bump_generation(); if let Some(ptr) = obj.prop_ptr_at(new_pos) { - self.bytecode[self.pc - 3] = new_shape_id & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(new_shape_id, ptr); self.kernel.prop_forge().upsert( new_shape_id, PropTemplate { @@ -545,6 +537,16 @@ impl Vm { Ok(()) } + fn write_ic_back(&mut self, shape_id: u32, ptr: *const JsValue) { + debug_assert!( + self.pc >= 3, + "IC write-back requires 3 extension words before pc" + ); + self.bytecode[self.pc - 3] = shape_id & 0x00FF_FFFF; + self.bytecode[self.pc - 2] = ptr as u32; + self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + } + pub fn rerun(&mut self) -> Result { self.clear_execution_state(); self.active_reg_limit = self.root_reg_limit; @@ -1081,9 +1083,7 @@ impl Vm { if let Some(vec) = obj.hash_props_vec() { if pos < vec.len() { let ptr = &*vec[pos] as *const JsValue; - self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(obj.shape_id(), ptr); self.regs[a] = unsafe { *(ptr) }; } else { self.regs[a] = self @@ -1107,9 +1107,7 @@ impl Vm { .lookup_position(obj.shape_id(), prop_name_si) { if let Some(ptr) = obj.prop_ptr_at(pos) { - self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(obj.shape_id(), ptr); } } self.regs[a] = val; @@ -1145,9 +1143,7 @@ impl Vm { { obj.set_prop_at(pos, self.regs[a]); if let Some(ptr) = obj.prop_ptr_at(pos) { - self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(obj.shape_id(), ptr); } } else { let new_shape_id = self @@ -1158,9 +1154,7 @@ impl Vm { let new_pos = obj.push_prop(self.regs[a]); obj.bump_generation(); if let Some(ptr) = obj.prop_ptr_at(new_pos) { - self.bytecode[self.pc - 3] = new_shape_id & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(new_shape_id, ptr); self.kernel.prop_forge().upsert( new_shape_id, PropTemplate { @@ -1495,9 +1489,7 @@ impl Vm { { obj.set_prop_at(pos, new_val); if let Some(ptr) = obj.prop_ptr_at(pos) { - self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(obj.shape_id(), ptr); } } else { let new_shape_id = self @@ -1508,9 +1500,7 @@ impl Vm { let new_pos = obj.push_prop(new_val); obj.bump_generation(); if let Some(ptr) = obj.prop_ptr_at(new_pos) { - self.bytecode[self.pc - 3] = new_shape_id & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(new_shape_id, ptr); self.kernel.prop_forge().upsert( new_shape_id, PropTemplate { @@ -1546,9 +1536,7 @@ impl Vm { { obj.set_prop_at(pos, new_val); if let Some(ptr) = obj.prop_ptr_at(pos) { - self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(obj.shape_id(), ptr); } } else { let new_shape_id = self @@ -1559,9 +1547,7 @@ impl Vm { let new_pos = obj.push_prop(new_val); obj.bump_generation(); if let Some(ptr) = obj.prop_ptr_at(new_pos) { - self.bytecode[self.pc - 3] = new_shape_id & 0x00FF_FFFF; - self.bytecode[self.pc - 2] = ptr as u32; - self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32; + self.write_ic_back(new_shape_id, ptr); self.kernel.prop_forge().upsert( new_shape_id, PropTemplate { @@ -2016,4 +2002,17 @@ mod tests { "unexpected error: {err}" ); } + + #[test] + fn write_ic_back_updates_three_extension_words() { + let mut vm = Vm::new(); + vm.bytecode = vec![0, 0, 0]; + vm.pc = 3; + let boxed = Box::new(JsValue::int(42)); + let ptr = &*boxed as *const JsValue; + vm.write_ic_back(0x1234_5678, ptr); + assert_eq!(vm.bytecode[0], 0x0034_5678); + assert_eq!(vm.bytecode[1], ptr as u32); + assert_eq!(vm.bytecode[2], (ptr as u64 >> 32) as u32); + } }