diff --git a/vm/src/object/core.rs b/vm/src/object/core.rs index dda35f968a..53c55957c8 100644 --- a/vm/src/object/core.rs +++ b/vm/src/object/core.rs @@ -734,26 +734,37 @@ impl PyObject { #[inline(always)] // the outer function is never inlined fn drop_slow_inner(&self) -> Result<(), ()> { - // CPython-compatible drop implementation - if let Some(slot_del) = self.class().mro_find_map(|cls| cls.slots.del.load()) { - let ret = crate::vm::thread::with_vm(self, |vm| { - self.0.ref_count.inc(); - if let Err(e) = slot_del(self, vm) { - let del_method = self.get_class_attr("__del__").unwrap(); + // __del__ is mostly not implemented + #[inline(never)] + #[cold] + fn call_slot_del( + zelf: &PyObject, + slot_del: fn(&PyObject, &VirtualMachine) -> PyResult<()>, + ) -> Result<(), ()> { + let ret = crate::vm::thread::with_vm(zelf, |vm| { + zelf.0.ref_count.inc(); + if let Err(e) = slot_del(zelf, vm) { + let del_method = zelf.get_class_attr("__del__").unwrap(); vm.run_unraisable(e, None, del_method); } - self.0.ref_count.dec() + zelf.0.ref_count.dec() }); match ret { // the decref right above set ref_count back to 0 - Some(true) => {} + Some(true) => Ok(()), // we've been resurrected by __del__ - Some(false) => return Err(()), + Some(false) => Err(()), None => { - warn!("couldn't run __del__ method for object") + warn!("couldn't run __del__ method for object"); + Ok(()) } } } + + // CPython-compatible drop implementation + if let Some(slot_del) = self.class().mro_find_map(|cls| cls.slots.del.load()) { + call_slot_del(self, slot_del)?; + } if let Some(wrl) = self.weak_ref_list() { wrl.clear(); } @@ -763,7 +774,6 @@ impl PyObject { /// Can only be called when ref_count has dropped to zero. `ptr` must be valid #[inline(never)] - #[cold] unsafe fn drop_slow(ptr: NonNull) { if let Err(()) = ptr.as_ref().drop_slow_inner() { // abort drop for whatever reason