1- use crate :: * ;
21use rustc_data_structures:: fx:: FxHashSet ;
32
3+ use crate :: * ;
4+
5+ pub trait VisitMachineValues {
6+ fn visit_machine_values ( & self , visit : & mut impl FnMut ( & Operand < Provenance > ) ) ;
7+ }
8+
49impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
510pub 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+
632 fn garbage_collect_tags ( & mut self ) -> InterpResult < ' tcx > {
733 let this = self . eval_context_mut ( ) ;
834 // 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> {
1238
1339 let mut tags = FxHashSet :: default ( ) ;
1440
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 {
6444 tags. insert ( sb) ;
6545 }
6646 }
47+ } ;
6748
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+ }
7756 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) ;
8859 }
60+ Operand :: Immediate ( Immediate :: Uninit ) => { }
8961 Operand :: Indirect ( MemPlace { ptr, .. } ) => {
9062 if let Some ( Provenance :: Concrete { sb, .. } ) = ptr. provenance {
9163 tags. insert ( sb) ;
9264 }
9365 }
94- Operand :: Immediate ( Immediate :: Uninit )
95- | Operand :: Immediate ( Immediate :: Scalar ( Scalar :: Int ( _) ) ) => { }
9666 }
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) ;
9978
10079 Ok ( ( ) )
10180 }
0 commit comments