@@ -5,8 +5,16 @@ use std::{alloc, slice};
5
5
use rustc_abi:: { Align , Size } ;
6
6
use rustc_middle:: mir:: interpret:: AllocBytes ;
7
7
8
+ #[ cfg( target_os = "linux" ) ]
9
+ use crate :: alloc:: isolated_alloc:: IsolatedAlloc ;
8
10
use crate :: helpers:: ToU64 as _;
9
11
12
+ #[ derive( Clone , Copy , Debug ) ]
13
+ pub enum MiriAllocParams {
14
+ Global ,
15
+ Isolated ,
16
+ }
17
+
10
18
/// Allocation bytes that explicitly handle the layout of the data they're storing.
11
19
/// This is necessary to interface with native code that accesses the program store in Miri.
12
20
#[ derive( Debug ) ]
@@ -18,13 +26,16 @@ pub struct MiriAllocBytes {
18
26
/// * If `self.layout.size() == 0`, then `self.ptr` was allocated with the equivalent layout with size 1.
19
27
/// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
20
28
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 ,
21
32
}
22
33
23
34
impl Clone for MiriAllocBytes {
24
35
fn clone ( & self ) -> Self {
25
36
let bytes: Cow < ' _ , [ u8 ] > = Cow :: Borrowed ( self ) ;
26
37
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 )
28
39
}
29
40
}
30
41
@@ -37,8 +48,23 @@ impl Drop for MiriAllocBytes {
37
48
} else {
38
49
self . layout
39
50
} ;
51
+
40
52
// SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
41
- unsafe { alloc:: dealloc ( self . ptr , alloc_layout) }
53
+ unsafe {
54
+ match self . params {
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
+ }
42
68
}
43
69
}
44
70
@@ -67,6 +93,7 @@ impl MiriAllocBytes {
67
93
fn alloc_with (
68
94
size : u64 ,
69
95
align : u64 ,
96
+ params : MiriAllocParams ,
70
97
alloc_fn : impl FnOnce ( Layout ) -> * mut u8 ,
71
98
) -> Result < MiriAllocBytes , ( ) > {
72
99
let size = usize:: try_from ( size) . map_err ( |_| ( ) ) ?;
@@ -80,22 +107,39 @@ impl MiriAllocBytes {
80
107
Err ( ( ) )
81
108
} else {
82
109
// SAFETY: All `MiriAllocBytes` invariants are fulfilled.
83
- Ok ( Self { ptr, layout } )
110
+ Ok ( Self { ptr, layout, params } )
84
111
}
85
112
}
86
113
}
87
114
88
115
impl AllocBytes for MiriAllocBytes {
89
- /// Placeholder!
90
- type AllocParams = ( ) ;
116
+ type AllocParams = MiriAllocParams ;
91
117
92
- fn from_bytes < ' a > ( slice : impl Into < Cow < ' a , [ u8 ] > > , align : Align , _params : ( ) ) -> Self {
118
+ fn from_bytes < ' a > (
119
+ slice : impl Into < Cow < ' a , [ u8 ] > > ,
120
+ align : Align ,
121
+ params : MiriAllocParams ,
122
+ ) -> Self {
93
123
let slice = slice. into ( ) ;
94
124
let size = slice. len ( ) ;
95
125
let align = align. bytes ( ) ;
96
126
// 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)
127
+ let alloc_fn = |layout| unsafe {
128
+ match params {
129
+ MiriAllocParams :: Global => alloc:: alloc ( layout) ,
130
+ MiriAllocParams :: Isolated => {
131
+ #[ cfg( target_os = "linux" ) ]
132
+ {
133
+ IsolatedAlloc :: alloc ( layout)
134
+ }
135
+ #[ cfg( not( target_os = "linux" ) ) ]
136
+ {
137
+ unreachable ! ( )
138
+ }
139
+ }
140
+ }
141
+ } ;
142
+ let alloc_bytes = MiriAllocBytes :: alloc_with ( size. to_u64 ( ) , align, params, alloc_fn)
99
143
. unwrap_or_else ( |( ) | {
100
144
panic ! ( "Miri ran out of memory: cannot create allocation of {size} bytes" )
101
145
} ) ;
@@ -105,12 +149,26 @@ impl AllocBytes for MiriAllocBytes {
105
149
alloc_bytes
106
150
}
107
151
108
- fn zeroed ( size : Size , align : Align , _params : ( ) ) -> Option < Self > {
152
+ fn zeroed ( size : Size , align : Align , params : MiriAllocParams ) -> Option < Self > {
109
153
let size = size. bytes ( ) ;
110
154
let align = align. bytes ( ) ;
111
155
// 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 ( )
156
+ let alloc_fn = |layout| unsafe {
157
+ match params {
158
+ MiriAllocParams :: Global => alloc:: alloc_zeroed ( layout) ,
159
+ MiriAllocParams :: Isolated => {
160
+ #[ cfg( target_os = "linux" ) ]
161
+ {
162
+ IsolatedAlloc :: alloc_zeroed ( layout)
163
+ }
164
+ #[ cfg( not( target_os = "linux" ) ) ]
165
+ {
166
+ unreachable ! ( )
167
+ }
168
+ }
169
+ }
170
+ } ;
171
+ MiriAllocBytes :: alloc_with ( size, align, params, alloc_fn) . ok ( )
114
172
}
115
173
116
174
fn as_mut_ptr ( & mut self ) -> * mut u8 {
0 commit comments