Skip to content

Commit d60aa47

Browse files
committed
Auto merge of #2139 - saethlin:lazy-current-span, r=RalfJung
Factor current-span logic into a caching handle After #2030 and while working on #1935 it became quite clear that we need to do some caching here, because some retag operations generate many calls to `log_invalidation`, and would thus search the current thread's stack _many_ times for a local crate. This caching fixes that. This handle type also has the nice benefit of tucking away all the `ThreadManager` + `CrateNum` logic.
2 parents 62ea0c8 + b20c6cf commit d60aa47

File tree

5 files changed

+79
-62
lines changed

5 files changed

+79
-62
lines changed

src/helpers.rs

+40-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ pub mod convert;
22

33
use std::mem;
44
use std::num::NonZeroUsize;
5-
use std::rc::Rc;
65
use std::time::Duration;
76

87
use log::trace;
@@ -14,7 +13,7 @@ use rustc_middle::ty::{
1413
layout::{LayoutOf, TyAndLayout},
1514
List, TyCtxt,
1615
};
17-
use rustc_span::{def_id::CrateNum, sym, Symbol};
16+
use rustc_span::{def_id::CrateNum, sym, Span, Symbol};
1817
use rustc_target::abi::{Align, FieldsShape, Size, Variants};
1918
use rustc_target::spec::abi::Abi;
2019

@@ -800,6 +799,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
800799
}
801800
}
802801

802+
impl<'mir, 'tcx> Evaluator<'mir, 'tcx> {
803+
pub fn current_span(&self) -> CurrentSpan<'_, 'mir, 'tcx> {
804+
CurrentSpan { span: None, machine: self }
805+
}
806+
}
807+
808+
/// A `CurrentSpan` should be created infrequently (ideally once) per interpreter step. It does
809+
/// nothing on creation, but when `CurrentSpan::get` is called, searches the current stack for the
810+
/// topmost frame which corresponds to a local crate, and returns the current span in that frame.
811+
/// The result of that search is cached so that later calls are approximately free.
812+
#[derive(Clone)]
813+
pub struct CurrentSpan<'a, 'tcx, 'mir> {
814+
span: Option<Span>,
815+
machine: &'a Evaluator<'tcx, 'mir>,
816+
}
817+
818+
impl<'a, 'tcx, 'mir> CurrentSpan<'a, 'tcx, 'mir> {
819+
pub fn get(&mut self) -> Span {
820+
*self.span.get_or_insert_with(|| Self::current_span(&self.machine))
821+
}
822+
823+
#[inline(never)]
824+
fn current_span(machine: &Evaluator<'_, '_>) -> Span {
825+
machine
826+
.threads
827+
.active_thread_stack()
828+
.into_iter()
829+
.rev()
830+
.find(|frame| {
831+
let def_id = frame.instance.def_id();
832+
def_id.is_local() || machine.local_crates.contains(&def_id.krate)
833+
})
834+
.map(|frame| frame.current_span())
835+
.unwrap_or(rustc_span::DUMMY_SP)
836+
}
837+
}
838+
803839
/// Check that the number of args is what we expect.
804840
pub fn check_arg_count<'a, 'tcx, const N: usize>(
805841
args: &'a [OpTy<'tcx, Tag>],
@@ -822,7 +858,7 @@ pub fn isolation_abort_error(name: &str) -> InterpResult<'static> {
822858

823859
/// Retrieve the list of local crates that should have been passed by cargo-miri in
824860
/// MIRI_LOCAL_CRATES and turn them into `CrateNum`s.
825-
pub fn get_local_crates(tcx: &TyCtxt<'_>) -> Rc<[CrateNum]> {
861+
pub fn get_local_crates(tcx: &TyCtxt<'_>) -> Vec<CrateNum> {
826862
// Convert the local crate names from the passed-in config into CrateNums so that they can
827863
// be looked up quickly during execution
828864
let local_crate_names = std::env::var("MIRI_LOCAL_CRATES")
@@ -836,7 +872,7 @@ pub fn get_local_crates(tcx: &TyCtxt<'_>) -> Rc<[CrateNum]> {
836872
local_crates.push(crate_num);
837873
}
838874
}
839-
Rc::from(local_crates.as_slice())
875+
local_crates
840876
}
841877

