@@ -28,13 +28,6 @@ use super::eval_context::{LocalValue, StackPopCleanup};
28
28
use super :: { Frame , Memory , Operand , MemPlace , Place , Value } ;
29
29
use const_eval:: CompileTimeInterpreter ;
30
30
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
-
38
31
#[ derive( Default ) ]
39
32
pub ( crate ) struct InfiniteLoopDetector < ' a , ' mir , ' tcx : ' a + ' mir > {
40
33
/// The set of all `EvalSnapshot` *hashes* observed by this detector.
@@ -53,28 +46,31 @@ pub(crate) struct InfiniteLoopDetector<'a, 'mir, 'tcx: 'a + 'mir> {
53
46
54
47
impl < ' a , ' mir , ' tcx > InfiniteLoopDetector < ' a , ' mir , ' tcx >
55
48
{
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
-
61
49
pub fn observe_and_analyze < ' b > (
62
50
& mut self ,
63
51
tcx : & TyCtxt < ' b , ' tcx , ' tcx > ,
52
+ span : Span ,
64
53
memory : & Memory < ' a , ' mir , ' tcx , CompileTimeInterpreter < ' a , ' mir , ' tcx > > ,
65
54
stack : & [ Frame < ' mir , ' tcx > ] ,
66
55
) -> EvalResult < ' tcx , ( ) > {
67
-
56
+ // Compute stack's hash before copying anything
68
57
let mut hcx = tcx. get_stable_hashing_context ( ) ;
69
58
let mut hasher = StableHasher :: < u64 > :: new ( ) ;
70
59
stack. hash_stable ( & mut hcx, & mut hasher) ;
71
60
let hash = hasher. finish ( ) ;
72
61
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
+ }
73
68
if self . hashes . insert ( hash) {
74
69
// No collision
75
70
return Ok ( ( ) )
76
71
}
77
72
73
+ // We need to make a full copy. NOW things that to get really expensive.
78
74
info ! ( "snapshotting the state of the interpreter" ) ;
79
75
80
76
if self . snapshots . insert ( EvalSnapshot :: new ( memory, stack) ) {
@@ -461,6 +457,9 @@ impl<'a, 'mir, 'tcx> Eq for EvalSnapshot<'a, 'mir, 'tcx>
461
457
impl < ' a , ' mir , ' tcx > PartialEq for EvalSnapshot < ' a , ' mir , ' tcx >
462
458
{
463
459
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!
464
463
self . snapshot ( ) == other. snapshot ( )
465
464
}
466
465
}
0 commit comments