]> git.lizzy.rs Git - rust.git/commitdiff
Factor current-span logic into a lazy caching handle
authorBen Kimock <kimockb@gmail.com>
Wed, 8 Dec 2021 03:05:13 +0000 (22:05 -0500)
committerBen Kimock <kimockb@gmail.com>
Sun, 22 May 2022 22:23:01 +0000 (18:23 -0400)
src/helpers.rs
src/lib.rs
src/machine.rs
src/stacked_borrows.rs
src/stacked_borrows/diagnostics.rs

index 6beb3f8c3bb0917d85ac10d558dcc93262cca503..2d1fffc6a125f3b845307a8414bb394e4e2ef6ff 100644 (file)
@@ -2,7 +2,6 @@
 
 use std::mem;
 use std::num::NonZeroUsize;
-use std::rc::Rc;
 use std::time::Duration;
 
 use log::trace;
@@ -14,7 +13,7 @@
     layout::{LayoutOf, TyAndLayout},
     List, TyCtxt,
 };
-use rustc_span::{def_id::CrateNum, sym, Symbol};
+use rustc_span::{def_id::CrateNum, sym, Span, Symbol};
 use rustc_target::abi::{Align, FieldsShape, Size, Variants};
 use rustc_target::spec::abi::Abi;
 
@@ -800,6 +799,43 @@ fn item_link_name(&self, def_id: DefId) -> Symbol {
     }
 }
 
+impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
+    pub fn current_span(&self) -> CurrentSpan<'_, 'mir, 'tcx> {
+        CurrentSpan { span: None, machine: self }
+    }
+}
+
+/// A `CurrentSpan` should be created infrequently (ideally once) per interpreter step. It does
+/// nothing on creation, but when `CurrentSpan::get` is called, searches the current stack for the
+/// topmost frame which corresponds to a local crate, and returns the current span in that frame.
+/// The result of that search is cached so that later calls are approximately free.
+#[derive(Clone)]
+pub struct CurrentSpan<'a, 'tcx, 'mir> {
+    span: Option<Span>,
+    machine: &'a Evaluator<'tcx, 'mir>,
+}
+
+impl<'a, 'tcx, 'mir> CurrentSpan<'a, 'tcx, 'mir> {
+    pub fn get(&mut self) -> Span {
+        *self.span.get_or_insert_with(|| Self::current_span(&self.machine))
+    }
+
+    #[inline(never)]
+    fn current_span(machine: &Evaluator<'_, '_>) -> Span {
+        machine
+            .threads
+            .active_thread_stack()
+            .into_iter()
+            .rev()
+            .find(|frame| {
+                let def_id = frame.instance.def_id();
+                def_id.is_local() || machine.local_crates.contains(&def_id.krate)
+            })
+            .map(|frame| frame.current_span())
+            .unwrap_or(rustc_span::DUMMY_SP)
+    }
+}
+
 /// Check that the number of args is what we expect.
 pub fn check_arg_count<'a, 'tcx, const N: usize>(
     args: &'a [OpTy<'tcx, Tag>],
@@ -822,7 +858,7 @@ pub fn isolation_abort_error(name: &str) -> InterpResult<'static> {
 
 /// Retrieve the list of local crates that should have been passed by cargo-miri in
 /// MIRI_LOCAL_CRATES and turn them into `CrateNum`s.
-pub fn get_local_crates(tcx: &TyCtxt<'_>) -> Rc<[CrateNum]> {
+pub fn get_local_crates(tcx: &TyCtxt<'_>) -> Vec<CrateNum> {
     // Convert the local crate names from the passed-in config into CrateNums so that they can
     // be looked up quickly during execution
     let local_crate_names = std::env::var("MIRI_LOCAL_CRATES")
@@ -836,7 +872,7 @@ pub fn get_local_crates(tcx: &TyCtxt<'_>) -> Rc<[CrateNum]> {
             local_crates.push(crate_num);
         }
     }
-    Rc::from(local_crates.as_slice())
+    local_crates
 }
 
 /// Formats an AllocRange like [0x1..0x3], for use in diagnostics.
index ee7a3bcdc5cbfd33db995f52a1523f3adaf1fde3..9fa2c61fd831a0b081948343758a5431d8ce6393 100644 (file)
@@ -77,7 +77,7 @@
 pub use crate::eval::{
     create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
 };
