@@ -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,19 +107,35 @@ 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
- 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 {
90
119
let slice = slice. into ( ) ;
91
120
let size = slice. len ( ) ;
92
121
let align = align. bytes ( ) ;
93
122
// 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, params, alloc_fn)
96
139
. unwrap_or_else ( |( ) | {
97
140
panic ! ( "Miri ran out of memory: cannot create allocation of {size} bytes" )
98
141
} ) ;
@@ -102,12 +145,26 @@ impl AllocBytes for MiriAllocBytes {
102
145
alloc_bytes
103
146
}
104
147
105
- fn zeroed ( size : Size , align : Align ) -> Option < Self > {
148
+ fn zeroed ( size : Size , align : Align , params : MiriAllocParams ) -> Option < Self > {
106
149
let size = size. bytes ( ) ;
107
150
let align = align. bytes ( ) ;
108
151
// 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 ( )
111
168
}
112
169
113
170
fn as_mut_ptr ( & mut self ) -> * mut u8 {
0 commit comments