@@ -32,9 +32,11 @@ pub enum SchedulingAction {
32
32
33
33
/// Timeout callbacks can be created by synchronization primitives to tell the
34
34
/// 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 > ;
38
40
39
41
/// A thread identifier.
40
42
#[ derive( Clone , Copy , Debug , PartialOrd , Ord , PartialEq , Eq , Hash ) ]
@@ -181,6 +183,46 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
181
183
}
182
184
}
183
185
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
+
184
226
/// A specific moment in time.
185
227
#[ derive( Debug ) ]
186
228
pub enum Time {
@@ -253,6 +295,29 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> {
253
295
}
254
296
}
255
297
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
+
256
321
impl < ' mir , ' tcx : ' mir > ThreadManager < ' mir , ' tcx > {
257
322
pub ( crate ) fn init ( ecx : & mut MiriInterpCx < ' mir , ' tcx > ) {
258
323
if ecx. tcx . sess . target . os . as_ref ( ) != "windows" {
@@ -625,33 +690,6 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
625
690
}
626
691
}
627
692
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
-
655
693
// Public interface to thread management.
656
694
impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriInterpCx < ' mir , ' tcx > { }
657
695
pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriInterpCxExt < ' mir , ' tcx > {
@@ -930,7 +968,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
930
968
// 2. Make the scheduler the only place that can change the active
931
969
// thread.
932
970
let old_thread = this. set_active_thread ( thread) ;
933
- callback ( this) ?;
971
+ callback. call ( this) ?;
934
972
this. set_active_thread ( old_thread) ;
935
973
Ok ( ( ) )
936
974
}
0 commit comments