842878
/// Formats an AllocRange like [0x1..0x3], for use in diagnostics.

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub use crate::diagnostics::{
7777
pub use crate::eval::{
7878
create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
7979
};
80-
pub use crate::helpers::EvalContextExt as HelpersEvalContextExt;
80+
pub use crate::helpers::{CurrentSpan, EvalContextExt as HelpersEvalContextExt};
8181
pub use crate::machine::{
8282
AllocExtra, Evaluator, FrameData, MiriEvalContext, MiriEvalContextExt, MiriMemoryKind, Tag,
8383
NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,

src/machine.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use std::cell::RefCell;
66
use std::collections::HashSet;
77
use std::fmt;
88
use std::num::NonZeroU64;
9-
use std::rc::Rc;
109
use std::time::Instant;
1110

1211
use rand::rngs::StdRng;
@@ -278,7 +277,7 @@ pub struct Evaluator<'mir, 'tcx> {
278277
pub(crate) backtrace_style: BacktraceStyle,
279278

280279
/// Crates which are considered local for the purposes of error reporting.
281-
pub(crate) local_crates: Rc<[CrateNum]>,
280+
pub(crate) local_crates: Vec<CrateNum>,
282281

283282
/// Mapping extern static names to their base pointer.
284283
extern_statics: FxHashMap<Symbol, Pointer<Tag>>,
@@ -584,8 +583,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
584583
alloc.size(),
585584
stacked_borrows,
586585
kind,
587-
&ecx.machine.threads,
588-
ecx.machine.local_crates.clone(),
586+
ecx.machine.current_span(),
589587
))
590588
} else {
591589
None
@@ -667,7 +665,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
667665
tag,
668666
range,
669667
machine.stacked_borrows.as_ref().unwrap(),
670-
&machine.threads,
668+
machine.current_span(),
671669
)
672670
} else {
673671
Ok(())
@@ -691,7 +689,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
691689
tag,
692690
range,
693691
machine.stacked_borrows.as_ref().unwrap(),
694-
&machine.threads,
692+
machine.current_span(),
695693
)
696694
} else {
697695
Ok(())

src/stacked_borrows.rs

+21-24
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use log::trace;
55
use std::cell::RefCell;
66
use std::fmt;
77
use std::num::NonZeroU64;
8-
use std::rc::Rc;
98

109
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1110
use rustc_hir::Mutability;
@@ -14,17 +13,14 @@ use rustc_middle::ty::{
1413
self,
1514
layout::{HasParamEnv, LayoutOf},
1615
};
17-
use rustc_span::def_id::CrateNum;
1816
use rustc_span::DUMMY_SP;
1917
use rustc_target::abi::Size;
2018
use std::collections::HashSet;
2119

2220
use crate::*;
2321

2422
pub mod diagnostics;
25-
use diagnostics::AllocHistory;
26-
27-
use diagnostics::TagHistory;
23+
use diagnostics::{AllocHistory, TagHistory};
2824

2925
pub type PtrId = NonZeroU64;
3026
pub type CallId = NonZeroU64;
@@ -376,7 +372,7 @@ impl<'tcx> Stack {
376372
tag: SbTag,
377373
(alloc_id, alloc_range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages
378374
global: &mut GlobalStateInner,
379-
threads: &ThreadManager<'_, 'tcx>,
375+
current_span: &mut CurrentSpan<'_, '_, 'tcx>,
380376
alloc_history: &mut AllocHistory,
381377
) -> InterpResult<'tcx> {
382378
// Two main steps: Find granting item, remove incompatible items above.
@@ -400,7 +396,7 @@ impl<'tcx> Stack {
400396
global,
401397
alloc_history,
402398
)?;
403-
alloc_history.log_invalidation(item.tag, alloc_range, threads);
399+
alloc_history.log_invalidation(item.tag, alloc_range, current_span);
404400
}
405401
} else {
406402
// On a read, *disable* all `Unique` above the granting item. This ensures U2 for read accesses.
@@ -422,7 +418,7 @@ impl<'tcx> Stack {
422418
alloc_history,
423419
)?;
424420
item.perm = Permission::Disabled;
425-
alloc_history.log_invalidation(item.tag, alloc_range, threads);
421+
alloc_history.log_invalidation(item.tag, alloc_range, current_span);
426422
}
427423
}
428424
}
@@ -471,7 +467,7 @@ impl<'tcx> Stack {
471467
new: Item,
472468
(alloc_id, alloc_range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages
473469
global: &mut GlobalStateInner,
474-
threads: &ThreadManager<'_, 'tcx>,
470+
current_span: &mut CurrentSpan<'_, '_, 'tcx>,
475471
alloc_history: &mut AllocHistory,
476472
) -> InterpResult<'tcx> {
477473
// Figure out which access `perm` corresponds to.
@@ -505,7 +501,7 @@ impl<'tcx> Stack {
505501
derived_from,
506502
(alloc_id, alloc_range, offset),
507503
global,
508-
threads,
504+
current_span,
509505
alloc_history,
510506
)?;
511507