-pub use crate::helpers::EvalContextExt as HelpersEvalContextExt;
+pub use crate::helpers::{CurrentSpan, EvalContextExt as HelpersEvalContextExt};
 pub use crate::machine::{
     AllocExtra, Evaluator, FrameData, MiriEvalContext, MiriEvalContextExt, MiriMemoryKind, Tag,
     NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
index 9e95c632c7f4170e49bd7ca2583a06a4804e1981..d78b0135e94fbe3f1d752f3a6e2b7b01755e00be 100644 (file)
@@ -6,7 +6,6 @@
 use std::collections::HashSet;
 use std::fmt;
 use std::num::NonZeroU64;
-use std::rc::Rc;
 use std::time::Instant;
 
 use rand::rngs::StdRng;
@@ -278,7 +277,7 @@ pub struct Evaluator<'mir, 'tcx> {
     pub(crate) backtrace_style: BacktraceStyle,
 
     /// Crates which are considered local for the purposes of error reporting.
-    pub(crate) local_crates: Rc<[CrateNum]>,
+    pub(crate) local_crates: Vec<CrateNum>,
 
     /// Mapping extern static names to their base pointer.
     extern_statics: FxHashMap<Symbol, Pointer<Tag>>,
@@ -584,8 +583,7 @@ fn init_allocation_extra<'b>(
                 alloc.size(),
                 stacked_borrows,
                 kind,
-                &ecx.machine.threads,
-                ecx.machine.local_crates.clone(),
+                ecx.machine.current_span(),
             ))
         } else {
             None
@@ -667,7 +665,7 @@ fn memory_read(
                 tag,
                 range,
                 machine.stacked_borrows.as_ref().unwrap(),
-                &machine.threads,
+                machine.current_span(),
             )
         } else {
             Ok(())
@@ -691,7 +689,7 @@ fn memory_written(
                 tag,
                 range,
                 machine.stacked_borrows.as_ref().unwrap(),
-                &machine.threads,
+                machine.current_span(),
             )
         } else {
             Ok(())
index d7c2139323245b85c87c5e4be650a86ebc924e6b..625ffb2c5d202526020efedfe9142810cfa3d496 100644 (file)
@@ -5,7 +5,6 @@
 use std::cell::RefCell;
 use std::fmt;
 use std::num::NonZeroU64;
-use std::rc::Rc;
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::Mutability;
@@ -14,7 +13,6 @@
     self,
     layout::{HasParamEnv, LayoutOf},
 };
-use rustc_span::def_id::CrateNum;
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::Size;
 use std::collections::HashSet;
@@ -22,9 +20,7 @@
 use crate::*;
 
 pub mod diagnostics;
-use diagnostics::AllocHistory;
-
-use diagnostics::TagHistory;
+use diagnostics::{AllocHistory, TagHistory};
 
 pub type PtrId = NonZeroU64;
 pub type CallId = NonZeroU64;
@@ -376,7 +372,7 @@ fn access(
         tag: SbTag,
         (alloc_id, alloc_range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages
         global: &mut GlobalStateInner,
-        threads: &ThreadManager<'_, 'tcx>,
+        current_span: &mut CurrentSpan<'_, '_, 'tcx>,
         alloc_history: &mut AllocHistory,
     ) -> InterpResult<'tcx> {
         // Two main steps: Find granting item, remove incompatible items above.
@@ -400,7 +396,7 @@ fn access(
                     global,
                     alloc_history,
                 )?;
-                alloc_history.log_invalidation(item.tag, alloc_range, threads);
+                alloc_history.log_invalidation(item.tag, alloc_range, current_span);
             }
         } else {
             // On a read, *disable* all `Unique` above the granting item.  This ensures U2 for read accesses.
@@ -422,7 +418,7 @@ fn access(
                         alloc_history,
                     )?;
                     item.perm = Permission::Disabled;
-                    alloc_history.log_invalidation(item.tag, alloc_range, threads);
+                    alloc_history.log_invalidation(item.tag, alloc_range, current_span);
                 }
             }
         }
