@@ -232,10 +232,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
232232 M :: GLOBAL_KIND . map( MemoryKind :: Machine ) ,
233233 "dynamically allocating global memory"
234234 ) ;
235- // This is a new allocation, not a new global one, so no `global_base_ptr`.
236- let alloc = M :: init_allocation_extra ( & self . extra , self . tcx , id, Cow :: Owned ( alloc) , Some ( kind) ) ;
235+ let alloc =
236+ M :: init_allocation_extra ( self , id, Cow :: Owned ( alloc) , Some ( kind) ) ;
237237 self . alloc_map . insert ( id, ( kind, alloc. into_owned ( ) ) ) ;
238- M :: tag_alloc_base_pointer ( self , Pointer :: new ( id, Size :: ZERO ) )
238+ M :: tag_alloc_base_pointer ( self , Pointer :: from ( id) )
239239 }
240240
241241 pub fn reallocate (
@@ -334,7 +334,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
334334
335335 // Let the machine take some extra action
336336 let size = alloc. size ( ) ;
337- M :: memory_deallocated ( & mut self . extra , & mut alloc. extra , ptr. provenance , alloc_range ( Size :: ZERO , size) ) ?;
337+ M :: memory_deallocated (
338+ & mut self . extra ,
339+ & mut alloc. extra ,
340+ ptr. provenance ,
341+ alloc_range ( Size :: ZERO , size) ,
342+ ) ?;
338343
339344 // Don't forget to remember size and align of this now-dead allocation
340345 let old = self . dead_alloc_map . insert ( alloc_id, ( size, alloc. align ) ) ;
@@ -492,21 +497,20 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
492497 /// this machine use the same pointer tag, so it is indirected through
493498 /// `M::tag_allocation`.
494499 fn get_global_alloc (
495- memory_extra : & M :: MemoryExtra ,
496- tcx : TyCtxt < ' tcx > ,
500+ & self ,
497501 id : AllocId ,
498502 is_write : bool ,
499503 ) -> InterpResult < ' tcx , Cow < ' tcx , Allocation < M :: PointerTag , M :: AllocExtra > > > {
500- let ( alloc, def_id) = match tcx. get_global_alloc ( id) {
504+ let ( alloc, def_id) = match self . tcx . get_global_alloc ( id) {
501505 Some ( GlobalAlloc :: Memory ( mem) ) => {
502506 // Memory of a constant or promoted or anonymous memory referenced by a static.
503507 ( mem, None )
504508 }
505509 Some ( GlobalAlloc :: Function ( ..) ) => throw_ub ! ( DerefFunctionPointer ( id) ) ,
506510 None => throw_ub ! ( PointerUseAfterFree ( id) ) ,
507511 Some ( GlobalAlloc :: Static ( def_id) ) => {
508- assert ! ( tcx. is_static( def_id) ) ;
509- assert ! ( !tcx. is_thread_local_static( def_id) ) ;
512+ assert ! ( self . tcx. is_static( def_id) ) ;
513+ assert ! ( !self . tcx. is_thread_local_static( def_id) ) ;
510514 // Notice that every static has two `AllocId` that will resolve to the same
511515 // thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
512516 // and the other one is maps to `GlobalAlloc::Memory`, this is returned by
@@ -517,19 +521,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
517521 // The `GlobalAlloc::Memory` branch here is still reachable though; when a static
518522 // contains a reference to memory that was created during its evaluation (i.e., not
519523 // to another static), those inner references only exist in "resolved" form.
520- if tcx. is_foreign_item ( def_id) {
524+ if self . tcx . is_foreign_item ( def_id) {
521525 throw_unsup ! ( ReadExternStatic ( def_id) ) ;
522526 }
523527
524- ( tcx. eval_static_initializer ( def_id) ?, Some ( def_id) )
528+ ( self . tcx . eval_static_initializer ( def_id) ?, Some ( def_id) )
525529 }
526530 } ;
527- M :: before_access_global ( memory_extra , id, alloc, def_id, is_write) ?;
531+ M :: before_access_global ( & self . extra , id, alloc, def_id, is_write) ?;
528532 let alloc = Cow :: Borrowed ( alloc) ;
529533 // We got tcx memory. Let the machine initialize its "extra" stuff.
530534 let alloc = M :: init_allocation_extra (
531- memory_extra,
532- tcx,
535+ self ,
533536 id, // always use the ID we got as input, not the "hidden" one.
534537 alloc,
535538 M :: GLOBAL_KIND . map ( MemoryKind :: Machine ) ,
@@ -548,7 +551,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
548551 // `get_global_alloc` that we can actually use directly without inserting anything anywhere.
549552 // So the error type is `InterpResult<'tcx, &Allocation<M::PointerTag>>`.
550553 let a = self . alloc_map . get_or ( id, || {
551- let alloc = Self :: get_global_alloc ( & self . extra , self . tcx , id, /*is_write*/ false )
554+ let alloc = self . get_global_alloc ( id, /*is_write*/ false )
552555 . map_err ( Err ) ?;
553556 match alloc {
554557 Cow :: Borrowed ( alloc) => {
@@ -619,30 +622,26 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
619622 id : AllocId ,
620623 ) -> InterpResult < ' tcx , ( & mut Allocation < M :: PointerTag , M :: AllocExtra > , & mut M :: MemoryExtra ) >
621624 {
622- let tcx = self . tcx ;
623- let memory_extra = & mut self . extra ;
624- let a = self . alloc_map . get_mut_or ( id, || {
625- // Need to make a copy, even if `get_global_alloc` is able
626- // to give us a cheap reference.
627- let alloc = Self :: get_global_alloc ( memory_extra, tcx, id, /*is_write*/ true ) ?;
625+ // We have "NLL problem case #3" here, which cannot be worked around without loss of
626+ // efficiency even for the common case where the key is in the map.
627+ // <https://rust-lang.github.io/rfcs/2094-nll.html#problem-case-3-conditional-control-flow-across-functions>
628+ // (Cannot use `get_mut_or` since `get_global_alloc` needs `&self`.)
629+ if self . alloc_map . get_mut ( id) . is_none ( ) {
630+ // Slow path.
631+ // Allocation not found locally, go look global.
632+ let alloc = self . get_global_alloc ( id, /*is_write*/ true ) ?;
628633 let kind = M :: GLOBAL_KIND . expect (
629634 "I got a global allocation that I have to copy but the machine does \
630635 not expect that to happen",
631636 ) ;
632- Ok ( ( MemoryKind :: Machine ( kind) , alloc. into_owned ( ) ) )
633- } ) ;
634- // Unpack the error type manually because type inference doesn't
635- // work otherwise (and we cannot help it because `impl Trait`)
636- match a {
637- Err ( e) => Err ( e) ,
638- Ok ( a) => {
639- let a = & mut a. 1 ;
640- if a. mutability == Mutability :: Not {
641- throw_ub ! ( WriteToReadOnly ( id) )
642- }
643- Ok ( ( a, memory_extra) )
644- }
637+ self . alloc_map . insert ( id, ( MemoryKind :: Machine ( kind) , alloc. into_owned ( ) ) ) ;
638+ }
639+
640+ let ( _kind, alloc) = self . alloc_map . get_mut ( id) . unwrap ( ) ;
641+ if alloc. mutability == Mutability :: Not {
642+ throw_ub ! ( WriteToReadOnly ( id) )
645643 }
644+ Ok ( ( alloc, & mut self . extra ) )
646645 }
647646
648647 /// "Safe" (bounds and align-checked) allocation access.
@@ -737,7 +736,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
737736 }
738737
739738 fn get_fn_alloc ( & self , id : AllocId ) -> Option < FnVal < ' tcx , M :: ExtraFnVal > > {
740- trace ! ( "reading fn ptr: {}" , id) ;
741739 if let Some ( extra) = self . extra_fn_ptr_map . get ( & id) {
742740 Some ( FnVal :: Other ( * extra) )
743741 } else {
@@ -752,6 +750,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
752750 & self ,
753751 ptr : Pointer < Option < M :: PointerTag > > ,
754752 ) -> InterpResult < ' tcx , FnVal < ' tcx , M :: ExtraFnVal > > {
753+ trace ! ( "get_fn({:?})" , ptr) ;
755754 let ( alloc_id, offset, ptr) = self . ptr_get_alloc ( ptr) ?;
756755 if offset. bytes ( ) != 0 {
757756 throw_ub ! ( InvalidFunctionPointer ( ptr. erase_for_fmt( ) ) )
@@ -1046,12 +1045,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
10461045 // since we don't want to keep any relocations at the target.
10471046 // (`get_bytes_with_uninit_and_ptr` below checks that there are no
10481047 // relocations overlapping the edges; those would not be handled correctly).
1049- let relocations = src_alloc. prepare_relocation_copy (
1050- self ,
1051- src_range,
1052- dest_offset,
1053- num_copies,
1054- ) ;
1048+ let relocations =
1049+ src_alloc. prepare_relocation_copy ( self , src_range, dest_offset, num_copies) ;
10551050 // Prepare a copy of the initialization mask.
10561051 let compressed = src_alloc. compress_uninit_range ( src_range) ;
10571052 // This checks relocation edges on the src.
@@ -1064,9 +1059,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
10641059 let ( dest_alloc, extra) = self . get_raw_mut ( dest_alloc_id) ?;
10651060 let dest_range = alloc_range ( dest_offset, size * num_copies) ;
10661061 M :: memory_written ( extra, & mut dest_alloc. extra , dest. provenance , dest_range) ?;
1067- let dest_bytes = dest_alloc
1068- . get_bytes_mut_ptr ( & tcx, dest_range)
1069- . as_mut_ptr ( ) ;
1062+ let dest_bytes = dest_alloc. get_bytes_mut_ptr ( & tcx, dest_range) . as_mut_ptr ( ) ;
10701063
10711064 if compressed. no_bytes_init ( ) {
10721065 // Fast path: If all bytes are `uninit` then there is nothing to copy. The target range
0 commit comments