Skip to content

Commit

Permalink
don't tag new memory inside memory.rs; add machine hook to tag new me…
Browse files Browse the repository at this point in the history
…mory
  • Loading branch information
RalfJung committed Oct 28, 2018
1 parent ff3b29f commit b2612cb
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 24 deletions.
13 changes: 11 additions & 2 deletions src/librustc_mir/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use syntax::ast::Mutability;
use syntax::source_map::{Span, DUMMY_SP};

use interpret::{self,
PlaceTy, MemPlace, OpTy, Operand, Value, Scalar, ConstValue,
PlaceTy, MemPlace, OpTy, Operand, Value, Scalar, ConstValue, Pointer,
EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup,
Allocation, AllocId, MemoryKind,
snapshot, RefTracking,
Expand Down Expand Up @@ -426,7 +426,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
}

#[inline(always)]
fn static_with_default_tag(
fn adjust_static_allocation(
alloc: &'_ Allocation
) -> Cow<'_, Allocation<Self::PointerTag>> {
// We do not use a tag so we can just cheaply forward the reference
Expand Down Expand Up @@ -465,6 +465,15 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
&ecx.stack[..],
)
}

#[inline(always)]
fn tag_new_allocation(
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
ptr: Pointer,
_kind: MemoryKind<Self::MemoryKinds>,
) -> EvalResult<'tcx, Pointer> {
Ok(ptr)
}
}

/// Project to a field of a (variant of a) const
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/interpret/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
def_id,
substs,
).ok_or_else(|| EvalErrorKind::TooGeneric.into());
let fn_ptr = self.memory.create_fn_alloc(instance?);
let fn_ptr = self.memory.create_fn_alloc(instance?).with_default_tag();
self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
}
ref other => bug!("reify fn pointer on {:?}", other),
Expand Down Expand Up @@ -143,7 +143,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
substs,
ty::ClosureKind::FnOnce,
);
let fn_ptr = self.memory.create_fn_alloc(instance);
let fn_ptr = self.memory.create_fn_alloc(instance).with_default_tag();
let val = Value::Scalar(Scalar::Ptr(fn_ptr.into()).into());
self.write_value(val, dest)?;
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
}

pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value<M::PointerTag>> {
let ptr = self.memory.allocate_static_bytes(s.as_bytes());
let ptr = self.memory.allocate_static_bytes(s.as_bytes()).with_default_tag();
Ok(Value::new_slice(Scalar::Ptr(ptr), s.len() as u64, self.tcx.tcx))
}

Expand Down
14 changes: 11 additions & 3 deletions src/librustc_mir/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {

/// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows"
/// <https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html>.
/// The `default()` is used for pointers to consts, statics, vtables and functions.
type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static;

/// Extra data stored in every allocation.
Expand Down Expand Up @@ -151,13 +152,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag, Self::AllocExtra>>>;

/// Called to turn an allocation obtained from the `tcx` into one that has
/// the appropriate tags on each pointer.
/// the right type for this machine.
///
/// This should avoid copying if no work has to be done! If this returns an owned
/// allocation (because a copy had to be done to add the tags), machine memory will
/// allocation (because a copy had to be done to add tags or metadata), machine memory will
/// cache the result. (This relies on `AllocMap::get_or` being able to add the
/// owned allocation to the map even when the map is shared.)
fn static_with_default_tag(
fn adjust_static_allocation(
alloc: &'_ Allocation
) -> Cow<'_, Allocation<Self::PointerTag, Self::AllocExtra>>;

Expand Down Expand Up @@ -204,6 +205,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
Ok(())
}

/// Add the tag for a newly allocated pointer.
fn tag_new_allocation(
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
ptr: Pointer,
kind: MemoryKind<Self::MemoryKinds>,
) -> EvalResult<'tcx, Pointer<Self::PointerTag>>;

/// Executed when evaluating the `&` operator: Creating a new reference.
/// This has the chance to adjust the tag. It should not change anything else!
/// `mutability` can be `None` in case a raw ptr is being created.
Expand Down
24 changes: 12 additions & 12 deletions src/librustc_mir/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
}
}

pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer<M::PointerTag> {
Pointer::from(self.tcx.alloc_map.lock().create_fn_alloc(instance)).with_default_tag()
pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer {
Pointer::from(self.tcx.alloc_map.lock().create_fn_alloc(instance))
}

pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer<M::PointerTag> {
Pointer::from(self.tcx.allocate_bytes(bytes)).with_default_tag()
pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer {
Pointer::from(self.tcx.allocate_bytes(bytes))
}

pub fn allocate_with(
Expand All @@ -140,9 +140,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
size: Size,
align: Align,
kind: MemoryKind<M::MemoryKinds>,
) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
let ptr = Pointer::from(self.allocate_with(Allocation::undef(size, align), kind)?);
Ok(ptr.with_default_tag())
) -> EvalResult<'tcx, Pointer> {
Ok(Pointer::from(self.allocate_with(Allocation::undef(size, align), kind)?))
}

pub fn reallocate(
Expand All @@ -153,17 +152,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
new_size: Size,
new_align: Align,
kind: MemoryKind<M::MemoryKinds>,
) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
) -> EvalResult<'tcx, Pointer> {
if ptr.offset.bytes() != 0 {
return err!(ReallocateNonBasePtr);
}

// For simplicities' sake, we implement reallocate as "alloc, copy, dealloc"
// For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
// FIXME: Do something more efficient.
let new_ptr = self.allocate(new_size, new_align, kind)?;
self.copy(
ptr.into(),
old_align,
new_ptr.into(),
new_ptr.with_default_tag().into(),
new_align,
old_size.min(new_size),
/*nonoverlapping*/ true,
Expand Down Expand Up @@ -347,7 +347,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
Some(AllocType::Memory(mem)) => {
// We got tcx memory. Let the machine figure out whether and how to
// turn that into memory with the right pointer tag.
return Ok(M::static_with_default_tag(mem))
return Ok(M::adjust_static_allocation(mem))
}
Some(AllocType::Function(..)) => {
return err!(DerefFunctionPointer)
Expand Down Expand Up @@ -381,7 +381,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
if let ConstValue::ByRef(_, allocation, _) = const_val.val {
// We got tcx memory. Let the machine figure out whether and how to
// turn that into memory with the right pointer tag.
M::static_with_default_tag(allocation)
M::adjust_static_allocation(allocation)
} else {
bug!("Matching on non-ByRef static")
}
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_mir/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,8 @@ where
}

/// Make sure that a place is in memory, and return where it is.
/// If the place currently refers to a local that doesn't yet have a matching allocation,
/// create such an allocation.
/// This is essentially `force_to_memplace`.
pub fn force_allocation(
&mut self,
Expand Down Expand Up @@ -899,10 +901,11 @@ where
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
if layout.is_unsized() {
assert!(self.tcx.features().unsized_locals, "cannot alloc memory for unsized type");
// FIXME: What should we do here?
// FIXME: What should we do here? We should definitely also tag!
Ok(MPlaceTy::dangling(layout, &self))
} else {
let ptr = self.memory.allocate(layout.size, layout.align, kind)?;
let ptr = M::tag_new_allocation(self, ptr, kind)?;
Ok(MPlaceTy::from_aligned_ptr(ptr, layout))
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_mir/interpret/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
ptr_size * (3 + methods.len() as u64),
ptr_align,
MemoryKind::Vtable,
)?;
)?.with_default_tag();

let drop = ::monomorphize::resolve_drop_in_place(*self.tcx, ty);
let drop = self.memory.create_fn_alloc(drop);
let drop = self.memory.create_fn_alloc(drop).with_default_tag();
self.memory.write_ptr_sized(vtable, ptr_align, Scalar::Ptr(drop).into())?;

let size_ptr = vtable.offset(ptr_size, &self)?;
Expand All @@ -69,7 +69,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
for (i, method) in methods.iter().enumerate() {
if let Some((def_id, substs)) = *method {
let instance = self.resolve(def_id, substs)?;
let fn_ptr = self.memory.create_fn_alloc(instance);
let fn_ptr = self.memory.create_fn_alloc(instance).with_default_tag();
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?;
self.memory.write_ptr_sized(method_ptr, ptr_align, Scalar::Ptr(fn_ptr).into())?;
}
Expand Down

0 comments on commit b2612cb

Please sign in to comment.