Skip to content

Commit ae227b5

Browse files
committed
add rustc-pr-pending changes
1 parent bb635b0 commit ae227b5

File tree

8 files changed

+101
-107
lines changed

8 files changed

+101
-107
lines changed

miri-script/src/commands.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::BTreeMap;
1+
use std::collections::HashMap;
22
use std::ffi::{OsStr, OsString};
33
use std::fmt::Write as _;
44
use std::fs::{self, File};
@@ -489,9 +489,7 @@ impl Command {
489489
sh.read_dir(benches_dir)?
490490
.into_iter()
491491
.filter(|path| path.is_dir())
492-
// Only keep the basename: that matches the usage with a manual bench list,
493-
// and it ensure the path concatenations below work as intended.
494-
.map(|path| path.file_name().unwrap().to_owned().into_string().unwrap())
492+
.map(|path| path.into_os_string().into_string().unwrap())
495493
.collect()
496494
} else {
497495
benches.into_iter().collect()
@@ -532,16 +530,14 @@ impl Command {
532530
stddev: f64,
533531
}
534532

535-
let gather_results = || -> Result<BTreeMap<&str, BenchResult>> {
533+
let gather_results = || -> Result<HashMap<&str, BenchResult>> {
536534
let baseline_temp_dir = results_json_dir.unwrap();
537-
let mut results = BTreeMap::new();
535+
let mut results = HashMap::new();
538536
for bench in &benches {
539-
let result = File::open(path!(baseline_temp_dir / format!("{bench}.bench.json")))
540-
.context("failed to read hyperfine JSON")?;
541-
let mut result: serde_json::Value = serde_json::from_reader(BufReader::new(result))
542-
.context("failed to parse hyperfine JSON")?;
543-
let result: BenchResult = serde_json::from_value(result["results"][0].take())
544-
.context("failed to interpret hyperfine JSON")?;
537+
let result = File::open(path!(baseline_temp_dir / format!("{bench}.bench.json")))?;
538+
let mut result: serde_json::Value =
539+
serde_json::from_reader(BufReader::new(result))?;
540+
let result: BenchResult = serde_json::from_value(result["results"][0].take())?;
545541
results.insert(bench as &str, result);
546542
}
547543
Ok(results)
@@ -553,15 +549,15 @@ impl Command {
553549
serde_json::to_writer_pretty(BufWriter::new(baseline), &results)?;
554550
} else if let Some(baseline_file) = load_baseline {
555551
let new_results = gather_results()?;
556-
let baseline_results: BTreeMap<String, BenchResult> = {
552+
let baseline_results: HashMap<String, BenchResult> = {
557553
let f = File::open(baseline_file)?;
558554
serde_json::from_reader(BufReader::new(f))?
559555
};
560556
println!(
561557
"Comparison with baseline (relative speed, lower is better for the new results):"
562558
);
563-
for (bench, new_result) in new_results {
564-
let Some(baseline_result) = baseline_results.get(bench) else { continue };
559+
for (bench, new_result) in new_results.iter() {
560+
let Some(baseline_result) = baseline_results.get(*bench) else { continue };
565561

566562
// Compare results (inspired by hyperfine)
567563
let ratio = new_result.mean / baseline_result.mean;

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e7f4317ea0e891296163414c6f681ccec976abc3
1+
2b96ddca1272960623e41829439df8dae82d20af

src/alloc/alloc_bytes.rs

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ use rustc_middle::mir::interpret::AllocBytes;
99
use crate::alloc::discrete_alloc::MachineAlloc;
1010
use crate::helpers::ToU64 as _;
1111

12+
#[derive(Clone, Copy, Debug)]
13+
pub enum MiriByteMdata {
14+
Global,
15+
Isolated,
16+
}
17+
1218
/// Allocation bytes that explicitly handle the layout of the data they're storing.
1319
/// This is necessary to interface with native code that accesses the program store in Miri.
1420
#[derive(Debug)]
@@ -21,15 +27,15 @@ pub struct MiriAllocBytes {
2127
/// * Otherwise, `self.ptr` points to memory allocated with `self.layout`.
2228
ptr: *mut u8,
2329
/// Whether this instance of `MiriAllocBytes` had its allocation created by calling `alloc::alloc()`
24-
/// (true) or the discrete allocator (false)
25-
alloc_is_global: bool,
30+
/// (`Global`) or the discrete allocator (`Isolated`)
31+
dsc: MiriByteMdata,
2632
}
2733

2834
impl Clone for MiriAllocBytes {
2935
fn clone(&self) -> Self {
3036
let bytes: Cow<'_, [u8]> = Cow::Borrowed(self);
3137
let align = Align::from_bytes(self.layout.align().to_u64()).unwrap();
32-
MiriAllocBytes::from_bytes(bytes, align)
38+
MiriAllocBytes::from_bytes(bytes, align, self.dsc)
3339
}
3440
}
3541

@@ -45,16 +51,15 @@ impl Drop for MiriAllocBytes {
4551

4652
// SAFETY: Invariant, `self.ptr` points to memory allocated with `self.layout`.
4753
unsafe {
48-
#[cfg(target_os = "linux")]
49-
{
50-
if self.alloc_is_global {
51-
alloc::dealloc(self.ptr, alloc_layout);
52-
} else {
53-
MachineAlloc::dealloc(self.ptr, alloc_layout);
54-
}
54+
match self.dsc {
55+
MiriByteMdata::Global => alloc::dealloc(self.ptr, alloc_layout),
56+
MiriByteMdata::Isolated => {
57+
#[cfg(target_os = "linux")]
58+
{MachineAlloc::dealloc(self.ptr, alloc_layout)}
59+
#[cfg(not(target_os = "linux"))]
60+
{unreachable!()}
61+
},
5562
}
56-
#[cfg(not(target_os = "linux"))]
57-
alloc::dealloc(self.ptr, alloc_layout);
5863
}
5964
}
6065
}
@@ -84,41 +89,45 @@ impl MiriAllocBytes {
8489
fn alloc_with(
8590
size: u64,
8691
align: u64,
87-
alloc_fn: impl FnOnce(Layout) -> (*mut u8, bool),
92+
dsc: MiriByteMdata,
93+
alloc_fn: impl FnOnce(Layout) -> *mut u8,
8894
) -> Result<MiriAllocBytes, ()> {
8995
let size = usize::try_from(size).map_err(|_| ())?;
9096
let align = usize::try_from(align).map_err(|_| ())?;
9197
let layout = Layout::from_size_align(size, align).map_err(|_| ())?;
9298
// When size is 0 we allocate 1 byte anyway, to ensure each allocation has a unique address.
9399
let alloc_layout =
94100
if size == 0 { Layout::from_size_align(1, align).unwrap() } else { layout };
95-
let (ptr, alloc_is_global) = alloc_fn(alloc_layout);
101+
let ptr = alloc_fn(alloc_layout);
96102
if ptr.is_null() {
97103
Err(())
98104
} else {
99105
// SAFETY: All `MiriAllocBytes` invariants are fulfilled.
100-
Ok(Self { ptr, layout, alloc_is_global })
106+
Ok(Self { ptr, layout, dsc })
101107
}
102108
}
103109
}
104110

105111
impl AllocBytes for MiriAllocBytes {
106-
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align) -> Self {
112+
type ByteMetadata = MiriByteMdata;
113+
114+
fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align, dsc: MiriByteMdata) -> Self {
107115
let slice = slice.into();
108116
let size = slice.len();
109117
let align = align.bytes();
110118
// SAFETY: `alloc_fn` will only be used with `size != 0`.
111119
let alloc_fn = |layout| unsafe {
112-
#[cfg(target_os = "linux")]
113-
{
114-
MachineAlloc::alloc(layout)
115-
}
116-
#[cfg(not(target_os = "linux"))]
117-
{
118-
(alloc::alloc(layout), true)
120+
match dsc {
121+
MiriByteMdata::Global => alloc::alloc(layout),
122+
MiriByteMdata::Isolated => {
123+
#[cfg(target_os = "linux")]
124+
{MachineAlloc::alloc(layout)}
125+
#[cfg(not(target_os = "linux"))]
126+
{unreachable!()}
127+
},
119128
}
120129
};
121-
let alloc_bytes = MiriAllocBytes::alloc_with(size.to_u64(), align, alloc_fn)
130+
let alloc_bytes = MiriAllocBytes::alloc_with(size.to_u64(), align, dsc, alloc_fn)
122131
.unwrap_or_else(|()| {
123132
panic!("Miri ran out of memory: cannot create allocation of {size} bytes")
124133
});
@@ -128,21 +137,22 @@ impl AllocBytes for MiriAllocBytes {
128137
alloc_bytes
129138
}
130139

131-
fn zeroed(size: Size, align: Align) -> Option<Self> {
140+
fn zeroed(size: Size, align: Align, dsc: MiriByteMdata) -> Option<Self> {
132141
let size = size.bytes();
133142
let align = align.bytes();
134143
// SAFETY: `alloc_fn` will only be used with `size != 0`.
135144
let alloc_fn = |layout| unsafe {
136-
#[cfg(target_os = "linux")]
137-
{
138-
MachineAlloc::alloc_zeroed(layout)
139-
}
140-
#[cfg(not(target_os = "linux"))]
141-
{
142-
(alloc::alloc_zeroed(layout), true)
145+
match dsc {
146+
MiriByteMdata::Global => alloc::alloc_zeroed(layout),
147+
MiriByteMdata::Isolated => {
148+
#[cfg(target_os = "linux")]
149+
{MachineAlloc::alloc_zeroed(layout)}
150+
#[cfg(not(target_os = "linux"))]
151+
{unreachable!()}
152+
},
143153
}
144154
};
145-
MiriAllocBytes::alloc_with(size, align, alloc_fn).ok()
155+
MiriAllocBytes::alloc_with(size, align, dsc, alloc_fn).ok()
146156
}
147157

148158
fn as_mut_ptr(&mut self) -> *mut u8 {
@@ -152,4 +162,8 @@ impl AllocBytes for MiriAllocBytes {
152162
fn as_ptr(&self) -> *const u8 {
153163
self.ptr
154164
}
165+
166+
fn get_mdata(&self) -> MiriByteMdata {
167+
self.dsc
168+
}
155169
}

src/alloc/discrete_alloc.rs

Lines changed: 21 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -25,38 +25,21 @@ pub struct MachineAlloc {
2525
allocated: Vec<Box<[u8]>>,
2626
/// The host (not emulated) page size.
2727
page_size: usize,
28-
/// If false, calls to `alloc()` and `alloc_zeroed()` just wrap the corresponding
29-
/// function in the global allocator. Otherwise, uses the pages tracked
30-
/// internally.
31-
enabled: bool,
3228
}
3329

3430
// SAFETY: We only point to heap-allocated data
3531
unsafe impl Send for MachineAlloc {}
3632

3733
impl MachineAlloc {
38-
/// Initializes the allocator. `page_size` is set to 4k as a placeholder to
39-
/// allow this function to be `const`; it is updated to its real value when
40-
/// `enable()` is called.
34+
/// Initializes the allocator. `page_size` is set to 0 as a placeholder to
35+
/// allow this function to be `const`; it is updated to its real value on
36+
/// the first call to `alloc()` or `alloc_zeroed()`.
4137
const fn empty() -> Self {
4238
Self {
4339
pages: Vec::new(),
4440
huge_allocs: Vec::new(),
4541
allocated: Vec::new(),
46-
page_size: 4096,
47-
enabled: true,
48-
}
49-
}
50-
51-
/// Enables the allocator. From this point onwards, calls to `alloc()` and
52-
/// `alloc_zeroed()` will return `(ptr, false)`.
53-
pub fn enable() {
54-
let mut alloc = ALLOCATOR.lock().unwrap();
55-
alloc.enabled = true;
56-
// This needs to specifically be the system pagesize!
57-
alloc.page_size = unsafe {
58-
// If sysconf errors, better to just panic
59-
libc::sysconf(libc::_SC_PAGE_SIZE).try_into().unwrap()
42+
page_size: 0,
6043
}
6144
}
6245

@@ -79,45 +62,35 @@ impl MachineAlloc {
7962
(size, align)
8063
}
8164

82-
/// Allocates memory as described in `Layout`. If `MachineAlloc::enable()`
83-
/// has *not* been called yet, this is just a wrapper for `(alloc::alloc(),
84-
/// true)`. Otherwise, it will allocate from its own memory pool and
85-
/// return `(ptr, false)`. The latter field is meant to correspond with the
86-
/// field `alloc_is_global` for `MiriAllocBytes`.
65+
/// Allocates memory as described in `Layout`.
8766
///
88-
/// SAFETY: See alloc::alloc()
67+
/// SAFETY: `See alloc::alloc()`
8968
#[inline]
90-
pub unsafe fn alloc(layout: Layout) -> (*mut u8, bool) {
69+
pub unsafe fn alloc(layout: Layout) -> *mut u8 {
9170
let mut alloc = ALLOCATOR.lock().unwrap();
9271
unsafe {
93-
if alloc.enabled {
94-
(alloc.alloc_inner(layout, false), false)
95-
} else {
96-
(alloc::alloc(layout), true)
97-
}
72+
alloc.alloc_inner(layout, false)
9873
}
9974
}
10075

101-
/// Same as `alloc()`, but zeroes out data before allocating. Instead
102-
/// wraps `alloc::alloc_zeroed()` if `MachineAlloc::enable()` has not been
103-
/// called yet.
76+
/// Same as `alloc()`, but zeroes out data before allocating.
10477
///
105-
/// SAFETY: See alloc::alloc_zeroed()
106-
pub unsafe fn alloc_zeroed(layout: Layout) -> (*mut u8, bool) {
78+
/// SAFETY: See `alloc::alloc_zeroed()`
79+
pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
10780
let mut alloc = ALLOCATOR.lock().unwrap();
108-
if alloc.enabled {
109-
let ptr = unsafe { alloc.alloc_inner(layout, true) };
110-
(ptr, false)
111-
} else {
112-
unsafe { (alloc::alloc_zeroed(layout), true) }
113-
}
81+
unsafe { alloc.alloc_inner(layout, true) }
11482
}
11583

116-
/// SAFETY: The allocator must have been `enable()`d already and
117-
/// the `layout` must be valid.
84+
/// SAFETY: See `alloc::alloc()`
11885
unsafe fn alloc_inner(&mut self, layout: Layout, zeroed: bool) -> *mut u8 {
11986
let (size, align) = MachineAlloc::normalized_layout(layout);
12087

88+
if self.page_size == 0 {
89+
unsafe {
90+
self.page_size = libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap();
91+
}
92+
}
93+
12194
if align > self.page_size || size > self.page_size {
12295
unsafe { self.alloc_multi_page(layout, zeroed) }
12396
} else {
@@ -160,13 +133,10 @@ impl MachineAlloc {
160133
ret
161134
}
162135

163-
/// Deallocates a pointer from the machine allocator. While not unsound,
164-
/// attempting to deallocate a pointer if `MachineAlloc` has not been enabled
165-
/// will likely result in a panic.
136+
/// Deallocates a pointer from the isolated allocator.
166137
///
167138
/// SAFETY: This pointer must have been allocated with `MachineAlloc::alloc()`
168-
/// (or `alloc_zeroed()`) which must have returned `(ptr, false)` specifically!
169-
/// If it returned `(ptr, true)`, then deallocate it with `alloc::dealloc()` instead.
139+
/// (or `alloc_zeroed()`) with the same layout as the one passed.
170140
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
171141
let mut alloc_guard = ALLOCATOR.lock().unwrap();
172142
// Doing it this way lets us grab 2 mutable references to different fields at once

src/alloc/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ mod alloc_bytes;
22
#[cfg(target_os = "linux")]
33
pub mod discrete_alloc;
44

5-
pub use self::alloc_bytes::MiriAllocBytes;
5+
pub use self::alloc_bytes::{MiriAllocBytes, MiriByteMdata};

src/alloc_addresses/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,12 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
135135
if this.machine.native_lib.is_some() {
136136
// In native lib mode, we use the "real" address of the bytes for this allocation.
137137
// This ensures the interpreted program and native code have the same view of memory.
138+
let dsc = this.machine.get_default_byte_mdata();
138139
let base_ptr = match info.kind {
139140
AllocKind::LiveData => {
140141
if memory_kind == MiriMemoryKind::Global.into() {
141142
// For new global allocations, we always pre-allocate the memory to be able use the machine address directly.
142-
let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align)
143+
let prepared_bytes = MiriAllocBytes::zeroed(info.size, info.align, dsc)
143144
.unwrap_or_else(|| {
144145
panic!("Miri ran out of memory: cannot create allocation of {size:?} bytes", size = info.size)
145146
});
@@ -159,7 +160,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
159160
AllocKind::Function | AllocKind::VTable => {
160161
// Allocate some dummy memory to get a unique address for this function/vtable.
161162
let alloc_bytes =
162-
MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap());
163+
MiriAllocBytes::from_bytes(&[0u8; 1], Align::from_bytes(1).unwrap(), dsc);
163164
let ptr = alloc_bytes.as_ptr();
164165
// Leak the underlying memory to ensure it remains unique.
165166
std::mem::forget(alloc_bytes);
@@ -429,7 +430,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
429430
prepared_alloc_bytes.copy_from_slice(bytes);
430431
interp_ok(prepared_alloc_bytes)
431432
} else {
432-
interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align))
433+
let dsc = this.machine.get_default_byte_mdata();
434+
interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align, dsc))
433435
}
434436
}
435437

src/concurrency/thread.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -894,12 +894,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
894894
if tcx.is_foreign_item(def_id) {
895895
throw_unsup_format!("foreign thread-local statics are not supported");
896896
}
897+
let dsc = this.machine.get_default_byte_mdata();
897898
let alloc = this.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?;
898899
// We make a full copy of this allocation.
899900
let mut alloc = alloc.inner().adjust_from_tcx(
900901
&this.tcx,
901902
|bytes, align| {
902-
interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align))
903+
interp_ok(MiriAllocBytes::from_bytes(std::borrow::Cow::Borrowed(bytes), align, dsc))
903904
},
904905
|ptr| this.global_root_pointer(ptr),
905906
)?;

0 commit comments

Comments
 (0)