]> git.lizzy.rs Git - rust.git/blobdiff - src/tools/miri/src/tag_gc.rs
Merge commit '266e96785ab71834b917bf474f130a6d8fdecd4b' into sync_cg_clif-2022-10-23
[rust.git] / src / tools / miri / src / tag_gc.rs
index e2273f055dd9b86bbce74ec4835437e59faebbdc..5aa653632f395818dc69ca5b13e34436fec63dbf 100644 (file)
 
 use crate::*;
 
-pub trait VisitMachineValues {
-    fn visit_machine_values(&self, visit: &mut ProvenanceVisitor);
+pub trait VisitTags {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag));
 }
 
-pub trait MachineValue {
-    fn visit_provenance(&self, tags: &mut FxHashSet<SbTag>);
+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);
+        }
+    }
 }
 
-pub struct ProvenanceVisitor {
-    tags: FxHashSet<SbTag>,
+impl<T: VisitTags> VisitTags for std::cell::RefCell<T> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        self.borrow().visit_tags(visit)
+    }
 }
 
-impl ProvenanceVisitor {
-    pub fn visit<V>(&mut self, v: V)
-    where
-        V: MachineValue,
-    {
-        v.visit_provenance(&mut self.tags);
+impl VisitTags for SbTag {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        visit(*self)
     }
 }
 
-impl<T: MachineValue> MachineValue for &T {
-    fn visit_provenance(&self, tags: &mut FxHashSet<SbTag>) {
-        (**self).visit_provenance(tags);
+impl VisitTags for Provenance {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
+        if let Provenance::Concrete { sb, .. } = self {
+            visit(*sb);
+        }
     }
 }
 
-impl MachineValue for Operand<Provenance> {
-    fn visit_provenance(&self, tags: &mut FxHashSet<SbTag>) {
+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 {
-            Operand::Immediate(Immediate::Scalar(s)) => {
-                s.visit_provenance(tags);
-            }
-            Operand::Immediate(Immediate::ScalarPair(s1, s2)) => {
-                s1.visit_provenance(tags);
-                s2.visit_provenance(tags);
-            }
-            Operand::Immediate(Immediate::Uninit) => {}
-            Operand::Indirect(p) => {
-                p.visit_provenance(tags);
-            }
+            Scalar::Ptr(ptr, _) => ptr.visit_tags(visit),
+            Scalar::Int(_) => (),
         }
     }
 }
 
-impl MachineValue for Scalar<Provenance> {
-    fn visit_provenance(&self, tags: &mut FxHashSet<SbTag>) {
-        if let Scalar::Ptr(ptr, _) = self {
-            if let Provenance::Concrete { sb, .. } = ptr.provenance {
-                tags.insert(sb);
+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 MachineValue for MemPlace<Provenance> {
-    fn visit_provenance(&self, tags: &mut FxHashSet<SbTag>) {
-        if let Some(Provenance::Concrete { sb, .. }) = self.ptr.provenance {
-            tags.insert(sb);
+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 MachineValue for SbTag {
-    fn visit_provenance(&self, tags: &mut FxHashSet<SbTag>) {
-        tags.insert(*self);
+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 MachineValue for Pointer<Provenance> {
-    fn visit_provenance(&self, tags: &mut FxHashSet<SbTag>) {
-        let (prov, _offset) = self.into_parts();
-        if let Provenance::Concrete { sb, .. } = prov {
-            tags.insert(sb);
+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 MachineValue for Pointer<Option<Provenance>> {
-    fn visit_provenance(&self, tags: &mut FxHashSet<SbTag>) {
-        let (prov, _offset) = self.into_parts();
-        if let Some(Provenance::Concrete { sb, .. }) = prov {
-            tags.insert(sb);
+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 VisitMachineValues for Allocation<Provenance, AllocExtra> {
-    fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) {
+impl VisitTags for Allocation<Provenance, AllocExtra> {
+    fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
         for (_size, prov) in self.provenance().iter() {
-            if let Provenance::Concrete { sb, .. } = prov {
-                visit.visit(*sb);
-            }
+            prov.visit_tags(visit);
         }
 
-        self.extra.visit_machine_values(visit);
+        self.extra.visit_tags(visit);
     }
 }
 
-impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
-    /// GC helper to visit everything that can store provenance. The `ProvenanceVisitor` knows how
-    /// to extract provenance from the interpreter data types.
-    fn visit_all_machine_values(&self, acc: &mut ProvenanceVisitor) {
-        let this = self.eval_context_ref();
-
+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 {
-                alloc.visit_machine_values(acc);
+                alloc.visit_tags(visit);
             }
         });
 
         // And all the other machine values.
-        this.machine.visit_machine_values(acc);
+        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.
@@ -126,9 +158,11 @@ fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> {
             return Ok(());
         }
 
-        let mut visitor = ProvenanceVisitor { tags: FxHashSet::default() };
-        this.visit_all_machine_values(&mut visitor);
-        self.remove_unreachable_tags(visitor.tags);
+        let mut tags = FxHashSet::default();
+        this.visit_tags(&mut |tag| {
+            tags.insert(tag);
+        });
+        self.remove_unreachable_tags(tags);
 
         Ok(())
     }