@@ -471,7 +467,7 @@ fn grant(
         new: Item,
         (alloc_id, alloc_range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages
         global: &mut GlobalStateInner,
-        threads: &ThreadManager<'_, 'tcx>,
+        current_span: &mut CurrentSpan<'_, '_, 'tcx>,
         alloc_history: &mut AllocHistory,
     ) -> InterpResult<'tcx> {
         // Figure out which access `perm` corresponds to.
@@ -505,7 +501,7 @@ fn grant(
                 derived_from,
                 (alloc_id, alloc_range, offset),
                 global,
-                threads,
+                current_span,
                 alloc_history,
             )?;
 
@@ -533,13 +529,13 @@ fn grant(
 /// Map per-stack operations to higher-level per-location-range operations.
 impl<'tcx> Stacks {
     /// Creates new stack with initial tag.
-    fn new(size: Size, perm: Permission, tag: SbTag, local_crates: Rc<[CrateNum]>) -> Self {
+    fn new(size: Size, perm: Permission, tag: SbTag) -> Self {
         let item = Item { perm, tag, protector: None };
         let stack = Stack { borrows: vec![item] };
 
         Stacks {
             stacks: RefCell::new(RangeMap::new(size, stack)),
-            history: RefCell::new(AllocHistory::new(local_crates)),
+            history: RefCell::new(AllocHistory::new()),
         }
     }
 
@@ -579,8 +575,7 @@ pub fn new_allocation(
         size: Size,
         state: &GlobalState,
         kind: MemoryKind<MiriMemoryKind>,
-        threads: &ThreadManager<'_, '_>,
-        local_crates: Rc<[CrateNum]>,
+        mut current_span: CurrentSpan<'_, '_, '_>,
     ) -> Self {
         let mut extra = state.borrow_mut();
         let (base_tag, perm) = match kind {
@@ -614,12 +609,12 @@ pub fn new_allocation(
                 (tag, Permission::SharedReadWrite)
             }
         };
-        let stacks = Stacks::new(size, perm, base_tag, local_crates);
+        let stacks = Stacks::new(size, perm, base_tag);
         stacks.history.borrow_mut().log_creation(
             None,
             base_tag,
             alloc_range(Size::ZERO, size),
-            threads,
+            &mut current_span,
         );
         stacks
     }
@@ -631,7 +626,7 @@ pub fn memory_read<'tcx>(
         tag: SbTag,
         range: AllocRange,
         state: &GlobalState,
-        threads: &ThreadManager<'_, 'tcx>,
+        mut current_span: CurrentSpan<'_, '_, 'tcx>,
     ) -> InterpResult<'tcx> {
         trace!(
             "read access with tag {:?}: {:?}, size {}",
@@ -646,7 +641,7 @@ pub fn memory_read<'tcx>(
                 tag,
                 (alloc_id, range, offset),
                 &mut state,
-                threads,
+                &mut current_span,
                 history,
             )
         })
@@ -659,7 +654,7 @@ pub fn memory_written<'tcx>(
         tag: SbTag,
         range: AllocRange,
         state: &GlobalState,
-        threads: &ThreadManager<'_, 'tcx>,
+        mut current_span: CurrentSpan<'_, '_, 'tcx>,
     ) -> InterpResult<'tcx> {
         trace!(
             "write access with tag {:?}: {:?}, size {}",
@@ -674,7 +669,7 @@ pub fn memory_written<'tcx>(
                 tag,
                 (alloc_id, range, offset),
                 &mut state,
-                threads,
+                &mut current_span,
                 history,
             )
         })
@@ -723,6 +718,7 @@ fn reborrow(
         }
         let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr)?;
 
+        let mut current_span = this.machine.current_span();
         {
             let extra = this.get_alloc_extra(alloc_id)?;
             let stacked_borrows =
@@ -732,10 +728,10 @@ fn reborrow(
                 Some(orig_tag),
                 new_tag,
                 alloc_range(base_offset, size),
-                &this.machine.threads,
+                &mut current_span,
             );
             if protect {
-                alloc_history.log_protector(orig_tag, new_tag, &this.machine.threads);
+                alloc_history.log_protector(orig_tag, new_tag, &mut current_span);
             }
         }
 
@@ -804,7 +800,7 @@ fn reborrow(
                             item,
                             (alloc_id, range, offset),
                             &mut *global,
-                            &this.machine.threads,
+                            &mut current_span,
                             history,
                         )
                     })
