Skip to content

Commit eac36ab

Browse files
committed
listened to reason and made my life so much easier
1 parent ccb844e commit eac36ab

File tree

4 files changed

+60
-121
lines changed

4 files changed

+60
-121
lines changed

src/alloc/alloc_bytes.rs

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

57
use rustc_abi::{Align, Size};
68
use rustc_middle::mir::interpret::AllocBytes;
@@ -9,10 +11,11 @@ use rustc_middle::mir::interpret::AllocBytes;
911
use crate::alloc::isolated_alloc::IsolatedAlloc;
1012
use crate::helpers::ToU64 as _;
1113

12-
#[derive(Clone, Copy, Debug)]
14+
#[derive(Clone, Debug)]
1315
pub enum MiriAllocParams {
1416
Global,
15-
Isolated(u64),
17+
#[cfg(target_os = "linux")]
18+
Isolated(Rc<RefCell<IsolatedAlloc>>),
1619
}
1720

1821
/// Allocation bytes that explicitly handle the layout of the data they're storing.
@@ -35,7 +38,7 @@ impl Clone for MiriAllocBytes {
3538
fn clone(&self) -> Self {
3639
let bytes: Cow<'_, [u8]> = Cow::Borrowed(self);
3740
let align = Align::from_bytes(self.layout.align().to_u64()).unwrap();
38-
MiriAllocBytes::from_bytes(bytes, align, self.params)
41+
MiriAllocBytes::from_bytes(bytes, align, self.params.clone())
3942
}
4043
}
4144

