@@ -32,9 +32,11 @@ pub enum SchedulingAction {
3232
3333/// Timeout callbacks can be created by synchronization primitives to tell the
3434/// scheduler that they should be called once some period of time passes.
35- type TimeoutCallback < ' mir , ' tcx > = Box <
36- dyn FnOnce ( & mut InterpCx < ' mir , ' tcx , MiriMachine < ' mir , ' tcx > > ) -> InterpResult < ' tcx > + ' tcx ,
37- > ;
35+ pub trait MachineCallback < ' mir , ' tcx > : VisitTags {
36+ fn call ( & self , ecx : & mut InterpCx < ' mir , ' tcx , MiriMachine < ' mir , ' tcx > > ) -> InterpResult < ' tcx > ;
37+ }
38+
39+ type TimeoutCallback < ' mir , ' tcx > = Box < dyn MachineCallback < ' mir , ' tcx > + ' tcx > ;
3840
3941/// A thread identifier.
4042#[ derive( Clone , Copy , Debug , PartialOrd , Ord , PartialEq , Eq , Hash ) ]
@@ -181,6 +183,46 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
181183 }
182184}
183185
186+ impl VisitTags for Thread < ' _ , ' _ > {
187+ fn visit_tags ( & self , visit : & mut dyn FnMut ( SbTag ) ) {
188+ let Thread { panic_payload, last_error, stack, state : _, thread_name : _, join_status : _ } =
189+ self ;
190+
191+ panic_payload. visit_tags ( visit) ;
192+ last_error. visit_tags ( visit) ;
193+ for frame in stack {
194+ frame. visit_tags ( visit)
195+ }
196+ }
197+ }
198+
199+ impl VisitTags for Frame < ' _ , ' _ , Provenance , FrameData < ' _ > > {
200+ fn visit_tags ( & self , visit : & mut dyn FnMut ( SbTag ) ) {
201+ let Frame {
202+ return_place,
203+ locals,
204+ extra,
205+ body : _,
206+ instance : _,
207+ return_to_block : _,
208+ loc : _,
209+ // There are some private fields we cannot access; they contain no tags.
210+ ..
211+ } = self ;
212+
213+ // Return place.
214+ return_place. visit_tags ( visit) ;
215+ // Locals.
216+ for local in locals. iter ( ) {
217+ if let LocalValue :: Live ( value) = & local. value {
218+ value. visit_tags ( visit) ;
219+ }
220+ }
221+
222+ extra. visit_tags ( visit) ;
223+ }
224+ }
225+
184226/// A specific moment in time.
185227#[ derive( Debug ) ]
186228pub enum Time {
@@ -253,6 +295,29 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> {
253295 }
254296}
255297
298+ impl VisitTags for ThreadManager < ' _ , ' _ > {
299+ fn visit_tags ( & self , visit : & mut dyn FnMut ( SbTag ) ) {
300+ let ThreadManager {
301+ threads,
302+ thread_local_alloc_ids,
303+ timeout_callbacks,
304+ active_thread : _,
305+ yield_active_thread : _,
306+ sync : _,
307+ } = self ;
308+
309+ for thread in threads {
310+ thread. visit_tags ( visit) ;
311+ }
312+ for ptr in thread_local_alloc_ids. borrow ( ) . values ( ) {
313+ ptr. visit_tags ( visit) ;
314+ }
315+ for callback in timeout_callbacks. values ( ) {
316+ callback. callback . visit_tags ( visit) ;
317+ }
318+ }
319+ }
320+
256321impl < ' mir , ' tcx : ' mir > ThreadManager < ' mir , ' tcx > {
257322 pub ( crate ) fn init ( ecx : & mut MiriInterpCx < ' mir , ' tcx > ) {
258323 if ecx. tcx . sess . target . os . as_ref ( ) != "windows" {
@@ -625,33 +690,6 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
625690 }
626691}
627692
628- impl VisitMachineValues for ThreadManager < ' _ , ' _ > {
629- fn visit_machine_values ( & self , visit : & mut impl FnMut ( & Operand < Provenance > ) ) {
630- // FIXME some other fields also contain machine values
631- let ThreadManager { threads, .. } = self ;
632-
633- for thread in threads {
634- // FIXME: implement VisitMachineValues for `Thread` and `Frame` instead.
635- // In particular we need to visit the `last_error` and `catch_unwind` fields.
636- if let Some ( payload) = thread. panic_payload {
637- visit ( & Operand :: Immediate ( Immediate :: Scalar ( payload) ) )
638- }
639- for frame in & thread. stack {
640- // Return place.
641- if let Place :: Ptr ( mplace) = * frame. return_place {
642- visit ( & Operand :: Indirect ( mplace) ) ;
643- }
644- // Locals.
645- for local in frame. locals . iter ( ) {
646- if let LocalValue :: Live ( value) = & local. value {
647- visit ( value) ;
648- }
649- }
650- }
651- }
652- }
653- }
654-
655693// Public interface to thread management.
656694impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
657695pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriInterpCxExt < ' mir , ' tcx > {
@@ -930,7 +968,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
930968 // 2. Make the scheduler the only place that can change the active
931969 // thread.
932970 let old_thread = this. set_active_thread ( thread) ;
933- callback ( this) ?;
971+ callback. call ( this) ?;
934972 this. set_active_thread ( old_thread) ;
935973 Ok ( ( ) )
936974 }
0 commit comments