@@ -5,8 +5,16 @@ use std::{alloc, slice};
55use rustc_abi:: { Align , Size } ;
66use rustc_middle:: mir:: interpret:: AllocBytes ;
77
8+ #[ cfg( target_os = "linux" ) ]
9+ use crate :: alloc:: isolated_alloc:: IsolatedAlloc ;
810use crate :: helpers:: ToU64 as _;
911
12+ #[ derive( Clone , Copy , Debug ) ]
13+ pub enum MiriAllocParams {
14+ Global ,
15+ Isolated ,
16+ }
17+
1018/// Allocation bytes that explicitly handle the layout of the data they're storing.
1119/// This is necessary to interface with native code that accesses the program store in Miri.
1220#[ derive( Debug ) ]
@@ -18,13 +26,16 @@ pub struct MiriAllocBytes {
1826 /// * If `self.layout.size() == 0`, then `self.ptr` was allocated with the equivalent layout with size 1.
1927 /// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
2028 ptr : * mut u8 ,
29+ /// Whether this instance of `MiriAllocBytes` had its allocation created by calling `alloc::alloc()`
30+ /// (`Global`) or the discrete allocator (`Isolated`)
31+ params : MiriAllocParams ,
2132}
2233
2334impl Clone for MiriAllocBytes {
2435 fn clone ( & self ) -> Self {
2536 let bytes: Cow < ' _ , [ u8 ] > = Cow :: Borrowed ( self ) ;
2637 let align = Align :: from_bytes ( self . layout . align ( ) . to_u64 ( ) ) . unwrap ( ) ;
27- MiriAllocBytes :: from_bytes ( bytes, align)
38+ MiriAllocBytes :: from_bytes ( bytes, align, self . params )
2839 }
2940}
3041
@@ -37,8 +48,23 @@ impl Drop for MiriAllocBytes {
3748 } else {
3849 self . layout
3950 } ;
51+
4052 // SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
41- unsafe { alloc:: dealloc ( self . ptr , alloc_layout) }
53+ unsafe {
54+ match self . dsc {
55+ MiriAllocParams :: Global => alloc:: dealloc ( self . ptr , alloc_layout) ,
56+ MiriAllocParams :: Isolated => {
57+ #[ cfg( target_os = "linux" ) ]
58+ {
59+ IsolatedAlloc :: dealloc ( self . ptr , alloc_layout)
60+ }
61+ #[ cfg( not( target_os = "linux" ) ) ]
62+ {
63+ unreachable ! ( )
64+ }
65+ }
66+ }
67+ }
4268 }
4369}
4470
@@ -67,6 +93,7 @@ impl MiriAllocBytes {
6793 fn alloc_with (
6894 size : u64 ,
6995 align : u64 ,
96+ params : MiriAllocParams ,
7097 alloc_fn : impl FnOnce ( Layout ) -> * mut u8 ,
7198 ) -> Result < MiriAllocBytes , ( ) > {
7299 let size = usize:: try_from ( size) . map_err ( |_| ( ) ) ?;
@@ -80,19 +107,35 @@ impl MiriAllocBytes {
80107 Err ( ( ) )
81108 } else {
82109 // SAFETY: All `MiriAllocBytes` invariants are fulfilled.
83- Ok ( Self { ptr, layout } )
110+ Ok ( Self { ptr, layout, params } )
84111 }
85112 }
86113}
87114
88115impl AllocBytes for MiriAllocBytes {
89- fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , align : Align ) -> Self {
116+ type AllocParams = MiriAllocParams ;
117+
118+ fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , align : Align , params : MiriAllocParams ) -> Self {
90119 let slice = slice. into ( ) ;
91120 let size = slice. len ( ) ;
92121 let align = align. bytes ( ) ;
93122 // SAFETY: `alloc_fn` will only be used with `size != 0`.
94- let alloc_fn = |layout| unsafe { alloc:: alloc ( layout) } ;
95- let alloc_bytes = MiriAllocBytes :: alloc_with ( size. to_u64 ( ) , align, alloc_fn)
123+ let alloc_fn = |layout| unsafe {
124+ match params {
125+ MiriAllocParams :: Global => alloc:: alloc ( layout) ,
126+ MiriAllocParams :: Isolated => {
127+ #[ cfg( target_os = "linux" ) ]
128+ {
129+ IsolatedAlloc :: alloc ( layout)
130+ }
131+ #[ cfg( not( target_os = "linux" ) ) ]
132+ {
133+ unreachable ! ( )
134+ }
135+ }
136+ }
137+ } ;
138+ let alloc_bytes = MiriAllocBytes :: alloc_with ( size. to_u64 ( ) , align, dsc, alloc_fn)
96139 . unwrap_or_else ( |( ) | {
97140 panic ! ( "Miri ran out of memory: cannot create allocation of {size} bytes" )
98141 } ) ;
@@ -102,12 +145,26 @@ impl AllocBytes for MiriAllocBytes {
102145 alloc_bytes
103146 }
104147
105- fn zeroed ( size : Size , align : Align ) -> Option < Self > {
148+ fn zeroed ( size : Size , align : Align , params : MiriAllocParams ) -> Option < Self > {
106149 let size = size. bytes ( ) ;
107150 let align = align. bytes ( ) ;
108151 // SAFETY: `alloc_fn` will only be used with `size != 0`.
109- let alloc_fn = |layout| unsafe { alloc:: alloc_zeroed ( layout) } ;
110- MiriAllocBytes :: alloc_with ( size, align, alloc_fn) . ok ( )
152+ let alloc_fn = |layout| unsafe {
153+ match params {
154+ MiriAllocParams :: Global => alloc:: alloc_zeroed ( layout) ,
155+ MiriAllocParams :: Isolated => {
156+ #[ cfg( target_os = "linux" ) ]
157+ {
158+ IsolatedAlloc :: alloc_zeroed ( layout)
159+ }
160+ #[ cfg( not( target_os = "linux" ) ) ]
161+ {
162+ unreachable ! ( )
163+ }
164+ }
165+ }
166+ } ;
167+ MiriAllocBytes :: alloc_with ( size, align, params, alloc_fn) . ok ( )
111168 }
112169
113170 fn as_mut_ptr ( & mut self ) -> * mut u8 {
0 commit comments