Skip to content

Commit c16336a

Browse files
committed
move loop detector constants to the module that uses them; make lifetime order in ConstPropagator consistent with Memory
1 parent b1453dd commit c16336a

File tree

3 files changed

+28
-29
lines changed

3 files changed

+28
-29
lines changed

src/librustc_mir/const_eval.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ use interpret::{self,
3434
snapshot,
3535
};
3636

37+
/// Number of steps until the detector even starts doing anything.
38+
/// Also, a warning is shown to the user when this number is reached.
39+
const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000;
40+
/// The number of steps between loop detector snapshots.
41+
/// Should be a power of two for performance reasons.
42+
const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
43+
3744
pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
3845
tcx: TyCtxt<'a, 'tcx, 'tcx>,
3946
instance: Instance<'tcx>,
@@ -245,7 +252,7 @@ impl<'a, 'mir, 'tcx> CompileTimeInterpreter<'a, 'mir, 'tcx> {
245252
fn new() -> Self {
246253
CompileTimeInterpreter {
247254
loop_detector: Default::default(),
248-
steps_since_detector_enabled: -snapshot::STEPS_UNTIL_DETECTOR_ENABLED,
255+
steps_since_detector_enabled: -STEPS_UNTIL_DETECTOR_ENABLED,
249256
}
250257
}
251258
}
@@ -349,22 +356,15 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
349356
return Ok(());
350357
}
351358

352-
*steps %= snapshot::DETECTOR_SNAPSHOT_PERIOD;
359+
*steps %= DETECTOR_SNAPSHOT_PERIOD;
353360
if *steps != 0 {
354361
return Ok(());
355362
}
356363
}
357364

358-
if ecx.machine.loop_detector.is_empty() {
359-
// First run of the loop detector
360-
361-
// FIXME(#49980): make this warning a lint
362-
ecx.tcx.sess.span_warn(ecx.frame().span,
363-
"Constant evaluating a complex constant, this might take some time");
364-
}
365-
366365
ecx.machine.loop_detector.observe_and_analyze(
367366
&ecx.tcx,
367+
ecx.frame().span,
368368
&ecx.memory,
369369
&ecx.stack[..],
370370
)

src/librustc_mir/interpret/snapshot.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,6 @@ use super::eval_context::{LocalValue, StackPopCleanup};
2828
use super::{Frame, Memory, Operand, MemPlace, Place, Value};
2929
use const_eval::CompileTimeInterpreter;
3030

31-
/// Number of steps until the detector even starts doing anything.
32-
/// Also, a warning is shown to the user when this number is reached.
33-
pub(crate) const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000;
34-
/// The number of steps between loop detector snapshots.
35-
/// Should be a power of two for performance reasons.
36-
pub(crate) const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
37-
3831
#[derive(Default)]
3932
pub(crate) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir> {
4033
/// The set of all `EvalSnapshot` *hashes* observed by this detector.
@@ -53,28 +46,31 @@ pub(crate) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir> {
5346

5447
impl<'a, 'mir, 'tcx> InfiniteLoopDetector<'a, 'mir, 'tcx>
5548
{
56-
/// Returns `true` if the loop detector has not yet observed a snapshot.
57-
pub fn is_empty(&self) -> bool {
58-
self.hashes.is_empty()
59-
}
60-
6149
pub fn observe_and_analyze<'b>(
6250
&mut self,
6351
tcx: &TyCtxt<'b, 'tcx, 'tcx>,
52+
span: Span,
6453
memory: &Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
6554
stack: &[Frame<'mir, 'tcx>],
6655
) -> EvalResult<'tcx, ()> {
67-
56+
// Compute stack's hash before copying anything
6857
let mut hcx = tcx.get_stable_hashing_context();
6958
let mut hasher = StableHasher::<u64>::new();
7059
stack.hash_stable(&mut hcx, &mut hasher);
7160
let hash = hasher.finish();
7261

62+
// Check if we know that hash already
63+
if self.hashes.is_empty() {
64+
// FIXME(#49980): make this warning a lint
65+
tcx.sess.span_warn(span,
66+
"Constant evaluating a complex constant, this might take some time");
67+
}
7368
if self.hashes.insert(hash) {
7469
// No collision
7570
return Ok(())
7671
}
7772

73+
// We need to make a full copy. NOW things that to get really expensive.
7874
info!("snapshotting the state of the interpreter");
7975

8076
if self.snapshots.insert(EvalSnapshot::new(memory, stack)) {
@@ -461,6 +457,9 @@ impl<'a, 'mir, 'tcx> Eq for EvalSnapshot<'a, 'mir, 'tcx>
461457
impl<'a, 'mir, 'tcx> PartialEq for EvalSnapshot<'a, 'mir, 'tcx>
462458
{
463459
fn eq(&self, other: &Self) -> bool {
460+
// FIXME: This looks to be a *ridicolously expensive* comparison operation.
461+
// Doesn't this make tons of copies? Either `snapshot` is very badly named,
462+
// or it does!
464463
self.snapshot() == other.snapshot()
465464
}
466465
}

src/librustc_mir/transform/const_prop.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ impl MirPass for ConstProp {
6868
type Const<'tcx> = (OpTy<'tcx>, Span);
6969

7070
/// Finds optimization opportunities on the MIR.
71-
struct ConstPropagator<'b, 'a, 'tcx:'a+'b> {
72-
ecx: EvalContext<'a, 'b, 'tcx, CompileTimeInterpreter<'a, 'b, 'tcx>>,
73-
mir: &'b Mir<'tcx>,
71+
struct ConstPropagator<'a, 'mir, 'tcx:'a+'mir> {
72+
ecx: EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
73+
mir: &'mir Mir<'tcx>,
7474
tcx: TyCtxt<'a, 'tcx, 'tcx>,
7575
source: MirSource,
7676
places: IndexVec<Local, Option<Const<'tcx>>>,
@@ -101,12 +101,12 @@ impl<'a, 'b, 'tcx> HasTyCtxt<'tcx> for &'a ConstPropagator<'a, 'b, 'tcx> {
101101
}
102102
}
103103

104-
impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
104+
impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
105105
fn new(
106-
mir: &'b Mir<'tcx>,
106+
mir: &'mir Mir<'tcx>,
107107
tcx: TyCtxt<'a, 'tcx, 'tcx>,
108108
source: MirSource,
109-
) -> ConstPropagator<'b, 'a, 'tcx> {
109+
) -> ConstPropagator<'a, 'mir, 'tcx> {
110110
let param_env = tcx.param_env(source.def_id);
111111
let substs = Substs::identity_for_item(tcx, source.def_id);
112112
let instance = Instance::new(source.def_id, substs);

0 commit comments

Comments
 (0)