@@ -10,30 +10,48 @@ use crate::*;
1010
1111impl < ' mir , ' tcx > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
1212pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
13- /// Returns the minimum alignment for the target architecture.
14- fn min_align ( & self ) -> Align {
13+ /// Returns the minimum alignment for the target architecture for allocations of the given size .
14+ fn min_align ( & self , size : u64 , kind : MiriMemoryKind ) -> Align {
1515 let this = self . eval_context_ref ( ) ;
1616 // List taken from `libstd/sys_common/alloc.rs`.
1717 let min_align = match this. tcx . tcx . sess . target . target . arch . as_str ( ) {
1818 "x86" | "arm" | "mips" | "powerpc" | "powerpc64" | "asmjs" | "wasm32" => 8 ,
1919 "x86_64" | "aarch64" | "mips64" | "s390x" | "sparc64" => 16 ,
2020 arch => bug ! ( "Unsupported target architecture: {}" , arch) ,
2121 } ;
22- Align :: from_bytes ( min_align) . unwrap ( )
22+ // Windows always aligns, even small allocations.
23+ // Source: <https://support.microsoft.com/en-us/help/286470/how-to-use-pageheap-exe-in-windows-xp-windows-2000-and-windows-server>
24+ // But jemalloc does not, so for the C heap we only align if the allocation is sufficiently big.
25+ if kind == MiriMemoryKind :: WinHeap || size >= min_align {
26+ return Align :: from_bytes ( min_align) . unwrap ( ) ;
27+ }
28+ // We have `size < min_align`. Round `size` *down* to the next power of two and use that.
29+ fn prev_power_of_two ( x : u64 ) -> u64 {
30+ let next_pow2 = x. next_power_of_two ( ) ;
31+ if next_pow2 == x {
32+ // x *is* a power of two, just use that.
33+ x
34+ } else {
35+ // x is between two powers, so next = 2*prev.
36+ next_pow2 / 2
37+ }
38+ }
39+ Align :: from_bytes ( prev_power_of_two ( size) ) . unwrap ( )
2340 }
2441
2542 fn malloc (
2643 & mut self ,
2744 size : u64 ,
2845 zero_init : bool ,
46+ kind : MiriMemoryKind ,
2947 ) -> Scalar < Tag > {
3048 let this = self . eval_context_mut ( ) ;
3149 let tcx = & { this. tcx . tcx } ;
3250 if size == 0 {
3351 Scalar :: from_int ( 0 , this. pointer_size ( ) )
3452 } else {
35- let align = this. min_align ( ) ;
36- let ptr = this. memory_mut ( ) . allocate ( Size :: from_bytes ( size) , align, MiriMemoryKind :: C . into ( ) ) ;
53+ let align = this. min_align ( size , kind ) ;
54+ let ptr = this. memory_mut ( ) . allocate ( Size :: from_bytes ( size) , align, kind . into ( ) ) ;
3755 if zero_init {
3856 // We just allocated this, the access cannot fail
3957 this. memory_mut ( )
@@ -47,14 +65,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4765 fn free (
4866 & mut self ,
4967 ptr : Scalar < Tag > ,
68+ kind : MiriMemoryKind ,
5069 ) -> InterpResult < ' tcx > {
5170 let this = self . eval_context_mut ( ) ;
5271 if !this. is_null ( ptr) ? {
5372 let ptr = this. force_ptr ( ptr) ?;
5473 this. memory_mut ( ) . deallocate (
5574 ptr,
5675 None ,
57- MiriMemoryKind :: C . into ( ) ,
76+ kind . into ( ) ,
5877 ) ?;
5978 }
6079 Ok ( ( ) )
@@ -64,39 +83,38 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6483 & mut self ,
6584 old_ptr : Scalar < Tag > ,
6685 new_size : u64 ,
86+ kind : MiriMemoryKind ,
6787 ) -> InterpResult < ' tcx , Scalar < Tag > > {
6888 let this = self . eval_context_mut ( ) ;
69- let align = this. min_align ( ) ;
89+ let new_align = this. min_align ( new_size , kind ) ;
7090 if this. is_null ( old_ptr) ? {
7191 if new_size == 0 {
7292 Ok ( Scalar :: from_int ( 0 , this. pointer_size ( ) ) )
7393 } else {
7494 let new_ptr = this. memory_mut ( ) . allocate (
7595 Size :: from_bytes ( new_size) ,
76- align ,
77- MiriMemoryKind :: C . into ( )
96+ new_align ,
97+ kind . into ( )
7898 ) ;
7999 Ok ( Scalar :: Ptr ( new_ptr) )
80100 }
81101 } else {
82102 let old_ptr = this. force_ptr ( old_ptr) ?;
83103 let memory = this. memory_mut ( ) ;
84- let old_size = Size :: from_bytes ( memory. get ( old_ptr. alloc_id ) ?. bytes . len ( ) as u64 ) ;
85104 if new_size == 0 {
86105 memory. deallocate (
87106 old_ptr,
88- Some ( ( old_size , align ) ) ,
89- MiriMemoryKind :: C . into ( ) ,
107+ None ,
108+ kind . into ( ) ,
90109 ) ?;
91110 Ok ( Scalar :: from_int ( 0 , this. pointer_size ( ) ) )
92111 } else {
93112 let new_ptr = memory. reallocate (
94113 old_ptr,
95- old_size,
96- align,
114+ None ,
97115 Size :: from_bytes ( new_size) ,
98- align ,
99- MiriMemoryKind :: C . into ( ) ,
116+ new_align ,
117+ kind . into ( ) ,
100118 ) ?;
101119 Ok ( Scalar :: Ptr ( new_ptr) )
102120 }
@@ -145,14 +163,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
145163 match link_name {
146164 "malloc" => {
147165 let size = this. read_scalar ( args[ 0 ] ) ?. to_usize ( this) ?;
148- let res = this. malloc ( size, /*zero_init:*/ false ) ;
166+ let res = this. malloc ( size, /*zero_init:*/ false , MiriMemoryKind :: C ) ;
149167 this. write_scalar ( res, dest) ?;
150168 }
151169 "calloc" => {
152170 let items = this. read_scalar ( args[ 0 ] ) ?. to_usize ( this) ?;
153171 let len = this. read_scalar ( args[ 1 ] ) ?. to_usize ( this) ?;
154172 let size = items. checked_mul ( len) . ok_or_else ( || InterpError :: Overflow ( mir:: BinOp :: Mul ) ) ?;
155- let res = this. malloc ( size, /*zero_init:*/ true ) ;
173+ let res = this. malloc ( size, /*zero_init:*/ true , MiriMemoryKind :: C ) ;
156174 this. write_scalar ( res, dest) ?;
157175 }
158176 "posix_memalign" => {
@@ -187,12 +205,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
187205 }
188206 "free" => {
189207 let ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
190- this. free ( ptr) ?;
208+ this. free ( ptr, MiriMemoryKind :: C ) ?;
191209 }
192210 "realloc" => {
193211 let old_ptr = this. read_scalar ( args[ 0 ] ) ?. not_undef ( ) ?;
194212 let new_size = this. read_scalar ( args[ 1 ] ) ?. to_usize ( this) ?;
195- let res = this. realloc ( old_ptr, new_size) ?;
213+ let res = this. realloc ( old_ptr, new_size, MiriMemoryKind :: C ) ?;
196214 this. write_scalar ( res, dest) ?;
197215 }
198216
@@ -262,12 +280,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
262280 if !align. is_power_of_two ( ) {
263281 return err ! ( HeapAllocNonPowerOfTwoAlignment ( align) ) ;
264282 }
283+ let align = Align :: from_bytes ( align) . unwrap ( ) ;
265284 let new_ptr = this. memory_mut ( ) . reallocate (
266285 ptr,
267- Size :: from_bytes ( old_size) ,
268- Align :: from_bytes ( align) . unwrap ( ) ,
286+ Some ( ( Size :: from_bytes ( old_size) , align) ) ,
269287 Size :: from_bytes ( new_size) ,
270- Align :: from_bytes ( align) . unwrap ( ) ,
288+ align,
271289 MiriMemoryKind :: Rust . into ( ) ,
272290 ) ?;
273291 this. write_scalar ( Scalar :: Ptr ( new_ptr) , dest) ?;
@@ -327,7 +345,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
327345 trace ! ( "__rust_maybe_catch_panic: {:?}" , f_instance) ;
328346
329347 // Now we make a function call.
330- // TODO: consider making this reusable? `InterpretCx ::step` does something similar
348+ // TODO: consider making this reusable? `InterpCx ::step` does something similar
331349 // for the TLS destructors, and of course `eval_main`.
332350 let mir = this. load_mir ( f_instance. def ) ?;
333351 let ret_place = MPlaceTy :: dangling ( this. layout_of ( this. tcx . mk_unit ( ) ) ?, this) . into ( ) ;
@@ -765,22 +783,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
765783 let flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
766784 let size = this. read_scalar ( args[ 2 ] ) ?. to_usize ( this) ?;
767785 let zero_init = ( flags & 0x00000008 ) != 0 ; // HEAP_ZERO_MEMORY
768- let res = this. malloc ( size, zero_init) ;
786+ let res = this. malloc ( size, zero_init, MiriMemoryKind :: WinHeap ) ;
769787 this. write_scalar ( res, dest) ?;
770788 }
771789 "HeapFree" => {
772790 let _handle = this. read_scalar ( args[ 0 ] ) ?. to_isize ( this) ?;
773791 let _flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
774792 let ptr = this. read_scalar ( args[ 2 ] ) ?. not_undef ( ) ?;
775- this. free ( ptr) ?;
793+ this. free ( ptr, MiriMemoryKind :: WinHeap ) ?;
776794 this. write_scalar ( Scalar :: from_int ( 1 , Size :: from_bytes ( 4 ) ) , dest) ?;
777795 }
778796 "HeapReAlloc" => {
779797 let _handle = this. read_scalar ( args[ 0 ] ) ?. to_isize ( this) ?;
780798 let _flags = this. read_scalar ( args[ 1 ] ) ?. to_u32 ( ) ?;
781799 let ptr = this. read_scalar ( args[ 2 ] ) ?. not_undef ( ) ?;
782800 let size = this. read_scalar ( args[ 3 ] ) ?. to_usize ( this) ?;
783- let res = this. realloc ( ptr, size) ?;
801+ let res = this. realloc ( ptr, size, MiriMemoryKind :: WinHeap ) ?;
784802 this. write_scalar ( res, dest) ?;
785803 }
786804
0 commit comments