1616//! integer. It is crucial that these operations call `check_align` *before*
1717//! short-circuiting the empty case!
1818
19- use std:: collections:: hash_map:: Entry ;
2019use std:: collections:: VecDeque ;
2120use std:: ptr;
2221use std:: borrow:: Cow ;
2322
2423use rustc:: ty:: { self , Instance , ParamEnv , query:: TyCtxtAt } ;
2524use rustc:: ty:: layout:: { self , Align , TargetDataLayout , Size , HasDataLayout } ;
26- use rustc:: mir:: interpret:: { Pointer , AllocId , Allocation , ConstValue , GlobalId ,
27- EvalResult , Scalar , EvalErrorKind , AllocType , PointerArithmetic ,
28- truncate} ;
25+ use rustc:: mir:: interpret:: {
26+ Pointer , AllocId , Allocation , ConstValue , GlobalId ,
27+ EvalResult , Scalar , EvalErrorKind , AllocType , PointerArithmetic ,
28+ truncate
29+ } ;
2930pub use rustc:: mir:: interpret:: { write_target_uint, read_target_uint} ;
3031use rustc_data_structures:: fx:: { FxHashSet , FxHashMap } ;
3132
3233use syntax:: ast:: Mutability ;
3334
34- use super :: { Machine , MonoHashMap , ScalarMaybeUndef } ;
35+ use super :: { Machine , AllocMap , ScalarMaybeUndef } ;
3536
3637#[ derive( Debug , PartialEq , Eq , Copy , Clone , Hash ) ]
3738pub enum MemoryKind < T > {
@@ -52,13 +53,13 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
5253 /// Allocations local to this instance of the miri engine. The kind
5354 /// helps ensure that the same mechanism is used for allocation and
5455 /// deallocation. When an allocation is not found here, it is a
55- /// static and looked up in the `tcx` for read access. If this machine
56- /// does pointer provenance tracking, the type of alloctions in `tcx`
57- /// and here do not match, so we have a `MonoHashMap` to be able to
58- /// put the "mapped" allocation into `alloc_map` even on a read access .
56+ /// static and looked up in the `tcx` for read access. Some machines may
57+ /// have to mutate this map even on a read-only access to a static (because
58+ /// they do pointer provenance tracking and the allocations in `tcx` have
59+ /// the wrong type), so we let the machine override this type .
5960 /// Either way, if the machine allows writing to a static, doing so will
6061 /// create a copy of the static allocation here.
61- alloc_map : MonoHashMap < AllocId , ( MemoryKind < M :: MemoryKinds > , Allocation < M :: PointerTag > ) > ,
62+ alloc_map : M :: MemoryMap ,
6263
6364 /// To be able to compare pointers with NULL, and to check alignment for accesses
6465 /// to ZSTs (where pointers may dangle), we keep track of the size even for allocations
@@ -106,7 +107,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
106107 pub fn new ( tcx : TyCtxtAt < ' a , ' tcx , ' tcx > , data : M :: MemoryData ) -> Self {
107108 Memory {
108109 data,
109- alloc_map : MonoHashMap :: default ( ) ,
110+ alloc_map : Default :: default ( ) ,
110111 dead_alloc_map : FxHashMap :: default ( ) ,
111112 tcx,
112113 }
@@ -419,30 +420,32 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
419420 & mut self ,
420421 id : AllocId ,
421422 ) -> EvalResult < ' tcx , & mut Allocation < M :: PointerTag > > {
422- Ok ( match self . alloc_map . entry ( id) {
423- // Normal alloc?
424- Entry :: Occupied ( alloc) => {
425- let alloc = & mut alloc. into_mut ( ) . 1 ;
426- if alloc. mutability == Mutability :: Immutable {
427- return err ! ( ModifiedConstantMemory ) ;
428- }
429- alloc
423+ let tcx = self . tcx ;
424+ let a = self . alloc_map . get_mut_or ( id, || {
425+ // Need to make a copy, even if `get_static_alloc` is able
426+ // to give us a cheap reference.
427+ let alloc = Self :: get_static_alloc ( tcx, id) ?;
428+ if alloc. mutability == Mutability :: Immutable {
429+ return err ! ( ModifiedConstantMemory ) ;
430430 }
431- // Static.
432- Entry :: Vacant ( entry) => {
433- // Need to make a copy, even if `get_static_alloc` is able
434- // to give us a cheap reference.
435- let alloc = Self :: get_static_alloc ( self . tcx , id) ?;
436- if alloc. mutability == Mutability :: Immutable {
431+ let kind = M :: STATIC_KIND . expect (
432+ "I got an owned allocation that I have to copy but the machine does \
433+ not expect that to happen"
434+ ) ;
435+ Ok ( ( MemoryKind :: Machine ( kind) , alloc. into_owned ( ) ) )
436+ } ) ;
437+ // Unpack the error type manually because type inference doesn't
438+ // work otherwise (and we cannot help it because `impl Trait`)
439+ match a {
440+ Err ( e) => Err ( e) ,
441+ Ok ( a) => {
442+ let a = & mut a. 1 ;
443+ if a. mutability == Mutability :: Immutable {
437444 return err ! ( ModifiedConstantMemory ) ;
438445 }
439- let kind = M :: STATIC_KIND . expect (
440- "I got an owned allocation that I have to copy but the machine does \
441- not expect that to happen"
442- ) ;
443- & mut entry. insert ( Box :: new ( ( MemoryKind :: Machine ( kind) , alloc. into_owned ( ) ) ) ) . 1
446+ Ok ( a)
444447 }
445- } )
448+ }
446449 }
447450
448451 pub fn get_fn ( & self , ptr : Pointer < M :: PointerTag > ) -> EvalResult < ' tcx , Instance < ' tcx > > {
@@ -534,8 +537,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
534537 let msg = format ! ( "Alloc {:<5} " , format!( "{}:" , id) ) ;
535538
536539 // normal alloc?
537- match self . alloc_map . get ( & id ) {
538- Some ( ( kind, alloc) ) => {
540+ match self . alloc_map . get_or ( id , || Err ( ( ) ) ) {
541+ Ok ( ( kind, alloc) ) => {
539542 let extra = match kind {
540543 MemoryKind :: Stack => " (stack)" . to_owned ( ) ,
541544 MemoryKind :: Vtable => " (vtable)" . to_owned ( ) ,
@@ -546,7 +549,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
546549 msg, alloc, extra
547550 ) ;
548551 } ,
549- None => {
552+ Err ( ( ) ) => {
550553 // static alloc?
551554 match self . tcx . alloc_map . lock ( ) . get ( id) {
552555 Some ( AllocType :: Memory ( alloc) ) => {
@@ -664,7 +667,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
664667}
665668
666669/// Interning (for CTFE)
667- impl < ' a , ' mir , ' tcx , M : Machine < ' a , ' mir , ' tcx , PointerTag =( ) > > Memory < ' a , ' mir , ' tcx , M > {
670+ impl < ' a , ' mir , ' tcx , M > Memory < ' a , ' mir , ' tcx , M >
671+ where
672+ M : Machine < ' a , ' mir , ' tcx , PointerTag =( ) > ,
673+ M :: MemoryMap : AllocMap < AllocId , ( MemoryKind < M :: MemoryKinds > , Allocation < ( ) > ) > ,
674+ {
668675 /// mark an allocation as static and initialized, either mutable or not
669676 pub fn intern_static (
670677 & mut self ,
0 commit comments