@@ -232,10 +232,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
232
232
M :: GLOBAL_KIND . map( MemoryKind :: Machine ) ,
233
233
"dynamically allocating global memory"
234
234
) ;
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) ) ;
237
237
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) )
239
239
}
240
240
241
241
pub fn reallocate (
@@ -334,7 +334,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
334
334
335
335
// Let the machine take some extra action
336
336
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
+ ) ?;
338
343
339
344
// Don't forget to remember size and align of this now-dead allocation
340
345
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> {
492
497
/// this machine use the same pointer tag, so it is indirected through
493
498
/// `M::tag_allocation`.
494
499
fn get_global_alloc (
495
- memory_extra : & M :: MemoryExtra ,
496
- tcx : TyCtxt < ' tcx > ,
500
+ & self ,
497
501
id : AllocId ,
498
502
is_write : bool ,
499
503
) -> 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) {
501
505
Some ( GlobalAlloc :: Memory ( mem) ) => {
502
506
// Memory of a constant or promoted or anonymous memory referenced by a static.
503
507
( mem, None )
504
508
}
505
509
Some ( GlobalAlloc :: Function ( ..) ) => throw_ub ! ( DerefFunctionPointer ( id) ) ,
506
510
None => throw_ub ! ( PointerUseAfterFree ( id) ) ,
507
511
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) ) ;
510
514
// Notice that every static has two `AllocId` that will resolve to the same
511
515
// thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
512
516
// 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> {
517
521
// The `GlobalAlloc::Memory` branch here is still reachable though; when a static
518
522
// contains a reference to memory that was created during its evaluation (i.e., not
519
523
// 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) {
521
525
throw_unsup ! ( ReadExternStatic ( def_id) ) ;
522
526
}
523
527
524
- ( tcx. eval_static_initializer ( def_id) ?, Some ( def_id) )
528
+ ( self . tcx . eval_static_initializer ( def_id) ?, Some ( def_id) )
525
529
}
526
530
} ;
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) ?;
528
532
let alloc = Cow :: Borrowed ( alloc) ;
529
533
// We got tcx memory. Let the machine initialize its "extra" stuff.
530
534
let alloc = M :: init_allocation_extra (
531
- memory_extra,
532
- tcx,
535
+ self ,
533
536
id, // always use the ID we got as input, not the "hidden" one.
534
537
alloc,
535
538
M :: GLOBAL_KIND . map ( MemoryKind :: Machine ) ,
@@ -548,7 +551,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
548
551
// `get_global_alloc` that we can actually use directly without inserting anything anywhere.
549
552
// So the error type is `InterpResult<'tcx, &Allocation<M::PointerTag>>`.
550
553
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 )
552
555
. map_err ( Err ) ?;
553
556
match alloc {
554
557
Cow :: Borrowed ( alloc) => {
@@ -619,30 +622,26 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
619
622
id : AllocId ,
620
623
) -> InterpResult < ' tcx , ( & mut Allocation < M :: PointerTag , M :: AllocExtra > , & mut M :: MemoryExtra ) >
621
624
{
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 ) ?;
628
633
let kind = M :: GLOBAL_KIND . expect (
629
634
"I got a global allocation that I have to copy but the machine does \
630
635
not expect that to happen",
631
636
) ;
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) )
645
643
}
644
+ Ok ( ( alloc, & mut self . extra ) )
646
645
}
647
646
648
647
/// "Safe" (bounds and align-checked) allocation access.
@@ -737,7 +736,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
737
736
}
738
737
739
738
fn get_fn_alloc ( & self , id : AllocId ) -> Option < FnVal < ' tcx , M :: ExtraFnVal > > {
740
- trace ! ( "reading fn ptr: {}" , id) ;
741
739
if let Some ( extra) = self . extra_fn_ptr_map . get ( & id) {
742
740
Some ( FnVal :: Other ( * extra) )
743
741
} else {
@@ -752,6 +750,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
752
750
& self ,
753
751
ptr : Pointer < Option < M :: PointerTag > > ,
754
752
) -> InterpResult < ' tcx , FnVal < ' tcx , M :: ExtraFnVal > > {
753
+ trace ! ( "get_fn({:?})" , ptr) ;
755
754
let ( alloc_id, offset, ptr) = self . ptr_get_alloc ( ptr) ?;
756
755
if offset. bytes ( ) != 0 {
757
756
throw_ub ! ( InvalidFunctionPointer ( ptr. erase_for_fmt( ) ) )
@@ -1046,12 +1045,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
1046
1045
// since we don't want to keep any relocations at the target.
1047
1046
// (`get_bytes_with_uninit_and_ptr` below checks that there are no
1048
1047
// 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) ;
1055
1050
// Prepare a copy of the initialization mask.
1056
1051
let compressed = src_alloc. compress_uninit_range ( src_range) ;
1057
1052
// This checks relocation edges on the src.
@@ -1064,9 +1059,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
1064
1059
let ( dest_alloc, extra) = self . get_raw_mut ( dest_alloc_id) ?;
1065
1060
let dest_range = alloc_range ( dest_offset, size * num_copies) ;
1066
1061
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 ( ) ;
1070
1063
1071
1064
if compressed. no_bytes_init ( ) {
1072
1065
// Fast path: If all bytes are `uninit` then there is nothing to copy. The target range
0 commit comments