Skip to content

Commit 9164512

Browse files
authored
Merge pull request rust-lang#4343 from nia-e/discrete-allocator
Isolate MiriMachine memory from Miri's
2 parents af48d42 + 47e24f0 commit 9164512

File tree

8 files changed

+526
-22
lines changed

8 files changed

+526
-22
lines changed

src/tools/miri/no_alloc

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"backtraces": {
3+
"mean": 2.3829520464,
4+
"stddev": 0.07651981051526706
5+
},
6+
"big-allocs": {
7+
"mean": 0.1673647059473684,
8+
"stddev": 0.013478818300072831
9+
},
10+
"mse": {
11+
"mean": 0.8133679916000001,
12+
"stddev": 0.050075600632164104
13+
},
14+
"range-iteration": {
15+
"mean": 4.243566763599999,
16+
"stddev": 0.03380701243732224
17+
},
18+
"serde1": {
19+
"mean": 2.589135003,
20+
"stddev": 0.0700829518878718
21+
},
22+
"serde2": {
23+
"mean": 5.955532229,
24+
"stddev": 0.20599769835375004
25+
},
26+
"slice-chunked": {
27+
"mean": 0.4702839168333333,
28+
"stddev": 0.017522346103318015
29+
},
30+
"slice-get-unchecked": {
31+
"mean": 0.8169163450000001,
32+
"stddev": 0.013873697449548328
33+
},
34+
"string-replace": {
35+
"mean": 0.5258388794,
36+
"stddev": 0.032950972318742694
37+
},
38+
"unicode": {
39+
"mean": 3.4562345727999997,
40+
"stddev": 0.11276913990962134
41+
},
42+
"zip-equal": {
43+
"mean": 3.0626452212,
44+
"stddev": 0.0554291549675083
45+
}
46+
}

src/tools/miri/src/alloc_bytes.rs renamed to src/tools/miri/src/alloc/alloc_bytes.rs

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
use std::alloc::Layout;
22
use std::borrow::Cow;
33
use std::{alloc, slice};
4+
#[cfg(target_os = "linux")]
5+
use std::{cell::RefCell, rc::Rc};
46

57
use rustc_abi::{Align, Size};
68
use rustc_middle::mir::interpret::AllocBytes;
79

10+
#[cfg(target_os = "linux")]
11+
use crate::alloc::isolated_alloc::IsolatedAlloc;
812
use 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

2337
impl 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

88111
impl 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

Comments
 (0)