Set the current span (somewhat) lazily

This commit is contained in:
Ben Kimock 2022-04-15 23:04:07 -04:00
parent f3f7e083dc
commit 5861d137b2
5 changed files with 58 additions and 33 deletions

View File

@ -165,10 +165,10 @@ pub fn report_error<'tcx, 'mir>(
];
match history {
Some(TagHistory::Tagged {tag, created: (created_range, created_span), invalidated, protected }) => {
let msg = format!("{:?} was created due to a retag at offsets {}", tag, HexRange(*created_range));
let msg = format!("{:?} was created by a retag at offsets {}", tag, HexRange(*created_range));
helps.push((Some(created_span.clone()), msg));
if let Some((invalidated_range, invalidated_span)) = invalidated {
let msg = format!("{:?} was later invalidated due to a retag at offsets {}", tag, HexRange(*invalidated_range));
let msg = format!("{:?} was later invalidated at offsets {}", tag, HexRange(*invalidated_range));
helps.push((Some(invalidated_span.clone()), msg));
}
if let Some((protecting_tag, protecting_tag_span, protection_span)) = protected {

View File

@ -16,6 +16,7 @@ use rustc_target::spec::abi::Abi;
use rustc_session::config::EntryFnType;
use std::collections::HashSet;
use rustc_span::DUMMY_SP;
use crate::*;
@ -283,24 +284,6 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
Ok((ecx, ret_place))
}
// This is potentially a performance hazard.
// Factoring it into its own function lets us keep an eye on how much it shows up in a profile.
fn set_current_span<'mir, 'tcx: 'mir>(ecx: &mut MiriEvalContext<'mir, 'tcx>) {
let current_span = Machine::stack(&ecx)
.into_iter()
.rev()
.find(|frame| {
let info =
FrameInfo { instance: frame.instance, span: frame.current_span(), lint_root: None };
ecx.machine.is_local(&info)
})
.map(|frame| frame.current_span())
.unwrap_or(rustc_span::DUMMY_SP);
if let Some(sb) = ecx.machine.stacked_borrows.as_mut() {
sb.get_mut().current_span = current_span;
}
}
/// Evaluates the entry function specified by `entry_id`.
/// Returns `Some(return_code)` if program executed completed.
/// Returns `None` if an evaluation error occured.
@ -328,8 +311,8 @@ pub fn eval_entry<'tcx>(
let info = ecx.preprocess_diagnostics();
match ecx.schedule()? {
SchedulingAction::ExecuteStep => {
if ecx.machine.stacked_borrows.is_some() {
set_current_span(&mut ecx);
if let Some(sb) = ecx.machine.stacked_borrows.as_mut() {
sb.get_mut().current_span = DUMMY_SP;
}
assert!(ecx.step()?, "a terminated thread was scheduled for execution");
}

View File

@ -25,6 +25,7 @@ use rustc_middle::{
};
use rustc_span::def_id::{CrateNum, DefId};
use rustc_span::symbol::{sym, Symbol};
use rustc_span::DUMMY_SP;
use rustc_target::abi::Size;
use rustc_target::spec::abi::Abi;
@ -561,6 +562,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
alloc: Cow<'b, Allocation>,
kind: Option<MemoryKind<Self::MemoryKind>>,
) -> Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>> {
set_current_span(&ecx.machine);
if ecx.machine.tracked_alloc_ids.contains(&id) {
register_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id));
}
@ -589,6 +591,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
ecx: &MiriEvalContext<'mir, 'tcx>,
ptr: Pointer<AllocId>,
) -> Pointer<Tag> {
set_current_span(&ecx.machine);
let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr);
let sb_tag = if let Some(stacked_borrows) = &ecx.machine.stacked_borrows {
stacked_borrows.borrow_mut().base_tag(ptr.provenance)
@ -624,6 +627,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
(alloc_id, tag): (AllocId, Self::TagExtra),
range: AllocRange,
) -> InterpResult<'tcx> {
set_current_span(&machine);
if let Some(data_race) = &alloc_extra.data_race {
data_race.read(alloc_id, range, machine.data_race.as_ref().unwrap())?;
}
@ -632,7 +636,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
alloc_id,
tag,
range,
machine.stacked_borrows.as_ref().unwrap(),
machine.stacked_borrows.as_ref().unwrap(),
)
} else {
Ok(())
@ -647,6 +651,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
(alloc_id, tag): (AllocId, Self::TagExtra),
range: AllocRange,
) -> InterpResult<'tcx> {
set_current_span(&machine);
if let Some(data_race) = &mut alloc_extra.data_race {
data_race.write(alloc_id, range, machine.data_race.as_mut().unwrap())?;
}
@ -670,6 +675,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
(alloc_id, tag): (AllocId, Self::TagExtra),
range: AllocRange,
) -> InterpResult<'tcx> {
set_current_span(&machine);
if machine.tracked_alloc_ids.contains(&alloc_id) {
register_diagnostic(NonHaltingDiagnostic::FreedAlloc(alloc_id));
}
@ -694,7 +700,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
kind: mir::RetagKind,
place: &PlaceTy<'tcx, Tag>,
) -> InterpResult<'tcx> {
if ecx.machine.stacked_borrows.is_some() { ecx.retag(kind, place) } else { Ok(()) }
if ecx.machine.stacked_borrows.is_some() {
set_current_span(&ecx.machine);
ecx.retag(kind, place)
} else {
Ok(())
}
}
#[inline(always)]
@ -740,7 +751,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
#[inline(always)]
fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
if ecx.machine.stacked_borrows.is_some() { ecx.retag_return_place() } else { Ok(()) }
if ecx.machine.stacked_borrows.is_some() {
set_current_span(&ecx.machine);
ecx.retag_return_place()
} else {
Ok(())
}
}
#[inline(always)]
@ -757,3 +773,29 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
res
}
}
// This is potentially a performance hazard.
// Factoring it into its own function lets us keep an eye on how much it shows up in a profile.
fn set_current_span<'mir, 'tcx: 'mir>(machine: &Evaluator<'mir, 'tcx>) {
if let Some(sb) = machine.stacked_borrows.as_ref() {
if sb.borrow().current_span != DUMMY_SP {
return;
}
let current_span = machine
.threads
.active_thread_stack()
.into_iter()
.rev()
.find(|frame| {
let info = FrameInfo {
instance: frame.instance,
span: frame.current_span(),
lint_root: None,
};
machine.is_local(&info)
})
.map(|frame| frame.current_span())
.unwrap_or(rustc_span::DUMMY_SP);
sb.borrow_mut().current_span = current_span;
}
}

