Skip to content

Commit 620f9ea

Browse files
committed
Remove const deduplication from the interpreter.
1 parent cbbad2d commit 620f9ea

File tree

4 files changed

+9
-84
lines changed

4 files changed

+9
-84
lines changed

compiler/rustc_const_eval/src/interpret/eval_context.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
559559
span: Span,
560560
layout: Option<TyAndLayout<'tcx>>,
561561
) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
562-
M::eval_mir_constant(self, *val, span, layout, |ecx, val, span, layout| {
563-
let const_val = val.eval(*ecx.tcx, ecx.typing_env, span).map_err(|err| {
562+
let const_val = val.eval(*self.tcx, self.typing_env, span).map_err(|err| {
564563
if M::ALL_CONSTS_ARE_PRECHECKED {
565564
match err {
566565
ErrorHandled::TooGeneric(..) => {},
@@ -576,11 +575,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
576575
}
577576
}
578577
}
579-
err.emit_note(*ecx.tcx);
578+
err.emit_note(*self.tcx);
580579
err
581580
})?;
582-
ecx.const_val_to_op(const_val, val.ty(), layout)
583-
})
581+
self.const_val_to_op(const_val, val.ty(), layout)
584582
}
585583

586584
#[must_use]

compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use rustc_middle::query::TyCtxtAt;
1212
use rustc_middle::ty::Ty;
1313
use rustc_middle::ty::layout::TyAndLayout;
1414
use rustc_middle::{mir, ty};
15-
use rustc_span::Span;
1615
use rustc_span::def_id::DefId;
1716
use rustc_target::callconv::FnAbi;
1817

@@ -587,27 +586,6 @@ pub trait Machine<'tcx>: Sized {
587586
interp_ok(())
588587
}
589588

590-
/// Evaluate the given constant. The `eval` function will do all the required evaluation,
591-
/// but this hook has the chance to do some pre/postprocessing.
592-
#[inline(always)]
593-
fn eval_mir_constant<F>(
594-
ecx: &InterpCx<'tcx, Self>,
595-
val: mir::Const<'tcx>,
596-
span: Span,
597-
layout: Option<TyAndLayout<'tcx>>,
598-
eval: F,
599-
) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>
600-
where
601-
F: Fn(
602-
&InterpCx<'tcx, Self>,
603-
mir::Const<'tcx>,
604-
Span,
605-
Option<TyAndLayout<'tcx>>,
606-
) -> InterpResult<'tcx, OpTy<'tcx, Self::Provenance>>,
607-
{
608-
eval(ecx, val, span, layout)
609-
}
610-
611589
/// Returns the salt to be used for a deduplicated global alloation.
612590
/// If the allocation is for a function, the instance is provided as well
613591
/// (this lets Miri ensure unique addresses for some functions).

src/tools/miri/src/machine.rs

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
use std::any::Any;
55
use std::borrow::Cow;
66
use std::cell::{Cell, RefCell};
7-
use std::collections::hash_map::Entry;
87
use std::path::Path;
98
use std::rc::Rc;
109
use std::{fmt, process};
@@ -70,12 +69,6 @@ pub struct FrameExtra<'tcx> {
7069
/// This is used by `MiriMachine::current_span` and `MiriMachine::caller_span`
7170
pub is_user_relevant: bool,
7271

73-
/// We have a cache for the mapping from [`mir::Const`] to resulting [`AllocId`].
74-
/// However, we don't want all frames to always get the same result, so we insert
75-
/// an additional bit of "salt" into the cache key. This salt is fixed per-frame
76-
/// so that within a call, a const will have a stable address.
77-
salt: usize,
78-
7972
/// Data race detector per-frame data.
8073
pub data_race: Option<data_race::FrameState>,
8174
}
@@ -88,14 +81,12 @@ impl<'tcx> std::fmt::Debug for FrameExtra<'tcx> {
8881
catch_unwind,
8982
timing: _,
9083
is_user_relevant,
91-
salt,
9284
data_race,
9385
} = self;
9486
f.debug_struct("FrameData")
9587
.field("borrow_tracker", borrow_tracker)
9688
.field("catch_unwind", catch_unwind)
9789
.field("is_user_relevant", is_user_relevant)
98-
.field("salt", salt)
9990
.field("data_race", data_race)
10091
.finish()
10192
}
@@ -108,7 +99,6 @@ impl VisitProvenance for FrameExtra<'_> {
10899
borrow_tracker,
109100
timing: _,
110101
is_user_relevant: _,
111-
salt: _,
112102
data_race: _,
113103
} = self;
114104

@@ -579,11 +569,6 @@ pub struct MiriMachine<'tcx> {
579569
/// diagnostics.
580570
pub(crate) allocation_spans: RefCell<FxHashMap<AllocId, (Span, Option<Span>)>>,
581571