@@ -533,13 +529,13 @@ impl<'tcx> Stack {
533529
/// Map per-stack operations to higher-level per-location-range operations.
534530
impl<'tcx> Stacks {
535531
/// Creates new stack with initial tag.
536-
fn new(size: Size, perm: Permission, tag: SbTag, local_crates: Rc<[CrateNum]>) -> Self {
532+
fn new(size: Size, perm: Permission, tag: SbTag) -> Self {
537533
let item = Item { perm, tag, protector: None };
538534
let stack = Stack { borrows: vec![item] };
539535

540536
Stacks {
541537
stacks: RefCell::new(RangeMap::new(size, stack)),
542-
history: RefCell::new(AllocHistory::new(local_crates)),
538+
history: RefCell::new(AllocHistory::new()),
543539
}
544540
}
545541

@@ -579,8 +575,7 @@ impl Stacks {
579575
size: Size,
580576
state: &GlobalState,
581577
kind: MemoryKind<MiriMemoryKind>,
582-
threads: &ThreadManager<'_, '_>,
583-
local_crates: Rc<[CrateNum]>,
578+
mut current_span: CurrentSpan<'_, '_, '_>,
584579
) -> Self {
585580
let mut extra = state.borrow_mut();
586581
let (base_tag, perm) = match kind {
@@ -614,12 +609,12 @@ impl Stacks {
614609
(tag, Permission::SharedReadWrite)
615610
}
616611
};
617-
let stacks = Stacks::new(size, perm, base_tag, local_crates);
612+
let stacks = Stacks::new(size, perm, base_tag);
618613
stacks.history.borrow_mut().log_creation(
619614
None,
620615
base_tag,
621616
alloc_range(Size::ZERO, size),
622-
threads,
617+
&mut current_span,
623618
);
624619
stacks
625620
}
@@ -631,7 +626,7 @@ impl Stacks {
631626
tag: SbTag,
632627
range: AllocRange,
633628
state: &GlobalState,
634-
threads: &ThreadManager<'_, 'tcx>,
629+
mut current_span: CurrentSpan<'_, '_, 'tcx>,
635630
) -> InterpResult<'tcx> {
636631
trace!(
637632
"read access with tag {:?}: {:?}, size {}",
@@ -646,7 +641,7 @@ impl Stacks {
646641
tag,
647642
(alloc_id, range, offset),
648643
&mut state,
649-
threads,
644+
&mut current_span,
650645
history,
651646
)
652647
})
@@ -659,7 +654,7 @@ impl Stacks {
659654
tag: SbTag,
660655
range: AllocRange,
661656
state: &GlobalState,
662-
threads: &ThreadManager<'_, 'tcx>,
657+
mut current_span: CurrentSpan<'_, '_, 'tcx>,
663658
) -> InterpResult<'tcx> {
664659
trace!(
665660
"write access with tag {:?}: {:?}, size {}",
@@ -674,7 +669,7 @@ impl Stacks {
674669
tag,
675670
(alloc_id, range, offset),
676671
&mut state,
677-
threads,
672+
&mut current_span,
678673
history,
679674
)
680675
})
@@ -723,6 +718,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
723718
}
724719
let (alloc_id, base_offset, orig_tag) = this.ptr_get_alloc_id(place.ptr)?;
725720

721+
let mut current_span = this.machine.current_span();
726722
{
727723
let extra = this.get_alloc_extra(alloc_id)?;
728724
let stacked_borrows =
@@ -732,10 +728,10 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
732728
Some(orig_tag),
733729
new_tag,
734730
alloc_range(base_offset, size),
735-
&this.machine.threads,
731+
&mut current_span,
736732
);
737733
if protect {
738-
alloc_history.log_protector(orig_tag, new_tag, &this.machine.threads);
734+
alloc_history.log_protector(orig_tag, new_tag, &mut current_span);
739735
}
740736
}
741737

@@ -804,7 +800,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
804800
item,
805801
(alloc_id, range, offset),
806802
&mut *global,
807-
&this.machine.threads,
803+
&mut current_span,
808804
history,
809805
)
810806
})
@@ -821,13 +817,14 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
821817
let item = Item { perm, tag: new_tag, protector };
822818
let range = alloc_range(base_offset, size);
823819
let mut global = machine.stacked_borrows.as_ref().unwrap().borrow_mut();
820+
let mut current_span = machine.current_span();
824821
stacked_borrows.for_each_mut(range, |offset, stack, history| {
825822
stack.grant(
826823
orig_tag,
827824
item,
828825
(alloc_id, range, offset),
829826
&mut global,
830-
&machine.threads,
827+
&mut current_span,
831828
history,
832829
)
833830
})?;

0 commit comments

Comments
 (0)