diff --git a/src/diagnostics.rs b/src/diagnostics.rs index c6b6c3388cab..bba1989e2d58 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -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 { diff --git a/src/eval.rs b/src/eval.rs index 8b964ba90f04..80738d33e0b9 100644 --- a/src/eval.rs +++ b/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"); } diff --git a/src/machine.rs b/src/machine.rs index 5f25fd298865..de9aaa2859d8 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -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>, ) -> Cow<'b, Allocation> { + 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, ) -> Pointer { + 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; + } +} diff --git a/src/stacked_borrows.rs b/src/stacked_borrows.rs index 225407a7bbfa..fcb702ea6ba8 100644 --- a/src/stacked_borrows.rs +++ b/src/stacked_borrows.rs @@ -125,9 +125,9 @@ struct AllocHistory { // The time tags can be compressed down to one bit per event, by just storing a Vec // where each bit is set to indicate if the event was a creation or a retag current_time: usize, - creations: Vec, - invalidations: Vec, - protectors: Vec, + 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>( diff --git a/src/thread.rs b/src/thread.rs index 8edd6672a747..5673af048fc5 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -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 }