@@ -3,7 +3,6 @@ use rustc::ty::layout::HasTyCtxt;
3
3
use rustc:: ty:: { self , Ty } ;
4
4
use std:: borrow:: { Borrow , Cow } ;
5
5
use std:: collections:: hash_map:: Entry ;
6
- use std:: convert:: TryFrom ;
7
6
use std:: hash:: Hash ;
8
7
9
8
use rustc_data_structures:: fx:: FxHashMap ;
@@ -13,13 +12,13 @@ use rustc_span::source_map::Span;
13
12
use rustc_span:: symbol:: Symbol ;
14
13
15
14
use 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 ,
18
17
} ;
19
18
20
19
use super :: error:: * ;
21
20
22
- impl < ' mir , ' tcx > InterpCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > {
21
+ impl < ' mir , ' tcx > InterpCx < ' mir , ' tcx , CompileTimeInterpreter > {
23
22
/// Evaluate a const function where all arguments (if any) are zero-sized types.
24
23
/// The evaluation is memoized thanks to the query system.
25
24
///
@@ -86,22 +85,13 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
86
85
}
87
86
}
88
87
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 ,
105
95
}
106
96
107
97
#[ derive( Copy , Clone , Debug ) ]
@@ -110,16 +100,9 @@ pub struct MemoryExtra {
110
100
pub ( super ) can_access_statics : bool ,
111
101
}
112
102
113
- impl < ' mir , ' tcx > CompileTimeInterpreter < ' mir , ' tcx > {
103
+ impl CompileTimeInterpreter {
114
104
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 }
123
106
}
124
107
}
125
108
@@ -173,8 +156,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
173
156
}
174
157
}
175
158
176
- crate type CompileTimeEvalContext < ' mir , ' tcx > =
177
- InterpCx < ' mir , ' tcx , CompileTimeInterpreter < ' mir , ' tcx > > ;
159
+ crate type CompileTimeEvalContext < ' mir , ' tcx > = InterpCx < ' mir , ' tcx , CompileTimeInterpreter > ;
178
160
179
161
impl interpret:: MayLeak for ! {
180
162
#[ inline( always) ]
@@ -184,7 +166,7 @@ impl interpret::MayLeak for ! {
184
166
}
185
167
}
186
168
187
- impl < ' mir , ' tcx > interpret:: Machine < ' mir , ' tcx > for CompileTimeInterpreter < ' mir , ' tcx > {
169
+ impl < ' mir , ' tcx > interpret:: Machine < ' mir , ' tcx > for CompileTimeInterpreter {
188
170
type MemoryKinds = !;
189
171
type PointerTag = ( ) ;
190
172
type ExtraFnVal = !;
@@ -345,26 +327,17 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
345
327
}
346
328
347
329
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 {
349
332
return Ok ( ( ) ) ;
350
333
}
351
334
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 )
364
338
}
365
339
366
- let span = ecx. frame ( ) . span ;
367
- ecx. machine . loop_detector . observe_and_analyze ( * ecx. tcx , span, & ecx. memory , & ecx. stack [ ..] )
340
+ Ok ( ( ) )
368
341
}
369
342
370
343
#[ inline( always) ]
0 commit comments