Auto merge of #2328 - RalfJung:perf, r=RalfJung

move checking ptr tracking on item pop into cold helper function

Before:
```
Benchmark 1: cargo miri run --manifest-path bench-cargo-miri/serde1/Cargo.toml
  Time (mean ± σ):      6.729 s ±  0.050 s    [User: 6.608 s, System: 0.124 s]
  Range (min … max):    6.665 s …  6.799 s    5 runs

Benchmark 2: cargo miri run --manifest-path bench-cargo-miri/unicode/Cargo.toml
  Time (mean ± σ):     20.923 s ±  0.271 s    [User: 20.386 s, System: 0.537 s]
  Range (min … max):   20.580 s … 21.165 s    5 runs
```
After:
```
Benchmark 1: cargo miri run --manifest-path bench-cargo-miri/serde1/Cargo.toml
  Time (mean ± σ):      6.562 s ±  0.023 s    [User: 6.430 s, System: 0.135 s]
  Range (min … max):    6.544 s …  6.594 s    5 runs

Benchmark 2: cargo miri run --manifest-path bench-cargo-miri/unicode/Cargo.toml
  Time (mean ± σ):     20.375 s ±  0.228 s    [User: 19.964 s, System: 0.413 s]
  Range (min … max):   20.201 s … 20.736 s    5 runs
```
Nothing major, but we'll take it I guess. 🤷

Fixes https://github.com/rust-lang/miri/issues/2132
This commit is contained in:
bors 2022-07-14 00:34:00 +00:00
commit af2c50fb89

View File

@ -316,11 +316,22 @@ impl<'tcx> Stack {
alloc_history: &mut AllocHistory,
threads: &ThreadManager<'_, 'tcx>,
) -> InterpResult<'tcx> {
if global.tracked_pointer_tags.contains(&item.tag()) {
register_diagnostic(NonHaltingDiagnostic::PoppedPointerTag(
*item,
provoking_access.map(|(tag, _alloc_range, _size, access)| (tag, access)),
));
if !global.tracked_pointer_tags.is_empty() {
check_tracked(item, &provoking_access, global);
#[inline(never)] // cold path
fn check_tracked(
item: &Item,
provoking_access: &Option<(SbTagExtra, AllocRange, Size, AccessKind)>,
global: &GlobalStateInner,
) {
if global.tracked_pointer_tags.contains(&item.tag()) {
register_diagnostic(NonHaltingDiagnostic::PoppedPointerTag(
*item,
provoking_access.map(|(tag, _alloc_range, _size, access)| (tag, access)),
));
}
}
}
if !item.protected() {
@ -341,40 +352,52 @@ impl<'tcx> Stack {
// which ends up about linear in the number of protected tags in the program into a
// constant time check (and a slow linear, because the tags in the frames aren't contiguous).
if global.protected_tags.contains(&item.tag()) {
// This path is cold because it is fatal to the program. So here it is fine to do the
// more expensive search to figure out which call is responsible for protecting this
// tag.
let call_id = threads
.all_stacks()
.flatten()
.map(|frame| {
frame
.extra
.stacked_borrows
.as_ref()
.expect("we should have Stacked Borrows data")
})
.find(|frame| frame.protected_tags.contains(&item.tag()))
.map(|frame| frame.call_id)
.unwrap(); // FIXME: Surely we should find something, but a panic seems wrong here?
if let Some((tag, _alloc_range, _offset, _access)) = provoking_access {
Err(err_sb_ub(
format!(
"not granting access to tag {:?} because incompatible item {:?} is protected by call {:?}",
tag, item, call_id
),
None,
tag.and_then(|tag| alloc_history.get_logs_relevant_to(tag, Some(item.tag()))),
))?
} else {
Err(err_sb_ub(
format!(
"deallocating while item {:?} is protected by call {:?}",
item, call_id
),
None,
None,
))?
return Err(protector_error(item, &provoking_access, alloc_history, threads));
#[inline(never)] // cold path
fn protector_error<'tcx>(
item: &Item,
provoking_access: &Option<(SbTagExtra, AllocRange, Size, AccessKind)>,
alloc_history: &mut AllocHistory,
threads: &ThreadManager<'_, 'tcx>,
) -> InterpErrorInfo<'tcx> {
// This path is cold because it is fatal to the program. So here it is fine to do the
// more expensive search to figure out which call is responsible for protecting this
// tag.
let call_id = threads
.all_stacks()
.flatten()
.map(|frame| {
frame
.extra
.stacked_borrows
.as_ref()
.expect("we should have Stacked Borrows data")
})
.find(|frame| frame.protected_tags.contains(&item.tag()))
.map(|frame| frame.call_id)
.unwrap(); // FIXME: Surely we should find something, but a panic seems wrong here?
if let Some((tag, _alloc_range, _offset, _access)) = provoking_access {
err_sb_ub(
format!(
"not granting access to tag {:?} because incompatible item {:?} is protected by call {:?}",
tag, item, call_id
),
None,
tag.and_then(|tag| {
alloc_history.get_logs_relevant_to(tag, Some(item.tag()))
}),
)
} else {
err_sb_ub(
format!(
"deallocating while item {:?} is protected by call {:?}",
item, call_id
),
None,
None,
)
}.into()
}
}
Ok(())