11use std:: alloc:: Layout ;
22use std:: borrow:: Cow ;
33use std:: { alloc, slice} ;
4+ #[ cfg( target_os = "linux" ) ]
5+ use std:: { cell:: RefCell , rc:: Rc } ;
46
57use rustc_abi:: { Align , Size } ;
68use rustc_middle:: mir:: interpret:: AllocBytes ;
79
10+ #[ cfg( target_os = "linux" ) ]
11+ use crate :: alloc:: isolated_alloc:: IsolatedAlloc ;
812use crate :: helpers:: ToU64 as _;
913
14+ #[ derive( Clone , Debug ) ]
15+ pub enum MiriAllocParams {
16+ Global ,
17+ #[ cfg( target_os = "linux" ) ]
18+ Isolated ( Rc < RefCell < IsolatedAlloc > > ) ,
19+ }
20+
1021/// Allocation bytes that explicitly handle the layout of the data they're storing.
1122/// This is necessary to interface with native code that accesses the program store in Miri.
1223#[ derive( Debug ) ]
@@ -18,13 +29,16 @@ pub struct MiriAllocBytes {
1829 /// * If `self.layout.size() == 0`, then `self.ptr` was allocated with the equivalent layout with size 1.
1930 /// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
2031 ptr : * mut u8 ,
32+ /// Whether this instance of `MiriAllocBytes` had its allocation created by calling `alloc::alloc()`
33+ /// (`Global`) or the discrete allocator (`Isolated`)
34+ params : MiriAllocParams ,
2135}
2236
2337impl Clone for MiriAllocBytes {
2438 fn clone ( & self ) -> Self {
2539 let bytes: Cow < ' _ , [ u8 ] > = Cow :: Borrowed ( self ) ;
2640 let align = Align :: from_bytes ( self . layout . align ( ) . to_u64 ( ) ) . unwrap ( ) ;
27- MiriAllocBytes :: from_bytes ( bytes, align, ( ) )
41+ MiriAllocBytes :: from_bytes ( bytes, align, self . params . clone ( ) )
2842 }
2943}
3044
@@ -37,8 +51,16 @@ impl Drop for MiriAllocBytes {
3751 } else {
3852 self . layout
3953 } ;
54+
4055 // SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
41- unsafe { alloc:: dealloc ( self . ptr , alloc_layout) }
56+ unsafe {
57+ match self . params . clone ( ) {
58+ MiriAllocParams :: Global => alloc:: dealloc ( self . ptr , alloc_layout) ,
59+ #[ cfg( target_os = "linux" ) ]
60+ MiriAllocParams :: Isolated ( alloc) =>
61+ alloc. borrow_mut ( ) . dealloc ( self . ptr , alloc_layout) ,
62+ }
63+ }
4264 }
4365}
4466
@@ -67,35 +89,45 @@ impl MiriAllocBytes {
6789 fn alloc_with (
6890 size : u64 ,
6991 align : u64 ,
70- alloc_fn : impl FnOnce ( Layout ) -> * mut u8 ,
92+ params : MiriAllocParams ,
93+ alloc_fn : impl FnOnce ( Layout , & MiriAllocParams ) -> * mut u8 ,
7194 ) -> Result < MiriAllocBytes , ( ) > {
7295 let size = usize:: try_from ( size) . map_err ( |_| ( ) ) ?;
7396 let align = usize:: try_from ( align) . map_err ( |_| ( ) ) ?;
7497 let layout = Layout :: from_size_align ( size, align) . map_err ( |_| ( ) ) ?;
7598 // When size is 0 we allocate 1 byte anyway, to ensure each allocation has a unique address.
7699 let alloc_layout =
77100 if size == 0 { Layout :: from_size_align ( 1 , align) . unwrap ( ) } else { layout } ;
78- let ptr = alloc_fn ( alloc_layout) ;
101+ let ptr = alloc_fn ( alloc_layout, & params ) ;
79102 if ptr. is_null ( ) {
80103 Err ( ( ) )
81104 } else {
82105 // SAFETY: All `MiriAllocBytes` invariants are fulfilled.
83- Ok ( Self { ptr, layout } )
106+ Ok ( Self { ptr, layout, params } )
84107 }
85108 }
86109}
87110
88111impl AllocBytes for MiriAllocBytes {
89- /// Placeholder!
90- type AllocParams = ( ) ;
112+ type AllocParams = MiriAllocParams ;
91113
92- fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , align : Align , _params : ( ) ) -> Self {
114+ fn from_bytes < ' a > (
115+ slice : impl Into < Cow < ' a , [ u8 ] > > ,
116+ align : Align ,
117+ params : MiriAllocParams ,
118+ ) -> Self {
93119 let slice = slice. into ( ) ;
94120 let size = slice. len ( ) ;
95121 let align = align. bytes ( ) ;
96122 // SAFETY: `alloc_fn` will only be used with `size != 0`.
97- let alloc_fn = |layout| unsafe { alloc:: alloc ( layout) } ;
98- let alloc_bytes = MiriAllocBytes :: alloc_with ( size. to_u64 ( ) , align, alloc_fn)
123+ let alloc_fn = |layout, params : & MiriAllocParams | unsafe {
124+ match params {
125+ MiriAllocParams :: Global => alloc:: alloc ( layout) ,
126+ #[ cfg( target_os = "linux" ) ]
127+ MiriAllocParams :: Isolated ( alloc) => alloc. borrow_mut ( ) . alloc ( layout) ,
128+ }
129+ } ;
130+ let alloc_bytes = MiriAllocBytes :: alloc_with ( size. to_u64 ( ) , align, params, alloc_fn)
99131 . unwrap_or_else ( |( ) | {
100132 panic ! ( "Miri ran out of memory: cannot create allocation of {size} bytes" )
101133 } ) ;
@@ -105,12 +137,18 @@ impl AllocBytes for MiriAllocBytes {
105137 alloc_bytes
106138 }
107139
108- fn zeroed ( size : Size , align : Align , _params : ( ) ) -> Option < Self > {
140+ fn zeroed ( size : Size , align : Align , params : MiriAllocParams ) -> Option < Self > {
109141 let size = size. bytes ( ) ;
110142 let align = align. bytes ( ) ;
111143 // SAFETY: `alloc_fn` will only be used with `size != 0`.
112- let alloc_fn = |layout| unsafe { alloc:: alloc_zeroed ( layout) } ;
113- MiriAllocBytes :: alloc_with ( size, align, alloc_fn) . ok ( )
144+ let alloc_fn = |layout, params : & MiriAllocParams | unsafe {
145+ match params {
146+ MiriAllocParams :: Global => alloc:: alloc_zeroed ( layout) ,
147+ #[ cfg( target_os = "linux" ) ]
148+ MiriAllocParams :: Isolated ( alloc) => alloc. borrow_mut ( ) . alloc_zeroed ( layout) ,
149+ }
150+ } ;
151+ MiriAllocBytes :: alloc_with ( size, align, params, alloc_fn) . ok ( )
114152 }
115153
116154 fn as_mut_ptr ( & mut self ) -> * mut u8 {
0 commit comments