(
&mut self,
_vm: &VirtualMachine,
oparg: LoadAttr,
instr_idx: usize,
cache_base: usize,
)
| 7423 | } |
| 7424 | |
| 7425 | fn specialize_load_attr( |
| 7426 | &mut self, |
| 7427 | _vm: &VirtualMachine, |
| 7428 | oparg: LoadAttr, |
| 7429 | instr_idx: usize, |
| 7430 | cache_base: usize, |
| 7431 | ) { |
| 7432 | // Pre-check: bail if already specialized by another thread |
| 7433 | if !matches!( |
| 7434 | self.code.instructions.read_op(instr_idx), |
| 7435 | Instruction::LoadAttr { .. } |
| 7436 | ) { |
| 7437 | return; |
| 7438 | } |
| 7439 | let obj = self.top_value(); |
| 7440 | let cls = obj.class(); |
| 7441 | |
| 7442 | // Check if this is a type object (class attribute access) |
| 7443 | if obj.downcast_ref::<PyType>().is_some() { |
| 7444 | self.specialize_class_load_attr(_vm, oparg, instr_idx, cache_base); |
| 7445 | return; |
| 7446 | } |
| 7447 | |
| 7448 | // Only specialize if getattro is the default (PyBaseObject::getattro) |
| 7449 | let is_default_getattro = cls |
| 7450 | .slots |
| 7451 | .getattro |
| 7452 | .load() |
| 7453 | .is_some_and(|f| f as usize == PyBaseObject::getattro as *const () as usize); |
| 7454 | if !is_default_getattro { |
| 7455 | let mut type_version = cls.tp_version_tag.load(Acquire); |
| 7456 | if type_version == 0 { |
| 7457 | type_version = cls.assign_version_tag(); |
| 7458 | } |
| 7459 | if type_version != 0 |
| 7460 | && !oparg.is_method() |
| 7461 | && !self.specialization_eval_frame_active(_vm) |
| 7462 | && cls.get_attr(identifier!(_vm, __getattr__)).is_none() |
| 7463 | && let Some(getattribute) = cls.get_attr(identifier!(_vm, __getattribute__)) |
| 7464 | && let Some(func) = getattribute.downcast_ref_if_exact::<PyFunction>(_vm) |
| 7465 | && func.can_specialize_call(2) |
| 7466 | { |
| 7467 | let func_version = func.get_version_for_current_state(); |
| 7468 | if func_version != 0 { |
| 7469 | let func_ptr = &*getattribute as *const PyObject as usize; |
| 7470 | unsafe { |
| 7471 | self.code |
| 7472 | .instructions |
| 7473 | .write_cache_u32(cache_base + 3, func_version); |
| 7474 | self.write_cached_descriptor(cache_base, type_version, func_ptr); |
| 7475 | } |
| 7476 | self.specialize_at( |
| 7477 | instr_idx, |
| 7478 | cache_base, |
| 7479 | Instruction::LoadAttrGetattributeOverridden, |
| 7480 | ); |
| 7481 | return; |
| 7482 | } |
no test coverage detected