Set the current span (somewhat) lazily
This commit is contained in:
parent
f3f7e083dc
commit
5861d137b2
@ -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 {
|
||||
|
23
src/eval.rs
23
src/eval.rs
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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>(
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user