perf: IC hit/miss 路径 depth=0 快速路径内联,跳过 proto 遍历函数调用
This commit is contained in:
@@ -207,23 +207,36 @@ impl Vm {
|
|||||||
prop_cache_miss();
|
prop_cache_miss();
|
||||||
ic_debug!("IC_GET miss shape={} prop={}", obj.shape_id(), prop_name_si);
|
ic_debug!("IC_GET miss shape={} prop={}", obj.shape_id(), prop_name_si);
|
||||||
let resolved = self.ordinary_get(obj, prop_name_si, val)?;
|
let resolved = self.ordinary_get(obj, prop_name_si, val)?;
|
||||||
// Walk proto chain to find which object actually owns this property.
|
// Try own property first (fast path, depth=0).
|
||||||
let mut cursor = obj_ptr;
|
if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) {
|
||||||
let mut depth = 0u8;
|
if !obj.is_accessor_meta(pos) {
|
||||||
loop {
|
ic_helper::write_ic_back(&mut self.bytecode, self.pc, obj.shape_id(), pos, 0);
|
||||||
let co = unsafe { &*cursor };
|
ic_debug!("IC_GET write-back own shape={} slot={}", obj.shape_id(), pos);
|
||||||
if let Some(pos) = self.kernel_core.shape_forge().lookup_position(co.shape_id(), prop_name_si) {
|
}
|
||||||
if !co.is_accessor_meta(pos) {
|
} else {
|
||||||
ic_helper::write_ic_back(&mut self.bytecode, self.pc, co.shape_id(), pos, depth);
|
// Walk proto chain to find which object actually owns this property.
|
||||||
ic_debug!("IC_GET write-back shape={} slot={} depth={}", co.shape_id(), pos, depth);
|
let mut cursor = obj.proto().as_js_object_ptr();
|
||||||
|
let mut depth = 1u8;
|
||||||
|
while !cursor.is_null() {
|
||||||
|
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_debug!(
|
||||||
|
"IC_GET write-back proto shape={} slot={} depth={}",
|
||||||
|
co_ref.shape_id(),
|
||||||
|
pos,
|
||||||
|
depth
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
if !co_ref.proto().is_object() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cursor = co_ref.proto().as_js_object_ptr();
|
||||||
|
depth += 1;
|
||||||
}
|
}
|
||||||
if !co.proto().is_object() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cursor = co.proto().as_js_object_ptr();
|
|
||||||
depth += 1;
|
|
||||||
}
|
}
|
||||||
self.regs[a] = resolved;
|
self.regs[a] = resolved;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ pub(crate) fn ic_get_hit(obj: &JsObject, shape_id: u32, slot_index: u32, proto_d
|
|||||||
if shape_id == 0 {
|
if shape_id == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
let target = resolve_proto_target_raw(obj as *const JsObject, proto_depth);
|
let target = resolve_proto_target_raw(obj as *const JsObject, proto_depth);
|
||||||
if target.is_null() {
|
if target.is_null() {
|
||||||
return None;
|
return None;
|
||||||
@@ -104,6 +110,13 @@ pub(crate) fn ic_set_hit(obj: &mut JsObject, shape_id: u32, slot_index: u32, pro
|
|||||||
if shape_id == 0 {
|
if shape_id == 0 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
let target = resolve_proto_target_raw(obj as *const JsObject, proto_depth);
|
let target = resolve_proto_target_raw(obj as *const JsObject, proto_depth);
|
||||||
if target.is_null() {
|
if target.is_null() {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -238,9 +238,17 @@ impl Vm {
|
|||||||
/// Perform ordinary_get and write back IC with proto chain depth.
|
/// Perform ordinary_get and write back IC with proto chain depth.
|
||||||
fn proto_chain_ic_get(&mut self, obj: &JsObject, prop_name_si: u32, receiver: JsValue) -> Result<JsValue, String> {
|
fn proto_chain_ic_get(&mut self, obj: &JsObject, prop_name_si: u32, receiver: JsValue) -> Result<JsValue, String> {
|
||||||
let resolved = self.ordinary_get(obj, prop_name_si, receiver)?;
|
let resolved = self.ordinary_get(obj, prop_name_si, receiver)?;
|
||||||
let mut cursor: *mut JsObject = obj as *const JsObject as *mut JsObject;
|
// Fast path: own property (depth=0).
|
||||||
let mut depth = 0u8;
|
if let Some(pos) = self.kernel_core.shape_forge().lookup_position(obj.shape_id(), prop_name_si) {
|
||||||
loop {
|
if !obj.is_accessor_meta(pos) {
|
||||||
|
crate::ic_helper::write_ic_back(&mut self.bytecode, self.pc, obj.shape_id(), pos, 0);
|
||||||
|
}
|
||||||
|
return Ok(resolved);
|
||||||
|
}
|
||||||
|
// Walk proto chain for inherited properties.
|
||||||
|
let mut cursor = obj.proto().as_js_object_ptr();
|
||||||
|
let mut depth = 1u8;
|
||||||
|
while !cursor.is_null() {
|
||||||
let co = unsafe { &*cursor };
|
let co = unsafe { &*cursor };
|
||||||
if let Some(pos) = self.kernel_core.shape_forge().lookup_position(co.shape_id(), prop_name_si) {
|
if let Some(pos) = self.kernel_core.shape_forge().lookup_position(co.shape_id(), prop_name_si) {
|
||||||
if !co.is_accessor_meta(pos) {
|
if !co.is_accessor_meta(pos) {
|
||||||
|
|||||||
Reference in New Issue
Block a user