@@ -535,41 +535,48 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
535535 id : AllocId ,
536536 liveness : AllocCheck ,
537537 ) -> InterpResult < ' static , ( Size , Align ) > {
538- // Regular allocations.
539- if let Ok ( alloc) = self . get ( id) {
540- return Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ;
541- }
542- // Function pointers.
543- if let Ok ( _) = self . get_fn_alloc ( id) {
544- return if let AllocCheck :: Dereferencable = liveness {
545- // The caller requested no function pointers.
546- err ! ( DerefFunctionPointer )
547- } else {
548- Ok ( ( Size :: ZERO , Align :: from_bytes ( 1 ) . unwrap ( ) ) )
549- } ;
550- }
551- // Foreign statics.
552- // Can't do this in the match argument, we may get cycle errors since the lock would
553- // be held throughout the match.
554- let alloc = self . tcx . alloc_map . lock ( ) . get ( id) ;
555- match alloc {
556- Some ( GlobalAlloc :: Static ( did) ) => {
557- assert ! ( self . tcx. is_foreign_item( did) ) ;
558- // Use size and align of the type
559- let ty = self . tcx . type_of ( did) ;
560- let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
561- return Ok ( ( layout. size , layout. align . abi ) ) ;
538+ // Don't use `self.get` here as that will
539+ // a) cause cycles in case `id` refers to a static
540+ // b) duplicate a static's allocation in miri
541+ match self . alloc_map . get_or ( id, || Err ( ( ) ) ) {
542+ Ok ( ( _, alloc) ) => Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ,
543+ Err ( ( ) ) => {
544+ // Not a local allocation, check the global `tcx.alloc_map`.
545+
546+ // Can't do this in the match argument, we may get cycle errors since the lock would
547+ // be held throughout the match.
548+ let alloc = self . tcx . alloc_map . lock ( ) . get ( id) ;
549+ match alloc {
550+ Some ( GlobalAlloc :: Static ( did) ) => {
551+ // Use size and align of the type.
552+ let ty = self . tcx . type_of ( did) ;
553+ let layout = self . tcx . layout_of ( ParamEnv :: empty ( ) . and ( ty) ) . unwrap ( ) ;
554+ Ok ( ( layout. size , layout. align . abi ) )
555+ } ,
556+ Some ( GlobalAlloc :: Memory ( alloc) ) =>
557+ // Need to duplicate the logic here, because the global allocations have
558+ // different associated types than the interpreter-local ones.
559+ Ok ( ( Size :: from_bytes ( alloc. bytes . len ( ) as u64 ) , alloc. align ) ) ,
560+ Some ( GlobalAlloc :: Function ( _) ) => {
561+ if let AllocCheck :: Dereferencable = liveness {
562+ // The caller requested no function pointers.
563+ err ! ( DerefFunctionPointer )
564+ } else {
565+ Ok ( ( Size :: ZERO , Align :: from_bytes ( 1 ) . unwrap ( ) ) )
566+ }
567+ } ,
568+ // The rest must be dead.
569+ None => if let AllocCheck :: MaybeDead = liveness {
570+ // Deallocated pointers are allowed, we should be able to find
571+ // them in the map.
572+ Ok ( * self . dead_alloc_map . get ( & id)
573+ . expect ( "deallocated pointers should all be recorded in \
574+ `dead_alloc_map`") )
575+ } else {
576+ err ! ( DanglingPointerDeref )
577+ } ,
578+ }
562579 }
563- _ => { }
564- }
565- // The rest must be dead.
566- if let AllocCheck :: MaybeDead = liveness {
567- // Deallocated pointers are allowed, we should be able to find
568- // them in the map.
569- Ok ( * self . dead_alloc_map . get ( & id)
570- . expect ( "deallocated pointers should all be recorded in `dead_alloc_map`" ) )
571- } else {
572- err ! ( DanglingPointerDeref )
573580 }
574581 }
575582
0 commit comments