1
- use crate :: * ;
2
1
use rustc_data_structures:: fx:: FxHashSet ;
3
2
3
+ use crate :: * ;
4
+
5
+ pub trait VisitMachineValues {
6
+ fn visit_machine_values ( & self , visit : & mut impl FnMut ( & Operand < Provenance > ) ) ;
7
+ }
8
+
4
9
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
5
10
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : MiriInterpCxExt < ' mir , ' tcx > {
11
+ /// Generic GC helper to visit everything that can store a value. The `acc` offers some chance to
12
+ /// accumulate everything.
13
+ fn visit_all_machine_values < T > (
14
+ & self ,
15
+ acc : & mut T ,
16
+ mut visit_operand : impl FnMut ( & mut T , & Operand < Provenance > ) ,
17
+ mut visit_alloc : impl FnMut ( & mut T , & Allocation < Provenance , AllocExtra > ) ,
18
+ ) {
19
+ let this = self . eval_context_ref ( ) ;
20
+
21
+ // Memory.
22
+ this. memory . alloc_map ( ) . iter ( |it| {
23
+ for ( _id, ( _kind, alloc) ) in it {
24
+ visit_alloc ( acc, alloc) ;
25
+ }
26
+ } ) ;
27
+
28
+ // And all the other machine values.
29
+ this. machine . visit_machine_values ( & mut |op| visit_operand ( acc, op) ) ;
30
+ }
31
+
6
32
fn garbage_collect_tags ( & mut self ) -> InterpResult < ' tcx > {
7
33
let this = self . eval_context_mut ( ) ;
8
34
// No reason to do anything at all if stacked borrows is off.
@@ -12,90 +38,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> {
12
38
13
39
let mut tags = FxHashSet :: default ( ) ;
14
40
15
- for thread in this. machine . threads . iter ( ) {
16
- if let Some ( Scalar :: Ptr (
17
- Pointer { provenance : Provenance :: Concrete { sb, .. } , .. } ,
18
- _,
19
- ) ) = thread. panic_payload
20
- {
21
- tags. insert ( sb) ;
22
- }
23
- }
24
-
25
- self . find_tags_in_tls ( & mut tags) ;
26
- self . find_tags_in_memory ( & mut tags) ;
27
- self . find_tags_in_locals ( & mut tags) ?;
28
-
29
- self . remove_unreachable_tags ( tags) ;
30
-
31
- Ok ( ( ) )
32
- }
33
-
34
- fn find_tags_in_tls ( & mut self , tags : & mut FxHashSet < SbTag > ) {
35
- let this = self . eval_context_mut ( ) ;
36
- this. machine . tls . iter ( |scalar| {
37
- if let Scalar :: Ptr ( Pointer { provenance : Provenance :: Concrete { sb, .. } , .. } , _) =
38
- scalar
39
- {
40
- tags. insert ( * sb) ;
41
- }
42
- } ) ;
43
- }
44
-
45
- fn find_tags_in_memory ( & mut self , tags : & mut FxHashSet < SbTag > ) {
46
- let this = self . eval_context_mut ( ) ;
47
- this. memory . alloc_map ( ) . iter ( |it| {
48
- for ( _id, ( _kind, alloc) ) in it {
49
- for ( _size, prov) in alloc. provenance ( ) . iter ( ) {
50
- if let Provenance :: Concrete { sb, .. } = prov {
51
- tags. insert ( * sb) ;
52
- }
53
- }
54
- }
55
- } ) ;
56
- }
57
-
58
- fn find_tags_in_locals ( & mut self , tags : & mut FxHashSet < SbTag > ) -> InterpResult < ' tcx > {
59
- let this = self . eval_context_mut ( ) ;
60
- for frame in this. machine . threads . all_stacks ( ) . flatten ( ) {
61
- // Handle the return place of each frame
62
- if let Ok ( return_place) = frame. return_place . try_as_mplace ( ) {
63
- if let Some ( Provenance :: Concrete { sb, .. } ) = return_place. ptr . provenance {
41
+ let visit_scalar = |tags : & mut FxHashSet < SbTag > , s : & Scalar < Provenance > | {
42
+ if let Scalar :: Ptr ( ptr, _) = s {
43
+ if let Provenance :: Concrete { sb, .. } = ptr. provenance {
64
44
tags. insert ( sb) ;
65
45
}
66
46
}
47
+ } ;
67
48
68
- for local in frame. locals . iter ( ) {
69
- let LocalValue :: Live ( value) = local. value else {
70
- continue ;
71
- } ;
72
- match value {
73
- Operand :: Immediate ( Immediate :: Scalar ( Scalar :: Ptr ( ptr, _) ) ) =>
74
- if let Provenance :: Concrete { sb, .. } = ptr. provenance {
75
- tags. insert ( sb) ;
76
- } ,
49
+ this. visit_all_machine_values (
50
+ & mut tags,
51
+ |tags, op| {
52
+ match op {
53
+ Operand :: Immediate ( Immediate :: Scalar ( s) ) => {
54
+ visit_scalar ( tags, s) ;
55
+ }
77
56
Operand :: Immediate ( Immediate :: ScalarPair ( s1, s2) ) => {
78
- if let Scalar :: Ptr ( ptr, _) = s1 {
79
- if let Provenance :: Concrete { sb, .. } = ptr. provenance {
80
- tags. insert ( sb) ;
81
- }
82
- }
83
- if let Scalar :: Ptr ( ptr, _) = s2 {
84
- if let Provenance :: Concrete { sb, .. } = ptr. provenance {
85
- tags. insert ( sb) ;
86
- }
87
- }
57
+ visit_scalar ( tags, s1) ;
58
+ visit_scalar ( tags, s2) ;
88
59
}
60
+ Operand :: Immediate ( Immediate :: Uninit ) => { }
89
61
Operand :: Indirect ( MemPlace { ptr, .. } ) => {
90
62
if let Some ( Provenance :: Concrete { sb, .. } ) = ptr. provenance {
91
63
tags. insert ( sb) ;
92
64
}
93
65
}
94
- Operand :: Immediate ( Immediate :: Uninit )
95
- | Operand :: Immediate ( Immediate :: Scalar ( Scalar :: Int ( _) ) ) => { }
96
66
}
97
- }
98
- }
67
+ } ,
68
+ |tags, alloc| {
69
+ for ( _size, prov) in alloc. provenance ( ) . iter ( ) {
70
+ if let Provenance :: Concrete { sb, .. } = prov {
71
+ tags. insert ( * sb) ;
72
+ }
73
+ }
74
+ } ,
75
+ ) ;
76
+
77
+ self . remove_unreachable_tags ( tags) ;
99
78
100
79
Ok ( ( ) )
101
80
}
0 commit comments