Skip to content

Commit 28c5fe2

Browse files
committed
Address CodeRabbit concerns: fix GC clearing and improve thread safety of lazy __dict__ recreation
1 parent f1d9358 commit 28c5fe2

File tree

2 files changed

+17
-9
lines changed

2 files changed

+17
-9
lines changed

crates/vm/src/builtins/object.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -558,11 +558,7 @@ pub fn object_get_dict(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyDict
558558
Ok(dict)
559559
} else {
560560
match obj.instance_dict() {
561-
Some(d) => {
562-
let dict = vm.ctx.new_dict();
563-
d.set(Some(dict.clone()));
564-
Ok(dict)
565-
}
561+
Some(d) => Ok(d.get_or_insert(vm)),
566562
None => Err(vm.new_attribute_error("This object has no __dict__")),
567563
}
568564
}

crates/vm/src/object/core.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -909,8 +909,8 @@ impl Py<PyWeak> {
909909
}
910910

911911
#[derive(Debug)]
912-
pub(super) struct InstanceDict {
913-
pub(super) d: PyRwLock<Option<PyDictRef>>,
912+
pub(crate) struct InstanceDict {
913+
pub(crate) d: PyRwLock<Option<PyDictRef>>,
914914
}
915915

916916
impl From<PyDictRef> for InstanceDict {
@@ -948,6 +948,17 @@ impl InstanceDict {
948948
pub fn into_inner(self) -> Option<PyDictRef> {
949949
self.d.into_inner()
950950
}
951+
952+
pub(crate) fn get_or_insert(&self, vm: &VirtualMachine) -> PyDictRef {
953+
let mut d = self.d.write();
954+
if let Some(existing) = d.as_ref() {
955+
existing.clone()
956+
} else {
957+
let dict = vm.ctx.new_dict();
958+
*d = Some(dict.clone());
959+
dict
960+
}
961+
}
951962
}
952963

953964
impl<T: PyPayload> PyInner<T> {
@@ -1776,8 +1787,9 @@ impl PyObject {
17761787
let ext = unsafe { &mut *ext_ptr };
17771788
if let Some(old_dict) = ext.dict.take() {
17781789
// Get the dict ref before dropping InstanceDict
1779-
let dict_ref = old_dict.into_inner();
1780-
result.push(dict_ref.into());
1790+
if let Some(dict_ref) = old_dict.into_inner() {
1791+
result.push(dict_ref.into());
1792+
}
17811793
}
17821794
for slot in ext.slots.iter() {
17831795
if let Some(val) = slot.write().take() {

0 commit comments

Comments
 (0)