]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/miri/src/tag_gc.rs
Auto merge of #102717 - beetrees:repr128-c-style-debuginfo, r=nagisa
[rust.git] / src / tools / miri / src / tag_gc.rs
index 9378cc1e9207dd03d612af92b8a65c4d3e186468..73712348f0d5f076cd3d81e662ecc112cafad175 100644 (file)
 
 use crate::*;
 
-pub trait VisitMachineValues {
-    fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand<Provenance>));
+pub trait VisitTags {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag));
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
-    /// Generic GC helper to visit everything that can store a value. The `acc` offers some chance to
-    /// accumulate everything.
-    fn visit_all_machine_values<T>(
-        &self,
-        acc: &mut T,
-        mut visit_operand: impl FnMut(&mut T, &Operand<Provenance>),
-        mut visit_alloc: impl FnMut(&mut T, &Allocation<Provenance, AllocExtra>),
-    ) {
-        let this = self.eval_context_ref();
+impl<T: VisitTags> VisitTags for Option<T> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        if let Some(x) = self {
+            x.visit_tags(visit);
+        }
+    }
+}
+
+impl<T: VisitTags> VisitTags for std::cell::RefCell<T> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        self.borrow().visit_tags(visit)
+    }
+}
+
+impl VisitTags for SbTag {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        visit(*self)
+    }
+}
+
+impl VisitTags for Provenance {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        if let Provenance::Concrete { sb, .. } = self {
+            visit(*sb);
+        }
+    }
+}
+
+impl VisitTags for Pointer<Provenance> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        let (prov, _offset) = self.into_parts();
+        prov.visit_tags(visit);
+    }
+}
 
+impl VisitTags for Pointer<Option<Provenance>> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        let (prov, _offset) = self.into_parts();
+        prov.visit_tags(visit);
+    }
+}
+
+impl VisitTags for Scalar<Provenance> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        match self {
+            Scalar::Ptr(ptr, _) => ptr.visit_tags(visit),
+            Scalar::Int(_) => (),
+        }
+    }
+}
+
+impl VisitTags for Immediate<Provenance> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        match self {
+            Immediate::Scalar(s) => {
+                s.visit_tags(visit);
+            }
+            Immediate::ScalarPair(s1, s2) => {
+                s1.visit_tags(visit);
+                s2.visit_tags(visit);
+            }
+            Immediate::Uninit => {}
+        }
+    }
+}
+
+impl VisitTags for MemPlaceMeta<Provenance> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        match self {
+            MemPlaceMeta::Meta(m) => m.visit_tags(visit),
+            MemPlaceMeta::None => {}
+        }
+    }
+}
+
+impl VisitTags for MemPlace<Provenance> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        let MemPlace { ptr, meta } = self;
+        ptr.visit_tags(visit);
+        meta.visit_tags(visit);
+    }
+}
+
+impl VisitTags for MPlaceTy<'_, Provenance> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        (**self).visit_tags(visit)
+    }
+}
+
+impl VisitTags for Place<Provenance> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        match self {
+            Place::Ptr(p) => p.visit_tags(visit),
+            Place::Local { .. } => {
+                // Will be visited as part of the stack frame.
+            }
+        }
+    }
+}
+
+impl VisitTags for PlaceTy<'_, Provenance> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        (**self).visit_tags(visit)
+    }
+}
+
+impl VisitTags for Operand<Provenance> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        match self {
+            Operand::Immediate(imm) => {
+                imm.visit_tags(visit);
+            }
+            Operand::Indirect(p) => {
+                p.visit_tags(visit);
+            }
+        }
+    }
+}
+
+impl VisitTags for Allocation<Provenance, AllocExtra> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        for prov in self.provenance().provenances() {
+            prov.visit_tags(visit);
+        }
+
+        self.extra.visit_tags(visit);
+    }
+}
+
+impl VisitTags for crate::MiriInterpCx<'_, '_> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
         // Memory.
-        this.memory.alloc_map().iter(|it| {
+        self.memory.alloc_map().iter(|it| {
             for (_id, (_kind, alloc)) in it {
-                visit_alloc(acc, alloc);
+                alloc.visit_tags(visit);
             }
         });
 
         // And all the other machine values.
-        this.machine.visit_machine_values(&mut |op| visit_operand(acc, op));
+        self.machine.visit_tags(visit);
     }
+}
 
+impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
+pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
     fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         // No reason to do anything at all if stacked borrows is off.
@@ -37,59 +159,9 @@ fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> {
         }
 
         let mut tags = FxHashSet::default();
-
-        let visit_scalar = |tags: &mut FxHashSet<SbTag>, s: &Scalar<Provenance>| {
-            if let Scalar::Ptr(ptr, _) = s {
-                if let Provenance::Concrete { sb, .. } = ptr.provenance {
-                    tags.insert(sb);
-                }
-            }
-        };
-
-        this.visit_all_machine_values(
-            &mut tags,
-            |tags, op| {
-                match op {
-                    Operand::Immediate(Immediate::Scalar(s)) => {
-                        visit_scalar(tags, s);
-                    }
-                    Operand::Immediate(Immediate::ScalarPair(s1, s2)) => {
-                        visit_scalar(tags, s1);
-                        visit_scalar(tags, s2);
-                    }
-                    Operand::Immediate(Immediate::Uninit) => {}
-                    Operand::Indirect(MemPlace { ptr, .. }) => {
-                        if let Some(Provenance::Concrete { sb, .. }) = ptr.provenance {
-                            tags.insert(sb);
-                        }
-                    }
-                }
-            },
-            |tags, alloc| {
-                for (_size, prov) in alloc.provenance().iter() {
-                    if let Provenance::Concrete { sb, .. } = prov {
-                        tags.insert(*sb);
-                    }
-                }
-                let stacks = alloc
-                    .extra
-                    .stacked_borrows
-                    .as_ref()
-                    .expect("we should not even enter the GC if Stacked Borrows is disabled");
-                tags.extend(&stacks.borrow().exposed_tags);
-
-                if let Some(store_buffers) = alloc.extra.weak_memory.as_ref() {
-                    store_buffers.iter(|val| {
-                        if let Scalar::Ptr(ptr, _) = val {
-                            if let Provenance::Concrete { sb, .. } = ptr.provenance {
-                                tags.insert(sb);
-                            }
-                        }
-                    });
-                }
-            },
-        );
-
+        this.visit_tags(&mut |tag| {
+            tags.insert(tag);
+        });
         self.remove_unreachable_tags(tags);
 
         Ok(())