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.
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(())
}