View File

@ -125,9 +125,9 @@ struct AllocHistory {
// The time tags can be compressed down to one bit per event, by just storing a Vec<u8>
// where each bit is set to indicate if the event was a creation or a retag
current_time: usize,
creations: Vec<Event>,
invalidations: Vec<Event>,
protectors: Vec<Protection>,
creations: smallvec::SmallVec<[Event; 2]>,
invalidations: smallvec::SmallVec<[Event; 1]>,
protectors: smallvec::SmallVec<[Protection; 1]>,
}
#[derive(Debug)]
@ -552,9 +552,9 @@ impl<'tcx> Stack {
// Two main steps: Find granting item, remove incompatible items above.
// Step 1: Find granting item.
let granting_idx = self.find_granting(access, tag).ok_or_else(|| {
self.access_error(access, tag, alloc_id, alloc_range, offset, global)
})?;
let granting_idx = self
.find_granting(access, tag)
.ok_or_else(|| self.access_error(access, tag, alloc_id, alloc_range, offset, global))?;
// Step 2: Remove incompatible items above them. Make sure we do not remove protected
// items. Behavior differs for reads and writes.
@ -852,7 +852,7 @@ impl Stacks {
let mut state = state.borrow_mut();
stack.access(AccessKind::Read, tag, (alloc_id, range, offset), &mut state)
})
}
}
#[inline(always)]
pub fn memory_written<'tcx>(

View File

@ -263,7 +263,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
}
/// Borrow the stack of the active thread.
fn active_thread_stack(&self) -> &[Frame<'mir, 'tcx, Tag, FrameData<'tcx>>] {
pub fn active_thread_stack(&self) -> &[Frame<'mir, 'tcx, Tag, FrameData<'tcx>>] {
&self.threads[self.active_thread].stack
}