@@ -3,7 +3,6 @@ use rustc::ty::layout::HasTyCtxt;
33use rustc:: ty:: { self , Ty } ;
44use std:: borrow:: { Borrow , Cow } ;
55use std:: collections:: hash_map:: Entry ;
6- use std:: convert:: TryFrom ;
76use std:: hash:: Hash ;
87
98use rustc_data_structures:: fx:: FxHashMap ;
@@ -13,13 +12,13 @@ use rustc_span::source_map::Span;
1312use rustc_span:: symbol:: Symbol ;
1413
1514use crate :: interpret:: {
16- self , snapshot , AllocId , Allocation , GlobalId , ImmTy , InterpCx , InterpResult , Memory ,
17- MemoryKind , OpTy , PlaceTy , Pointer , Scalar ,
15+ self , AllocId , Allocation , GlobalId , ImmTy , InterpCx , InterpResult , Memory , MemoryKind , OpTy ,
16+ PlaceTy , Pointer , Scalar ,
1817} ;
1918
2019use super :: error:: * ;
2120
22- impl < ' mir , ' tcx > InterpCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > {
21+ impl < ' mir , ' tcx > InterpCx < ' mir , ' tcx , CompileTimeInterpreter > {
2322 /// Evaluate a const function where all arguments (if any) are zero-sized types.
2423 /// The evaluation is memoized thanks to the query system.
2524 ///
@@ -86,22 +85,13 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
8685 }
8786}
8887
89- /// The number of steps between loop detector snapshots.
90- /// Should be a power of two for performance reasons.
91- const DETECTOR_SNAPSHOT_PERIOD : isize = 256 ;
92-
93- // Extra machine state for CTFE, and the Machine instance
94- pub struct CompileTimeInterpreter < ' mir , ' tcx > {
95- /// When this value is negative, it indicates the number of interpreter
96- /// steps *until* the loop detector is enabled. When it is positive, it is
97- /// the number of steps after the detector has been enabled modulo the loop
98- /// detector period.
99- pub ( super ) steps_since_detector_enabled : isize ,
100-
101- pub ( super ) is_detector_enabled : bool ,
102-
103- /// Extra state to detect loops.
104- pub ( super ) loop_detector : snapshot:: InfiniteLoopDetector < ' mir , ' tcx > ,
88+ /// Extra machine state for CTFE, and the Machine instance
89+ pub struct CompileTimeInterpreter {
90+ /// For now, the number of terminators that can be evaluated before we throw a resource
91+ /// exhuastion error.
92+ ///
93+ /// Setting this to `0` disables the limit and allows the interpreter to run forever.
94+ pub steps_remaining : usize ,
10595}
10696
10797#[ derive( Copy , Clone , Debug ) ]
@@ -110,16 +100,9 @@ pub struct MemoryExtra {
110100 pub ( super ) can_access_statics : bool ,
111101}
112102
113- impl < ' mir , ' tcx > CompileTimeInterpreter < ' mir , ' tcx > {
103+ impl CompileTimeInterpreter {
114104 pub ( super ) fn new ( const_eval_limit : usize ) -> Self {
115- let steps_until_detector_enabled =
116- isize:: try_from ( const_eval_limit) . unwrap_or ( std:: isize:: MAX ) ;
117-
118- CompileTimeInterpreter {
119- loop_detector : Default :: default ( ) ,
120- steps_since_detector_enabled : -steps_until_detector_enabled,
121- is_detector_enabled : const_eval_limit != 0 ,
122- }
105+ CompileTimeInterpreter { steps_remaining : const_eval_limit }
123106 }
124107}
125108
@@ -173,8 +156,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
173156 }
174157}
175158
176- crate type CompileTimeEvalContext < ' mir , ' tcx > =
177- InterpCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > ;
159+ crate type CompileTimeEvalContext < ' mir , ' tcx > = InterpCx < ' mir , ' tcx , CompileTimeInterpreter > ;
178160
179161impl interpret:: MayLeak for ! {
180162 #[ inline( always) ]
@@ -184,7 +166,7 @@ impl interpret::MayLeak for ! {
184166 }
185167}
186168
187- impl < ' mir , ' tcx > interpret:: Machine < ' mir , ' tcx > for CompileTimeInterpreter < ' mir , ' tcx > {
169+ impl < ' mir , ' tcx > interpret:: Machine < ' mir , ' tcx > for CompileTimeInterpreter {
188170 type MemoryKinds = !;
189171 type PointerTag = ( ) ;
190172 type ExtraFnVal = !;
@@ -345,26 +327,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
345327 }
346328
347329 fn before_terminator ( ecx : & mut InterpCx < ' mir , ' tcx , Self > ) -> InterpResult < ' tcx > {
348- if !ecx. machine . is_detector_enabled {
330+ // The step limit has already been hit in a previous call to `before_terminator`.
331+ if ecx. machine . steps_remaining == 0 {
349332 return Ok ( ( ) ) ;
350333 }
351334
352- {
353- let steps = & mut ecx. machine . steps_since_detector_enabled ;
354-
355- * steps += 1 ;
356- if * steps < 0 {
357- return Ok ( ( ) ) ;
358- }
359-
360- * steps %= DETECTOR_SNAPSHOT_PERIOD ;
361- if * steps != 0 {
362- return Ok ( ( ) ) ;
363- }
335+ ecx. machine . steps_remaining -= 1 ;
336+ if ecx. machine . steps_remaining == 0 {
337+ throw_exhaust ! ( StepLimitReached )
364338 }
365339
366- let span = ecx. frame ( ) . span ;
367- ecx. machine . loop_detector . observe_and_analyze ( * ecx. tcx , span, & ecx. memory , & ecx. stack [ ..] )
340+ Ok ( ( ) )
368341 }
369342
370343 #[ inline( always) ]
0 commit comments