@@ -164,100 +164,50 @@ pub struct SynchronizationObjects {
164
164
impl < ' tcx > EvalContextExtPriv < ' tcx > for crate :: MiriInterpCx < ' tcx > { }
165
165
pub ( super ) trait EvalContextExtPriv < ' tcx > : crate :: MiriInterpCxExt < ' tcx > {
166
166
/// 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.
168
171
#[ inline]
169
- fn get_or_create_id < Id : SyncId > (
172
+ fn get_or_create_id < Id : SyncId + Idx , T : Default > (
170
173
& mut self ,
171
- next_id : Id ,
172
174
lock_op : & OpTy < ' tcx > ,
173
175
lock_layout : TyAndLayout < ' tcx > ,
174
176
offset : u64 ,
177
+ get_objs : impl for < ' a > Fn ( & ' a mut MiriInterpCx < ' tcx > ) -> & ' a mut IndexVec < Id , T > ,
175
178
) -> InterpResult < ' tcx , Option < Id > > {
176
179
let this = self . eval_context_mut ( ) ;
177
180
let value_place =
178
181
this. deref_pointer_and_offset ( lock_op, offset, lock_layout, this. machine . layouts . u32 ) ?;
182
+ let next_index = get_objs ( this) . next_index ( ) ;
179
183
180
184
// Since we are lazy, this update has to be atomic.
181
185
let ( old, success) = this
182
186
. atomic_compare_exchange_scalar (
183
187
& value_place,
184
188
& ImmTy :: from_uint ( 0u32 , this. machine . layouts . u32 ) ,
185
- Scalar :: from_u32 ( next_id . to_u32 ( ) ) ,
189
+ Scalar :: from_u32 ( next_index . to_u32 ( ) ) ,
186
190
AtomicRwOrd :: Relaxed , // deliberately *no* synchronization
187
191
AtomicReadOrd :: Relaxed ,
188
192
false ,
189
193
) ?
190
194
. to_scalar_pair ( ) ;
191
195
192
196
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 ( ) ) ;
216
200
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)
235
202
} 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)
254
209
}
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
+ } )
261
211
}
262
212
263
213
fn condvar_reacquire_mutex (
@@ -293,9 +243,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
293
243
offset : u64 ,
294
244
) -> InterpResult < ' tcx , MutexId > {
295
245
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 ( ) )
299
248
}
300
249
301
250
fn rwlock_get_or_create_id (
@@ -305,9 +254,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
305
254
offset : u64 ,
306
255
) -> InterpResult < ' tcx , RwLockId > {
307
256
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 ( ) )
311
259
}
312
260
313
261
fn condvar_get_or_create_id (
@@ -317,9 +265,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
317
265
offset : u64 ,
318
266
) -> InterpResult < ' tcx , CondvarId > {
319
267
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 ( ) )
323
270
}
324
271
325
272
#[ inline]
0 commit comments