miri: optimize zeroed alloc
Co-authored-by: Ralf Jung <post@ralfj.de>
This commit is contained in:
parent
8231e8599e
commit
eee9df43e6
14 changed files with 88 additions and 79 deletions
|
@ -270,6 +270,12 @@ impl AllocRange {
|
|||
}
|
||||
}
|
||||
|
||||
/// Whether a new allocation should be initialized with zero-bytes.
|
||||
pub enum AllocInit {
|
||||
Uninit,
|
||||
Zero,
|
||||
}
|
||||
|
||||
// The constructors are all without extra; the extra gets added by a machine hook later.
|
||||
impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
|
||||
/// Creates an allocation initialized by the given bytes
|
||||
|
@ -294,7 +300,12 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
|
|||
Allocation::from_bytes(slice, Align::ONE, Mutability::Not)
|
||||
}
|
||||
|
||||
fn uninit_inner<R>(size: Size, align: Align, fail: impl FnOnce() -> R) -> Result<Self, R> {
|
||||
fn new_inner<R>(
|
||||
size: Size,
|
||||
align: Align,
|
||||
init: AllocInit,
|
||||
fail: impl FnOnce() -> R,
|
||||
) -> Result<Self, R> {
|
||||
// We raise an error if we cannot create the allocation on the host.
|
||||
// This results in an error that can happen non-deterministically, since the memory
|
||||
// available to the compiler can change between runs. Normally queries are always
|
||||
|
@ -306,7 +317,10 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
|
|||
Ok(Allocation {
|
||||
bytes,
|
||||
provenance: ProvenanceMap::new(),
|
||||
init_mask: InitMask::new(size, false),
|
||||
init_mask: InitMask::new(size, match init {
|
||||
AllocInit::Uninit => false,
|
||||
AllocInit::Zero => true,
|
||||
}),
|
||||
align,
|
||||
mutability: Mutability::Mut,
|
||||
extra: (),
|
||||
|
@ -315,8 +329,8 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
|
|||
|
||||
/// Try to create an Allocation of `size` bytes, failing if there is not enough memory
|
||||
/// available to the compiler to do so.
|
||||
pub fn try_uninit<'tcx>(size: Size, align: Align) -> InterpResult<'tcx, Self> {
|
||||
Self::uninit_inner(size, align, || {
|
||||
pub fn try_new<'tcx>(size: Size, align: Align, init: AllocInit) -> InterpResult<'tcx, Self> {
|
||||
Self::new_inner(size, align, init, || {
|
||||
ty::tls::with(|tcx| tcx.dcx().delayed_bug("exhausted memory during interpretation"));
|
||||
InterpErrorKind::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
|
||||
})
|
||||
|
@ -328,8 +342,8 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
|
|||
///
|
||||
/// Example use case: To obtain an Allocation filled with specific data,
|
||||
/// first call this function and then call write_scalar to fill in the right data.
|
||||
pub fn uninit(size: Size, align: Align) -> Self {
|
||||
match Self::uninit_inner(size, align, || {
|
||||
pub fn new(size: Size, align: Align, init: AllocInit) -> Self {
|
||||
match Self::new_inner(size, align, init, || {
|
||||
panic!(
|
||||
"interpreter ran out of memory: cannot create allocation of {} bytes",
|
||||
size.bytes()
|
||||
|
|
|
@ -30,8 +30,8 @@ pub use {
|
|||
};
|
||||
|
||||
pub use self::allocation::{
|
||||
AllocBytes, AllocError, AllocRange, AllocResult, Allocation, ConstAllocation, InitChunk,
|
||||
InitChunkIter, alloc_range,
|
||||
AllocBytes, AllocError, AllocInit, AllocRange, AllocResult, Allocation, ConstAllocation,
|
||||
InitChunk, InitChunkIter, alloc_range,
|
||||
};
|
||||
pub use self::error::{
|
||||
BadBytesAccess, CheckAlignMsg, CheckInAllocMsg, ErrorHandled, EvalStaticInitializerRawResult,
|
||||
|
|
|
@ -4,7 +4,9 @@ use rustc_ast::Mutability;
|
|||
use rustc_macros::HashStable;
|
||||
use rustc_type_ir::elaborate;
|
||||
|
||||
use crate::mir::interpret::{AllocId, Allocation, CTFE_ALLOC_SALT, Pointer, Scalar, alloc_range};
|
||||
use crate::mir::interpret::{
|
||||
AllocId, AllocInit, Allocation, CTFE_ALLOC_SALT, Pointer, Scalar, alloc_range,
|
||||
};
|
||||
use crate::ty::{self, Instance, PolyTraitRef, Ty, TyCtxt};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, HashStable)]
|
||||
|
@ -108,7 +110,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
|
|||
let ptr_align = tcx.data_layout.pointer_align.abi;
|
||||
|
||||
let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
|
||||
let mut vtable = Allocation::uninit(vtable_size, ptr_align);
|
||||
let mut vtable = Allocation::new(vtable_size, ptr_align, AllocInit::Uninit);
|
||||
|
||||
// No need to do any alignment checks on the memory accesses below, because we know the
|
||||
// allocation is correctly aligned as we created it above. Also we're only offsetting by
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue