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, ¶ms );
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