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