fix: 数组属性存储机制(array_prop_count 显式元素数 + shape 属性偏移 + IC/prop_forge 对齐)

This commit is contained in:
2026-08-07 21:53:45 +08:00
parent db04bc25c9
commit 31542a2576
7 changed files with 103 additions and 41 deletions
+3 -3
View File
@@ -170,8 +170,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);
if obj.has_prop_meta() {
let val = self.ordinary_get_with_target(obj, prop_name_si, val, a as u8)?;
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() {
self.regs[a] = val;
}
@@ -194,7 +193,7 @@ impl Vm {
prop_name_si,
template.position
);
self.regs[a] = obj.get_prop_at(template.position);
self.regs[a] = obj.get_prop_shape(template.position);
} else {
ic_debug!("IC_GET miss shape={} prop={}", obj.shape_id(), prop_name_si);
self.regs[a] = self.ordinary_get(obj, prop_name_si, val)?;
@@ -445,3 +444,4 @@ impl Vm {
Ok(false)
}
}
+7 -4
View File
@@ -85,7 +85,9 @@ pub(crate) fn ic_get_hit(obj: &JsObject, shape_id: u32, slot_index: u32, proto_d
}
if proto_depth == 0 {
if obj.shape_id() == shape_id && slot_index < obj.prop_vec_len() as u32 {
return Some(obj.get_prop_at(slot_index));
let v = obj.get_prop_shape(slot_index);
eprintln!("[DBG] ic_get_hit shape={} slot={} apc={} v={:?}", shape_id, slot_index, obj.array_prop_count, v);
return Some(v);
}
return None;
}
@@ -95,7 +97,7 @@ pub(crate) fn ic_get_hit(obj: &JsObject, shape_id: u32, slot_index: u32, proto_d
}
let target_ref = unsafe { &*target };
if target_ref.shape_id() == shape_id && slot_index < target_ref.prop_vec_len() as u32 {
Some(target_ref.get_prop_at(slot_index))
Some(target_ref.get_prop_shape(slot_index))
} else {
None
}
@@ -108,7 +110,7 @@ pub(crate) fn ic_set_hit(obj: &mut JsObject, shape_id: u32, slot_index: u32, pro
}
if proto_depth == 0 {
if obj.shape_id() == shape_id && slot_index < obj.prop_vec_len() as u32 {
obj.set_prop_at(slot_index, value);
obj.set_prop_shape(slot_index, value);
return true;
}
return false;
@@ -119,9 +121,10 @@ pub(crate) fn ic_set_hit(obj: &mut JsObject, shape_id: u32, slot_index: u32, pro
}
let target_ref = unsafe { &*target };
if target_ref.shape_id() == shape_id && slot_index < target_ref.prop_vec_len() as u32 {
unsafe { &mut *(target as *mut JsObject) }.set_prop_at(slot_index, value);
unsafe { &mut *(target as *mut JsObject) }.set_prop_shape(slot_index, value);
true
} else {
false
}
}
+17 -4
View File
@@ -700,11 +700,23 @@ impl Vm {
.shape_forge()
.lookup_position(obj.shape_id(), prop_name_si)
.and_then(|pos| {
let val = obj.get_prop_at(pos);
if !val.is_undefined() || obj.prop_vec_len() > pos as usize {
Some(pos)
if obj.is_array() {
// 数组属性存储索引 = array_prop_count + shape 槽位(与元素区分)。
let idx = obj.array_prop_count as usize + pos as usize;
let val = obj.get_prop_at(idx);
eprintln!("[DBG] gos array prop pos={} apc={} idx={} val={:?}", pos, obj.array_prop_count, idx, val);
if !val.is_undefined() {
Some(idx as u32)
} else {
None
}
} else {
None
let val = obj.get_prop_at(pos);
if !val.is_undefined() || obj.prop_vec_len() > pos as usize {
Some(pos)
} else {
None
}
}
})
}
@@ -1805,3 +1817,4 @@ mod tests {
assert_eq!(vm.reg(255), JsValue::int(13));
}
}
+9 -3
View File
@@ -309,10 +309,11 @@ impl Vm {
pub(crate) fn set_or_create_prop_value(&mut self, obj: &mut JsObject, prop_name_si: u32, val: JsValue) {
vm_trace!("set_or_create_prop_value: shape_id={} prop_name_si={}", obj.shape_id(), prop_name_si);
if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) {
obj.set_prop_at(pos, val);
obj.set_prop_shape(pos, val);
} else {
let new_shape_id = self.kernel_core.shape_forge().make_shape(obj.shape_id(), prop_name_si);
obj.set_shape_id(new_shape_id);
// 数组对象:属性追加到 hash_props 属性区(元素之后),array_prop_count 不变。
obj.push_prop(val);
obj.bump_generation();
}
@@ -324,11 +325,16 @@ impl Vm {
vm_trace!("define_data_property: shape={} prop_si={}", obj.shape_id(), prop_name_si);
let val = self.promote_if_needed_for_write_ptr(obj as *mut JsObject, val);
let pos = if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) {
pos
// shape 槽位 → 存储索引(数组属性在元素区之后)。
if obj.is_array() {
obj.array_prop_count as usize + pos as usize
} else {
pos as usize
}
} else {
let new_shape_id = self.kernel_core.shape_forge().make_shape(obj.shape_id(), prop_name_si);
obj.set_shape_id(new_shape_id);
obj.push_prop(JsValue::undefined())
obj.push_prop(JsValue::undefined()) as usize
};
if let Some(current) = obj.prop_meta_at(pos) {
if !current.attributes.configurable() {