Skip to content

Commit 61a999a

Browse files
committed
Move InfiniteLoopDetector to snapshot.rs
1 parent a26ceb3 commit 61a999a

File tree

2 files changed

+75
-73
lines changed

2 files changed

+75
-73
lines changed

src/librustc_mir/interpret/eval_context.rs

+2-69
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,14 @@ use std::mem;
1414
use rustc::hir::def_id::DefId;
1515
use rustc::hir::def::Def;
1616
use rustc::hir::map::definitions::DefPathData;
17-
use rustc::ich::{StableHashingContext, StableHashingContextProvider};
17+
use rustc::ich::StableHashingContext;
1818
use rustc::mir;
1919
use rustc::ty::layout::{
2020
self, Size, Align, HasDataLayout, LayoutOf, TyLayout
2121
};
2222
use rustc::ty::subst::{Subst, Substs};
2323
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
2424
use rustc::ty::query::TyCtxtAt;
25-
use rustc_data_structures::fx::FxHashSet;
2625
use rustc_data_structures::indexed_vec::IndexVec;
2726
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
2827
use rustc::mir::interpret::{
@@ -39,7 +38,7 @@ use super::{
3938
Memory, Machine
4039
};
4140

42-
use super::snapshot::EvalSnapshot;
41+
use super::snapshot::InfiniteLoopDetector;
4342

4443
pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
4544
/// Stores the `Machine` instance.
@@ -189,72 +188,6 @@ impl_stable_hash_for!(enum self::LocalValue {
189188
Live(x),
190189
});
191190

192-
pub(super) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
193-
/// The set of all `EvalSnapshot` *hashes* observed by this detector.
194-
///
195-
/// When a collision occurs in this table, we store the full snapshot in
196-
/// `snapshots`.
197-
hashes: FxHashSet<u64>,
198-
199-
/// The set of all `EvalSnapshot`s observed by this detector.
200-
///
201-
/// An `EvalSnapshot` will only be fully cloned once it has caused a
202-
/// collision in `hashes`. As a result, the detector must observe at least
203-
/// *two* full cycles of an infinite loop before it triggers.
204-
snapshots: FxHashSet<EvalSnapshot<'a, 'mir, 'tcx, M>>,
205-
}
206-
207-
impl<'a, 'mir, 'tcx, M> Default for InfiniteLoopDetector<'a, 'mir, 'tcx, M>
208-
where M: Machine<'mir, 'tcx>,
209-
'tcx: 'a + 'mir,
210-
{
211-
fn default() -> Self {
212-
InfiniteLoopDetector {
213-
hashes: FxHashSet::default(),
214-
snapshots: FxHashSet::default(),
215-
}
216-
}
217-
}
218-
219-
impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
220-
where M: Machine<'mir, 'tcx>,
221-
'tcx: 'a + 'mir,
222-
{
223-
/// Returns `true` if the loop detector has not yet observed a snapshot.
224-
pub fn is_empty(&self) -> bool {
225-
self.hashes.is_empty()
226-
}
227-
228-
pub fn observe_and_analyze(
229-
&mut self,
230-
tcx: &TyCtxt<'b, 'tcx, 'tcx>,
231-
machine: &M,
232-
memory: &Memory<'a, 'mir, 'tcx, M>,
233-
stack: &[Frame<'mir, 'tcx>],
234-
) -> EvalResult<'tcx, ()> {
235-
236-
let mut hcx = tcx.get_stable_hashing_context();
237-
let mut hasher = StableHasher::<u64>::new();
238-
(machine, stack).hash_stable(&mut hcx, &mut hasher);
239-
let hash = hasher.finish();
240-
241-
if self.hashes.insert(hash) {
242-
// No collision
243-
return Ok(())
244-
}
245-
246-
info!("snapshotting the state of the interpreter");
247-
248-
if self.snapshots.insert(EvalSnapshot::new(machine, memory, stack)) {
249-
// Spurious collision or first cycle
250-
return Ok(())
251-
}
252-
253-
// Second cycle
254-
Err(EvalErrorKind::InfiniteLoop.into())
255-
}
256-
}
257-
258191
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for &'a EvalContext<'a, 'mir, 'tcx, M> {
259192
#[inline]
260193
fn data_layout(&self) -> &layout::TargetDataLayout {

src/librustc_mir/interpret/snapshot.rs

+73-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ use std::hash::{Hash, Hasher};
33
use rustc::ich::{StableHashingContext, StableHashingContextProvider};
44
use rustc::mir;
55
use rustc::mir::interpret::{
6-
AllocId, Pointer, Scalar, ScalarMaybeUndef, Relocations, Allocation, UndefMask
6+
AllocId, Pointer, Scalar, ScalarMaybeUndef,
7+
Relocations, Allocation, UndefMask,
8+
EvalResult, EvalErrorKind,
79
};
810

9-
use rustc::ty;
11+
use rustc::ty::{self, TyCtxt};
1012
use rustc::ty::layout::Align;
13+
use rustc_data_structures::fx::FxHashSet;
1114
use rustc_data_structures::indexed_vec::IndexVec;
1215
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
1316
use syntax::ast::Mutability;
@@ -16,6 +19,72 @@ use syntax::source_map::Span;
1619
use super::eval_context::{LocalValue, StackPopCleanup};
1720
use super::{Frame, Memory, Machine, Operand, MemPlace, Place, Value};
1821

22+
pub(super) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
23+
/// The set of all `EvalSnapshot` *hashes* observed by this detector.
24+
///
25+
/// When a collision occurs in this table, we store the full snapshot in
26+
/// `snapshots`.
27+
hashes: FxHashSet<u64>,
28+
29+
/// The set of all `EvalSnapshot`s observed by this detector.
30+
///
31+
/// An `EvalSnapshot` will only be fully cloned once it has caused a
32+
/// collision in `hashes`. As a result, the detector must observe at least
33+
/// *two* full cycles of an infinite loop before it triggers.
34+
snapshots: FxHashSet<EvalSnapshot<'a, 'mir, 'tcx, M>>,
35+
}
36+
37+
impl<'a, 'mir, 'tcx, M> Default for InfiniteLoopDetector<'a, 'mir, 'tcx, M>
38+
where M: Machine<'mir, 'tcx>,
39+
'tcx: 'a + 'mir,
40+
{
41+
fn default() -> Self {
42+
InfiniteLoopDetector {
43+
hashes: FxHashSet::default(),
44+
snapshots: FxHashSet::default(),
45+
}
46+
}
47+
}
48+
49+
impl<'a, 'mir, 'tcx, M> InfiniteLoopDetector<'a, 'mir, 'tcx, M>
50+
where M: Machine<'mir, 'tcx>,
51+
'tcx: 'a + 'mir,
52+
{
53+
/// Returns `true` if the loop detector has not yet observed a snapshot.
54+
pub fn is_empty(&self) -> bool {
55+
self.hashes.is_empty()
56+
}
57+
58+
pub fn observe_and_analyze(
59+
&mut self,
60+
tcx: &TyCtxt<'b, 'tcx, 'tcx>,
61+
machine: &M,
62+
memory: &Memory<'a, 'mir, 'tcx, M>,
63+
stack: &[Frame<'mir, 'tcx>],
64+
) -> EvalResult<'tcx, ()> {
65+
66+
let mut hcx = tcx.get_stable_hashing_context();
67+
let mut hasher = StableHasher::<u64>::new();
68+
(machine, stack).hash_stable(&mut hcx, &mut hasher);
69+
let hash = hasher.finish();
70+
71+
if self.hashes.insert(hash) {
72+
// No collision
73+
return Ok(())
74+
}
75+
76+
info!("snapshotting the state of the interpreter");
77+
78+
if self.snapshots.insert(EvalSnapshot::new(machine, memory, stack)) {
79+
// Spurious collision or first cycle
80+
return Ok(())
81+
}
82+
83+
// Second cycle
84+
Err(EvalErrorKind::InfiniteLoop.into())
85+
}
86+
}
87+
1988
trait SnapshotContext<'a> {
2089
fn resolve(&'a self, id: &AllocId) -> Option<&'a Allocation>;
2190
}
@@ -269,7 +338,7 @@ impl<'a, 'b, 'mir, 'tcx, M> SnapshotContext<'b> for Memory<'a, 'mir, 'tcx, M>
269338
}
270339

271340
/// The virtual machine state during const-evaluation at a given point in time.
272-
pub struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
341+
struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
273342
machine: M,
274343
memory: Memory<'a, 'mir, 'tcx, M>,
275344
stack: Vec<Frame<'mir, 'tcx>>,
@@ -278,7 +347,7 @@ pub struct EvalSnapshot<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
278347
impl<'a, 'mir, 'tcx, M> EvalSnapshot<'a, 'mir, 'tcx, M>
279348
where M: Machine<'mir, 'tcx>,
280349
{
281-
pub fn new(
350+
fn new(
282351
machine: &M,
283352
memory: &Memory<'a, 'mir, 'tcx, M>,
284353
stack: &[Frame<'mir, 'tcx>]) -> Self {

0 commit comments

Comments
 (0)