fix: 修复跨 VM 共享 Shape 指针问题

This commit is contained in:
2026-06-07 15:33:52 +08:00
parent f725d81b36
commit 3b3d9c224a
2 changed files with 68 additions and 50 deletions
+8 -8
View File
@@ -7,7 +7,7 @@ use crate::shape_forge::ShapeId;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PropTemplate { pub struct PropTemplate {
pub shape_id: ShapeId, pub shape_id: ShapeId,
pub ptr_bits: u64, pub position: u8,
pub generation: u32, pub generation: u32,
} }
@@ -67,13 +67,13 @@ mod tests {
let forge = PropForge::new(); let forge = PropForge::new();
let t = PropTemplate { let t = PropTemplate {
shape_id: 1, shape_id: 1,
ptr_bits: 3, position: 3,
generation: 10, generation: 10,
}; };
forge.upsert(1, t); forge.upsert(1, t);
let got = forge.get_template(1).unwrap(); let got = forge.get_template(1).unwrap();
assert_eq!(got.shape_id, 1); assert_eq!(got.shape_id, 1);
assert_eq!(got.ptr_bits, 3); assert_eq!(got.position, 3);
assert_eq!(got.generation, 10); assert_eq!(got.generation, 10);
} }
@@ -84,7 +84,7 @@ mod tests {
1, 1,
PropTemplate { PropTemplate {
shape_id: 1, shape_id: 1,
ptr_bits: 3, position: 3,
generation: 10, generation: 10,
}, },
); );
@@ -92,7 +92,7 @@ mod tests {
1, 1,
PropTemplate { PropTemplate {
shape_id: 1, shape_id: 1,
ptr_bits: 7, position: 7,
generation: 5, generation: 5,
}, },
); );
@@ -107,7 +107,7 @@ mod tests {
1, 1,
PropTemplate { PropTemplate {
shape_id: 1, shape_id: 1,
ptr_bits: 3, position: 3,
generation: 5, generation: 5,
}, },
); );
@@ -115,12 +115,12 @@ mod tests {
1, 1,
PropTemplate { PropTemplate {
shape_id: 1, shape_id: 1,
ptr_bits: 7, position: 7,
generation: 10, generation: 10,
}, },
); );
let got = forge.get_template(1).unwrap(); let got = forge.get_template(1).unwrap();
assert_eq!(got.generation, 10); assert_eq!(got.generation, 10);
assert_eq!(got.ptr_bits, 7); assert_eq!(got.position, 7);
} }
} }
+60 -42
View File
@@ -571,6 +571,17 @@ impl Vm {
self.kernel.string_forge().lookup(val.as_string_index()) self.kernel.string_forge().lookup(val.as_string_index())
} }
fn template_prop_ptr(&self, obj: &JsObject, template: &PropTemplate) -> Option<*const JsValue> {
let pos = template.position as usize;
obj.hash_props_vec().and_then(|vec| {
if pos < vec.len() {
Some(&*vec[pos] as *const JsValue)
} else {
None
}
})
}
fn resolve_property(&self, obj: &JsObject, prop_name_si: u32) -> Option<JsValue> { fn resolve_property(&self, obj: &JsObject, prop_name_si: u32) -> Option<JsValue> {
if let Some(pos) = self if let Some(pos) = self
.kernel .kernel
@@ -634,7 +645,7 @@ impl Vm {
new_shape_id, new_shape_id,
PropTemplate { PropTemplate {
shape_id: new_shape_id, shape_id: new_shape_id,
ptr_bits: ptr as u64, position: new_pos,
generation: obj.generation(), generation: obj.generation(),
}, },
); );
@@ -954,12 +965,19 @@ impl Vm {
} else if let Some(template) = } else if let Some(template) =
self.kernel.prop_forge().get_template(obj.shape_id()) self.kernel.prop_forge().get_template(obj.shape_id())
{ {
if template.ptr_bits != 0 { let pos = template.position as usize;
let ptr = template.ptr_bits; if let Some(vec) = obj.hash_props_vec() {
self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; if pos < vec.len() {
self.bytecode[self.pc - 2] = ptr as u32; let ptr = &*vec[pos] as *const JsValue;
self.bytecode[self.pc - 1] = (ptr >> 32) as u32; self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF;
self.regs[a] = unsafe { *(ptr as *const JsValue) }; self.bytecode[self.pc - 2] = ptr as u32;
self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32;
self.regs[a] = unsafe { *(ptr) };
} else {
self.regs[a] = self
.resolve_property(obj, prop_name_si)
.unwrap_or(JsValue::undefined());
}
} else { } else {
self.regs[a] = self self.regs[a] = self
.resolve_property(obj, prop_name_si) .resolve_property(obj, prop_name_si)
@@ -1029,7 +1047,7 @@ impl Vm {
new_shape_id, new_shape_id,
PropTemplate { PropTemplate {
shape_id: new_shape_id, shape_id: new_shape_id,
ptr_bits: ptr as u64, position: new_pos,
generation: obj.generation(), generation: obj.generation(),
}, },
); );
@@ -1306,12 +1324,12 @@ impl Vm {
} else if let Some(template) = } else if let Some(template) =
self.kernel.prop_forge().get_template(obj.shape_id()) self.kernel.prop_forge().get_template(obj.shape_id())
{ {
if template.ptr_bits != 0 { if let Some(ptr) = self.template_prop_ptr(obj, &template) {
let ptr = template.ptr_bits;
self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF;
self.bytecode[self.pc - 2] = ptr as u32; self.bytecode[self.pc - 2] = ptr as u32;
self.bytecode[self.pc - 1] = (ptr >> 32) as u32; self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32;
unsafe { *(ptr as *const JsValue) } unsafe { *ptr }
} else { } else {
self.resolve_property(obj, prop_name_si) self.resolve_property(obj, prop_name_si)
.unwrap_or(JsValue::undefined()) .unwrap_or(JsValue::undefined())
@@ -1367,7 +1385,7 @@ impl Vm {
new_shape_id, new_shape_id,
PropTemplate { PropTemplate {
shape_id: new_shape_id, shape_id: new_shape_id,
ptr_bits: ptr as u64, position: new_pos,
generation: obj.generation(), generation: obj.generation(),
}, },
); );
@@ -1400,12 +1418,12 @@ impl Vm {
} else if let Some(template) = } else if let Some(template) =
self.kernel.prop_forge().get_template(obj.shape_id()) self.kernel.prop_forge().get_template(obj.shape_id())
{ {
if template.ptr_bits != 0 { if let Some(ptr) = self.template_prop_ptr(obj, &template) {
let ptr = template.ptr_bits;
self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF;
self.bytecode[self.pc - 2] = ptr as u32; self.bytecode[self.pc - 2] = ptr as u32;
self.bytecode[self.pc - 1] = (ptr >> 32) as u32; self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32;
unsafe { *(ptr as *const JsValue) } unsafe { *ptr }
} else { } else {
self.resolve_property(obj, prop_name_si) self.resolve_property(obj, prop_name_si)
.unwrap_or(JsValue::undefined()) .unwrap_or(JsValue::undefined())
@@ -1461,7 +1479,7 @@ impl Vm {
new_shape_id, new_shape_id,
PropTemplate { PropTemplate {
shape_id: new_shape_id, shape_id: new_shape_id,
ptr_bits: ptr as u64, position: new_pos,
generation: obj.generation(), generation: obj.generation(),
}, },
); );
@@ -1564,12 +1582,12 @@ impl Vm {
} else if let Some(template) = } else if let Some(template) =
self.kernel.prop_forge().get_template(obj.shape_id()) self.kernel.prop_forge().get_template(obj.shape_id())
{ {
if template.ptr_bits != 0 { if let Some(ptr) = self.template_prop_ptr(obj, &template) {
let ptr = template.ptr_bits;
self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF;
self.bytecode[self.pc - 2] = ptr as u32; self.bytecode[self.pc - 2] = ptr as u32;
self.bytecode[self.pc - 1] = (ptr >> 32) as u32; self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32;
unsafe { *(ptr as *const JsValue) } unsafe { *ptr }
} else { } else {
self.resolve_property(obj, prop_name_si) self.resolve_property(obj, prop_name_si)
.unwrap_or(JsValue::undefined()) .unwrap_or(JsValue::undefined())
@@ -1628,12 +1646,12 @@ impl Vm {
} else if let Some(template) = } else if let Some(template) =
self.kernel.prop_forge().get_template(obj.shape_id()) self.kernel.prop_forge().get_template(obj.shape_id())
{ {
if template.ptr_bits != 0 { if let Some(ptr) = self.template_prop_ptr(obj, &template) {
let ptr = template.ptr_bits;
self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF;
self.bytecode[self.pc - 2] = ptr as u32; self.bytecode[self.pc - 2] = ptr as u32;
self.bytecode[self.pc - 1] = (ptr >> 32) as u32; self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32;
unsafe { *(ptr as *const JsValue) } unsafe { *ptr }
} else { } else {
self.resolve_property(obj, prop_name_si) self.resolve_property(obj, prop_name_si)
.unwrap_or(JsValue::undefined()) .unwrap_or(JsValue::undefined())
@@ -1683,12 +1701,12 @@ impl Vm {
} else if let Some(template) = } else if let Some(template) =
self.kernel.prop_forge().get_template(obj.shape_id()) self.kernel.prop_forge().get_template(obj.shape_id())
{ {
if template.ptr_bits != 0 { if let Some(ptr) = self.template_prop_ptr(obj, &template) {
let ptr = template.ptr_bits;
self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF;
self.bytecode[self.pc - 2] = ptr as u32; self.bytecode[self.pc - 2] = ptr as u32;
self.bytecode[self.pc - 1] = (ptr >> 32) as u32; self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32;
unsafe { *(ptr as *const JsValue) } unsafe { *ptr }
} else { } else {
self.resolve_property(obj, prop_name_si) self.resolve_property(obj, prop_name_si)
.unwrap_or(JsValue::undefined()) .unwrap_or(JsValue::undefined())
@@ -1738,12 +1756,12 @@ impl Vm {
} else if let Some(template) = } else if let Some(template) =
self.kernel.prop_forge().get_template(obj.shape_id()) self.kernel.prop_forge().get_template(obj.shape_id())
{ {
if template.ptr_bits != 0 { if let Some(ptr) = self.template_prop_ptr(obj, &template) {
let ptr = template.ptr_bits;
self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF;
self.bytecode[self.pc - 2] = ptr as u32; self.bytecode[self.pc - 2] = ptr as u32;
self.bytecode[self.pc - 1] = (ptr >> 32) as u32; self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32;
unsafe { *(ptr as *const JsValue) } unsafe { *ptr }
} else { } else {
self.resolve_property(obj, prop_name_si) self.resolve_property(obj, prop_name_si)
.unwrap_or(JsValue::undefined()) .unwrap_or(JsValue::undefined())
@@ -1793,12 +1811,12 @@ impl Vm {
} else if let Some(template) = } else if let Some(template) =
self.kernel.prop_forge().get_template(obj.shape_id()) self.kernel.prop_forge().get_template(obj.shape_id())
{ {
if template.ptr_bits != 0 { if let Some(ptr) = self.template_prop_ptr(obj, &template) {
let ptr = template.ptr_bits;
self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF;
self.bytecode[self.pc - 2] = ptr as u32; self.bytecode[self.pc - 2] = ptr as u32;
self.bytecode[self.pc - 1] = (ptr >> 32) as u32; self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32;
unsafe { *(ptr as *const JsValue) } unsafe { *ptr }
} else { } else {
self.resolve_property(obj, prop_name_si) self.resolve_property(obj, prop_name_si)
.unwrap_or(JsValue::undefined()) .unwrap_or(JsValue::undefined())
@@ -1848,12 +1866,12 @@ impl Vm {
} else if let Some(template) = } else if let Some(template) =
self.kernel.prop_forge().get_template(obj.shape_id()) self.kernel.prop_forge().get_template(obj.shape_id())
{ {
if template.ptr_bits != 0 { if let Some(ptr) = self.template_prop_ptr(obj, &template) {
let ptr = template.ptr_bits;
self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF; self.bytecode[self.pc - 3] = obj.shape_id() & 0x00FF_FFFF;
self.bytecode[self.pc - 2] = ptr as u32; self.bytecode[self.pc - 2] = ptr as u32;
self.bytecode[self.pc - 1] = (ptr >> 32) as u32; self.bytecode[self.pc - 1] = (ptr as u64 >> 32) as u32;
unsafe { *(ptr as *const JsValue) } unsafe { *ptr }
} else { } else {
self.resolve_property(obj, prop_name_si) self.resolve_property(obj, prop_name_si)
.unwrap_or(JsValue::undefined()) .unwrap_or(JsValue::undefined())