Skip to content

Commit

Permalink
Add a shim that lets us manually run the GC
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed Oct 13, 2023
1 parent 8c610f8 commit 8203131
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
// where it mistakenly removes an important tag become visible.
if ecx.machine.gc_interval > 0 && ecx.machine.since_gc >= ecx.machine.gc_interval {
ecx.machine.since_gc = 0;
ecx.garbage_collect_tags()?;
ecx.run_provenance_gc();
}

// These are our preemption points.
Expand Down
8 changes: 1 addition & 7 deletions src/provenance_gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,8 @@ impl VisitTags for crate::MiriInterpCx<'_, '_> {

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> {
fn run_provenance_gc(&mut self) {
let this = self.eval_context_mut();
// No reason to do anything at all if stacked borrows is off.
if this.machine.borrow_tracker.is_none() {
return Ok(());
}

let mut tags = FxHashSet::default();
let mut alloc_ids = FxHashSet::default();
Expand All @@ -168,8 +164,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
});
self.remove_unreachable_tags(tags);
self.remove_unreachable_allocs(alloc_ids);

Ok(())
}

fn remove_unreachable_tags(&mut self, tags: FxHashSet<BorTag>) {
Expand Down
4 changes: 4 additions & 0 deletions src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,10 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
// shim, add it to the corresponding submodule.
match link_name.as_str() {
// Miri-specific extern functions
"miri_run_provenance_gc" => {
let [] = this.check_shim(abi, Abi::Rust, link_name, args)?;
this.run_provenance_gc();
}
"miri_get_alloc_id" => {
let [ptr] = this.check_shim(abi, Abi::Rust, link_name, args)?;
let ptr = this.read_pointer(ptr)?;
Expand Down
30 changes: 14 additions & 16 deletions tests/pass/ptr_int_casts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
use std::mem;
use std::ptr;

extern "Rust" {
fn miri_run_provenance_gc();
}

fn eq_ref<T>(x: &T, y: &T) -> bool {
x as *const _ == y as *const _
}
Expand Down Expand Up @@ -47,25 +51,19 @@ fn ptr_int_casts() {
// involving types other than usize
assert_eq!((-1i32) as usize as *const i32 as usize, (-1i32) as usize);

// Stress-test that the GC doesn't delete context that would prevent us from casting from int
// Check that the GC doesn't delete context that would prevent us from casting from int
// to pointer correctly after the allocation is dead.
let mut ptrs: Vec<*const u8> = Vec::new();
let mut ints: Vec<usize> = Vec::new();

for _ in 0..100 {
let (ptr, int) = {
let local = 0u8;
let ptr = &local as *const u8;
ptrs.push(ptr);
ints.push(ptr as usize);

let b = Box::new(0u8);
let ptr = &*b as *const u8;
ptrs.push(ptr);
ints.push(ptr as usize);
}

let later_ints: Vec<usize> = ptrs.iter().map(|p| *p as usize).collect();
assert_eq!(ints, later_ints);
(ptr, ptr as usize)
};
// Manually run the GC, instead of just hoping that it runs at the right time.
unsafe { miri_run_provenance_gc() }
let later_int = ptr as usize;
assert_eq!(int, later_int);
let later_ptr = int as *const u8;
assert_eq!(ptr, later_ptr);
}

fn ptr_int_ops() {
Expand Down

0 comments on commit 8203131

Please sign in to comment.