Skip to content

Commit

Permalink
Extend the BorTag GC to AllocIds
Browse files Browse the repository at this point in the history
  • Loading branch information
saethlin committed Oct 4, 2023
1 parent 448452d commit cdffee5
Show file tree
Hide file tree
Showing 20 changed files with 429 additions and 0 deletions.
11 changes: 11 additions & 0 deletions src/borrow_tracker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ impl VisitTags for FrameState {
fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) {
// `protected_tags` are already recorded by `GlobalStateInner`.
}

fn visit_prov(&self, _visit: &mut dyn FnMut(AllocId)) {}
}

/// Extra global state, available to the memory access hooks.
Expand Down Expand Up @@ -115,6 +117,8 @@ impl VisitTags for GlobalStateInner {
// The only other candidate is base_ptr_tags, and that does not need visiting since we don't ever
// GC the bottommost/root tag.
}

fn visit_prov(&self, _visit: &mut dyn FnMut(AllocId)) {}
}

/// We need interior mutable access to the global state.
Expand Down Expand Up @@ -459,4 +463,11 @@ impl VisitTags for AllocState {
AllocState::TreeBorrows(tb) => tb.visit_tags(visit),
}
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
match self {
AllocState::StackedBorrows(sb) => sb.visit_prov(visit),
AllocState::TreeBorrows(tb) => tb.visit_prov(visit),
}
}
}
4 changes: 4 additions & 0 deletions src/borrow_tracker/stacked_borrows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,10 @@ impl VisitTags for Stacks {
visit(tag);
}
}

fn visit_prov(&self, _visit: &mut dyn FnMut(AllocId)) {
/* No allocs */
}
}

/// Map per-stack operations to higher-level per-location-range operations.
Expand Down
4 changes: 4 additions & 0 deletions src/borrow_tracker/tree_borrows/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,10 @@ impl VisitTags for Tree {
// (the `root` node of `Tree` is not an `Option<_>`)
visit(self.nodes.get(self.root).unwrap().tag)
}

fn visit_prov(&self, _visit: &mut dyn FnMut(AllocId)) {
/* No allocs */
}
}

/// Relative position of the access
Expand Down
8 changes: 8 additions & 0 deletions src/concurrency/data_race.rs
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,10 @@ impl VisitTags for VClockAlloc {
fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) {
// No tags here.
}

fn visit_prov(&self, _visit: &mut dyn FnMut(AllocId)) {
// No allocs here.
}
}

impl VClockAlloc {
Expand Down Expand Up @@ -1278,6 +1282,10 @@ impl VisitTags for GlobalState {
fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) {
// We don't have any tags.
}

fn visit_prov(&self, _visit: &mut dyn FnMut(AllocId)) {
// No allocs here.
}
}

impl GlobalState {
Expand Down
6 changes: 6 additions & 0 deletions src/concurrency/init_once.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ impl<'mir, 'tcx> VisitTags for InitOnce<'mir, 'tcx> {
waiter.callback.visit_tags(visit);
}
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
for waiter in self.waiters.iter() {
waiter.callback.visit_prov(visit);
}
}
}

impl<'mir, 'tcx: 'mir> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
Expand Down
6 changes: 6 additions & 0 deletions src/concurrency/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ impl<'mir, 'tcx> VisitTags for SynchronizationState<'mir, 'tcx> {
init_once.visit_tags(visit);
}
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
for init_once in self.init_onces.iter() {
init_once.visit_prov(visit);
}
}
}

// Private extension trait for local helper methods
Expand Down
75 changes: 75 additions & 0 deletions src/concurrency/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,27 @@ impl VisitTags for Thread<'_, '_> {
frame.visit_tags(visit)
}
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
let Thread {
panic_payloads: panic_payload,
last_error,
stack,
top_user_relevant_frame: _,
state: _,
thread_name: _,
join_status: _,
on_stack_empty: _, // we assume the closure captures no GC-relevant state
} = self;

for payload in panic_payload {
payload.visit_prov(visit);
}
last_error.visit_prov(visit);
for frame in stack {
frame.visit_prov(visit)
}
}
}

impl VisitTags for Frame<'_, '_, Provenance, FrameExtra<'_>> {
Expand Down Expand Up @@ -274,6 +295,38 @@ impl VisitTags for Frame<'_, '_, Provenance, FrameExtra<'_>> {

extra.visit_tags(visit);
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
let Frame {
return_place,
locals,
extra,
body: _,
instance: _,
return_to_block: _,
loc: _,
// There are some private fields we cannot access; they contain no tags.
..
} = self;

// Return place.
return_place.visit_prov(visit);
// Locals.
for local in locals.iter() {
match local.as_mplace_or_imm() {
None => {}
Some(Either::Left((ptr, meta))) => {
ptr.visit_prov(visit);
meta.visit_prov(visit);
}
Some(Either::Right(imm)) => {
imm.visit_prov(visit);
}
}
}

extra.visit_prov(visit);
}
}

/// A specific moment in time.
Expand Down Expand Up @@ -354,6 +407,28 @@ impl VisitTags for ThreadManager<'_, '_> {
}
sync.visit_tags(visit);
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
let ThreadManager {
threads,
thread_local_alloc_ids,
timeout_callbacks,
active_thread: _,
yield_active_thread: _,
sync,
} = self;

for thread in threads {
thread.visit_prov(visit);
}
for ptr in thread_local_alloc_ids.borrow().values() {
ptr.visit_prov(visit);
}
for callback in timeout_callbacks.values() {
callback.callback.visit_prov(visit);
}
sync.visit_prov(visit);
}
}

impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> {
Expand Down
11 changes: 11 additions & 0 deletions src/concurrency/weak_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ impl VisitTags for StoreBufferAlloc {
val.visit_tags(visit);
}
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
let Self { store_buffers } = self;
for val in store_buffers
.borrow()
.iter()
.flat_map(|buf| buf.buffer.iter().map(|element| &element.val))
{
val.visit_prov(visit);
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
11 changes: 11 additions & 0 deletions src/intptrcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ impl VisitTags for GlobalStateInner {
fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) {
// Nothing to visit here.
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
for id in &self.exposed {
id.visit_prov(visit)
}
}
}

impl GlobalStateInner {
Expand All @@ -63,6 +69,11 @@ impl GlobalStateInner {
}

impl<'mir, 'tcx> GlobalStateInner {
pub fn remove_unreachable_allocs(&mut self, live_allocs: &FxHashSet<AllocId>) {
self.int_to_ptr_map.retain(|(_, id)| live_allocs.contains(id));
self.base_addr.retain(|id, _| live_allocs.contains(id));
}

// Returns the exposed `AllocId` that corresponds to the specified addr,
// or `None` if the addr is out of bounds
fn alloc_id_from_addr(ecx: &MiriInterpCx<'mir, 'tcx>, addr: u64) -> Option<AllocId> {
Expand Down
81 changes: 81 additions & 0 deletions src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ impl VisitTags for FrameExtra<'_> {
catch_unwind.visit_tags(visit);
borrow_tracker.visit_tags(visit);
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
let FrameExtra { catch_unwind, borrow_tracker, timing: _, is_user_relevant: _ } = self;

catch_unwind.visit_prov(visit);
borrow_tracker.visit_prov(visit);
}
}

/// Extra memory kinds
Expand Down Expand Up @@ -302,6 +309,14 @@ impl VisitTags for AllocExtra<'_> {
data_race.visit_tags(visit);
weak_memory.visit_tags(visit);
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
let AllocExtra { borrow_tracker, data_race, weak_memory, backtrace: _ } = self;

borrow_tracker.visit_prov(visit);
data_race.visit_prov(visit);
weak_memory.visit_prov(visit);
}
}

/// Precomputed layouts of primitive types
Expand Down Expand Up @@ -843,6 +858,72 @@ impl VisitTags for MiriMachine<'_, '_> {
ptr.visit_tags(visit);
}
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
#[rustfmt::skip]
let MiriMachine {
threads,
tls,
env_vars,
main_fn_ret_place,
argc,
argv,
cmd_line,
extern_statics,
dir_handler,
borrow_tracker,
data_race,
intptrcast,
file_handler,
tcx: _,
isolated_op: _,
validate: _,
enforce_abi: _,
clock: _,
layouts: _,
static_roots: _,
profiler: _,
string_cache: _,
exported_symbols_cache: _,
panic_on_unsupported: _,
backtrace_style: _,
local_crates: _,
rng: _,
tracked_alloc_ids: _,
check_alignment: _,
cmpxchg_weak_failure_rate: _,
mute_stdout_stderr: _,
weak_memory: _,
preemption_rate: _,
report_progress: _,
basic_block_count: _,
external_so_lib: _,
gc_interval: _,
since_gc: _,
num_cpus: _,
page_size: _,
stack_addr: _,
stack_size: _,
collect_leak_backtraces: _,
allocation_spans: _,
} = self;

threads.visit_prov(visit);
tls.visit_prov(visit);
env_vars.visit_prov(visit);
dir_handler.visit_prov(visit);
file_handler.visit_prov(visit);
data_race.visit_prov(visit);
borrow_tracker.visit_prov(visit);
intptrcast.visit_prov(visit);
main_fn_ret_place.visit_prov(visit);
argc.visit_prov(visit);
argv.visit_prov(visit);
cmd_line.visit_prov(visit);
for ptr in extern_statics.values() {
ptr.visit_prov(visit);
}
}
}

/// A rustc InterpCx for Miri.
Expand Down
9 changes: 9 additions & 0 deletions src/shims/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ impl VisitTags for EnvVars<'_> {
ptr.visit_tags(visit);
}
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
let EnvVars { map, environ } = self;

environ.visit_prov(visit);
for ptr in map.values() {
ptr.visit_prov(visit);
}
}
}

impl<'tcx> EnvVars<'tcx> {
Expand Down
7 changes: 7 additions & 0 deletions src/shims/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ impl VisitTags for CatchUnwindData<'_> {
data.visit_tags(visit);
dest.visit_tags(visit);
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
let CatchUnwindData { catch_fn, data, dest, ret: _ } = self;
catch_fn.visit_prov(visit);
data.visit_prov(visit);
dest.visit_prov(visit);
}
}

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
Expand Down
1 change: 1 addition & 0 deletions src/shims/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ struct UnblockCallback {

impl VisitTags for UnblockCallback {
fn visit_tags(&self, _visit: &mut dyn FnMut(BorTag)) {}
fn visit_prov(&self, _visit: &mut dyn FnMut(AllocId)) {}
}

impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for UnblockCallback {
Expand Down
11 changes: 11 additions & 0 deletions src/shims/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,17 @@ impl VisitTags for TlsData<'_> {
scalar.visit_tags(visit);
}
}

fn visit_prov(&self, visit: &mut dyn FnMut(AllocId)) {
let TlsData { keys, macos_thread_dtors, next_key: _ } = self;

for scalar in keys.values().flat_map(|v| v.data.values()) {
scalar.visit_prov(visit);
}
for (_, scalar) in macos_thread_dtors.values() {
scalar.visit_prov(visit);
}
}
}

#[derive(Debug, Default)]
Expand Down
Loading

0 comments on commit cdffee5

Please sign in to comment.