@@ -51,12 +54,11 @@ impl Drop for MiriAllocBytes {
5154

5255
// SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
5356
unsafe {
54-
match self.params {
57+
match self.params.clone() {
5558
MiriAllocParams::Global => alloc::dealloc(self.ptr, alloc_layout),
5659
#[cfg(target_os = "linux")]
57-
MiriAllocParams::Isolated(id) => IsolatedAlloc::dealloc(self.ptr, alloc_layout, id),
58-
#[cfg(not(target_os = "linux"))]
59-
MiriAllocParams::Isolated(_) => unreachable!(),
60+
MiriAllocParams::Isolated(alloc) =>
61+
alloc.borrow_mut().dealloc(self.ptr, alloc_layout),
6062
}
6163
}
6264
}
@@ -117,14 +119,13 @@ impl AllocBytes for MiriAllocBytes {
117119
let slice = slice.into();
118120
let size = slice.len();
119121
let align = align.bytes();
122+
let p_clone = params.clone();
120123
// SAFETY: `alloc_fn` will only be used with `size != 0`.
121124
let alloc_fn = |layout| unsafe {
122-
match params {
125+
match p_clone {
123126
MiriAllocParams::Global => alloc::alloc(layout),
124127
#[cfg(target_os = "linux")]
125-
MiriAllocParams::Isolated(id) => IsolatedAlloc::alloc(layout, id),
126-
#[cfg(not(target_os = "linux"))]
127-
MiriAllocParams::Isolated(_) => unreachable!(),
128+
MiriAllocParams::Isolated(alloc) => alloc.borrow_mut().alloc(layout),
128129
}
129130
};
130131
let alloc_bytes = MiriAllocBytes::alloc_with(size.to_u64(), align, params, alloc_fn)
@@ -140,14 +141,13 @@ impl AllocBytes for MiriAllocBytes {
140141
fn zeroed(size: Size, align: Align, params: MiriAllocParams) -> Option<Self> {
141142
let size = size.bytes();
142143
let align = align.bytes();
144+
let p_clone = params.clone();
143145
// SAFETY: `alloc_fn` will only be used with `size != 0`.
144146
let alloc_fn = |layout| unsafe {
145-
match params {
147+
match p_clone {
146148
MiriAllocParams::Global => alloc::alloc_zeroed(layout),
147149
#[cfg(target_os = "linux")]
148-
MiriAllocParams::Isolated(id) => IsolatedAlloc::alloc_zeroed(layout, id),
149-
#[cfg(not(target_os = "linux"))]
150-
MiriAllocParams::Isolated(_) => unreachable!(),
150+
MiriAllocParams::Isolated(alloc) => alloc.borrow_mut().alloc_zeroed(layout),
151151
}
152152
};
153153
MiriAllocBytes::alloc_with(size, align, params, alloc_fn).ok()

src/alloc/isolated_alloc.rs

Lines changed: 39 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,11 @@
11
use std::alloc::{self, Layout};
2-
use std::collections::HashMap;
3-
use std::hash::{BuildHasherDefault, DefaultHasher};
4-
use std::sync;
52

63
use rustc_index::bit_set::DenseBitSet;
74

8-
static ALLOCATOR: sync::Mutex<IsolatedAlloc> = sync::Mutex::new(IsolatedAlloc::empty());
9-
10-
pub struct IsolatedAlloc {
11-
/// A map of machine ID to allocator. If running in multi-seeded mode,
12-
/// each machine should have its own pool of memory that can be accessed
13-
/// separately. We use the normal `HashMap` type so that it's available
14-
/// in a `const` context.
15-
#[allow(rustc::default_hash_types)]
16-
allocators: HashMap<u64, IsolatedAllocInner, BuildHasherDefault<DefaultHasher>>,
17-
/// The host (not emulated) page size, or 0 if it has not yet been set.
18-
page_size: usize,
19-
}
20-
215
/// A dedicated allocator for interpreter memory contents, ensuring they are stored on dedicated
226
/// pages (not mixed with Miri's own memory). This is very useful for native-lib mode.
237
#[derive(Debug)]
24-
pub struct IsolatedAllocInner {
8+
pub struct IsolatedAlloc {
259
/// Pointers to page-aligned memory that has been claimed by the allocator.
2610
/// Every pointer here must point to a page-sized allocation claimed via
2711
/// the global allocator.
@@ -38,80 +22,19 @@ pub struct IsolatedAllocInner {
3822
/// indexing into it should be done with a value one-eighth of the corresponding
3923
/// offset on the matching `page_ptrs` element.
4024
page_infos: Vec<DenseBitSet<usize>>,
25+
/// The host (not emulated) page size, or 0 if it has not yet been set.
26+
page_size: usize,
4127
}
4228

43-
// SAFETY: We only point to heap-allocated data
44-
unsafe impl Send for IsolatedAlloc {}
45-
4629
impl IsolatedAlloc {
47-
/// Initializes the allocator. `page_size` is set to 0 as a placeholder to
48-
/// allow this function to be `const`; it is updated to its real value on
49-
/// the first call to `alloc()` or `alloc_zeroed()`.
50-
const fn empty() -> Self {
51-
// We need this to be `const`
52-
#[allow(rustc::default_hash_types)]
53-
Self { allocators: HashMap::with_hasher(BuildHasherDefault::new()), page_size: 0 }
54-
}
55-
56-
/// Allocates memory as described in `Layout`, from the pool marked by
57-
/// `id`. Note that the same `id` must be used upon calling `dealloc`.
58-
///
59-
/// SAFETY: See `alloc::alloc()`.
60-
pub unsafe fn alloc(layout: Layout, id: u64) -> *mut u8 {
61-
unsafe { Self::alloc_inner(layout, id, false) }
62-
}
63-
64-
/// Same as `alloc()`, but zeroes out data before allocating.
65-
///
66-
/// SAFETY: See `alloc::alloc_zeroed()`.
67-
pub unsafe fn alloc_zeroed(layout: Layout, id: u64) -> *mut u8 {
68-
unsafe { Self::alloc_inner(layout, id, true) }
69-
}
70-
71-
/// Abstracts over `alloc` and `alloc_zeroed`.
72-
///
73-
/// SAFETY: See `alloc::alloc()`/`alloc::alloc_zeroed()`.
74-
unsafe fn alloc_inner(layout: Layout, id: u64, zeroed: bool) -> *mut u8 {
75-
let mut alloc = ALLOCATOR.lock().unwrap();
76-
if alloc.page_size == 0 {
77-
unsafe {
78-
alloc.page_size = libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap();
79-
}
80-
}
81-
// Store this this AFTER setting the page size
82-
let page_size = alloc.page_size;
83-
84-
match alloc.allocators.get_mut(&id) {
85-
Some(alloc_inner) => unsafe { alloc_inner.allocate(layout, page_size, zeroed) },
86-
None => {
87-
let mut new_inner = IsolatedAllocInner::new();
88-
let ret = unsafe { new_inner.allocate(layout, page_size, zeroed) };
89-
alloc.allocators.insert(id, new_inner);
90-
ret
91-
}
92-
}
93-
}
94-
95-
/// Deallocates a pointer from the memory pool associated with a given `id`.
96-
///
97-
/// SAFETY: See `alloc::dealloc()`, with the extra caveat that `id` must
98-
/// correspond to the `id` used upon first allocating the memory.
99-
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout, id: u64) {
100-
let mut alloc = ALLOCATOR.lock().unwrap();
101-
let page_size = alloc.page_size;
102-
let alloc_inner = alloc.allocators.get_mut(&id).unwrap();
103-
unsafe { alloc_inner.deallocate(ptr, layout, page_size) };
104-
// Remove if the machine with that id no longer has any memory
105-
if alloc_inner.huge_ptrs.is_empty() && alloc_inner.page_ptrs.is_empty() {
106-
alloc.allocators.remove(&id);
107-
}
108-
}
109-
}
110-
111-
impl IsolatedAllocInner {
11230
/// Creates an empty allocator.
113-
const fn new() -> Self {
114-
Self { page_ptrs: Vec::new(), huge_ptrs: Vec::new(), page_infos: Vec::new() }
31+
pub fn new() -> Self {
32+
Self {
33+
page_ptrs: Vec::new(),
34+
huge_ptrs: Vec::new(),
35+
page_infos: Vec::new(),
36+
page_size: unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() },
37+
}
11538
}
11639

11740
/// Expands the available memory pool by adding one page.
@@ -137,24 +60,40 @@ impl IsolatedAllocInner {
13760
(size, align)
13861
}
13962

63+
/// Allocates memory as described in `Layout`. This memory should be deallocated
64+
/// by calling `dealloc` on this same allocator.
65+
///
66+
/// SAFETY: See `alloc::alloc()`
67+
pub fn alloc(&mut self, layout: Layout) -> *mut u8 {
68+
unsafe { self.allocate(layout, false) }
69+
}
70+
71+
/// Same as `alloc`, but zeroes out the memory.
72+
///
73+
/// SAFETY: See `alloc::alloc_zeroed()`
74+
pub fn alloc_zeroed(&mut self, layout: Layout) -> *mut u8 {
75+
unsafe { self.allocate(layout, true) }
76+
}
77+
14078
/// Abstracts over the logic of `alloc_zeroed` vs `alloc`, as determined by
14179
/// the `zeroed` argument.
14280
///
14381
/// SAFETY: See `alloc::alloc()`, with the added restriction that `page_size`
14482
/// corresponds to the host pagesize.
145-
unsafe fn allocate(&mut self, layout: Layout, page_size: usize, zeroed: bool) -> *mut u8 {
146-
if layout.align() > page_size || layout.size() > page_size {
83+
unsafe fn allocate(&mut self, layout: Layout, zeroed: bool) -> *mut u8 {
84+
if layout.align() > self.page_size || layout.size() > self.page_size {
14785
unsafe { self.alloc_multi_page(layout, zeroed) }
14886
} else {
14987
for (&mut page, pinfo) in std::iter::zip(&mut self.page_ptrs, &mut self.page_infos) {
15088
if let Some(ptr) =
151-
unsafe { Self::alloc_from_page(page_size, layout, page, pinfo, zeroed) }
89+
unsafe { Self::alloc_from_page(self.page_size, layout, page, pinfo, zeroed) }
15290
{
15391
return ptr;
15492
}
15593
}
15694

15795
// We get here only if there's no space in our existing pages
96+
let page_size = self.page_size;
15897
let (page, pinfo) = self.add_page(page_size);
15998
unsafe { Self::alloc_from_page(page_size, layout, page, pinfo, zeroed).unwrap() }
16099
}
@@ -171,7 +110,7 @@ impl IsolatedAllocInner {
171110
pinfo: &mut DenseBitSet<usize>,
172111
zeroed: bool,
173112
) -> Option<*mut u8> {
174-
let (size, align) = IsolatedAllocInner::normalized_layout(layout);
113+
let (size, align) = IsolatedAlloc::normalized_layout(layout);
175114

176115
// Check every alignment-sized block and see if there exists a `size`
177116
// chunk of empty space i.e. forall idx . !pinfo.contains(idx / 8)
@@ -213,15 +152,14 @@ impl IsolatedAllocInner {
213152
///
214153
/// SAFETY: This pointer must have been allocated by calling `alloc()` (or
215154
/// `alloc_zeroed()`) with the same layout as the one passed on this same
216-
/// `IsolatedAllocInner`, and `page_size` must correspond to the host
217-
/// pagesize.
218-
unsafe fn deallocate(&mut self, ptr: *mut u8, layout: Layout, page_size: usize) {
219-
let (size, align) = IsolatedAllocInner::normalized_layout(layout);
155+
/// `IsolatedAlloc`.
156+
pub unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
157+
let (size, align) = IsolatedAlloc::normalized_layout(layout);
220158

221-
let ptr_idx = ptr.addr() % page_size;
159+
let ptr_idx = ptr.addr() % self.page_size;
222160
let page_addr = ptr.addr() - ptr_idx;
223161

224-
if align > page_size || size > page_size {
162+
if align > self.page_size || size > self.page_size {
225163
unsafe {
226164
self.dealloc_multi_page(ptr, layout);
227165
}
@@ -242,7 +180,8 @@ impl IsolatedAllocInner {
242180
}
243181

244182
let mut free = vec![];
245-
let page_layout = unsafe { Layout::from_size_align_unchecked(page_size, page_size) };
183+
let page_layout =
184+
unsafe { Layout::from_size_align_unchecked(self.page_size, self.page_size) };
246185
for (idx, pinfo) in self.page_infos.iter().enumerate() {
247186
if pinfo.is_empty() {
248187
free.push(idx);
@@ -271,7 +210,7 @@ impl IsolatedAllocInner {
271210
}
272211
}
273212
}
274-
213+
/*
275214
#[cfg(test)]
276215
mod tests {
277216
use super::*;
@@ -365,3 +304,4 @@ mod tests {
365304
assert!(!alloc.allocators.contains_key(&4));
366305
}
367306
}
307+
*/

src/concurrency/thread.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -906,7 +906,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
906906
interp_ok(MiriAllocBytes::from_bytes(
907907
std::borrow::Cow::Borrowed(bytes),
908908
align,
909-
params,
909+
params.clone(),
910910
))
911911
},
912912
|ptr| this.global_root_pointer(ptr),

src/machine.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -532,10 +532,9 @@ pub struct MiriMachine<'tcx> {
532532
/// Needs to be queried by ptr_to_int, hence needs interior mutability.
533533
pub(crate) rng: RefCell<StdRng>,
534534

535-
/// The seed for the RNG, also used as a unique identifier for the machine.
536-
/// If multiple machines exist, this must be different for each.
535+
/// The allocator used for the machine's `AllocBytes`.
537536
#[cfg(target_os = "linux")]
538-
pub(crate) seed: u64,
537+
pub(crate) allocator: Rc<RefCell<crate::alloc::isolated_alloc::IsolatedAlloc>>,
539538

540539
/// The allocation IDs to report when they are being allocated
541540
/// (helps for debugging memory leaks and use after free bugs).
@@ -722,7 +721,7 @@ impl<'tcx> MiriMachine<'tcx> {
722721
extern_statics: FxHashMap::default(),
723722
rng: RefCell::new(rng),
724723
#[cfg(target_os = "linux")]
725-
seed,
724+
allocator: Rc::new(RefCell::new(crate::alloc::isolated_alloc::IsolatedAlloc::new())),
726725
tracked_alloc_ids: config.tracked_alloc_ids.clone(),
727726
track_alloc_accesses: config.track_alloc_accesses,
728727
check_alignment: config.check_alignment,
@@ -926,7 +925,7 @@ impl VisitProvenance for MiriMachine<'_> {
926925
local_crates: _,
927926
rng: _,
928927
#[cfg(target_os = "linux")]
929-
seed: _,
928+
allocator: _,
930929
tracked_alloc_ids: _,
931930
track_alloc_accesses: _,
932931
check_alignment: _,
@@ -1819,7 +1818,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
18191818

18201819
#[cfg(target_os = "linux")]
18211820
if self.native_lib.is_some() {
1822-
MiriAllocParams::Isolated(self.seed)
1821+
MiriAllocParams::Isolated(self.allocator.clone())
18231822
} else {
18241823
MiriAllocParams::Global
18251824
}

0 commit comments

Comments
 (0)