Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions crates/perry-runtime/src/closure/dynamic_props.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,27 @@ pub(crate) fn visit_closure_static_prototype_slot_mut(
if owner == 0 {
return;
}
// Take the entry OUT and run the visit with the lock RELEASED: a
// copying-minor rewrite visitor can move the prototype closure, and
// move fixup re-enters `closure_dynamic_props_owner_moved`, which
// takes this same lock — visiting under it self-deadlocks the
// collector (the geisterhand+reviver GC test wedged CI's cargo-test
// at the 3h job timeout). Same remove → visit → merge-back pattern
// as `visit_closure_dynamic_prop_values_mut` above and the roots
// scanner below.
let Some(mut proto_bits) = get_closure_prototypes()
.lock()
.ok()
.and_then(|mut prototypes| prototypes.remove(&owner))
else {
return;
};
visit(&mut proto_bits as *mut u64);
// The visit can forward the owner itself (self-referential
// prototype); re-key like the roots scanner does.
let new_owner = forwarded_heap_owner(owner).unwrap_or(owner);
if let Ok(mut prototypes) = get_closure_prototypes().lock() {
if let Some(proto_bits) = prototypes.get_mut(&owner) {
visit(proto_bits as *mut u64);
}
prototypes.insert(new_owner, proto_bits);
}
}

Expand Down
26 changes: 23 additions & 3 deletions crates/perry-runtime/src/object/prototype_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,30 @@ pub(crate) fn visit_object_static_prototype_slot_mut(
if owner == 0 {
return;
}
// Take the entry OUT and run the visit with the lock RELEASED: a
// copying-minor rewrite visitor can move the prototype object, and
// move fixup re-enters `object_static_prototype_owner_moved`, which
// takes this same lock — visiting under it self-deadlocks the
// collector. Same hazard and fix as the closure static-prototype
// visitor in `closure::dynamic_props`.
let Some(mut proto_bits) = get_object_prototypes()
.lock()
.ok()
.and_then(|mut map| map.remove(&owner))
else {
return;
};
visit(&mut proto_bits as *mut u64);
// The visit can forward the owner itself (self-referential
// prototype); re-key the entry to the forwarded address.
let new_owner = unsafe {
crate::value::addr_class::try_read_gc_header(owner)
.filter(|h| h.gc_flags & crate::gc::GC_FLAG_FORWARDED != 0)
.map(|h| crate::gc::forwarding_address(h as *const _) as usize)
.unwrap_or(owner)
};
if let Ok(mut map) = get_object_prototypes().lock() {
if let Some(proto_bits) = map.get_mut(&owner) {
visit(proto_bits as *mut u64);
}
map.insert(new_owner, proto_bits);
}
}

Expand Down
Loading