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 {
|
match history {
|
||||||
Some(TagHistory::Tagged {tag, created: (created_range, created_span), invalidated, protected }) => {
|
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));
|
helps.push((Some(created_span.clone()), msg));
|
||||||
if let Some((invalidated_range, invalidated_span)) = invalidated {
|
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));
|
helps.push((Some(invalidated_span.clone()), msg));
|
||||||
}
|
}
|
||||||
if let Some((protecting_tag, protecting_tag_span, protection_span)) = protected {
|
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 rustc_session::config::EntryFnType;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
use rustc_span::DUMMY_SP;
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
@ -283,24 +284,6 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
|
|||||||
Ok((ecx, ret_place))
|
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`.
|
/// Evaluates the entry function specified by `entry_id`.
|
||||||
/// Returns `Some(return_code)` if program executed completed.
|
/// Returns `Some(return_code)` if program executed completed.
|
||||||
/// Returns `None` if an evaluation error occured.
|
/// Returns `None` if an evaluation error occured.
|
||||||
@ -328,8 +311,8 @@ pub fn eval_entry<'tcx>(
|
|||||||
let info = ecx.preprocess_diagnostics();
|
let info = ecx.preprocess_diagnostics();
|
||||||
match ecx.schedule()? {
|
match ecx.schedule()? {
|
||||||
SchedulingAction::ExecuteStep => {
|
SchedulingAction::ExecuteStep => {
|
||||||
if ecx.machine.stacked_borrows.is_some() {
|
if let Some(sb) = ecx.machine.stacked_borrows.as_mut() {
|
||||||
set_current_span(&mut ecx);
|
sb.get_mut().current_span = DUMMY_SP;
|
||||||
}
|
}
|
||||||
assert!(ecx.step()?, "a terminated thread was scheduled for execution");
|
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::def_id::{CrateNum, DefId};
|
||||||
use rustc_span::symbol::{sym, Symbol};
|
use rustc_span::symbol::{sym, Symbol};
|
||||||
|
use rustc_span::DUMMY_SP;
|
||||||
use rustc_target::abi::Size;
|
use rustc_target::abi::Size;
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
@ -561,6 +562,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
|
|||||||
alloc: Cow<'b, Allocation>,
|
alloc: Cow<'b, Allocation>,
|
||||||
kind: Option<MemoryKind<Self::MemoryKind>>,
|
kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||||
) -> Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>> {
|
) -> Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>> {
|
||||||
|
set_current_span(&ecx.machine);
|
||||||
if ecx.machine.tracked_alloc_ids.contains(&id) {
|
if ecx.machine.tracked_alloc_ids.contains(&id) {
|
||||||
register_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id));
|
register_diagnostic(NonHaltingDiagnostic::CreatedAlloc(id));
|
||||||
}
|
}
|
||||||
@ -589,6 +591,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
|
|||||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||||
ptr: Pointer<AllocId>,
|
ptr: Pointer<AllocId>,
|
||||||
) -> Pointer<Tag> {
|
) -> Pointer<Tag> {
|
||||||
|
set_current_span(&ecx.machine);
|
||||||
let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr);
|
let absolute_addr = intptrcast::GlobalStateInner::rel_ptr_to_addr(ecx, ptr);
|
||||||
let sb_tag = if let Some(stacked_borrows) = &ecx.machine.stacked_borrows {
|
let sb_tag = if let Some(stacked_borrows) = &ecx.machine.stacked_borrows {
|
||||||
stacked_borrows.borrow_mut().base_tag(ptr.provenance)
|
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),
|
(alloc_id, tag): (AllocId, Self::TagExtra),
|
||||||
range: AllocRange,
|
range: AllocRange,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
|
set_current_span(&machine);
|
||||||
if let Some(data_race) = &alloc_extra.data_race {
|
if let Some(data_race) = &alloc_extra.data_race {
|
||||||
data_race.read(alloc_id, range, machine.data_race.as_ref().unwrap())?;
|
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,
|
alloc_id,
|
||||||
tag,
|
tag,
|
||||||
range,
|
range,
|
||||||
machine.stacked_borrows.as_ref().unwrap(),
|
machine.stacked_borrows.as_ref().unwrap(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -647,6 +651,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
|
|||||||
(alloc_id, tag): (AllocId, Self::TagExtra),
|
(alloc_id, tag): (AllocId, Self::TagExtra),
|
||||||
range: AllocRange,
|
range: AllocRange,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
|
set_current_span(&machine);
|
||||||
if let Some(data_race) = &mut alloc_extra.data_race {
|
if let Some(data_race) = &mut alloc_extra.data_race {
|
||||||
data_race.write(alloc_id, range, machine.data_race.as_mut().unwrap())?;
|
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),
|
(alloc_id, tag): (AllocId, Self::TagExtra),
|
||||||
range: AllocRange,
|
range: AllocRange,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
|
set_current_span(&machine);
|
||||||
if machine.tracked_alloc_ids.contains(&alloc_id) {
|
if machine.tracked_alloc_ids.contains(&alloc_id) {
|
||||||
register_diagnostic(NonHaltingDiagnostic::FreedAlloc(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,
|
kind: mir::RetagKind,
|
||||||
place: &PlaceTy<'tcx, Tag>,
|
place: &PlaceTy<'tcx, Tag>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> 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)]
|
#[inline(always)]
|
||||||
@ -740,7 +751,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
|
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)]
|
#[inline(always)]
|
||||||
@ -757,3 +773,29 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
|
|||||||
res
|
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>
|
// 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
|
// where each bit is set to indicate if the event was a creation or a retag
|
||||||
current_time: usize,
|
current_time: usize,
|
||||||
creations: Vec<Event>,
|
creations: smallvec::SmallVec<[Event; 2]>,
|
||||||
invalidations: Vec<Event>,
|
invalidations: smallvec::SmallVec<[Event; 1]>,
|
||||||
protectors: Vec<Protection>,
|
protectors: smallvec::SmallVec<[Protection; 1]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -552,9 +552,9 @@ impl<'tcx> Stack {
|
|||||||
// Two main steps: Find granting item, remove incompatible items above.
|
// Two main steps: Find granting item, remove incompatible items above.
|
||||||
|
|
||||||
// Step 1: Find granting item.
|
// Step 1: Find granting item.
|
||||||
let granting_idx = self.find_granting(access, tag).ok_or_else(|| {
|
let granting_idx = self
|
||||||
self.access_error(access, tag, alloc_id, alloc_range, offset, global)
|
.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
|
// Step 2: Remove incompatible items above them. Make sure we do not remove protected
|
||||||
// items. Behavior differs for reads and writes.
|
// items. Behavior differs for reads and writes.
|
||||||
@ -852,7 +852,7 @@ impl Stacks {
|
|||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
stack.access(AccessKind::Read, tag, (alloc_id, range, offset), &mut state)
|
stack.access(AccessKind::Read, tag, (alloc_id, range, offset), &mut state)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn memory_written<'tcx>(
|
pub fn memory_written<'tcx>(
|
||||||
|
@ -263,7 +263,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow the stack of the active thread.
|
/// 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
|
&self.threads[self.active_thread].stack
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user