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 ;
12+ use crate :: helpers:: ToU64 as _;
13+
14+ #[ derive( Clone , Debug ) ]
15+ pub enum MiriAllocParams {
16+ Global ,
17+ #[ cfg( target_os = "linux" ) ]
18+ Isolated ( Rc < RefCell < IsolatedAlloc > > ) ,
19+ }
20+
821/// Allocation bytes that explicitly handle the layout of the data they're storing.
922/// This is necessary to interface with native code that accesses the program store in Miri.
1023#[ derive( Debug ) ]
@@ -16,13 +29,16 @@ pub struct MiriAllocBytes {
1629 /// * If `self.layout.size() == 0`, then `self.ptr` was allocated with the equivalent layout with size 1.
1730 /// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
1831 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 ,
1935}
2036
2137impl Clone for MiriAllocBytes {
2238 fn clone ( & self ) -> Self {
2339 let bytes: Cow < ' _ , [ u8 ] > = Cow :: Borrowed ( self ) ;
24- let align = Align :: from_bytes ( self . layout . align ( ) . try_into ( ) . unwrap ( ) ) . unwrap ( ) ;
25- MiriAllocBytes :: from_bytes ( bytes, align)
40+ let align = Align :: from_bytes ( self . layout . align ( ) . to_u64 ( ) ) . unwrap ( ) ;
41+ MiriAllocBytes :: from_bytes ( bytes, align, self . params . clone ( ) )
2642 }
2743}
2844
@@ -35,8 +51,16 @@ impl Drop for MiriAllocBytes {
3551 } else {
3652 self . layout
3753 } ;
54+
3855 // SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
39- 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+ }
4064 }
4165}
4266
@@ -65,32 +89,45 @@ impl MiriAllocBytes {
6589 fn alloc_with (
6690 size : u64 ,
6791 align : u64 ,
68- alloc_fn : impl FnOnce ( Layout ) -> * mut u8 ,
92+ params : MiriAllocParams ,
93+ alloc_fn : impl FnOnce ( Layout , & MiriAllocParams ) -> * mut u8 ,
6994 ) -> Result < MiriAllocBytes , ( ) > {
7095 let size = usize:: try_from ( size) . map_err ( |_| ( ) ) ?;
7196 let align = usize:: try_from ( align) . map_err ( |_| ( ) ) ?;
7297 let layout = Layout :: from_size_align ( size, align) . map_err ( |_| ( ) ) ?;
7398 // When size is 0 we allocate 1 byte anyway, to ensure each allocation has a unique address.
7499 let alloc_layout =
75100 if size == 0 { Layout :: from_size_align ( 1 , align) . unwrap ( ) } else { layout } ;
76- let ptr = alloc_fn ( alloc_layout) ;
101+ let ptr = alloc_fn ( alloc_layout, & params ) ;
77102 if ptr. is_null ( ) {
78103 Err ( ( ) )
79104 } else {
80105 // SAFETY: All `MiriAllocBytes` invariants are fulfilled.
81- Ok ( Self { ptr, layout } )
106+ Ok ( Self { ptr, layout, params } )
82107 }
83108 }
84109}
85110
86111impl AllocBytes for MiriAllocBytes {
87- fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , align : Align ) -> Self {
112+ type AllocParams = MiriAllocParams ;
113+
114+ fn from_bytes < ' a > (
115+ slice : impl Into < Cow < ' a , [ u8 ] > > ,
116+ align : Align ,
117+ params : MiriAllocParams ,
118+ ) -> Self {
88119 let slice = slice. into ( ) ;
89120 let size = slice. len ( ) ;
90121 let align = align. bytes ( ) ;
91122 // SAFETY: `alloc_fn` will only be used with `size != 0`.
92- let alloc_fn = |layout| unsafe { alloc:: alloc ( layout) } ;
93- let alloc_bytes = MiriAllocBytes :: alloc_with ( size. try_into ( ) . unwrap ( ) , 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)
94131 . unwrap_or_else ( |( ) | {
95132 panic ! ( "Miri ran out of memory: cannot create allocation of {size} bytes" )
96133 } ) ;
@@ -100,12 +137,18 @@ impl AllocBytes for MiriAllocBytes {
100137 alloc_bytes
101138 }
102139
103- fn zeroed ( size : Size , align : Align ) -> Option < Self > {
140+ fn zeroed ( size : Size , align : Align , params : MiriAllocParams ) -> Option < Self > {
104141 let size = size. bytes ( ) ;
105142 let align = align. bytes ( ) ;
106143 // SAFETY: `alloc_fn` will only be used with `size != 0`.
107- let alloc_fn = |layout| unsafe { alloc:: alloc_zeroed ( layout) } ;
108- 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 ( )
109152 }
110153
111154 fn as_mut_ptr ( & mut self ) -> * mut u8 {
0 commit comments