2 use rustc_data_structures::fx::FxHashSet;
4 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
5 pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
6 fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> {
7 let this = self.eval_context_mut();
8 // No reason to do anything at all if stacked borrows is off.
9 if this.machine.stacked_borrows.is_none() {
13 let mut tags = FxHashSet::default();
15 for thread in this.machine.threads.iter() {
16 if let Some(Scalar::Ptr(
17 Pointer { provenance: Provenance::Concrete { sb, .. }, .. },
19 )) = thread.panic_payload
25 self.find_tags_in_tls(&mut tags);
26 self.find_tags_in_memory(&mut tags);
27 self.find_tags_in_locals(&mut tags)?;
29 self.remove_unreachable_tags(tags);
34 fn find_tags_in_tls(&mut self, tags: &mut FxHashSet<SbTag>) {
35 let this = self.eval_context_mut();
36 this.machine.tls.iter(|scalar| {
37 if let Scalar::Ptr(Pointer { provenance: Provenance::Concrete { sb, .. }, .. }, _) =
45 fn find_tags_in_memory(&mut self, tags: &mut FxHashSet<SbTag>) {
46 let this = self.eval_context_mut();
47 this.memory.alloc_map().iter(|it| {
48 for (_id, (_kind, alloc)) in it {
49 for (_size, prov) in alloc.provenance().iter() {
50 if let Provenance::Concrete { sb, .. } = prov {
58 fn find_tags_in_locals(&mut self, tags: &mut FxHashSet<SbTag>) -> InterpResult<'tcx> {
59 let this = self.eval_context_mut();
60 for frame in this.machine.threads.all_stacks().flatten() {
61 // Handle the return place of each frame
62 if let Ok(return_place) = frame.return_place.try_as_mplace() {
63 if let Some(Provenance::Concrete { sb, .. }) = return_place.ptr.provenance {
68 for local in frame.locals.iter() {
69 let LocalValue::Live(value) = local.value else {
73 Operand::Immediate(Immediate::Scalar(Scalar::Ptr(ptr, _))) =>
74 if let Provenance::Concrete { sb, .. } = ptr.provenance {
77 Operand::Immediate(Immediate::ScalarPair(s1, s2)) => {
78 if let Scalar::Ptr(ptr, _) = s1 {
79 if let Provenance::Concrete { sb, .. } = ptr.provenance {
83 if let Scalar::Ptr(ptr, _) = s2 {
84 if let Provenance::Concrete { sb, .. } = ptr.provenance {
89 Operand::Indirect(MemPlace { ptr, .. }) => {
90 if let Some(Provenance::Concrete { sb, .. }) = ptr.provenance {
94 Operand::Immediate(Immediate::Uninit)
95 | Operand::Immediate(Immediate::Scalar(Scalar::Int(_))) => {}
103 fn remove_unreachable_tags(&mut self, tags: FxHashSet<SbTag>) {
104 let this = self.eval_context_mut();
105 this.memory.alloc_map().iter(|it| {
106 for (_id, (_kind, alloc)) in it {
113 .remove_unreachable_tags(&tags);