16
16
//! integer. It is crucial that these operations call `check_align` *before*
17
17
//! short-circuiting the empty case!
18
18
19
- use std:: collections:: hash_map:: Entry ;
20
19
use std:: collections:: VecDeque ;
21
20
use std:: ptr;
22
21
use std:: borrow:: Cow ;
23
22
24
23
use rustc:: ty:: { self , Instance , ParamEnv , query:: TyCtxtAt } ;
25
24
use 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
+ } ;
29
30
pub use rustc:: mir:: interpret:: { write_target_uint, read_target_uint} ;
30
31
use rustc_data_structures:: fx:: { FxHashSet , FxHashMap } ;
31
32
32
33
use syntax:: ast:: Mutability ;
33
34
34
- use super :: { Machine , MonoHashMap , ScalarMaybeUndef } ;
35
+ use super :: { Machine , AllocMap , ScalarMaybeUndef } ;
35
36
36
37
#[ derive( Debug , PartialEq , Eq , Copy , Clone , Hash ) ]
37
38
pub enum MemoryKind < T > {
@@ -52,13 +53,13 @@ pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
52
53
/// Allocations local to this instance of the miri engine. The kind
53
54
/// helps ensure that the same mechanism is used for allocation and
54
55
/// 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 .
59
60
/// Either way, if the machine allows writing to a static, doing so will
60
61
/// create a copy of the static allocation here.
61
- alloc_map : MonoHashMap < AllocId , ( MemoryKind < M :: MemoryKinds > , Allocation < M :: PointerTag > ) > ,
62
+ alloc_map : M :: MemoryMap ,
62
63
63
64
/// To be able to compare pointers with NULL, and to check alignment for accesses
64
65
/// 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> {
106
107
pub fn new ( tcx : TyCtxtAt < ' a , ' tcx , ' tcx > , data : M :: MemoryData ) -> Self {
107
108
Memory {
108
109
data,
109
- alloc_map : MonoHashMap :: default ( ) ,
110
+ alloc_map : Default :: default ( ) ,
110
111
dead_alloc_map : FxHashMap :: default ( ) ,
111
112
tcx,
112
113
}
@@ -419,30 +420,32 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
419
420
& mut self ,
420
421
id : AllocId ,
421
422
) -> 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 ) ;
430
430
}
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 {
437
444
return err ! ( ModifiedConstantMemory ) ;
438
445
}
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)
444
447
}
445
- } )
448
+ }
446
449
}
447
450
448
451
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> {
534
537
let msg = format ! ( "Alloc {:<5} " , format!( "{}:" , id) ) ;
535
538
536
539
// 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) ) => {
539
542
let extra = match kind {
540
543
MemoryKind :: Stack => " (stack)" . to_owned ( ) ,
541
544
MemoryKind :: Vtable => " (vtable)" . to_owned ( ) ,
@@ -546,7 +549,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
546
549
msg, alloc, extra
547
550
) ;
548
551
} ,
549
- None => {
552
+ Err ( ( ) ) => {
550
553
// static alloc?
551
554
match self . tcx . alloc_map . lock ( ) . get ( id) {
552
555
Some ( AllocType :: Memory ( alloc) ) => {
@@ -664,7 +667,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
664
667
}
665
668
666
669
/// 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
+ {
668
675
/// mark an allocation as static and initialized, either mutable or not
669
676
pub fn intern_static (
670
677
& mut self ,
0 commit comments