@@ -164,100 +164,50 @@ pub struct SynchronizationObjects {
164164impl < ' tcx > EvalContextExtPriv < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
165165pub ( super ) trait EvalContextExtPriv < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
166166 /// Lazily initialize the ID of this Miri sync structure.
167- /// ('0' indicates uninit.)
167+ /// If memory stores '0', that indicates uninit and we generate a new instance.
168+ /// Returns `None` if memory stores a non-zero invalid ID.
169+ ///
170+ /// `get_objs` must return the `IndexVec` that stores all the objects of this type.
168171 #[ inline]
169- fn get_or_create_id < Id : SyncId > (
172+ fn get_or_create_id < Id : SyncId + Idx , T : Default > (
170173 & mut self ,
171- next_id : Id ,
172174 lock_op : & OpTy < ' tcx > ,
173175 lock_layout : TyAndLayout < ' tcx > ,
174176 offset : u64 ,
177+ get_objs : impl for < ' a > Fn ( & ' a mut MiriInterpCx < ' tcx > ) -> & ' a mut IndexVec < Id , T > ,
175178 ) -> InterpResult < ' tcx , Option < Id > > {
176179 let this = self . eval_context_mut ( ) ;
177180 let value_place =
178181 this. deref_pointer_and_offset ( lock_op, offset, lock_layout, this. machine . layouts . u32 ) ?;
182+ let next_index = get_objs ( this) . next_index ( ) ;
179183
180184 // Since we are lazy, this update has to be atomic.
181185 let ( old, success) = this
182186 . atomic_compare_exchange_scalar (
183187 & value_place,
184188 & ImmTy :: from_uint ( 0u32 , this. machine . layouts . u32 ) ,
185- Scalar :: from_u32 ( next_id . to_u32 ( ) ) ,
189+ Scalar :: from_u32 ( next_index . to_u32 ( ) ) ,
186190 AtomicRwOrd :: Relaxed , // deliberately *no* synchronization
187191 AtomicReadOrd :: Relaxed ,
188192 false ,
189193 ) ?
190194 . to_scalar_pair ( ) ;
191195
192196 Ok ( if success. to_bool ( ) . expect ( "compare_exchange's second return value is a bool" ) {
193- // Caller of the closure needs to allocate next_id
194- None
195- } else {
196- Some ( Id :: from_u32 ( old. to_u32 ( ) . expect ( "layout is u32" ) ) )
197- } )
198- }
199-
200- /// Provides the closure with the next MutexId. Creates that mutex if the closure returns None,
201- /// otherwise returns the value from the closure.
202- #[ inline]
203- fn mutex_get_or_create < F > ( & mut self , existing : F ) -> InterpResult < ' tcx , MutexId >
204- where
205- F : FnOnce ( & mut MiriInterpCx < ' tcx > , MutexId ) -> InterpResult < ' tcx , Option < MutexId > > ,
206- {
207- let this = self . eval_context_mut ( ) ;
208- let next_index = this. machine . sync . mutexes . next_index ( ) ;
209- if let Some ( old) = existing ( this, next_index) ? {
210- if this. machine . sync . mutexes . get ( old) . is_none ( ) {
211- throw_ub_format ! ( "mutex has invalid ID" ) ;
212- }
213- Ok ( old)
214- } else {
215- let new_index = this. machine . sync . mutexes . push ( Default :: default ( ) ) ;
197+ // We set the in-memory ID to `next_index`, now also create this object in the machine
198+ // state.
199+ let new_index = get_objs ( this) . push ( T :: default ( ) ) ;
216200 assert_eq ! ( next_index, new_index) ;
217- Ok ( new_index)
218- }
219- }
220-
221- /// Provides the closure with the next RwLockId. Creates that RwLock if the closure returns None,
222- /// otherwise returns the value from the closure.
223- #[ inline]
224- fn rwlock_get_or_create < F > ( & mut self , existing : F ) -> InterpResult < ' tcx , RwLockId >
225- where
226- F : FnOnce ( & mut MiriInterpCx < ' tcx > , RwLockId ) -> InterpResult < ' tcx , Option < RwLockId > > ,
227- {
228- let this = self . eval_context_mut ( ) ;
229- let next_index = this. machine . sync . rwlocks . next_index ( ) ;
230- if let Some ( old) = existing ( this, next_index) ? {
231- if this. machine . sync . rwlocks . get ( old) . is_none ( ) {
232- throw_ub_format ! ( "rwlock has invalid ID" ) ;
233- }
234- Ok ( old)
201+ Some ( new_index)
235202 } else {
236- let new_index = this. machine . sync . rwlocks . push ( Default :: default ( ) ) ;
237- assert_eq ! ( next_index, new_index) ;
238- Ok ( new_index)
239- }
240- }
241-
242- /// Provides the closure with the next CondvarId. Creates that Condvar if the closure returns None,
243- /// otherwise returns the value from the closure.
244- #[ inline]
245- fn condvar_get_or_create < F > ( & mut self , existing : F ) -> InterpResult < ' tcx , CondvarId >
246- where
247- F : FnOnce ( & mut MiriInterpCx < ' tcx > , CondvarId ) -> InterpResult < ' tcx , Option < CondvarId > > ,
248- {
249- let this = self . eval_context_mut ( ) ;
250- let next_index = this. machine . sync . condvars . next_index ( ) ;
251- if let Some ( old) = existing ( this, next_index) ? {
252- if this. machine . sync . condvars . get ( old) . is_none ( ) {
253- throw_ub_format ! ( "condvar has invalid ID" ) ;
203+ let id = Id :: from_u32 ( old. to_u32 ( ) . expect ( "layout is u32" ) ) ;
204+ if get_objs ( this) . get ( id) . is_none ( ) {
205+ // The in-memory ID is invalid.
206+ None
207+ } else {
208+ Some ( id)
254209 }
255- Ok ( old)
256- } else {
257- let new_index = this. machine . sync . condvars . push ( Default :: default ( ) ) ;
258- assert_eq ! ( next_index, new_index) ;
259- Ok ( new_index)
260- }
210+ } )
261211 }
262212
263213 fn condvar_reacquire_mutex (
@@ -293,9 +243,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
293243 offset : u64 ,
294244 ) -> InterpResult < ' tcx , MutexId > {
295245 let this = self . eval_context_mut ( ) ;
296- this. mutex_get_or_create ( |ecx, next_id| {
297- ecx. get_or_create_id ( next_id, lock_op, lock_layout, offset)
298- } )
246+ this. get_or_create_id ( lock_op, lock_layout, offset, |ecx| & mut ecx. machine . sync . mutexes ) ?
247+ . ok_or_else ( || err_ub_format ! ( "mutex has invalid ID" ) . into ( ) )
299248 }
300249
301250 fn rwlock_get_or_create_id (
@@ -305,9 +254,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
305254 offset : u64 ,
306255 ) -> InterpResult < ' tcx , RwLockId > {
307256 let this = self . eval_context_mut ( ) ;
308- this. rwlock_get_or_create ( |ecx, next_id| {
309- ecx. get_or_create_id ( next_id, lock_op, lock_layout, offset)
310- } )
257+ this. get_or_create_id ( lock_op, lock_layout, offset, |ecx| & mut ecx. machine . sync . rwlocks ) ?
258+ . ok_or_else ( || err_ub_format ! ( "rwlock has invalid ID" ) . into ( ) )
311259 }
312260
313261 fn condvar_get_or_create_id (
@@ -317,9 +265,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
317265 offset : u64 ,
318266 ) -> InterpResult < ' tcx , CondvarId > {
319267 let this = self . eval_context_mut ( ) ;
320- this. condvar_get_or_create ( |ecx, next_id| {
321- ecx. get_or_create_id ( next_id, lock_op, lock_layout, offset)
322- } )
268+ this. get_or_create_id ( lock_op, lock_layout, offset, |ecx| & mut ecx. machine . sync . condvars ) ?
269+ . ok_or_else ( || err_ub_format ! ( "condvar has invalid ID" ) . into ( ) )
323270 }
324271
325272 #[ inline]
0 commit comments