@@ -821,13 +817,14 @@ fn reborrow(
         let item = Item { perm, tag: new_tag, protector };
         let range = alloc_range(base_offset, size);
         let mut global = machine.stacked_borrows.as_ref().unwrap().borrow_mut();
+        let mut current_span = machine.current_span();
         stacked_borrows.for_each_mut(range, |offset, stack, history| {
             stack.grant(
                 orig_tag,
                 item,
                 (alloc_id, range, offset),
                 &mut global,
-                &machine.threads,
+                &mut current_span,
                 history,
             )
         })?;
index 734c3a14e3b3b69e9931b351e427ea0b395e5ac2..f3692cdeeb043c02b09e399f590f13126531b922 100644 (file)
@@ -1,17 +1,14 @@
 use smallvec::SmallVec;
-use std::rc::Rc;
 
 use rustc_middle::mir::interpret::{AllocId, AllocRange};
-use rustc_span::def_id::CrateNum;
 use rustc_span::{Span, SpanData};
 use rustc_target::abi::Size;
 
-use crate::helpers::HexRange;
+use crate::helpers::{CurrentSpan, HexRange};
 use crate::stacked_borrows::{err_sb_ub, AccessKind, Permission};
 use crate::Item;
 use crate::SbTag;
 use crate::Stack;
-use crate::ThreadManager;
 
 use rustc_middle::mir::interpret::InterpError;
 
@@ -23,8 +20,6 @@ pub struct AllocHistory {
     creations: smallvec::SmallVec<[Event; 2]>,
     invalidations: smallvec::SmallVec<[Event; 1]>,
     protectors: smallvec::SmallVec<[Protection; 1]>,
-    /// This field is a clone of the `local_crates` field on `Evaluator`.
-    local_crates: Rc<[CrateNum]>,
 }
 
 #[derive(Clone, Debug)]
@@ -59,37 +54,23 @@ pub enum TagHistory {
 }
 
 impl AllocHistory {
-    pub fn new(local_crates: Rc<[CrateNum]>) -> Self {
+    pub fn new() -> Self {
         Self {
             current_time: 0,
             creations: SmallVec::new(),
             invalidations: SmallVec::new(),
             protectors: SmallVec::new(),
-            local_crates,
         }
     }
 
-    fn current_span(&self, threads: &ThreadManager<'_, '_>) -> Span {
-        threads
-            .active_thread_stack()
-            .into_iter()
-            .rev()
-            .find(|frame| {
-                let def_id = frame.instance.def_id();
-                def_id.is_local() || self.local_crates.contains(&def_id.krate)
-            })
-            .map(|frame| frame.current_span())
-            .unwrap_or(rustc_span::DUMMY_SP)
-    }
-
     pub fn log_creation(
         &mut self,
         parent: Option<SbTag>,
         tag: SbTag,
         range: AllocRange,
-        threads: &ThreadManager<'_, '_>,
+        current_span: &mut CurrentSpan<'_, '_, '_>,
     ) {
-        let span = self.current_span(threads);
+        let span = current_span.get();
         self.creations.push(Event { parent, tag, range, span, time: self.current_time });
         self.current_time += 1;
     }
@@ -98,15 +79,20 @@ pub fn log_invalidation(
         &mut self,
         tag: SbTag,
         range: AllocRange,
-        threads: &ThreadManager<'_, '_>,
+        current_span: &mut CurrentSpan<'_, '_, '_>,
     ) {
-        let span = self.current_span(threads);
+        let span = current_span.get();
         self.invalidations.push(Event { parent: None, tag, range, span, time: self.current_time });
         self.current_time += 1;
     }
 
-    pub fn log_protector(&mut self, orig_tag: SbTag, tag: SbTag, threads: &ThreadManager<'_, '_>) {
-        let span = self.current_span(threads);
+    pub fn log_protector(
+        &mut self,
+        orig_tag: SbTag,
+        tag: SbTag,
+        current_span: &mut CurrentSpan<'_, '_, '_>,
+    ) {
+        let span = current_span.get();
         self.protectors.push(Protection { orig_tag, tag, span });
         self.current_time += 1;
     }