11use std:: cell:: { Cell , RefCell } ;
22
3+ use rand:: Rng ;
4+
35use rustc:: mir:: interpret:: { AllocId , Pointer , InterpResult } ;
46use rustc_mir:: interpret:: Memory ;
57use rustc_target:: abi:: Size ;
@@ -73,14 +75,24 @@ impl<'mir, 'tcx> GlobalState {
7375 let mut global_state = memory. extra . intptrcast . borrow_mut ( ) ;
7476
7577 let alloc = memory. get ( ptr. alloc_id ) ?;
78+ let align = alloc. align . bytes ( ) ;
7679
7780 let base_addr = match alloc. extra . intptrcast . base_addr . get ( ) {
7881 Some ( base_addr) => base_addr,
7982 None => {
8083 // This allocation does not have a base address yet, pick one.
81- let base_addr = Self :: align_addr ( global_state. next_base_addr , alloc. align . bytes ( ) ) ;
82- global_state. next_base_addr = base_addr + alloc. bytes . len ( ) as u64 ;
84+ // Leave some space to the previous allocation, to give it some chance to be less aligned.
85+ let slack = {
86+ let mut rng = memory. extra . rng . as_ref ( ) . unwrap ( ) . borrow_mut ( ) ;
87+ // This means that `(global_state.next_base_addr + slack) % 16` is uniformly distributed.
88+ rng. gen_range ( 0 , 16 )
89+ } ;
90+ // From next_base_addr + slack, round up to adjust for alignment.
91+ let base_addr = Self :: align_addr ( global_state. next_base_addr + slack, align) ;
8392 alloc. extra . intptrcast . base_addr . set ( Some ( base_addr) ) ;
93+
94+ // Remember next base address.
95+ global_state. next_base_addr = base_addr + alloc. bytes . len ( ) as u64 ;
8496 // Given that `next_base_addr` increases in each allocation, pushing the
8597 // corresponding tuple keeps `int_to_ptr_map` sorted
8698 global_state. int_to_ptr_map . push ( ( base_addr, ptr. alloc_id ) ) ;
@@ -89,13 +101,27 @@ impl<'mir, 'tcx> GlobalState {
89101 }
90102 } ;
91103
92- debug_assert_eq ! ( base_addr % alloc . align. bytes ( ) , 0 ) ; // sanity check
104+ debug_assert_eq ! ( base_addr % align, 0 ) ; // sanity check
93105 Ok ( base_addr + ptr. offset . bytes ( ) )
94106 }
95107
96108 /// Shifts `addr` to make it aligned with `align` by rounding `addr` to the smallest multiple
97- /// of `align` that is strictly larger to `addr`
109+ /// of `align` that is larger or equal to `addr`
98110 fn align_addr ( addr : u64 , align : u64 ) -> u64 {
99- addr + align - addr % align
111+ match addr % align {
112+ 0 => addr,
113+ rem => addr + align - rem
114+ }
115+ }
116+ }
117+
118+ #[ cfg( test) ]
119+ mod tests {
120+ use super :: * ;
121+
122+ #[ test]
123+ fn test_align_addr ( ) {
124+ assert_eq ! ( GlobalState :: align_addr( 37 , 4 ) , 40 ) ;
125+ assert_eq ! ( GlobalState :: align_addr( 44 , 4 ) , 44 ) ;
100126 }
101127}
0 commit comments