582-
/// Maps MIR consts to their evaluated result. We combine the const with a "salt" (`usize`)
583-
/// that is fixed per stack frame; this lets us have sometimes different results for the
584-
/// same const while ensuring consistent results within a single call.
585-
const_cache: RefCell<FxHashMap<(mir::Const<'tcx>, usize), OpTy<'tcx>>>,
586-
587572
/// For each allocation, an offset inside that allocation that was deemed aligned even for
588573
/// symbolic alignment checks. This cannot be stored in `AllocExtra` since it needs to be
589574
/// tracked for vtables and function allocations as well as regular allocations.
@@ -764,7 +749,6 @@ impl<'tcx> MiriMachine<'tcx> {
764749
stack_size,
765750
collect_leak_backtraces: config.collect_leak_backtraces,
766751
allocation_spans: RefCell::new(FxHashMap::default()),
767-
const_cache: RefCell::new(FxHashMap::default()),
768752
symbolic_alignment: RefCell::new(FxHashMap::default()),
769753
union_data_ranges: FxHashMap::default(),
770754
pthread_mutex_sanity: Cell::new(false),
@@ -942,7 +926,6 @@ impl VisitProvenance for MiriMachine<'_> {
942926
stack_size: _,
943927
collect_leak_backtraces: _,
944928
allocation_spans: _,
945-
const_cache: _,
946929
symbolic_alignment: _,
947930
union_data_ranges: _,
948931
pthread_mutex_sanity: _,
@@ -1579,7 +1562,6 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
15791562
catch_unwind: None,
15801563
timing,
15811564
is_user_relevant: ecx.machine.is_user_relevant(&frame),
1582-
salt: ecx.machine.rng.borrow_mut().random_range(0..ADDRS_PER_ANON_GLOBAL),
15831565
data_race: ecx
15841566
.machine
15851567
.data_race
@@ -1738,33 +1720,6 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
17381720
interp_ok(())
17391721
}
17401722

1741-
fn eval_mir_constant<F>(
1742-
ecx: &InterpCx<'tcx, Self>,
1743-
val: mir::Const<'tcx>,
1744-
span: Span,
1745-
layout: Option<TyAndLayout<'tcx>>,
1746-
eval: F,
1747-
) -> InterpResult<'tcx, OpTy<'tcx>>
1748-
where
1749-
F: Fn(
1750-
&InterpCx<'tcx, Self>,
1751-
mir::Const<'tcx>,
1752-
Span,
1753-
Option<TyAndLayout<'tcx>>,
1754-
) -> InterpResult<'tcx, OpTy<'tcx>>,
1755-
{
1756-
let frame = ecx.active_thread_stack().last().unwrap();
1757-
let mut cache = ecx.machine.const_cache.borrow_mut();
1758-
match cache.entry((val, frame.extra.salt)) {
1759-
Entry::Vacant(ve) => {
1760-
let op = eval(ecx, val, span, layout)?;
1761-
ve.insert(op.clone());
1762-
interp_ok(op)
1763-
}
1764-
Entry::Occupied(oe) => interp_ok(oe.get().clone()),
1765-
}
1766-
}
1767-
17681723
fn get_global_alloc_salt(
17691724
ecx: &InterpCx<'tcx, Self>,
17701725
instance: Option<ty::Instance<'tcx>>,

src/tools/miri/tests/pass/const-addrs.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
// The const fn interpreter creates a new AllocId every time it evaluates any const.
2-
// If we do that in Miri, repeatedly evaluating a const causes unbounded memory use
3-
// we need to keep track of the base address for that AllocId, and the allocation is never
4-
// deallocated.
5-
// In Miri we explicitly store previously-assigned AllocIds for each const and ensure
6-
// that we only hand out a finite number of AllocIds per const.
7-
// MIR inlining will put every evaluation of the const we're repeatedly evaluating into the same
8-
// stack frame, breaking this test.
1+
// The interpreter used to create a new AllocId every time it evaluates any const.
2+
// This caused unbounded memory use in Miri.
3+
// This test verifies that we only create a bounded amount of addresses for any given const.
4+
// In practice, the interpreter always returns the same address, but we *do not guarantee* it.
95
//@compile-flags: -Zinline-mir=no
106

117
const EVALS: usize = 256;
@@ -16,10 +12,8 @@ fn main() {
1612
for _ in 0..EVALS {
1713
addrs.insert(const_addr());
1814
}
19-
// Check that the const allocation has multiple base addresses
20-
assert!(addrs.len() > 1);
21-
// But also that we get a limited number of unique base addresses
22-
assert!(addrs.len() < EVALS);
15+
// Check that we always return the same base address for the const allocation.
16+
assert_eq!(addrs.len(), 1);
2317

2418
// Check that within a call we always produce the same address
2519
let mut prev = 0;

0 commit comments

Comments
 (0)