Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stacked borrows: Support 2 phase borrows #56307

Merged
merged 4 commits into from
Dec 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 12 additions & 45 deletions src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,51 +193,18 @@ for mir::TerminatorKind<'gcx> {

impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });

impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
for mir::StatementKind<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
mem::discriminant(self).hash_stable(hcx, hasher);

match *self {
mir::StatementKind::Assign(ref place, ref rvalue) => {
place.hash_stable(hcx, hasher);
rvalue.hash_stable(hcx, hasher);
}
mir::StatementKind::FakeRead(ref cause, ref place) => {
cause.hash_stable(hcx, hasher);
place.hash_stable(hcx, hasher);
}
mir::StatementKind::SetDiscriminant { ref place, variant_index } => {
place.hash_stable(hcx, hasher);
variant_index.hash_stable(hcx, hasher);
}
mir::StatementKind::StorageLive(ref place) |
mir::StatementKind::StorageDead(ref place) => {
place.hash_stable(hcx, hasher);
}
mir::StatementKind::EscapeToRaw(ref place) => {
place.hash_stable(hcx, hasher);
}
mir::StatementKind::Retag { fn_entry, ref place } => {
fn_entry.hash_stable(hcx, hasher);
place.hash_stable(hcx, hasher);
}
mir::StatementKind::AscribeUserType(ref place, ref variance, ref c_ty) => {
place.hash_stable(hcx, hasher);
variance.hash_stable(hcx, hasher);
c_ty.hash_stable(hcx, hasher);
}
mir::StatementKind::Nop => {}
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
asm.hash_stable(hcx, hasher);
outputs.hash_stable(hcx, hasher);
inputs.hash_stable(hcx, hasher);
}
}
}
}
impl_stable_hash_for!(impl<'gcx> for enum mir::StatementKind<'gcx> [ mir::StatementKind ] {
Assign(place, rvalue),
FakeRead(cause, place),
SetDiscriminant { place, variant_index },
StorageLive(place),
StorageDead(place),
EscapeToRaw(place),
Retag { fn_entry, two_phase, place },
AscribeUserType(place, variance, c_ty),
Nop,
InlineAsm { asm, outputs, inputs },
});

impl_stable_hash_for!(enum mir::FakeReadCause { ForMatchGuard, ForMatchedPlace, ForLet });

Expand Down
8 changes: 8 additions & 0 deletions src/librustc/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ impl<'tcx, Tag> Scalar<Tag> {
}
}

#[inline]
pub fn with_tag(self, new_tag: Tag) -> Self {
match self {
Scalar::Ptr(ptr) => Scalar::Ptr(Pointer { tag: new_tag, ..ptr }),
Scalar::Bits { bits, size } => Scalar::Bits { bits, size },
}
}

#[inline]
pub fn ptr_null(cx: &impl HasDataLayout) -> Self {
Scalar::Bits {
Expand Down
14 changes: 11 additions & 3 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1778,6 +1778,10 @@ pub enum StatementKind<'tcx> {
/// `fn_entry` indicates whether this is the initial retag that happens in the
/// function prolog.
fn_entry: bool,
/// `two_phase` indicates whether this is just the reservation action of
/// a two-phase borrow.
two_phase: bool,
/// The place to retag
place: Place<'tcx>,
},

Expand Down Expand Up @@ -1841,8 +1845,12 @@ impl<'tcx> Debug for Statement<'tcx> {
match self.kind {
Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv),
FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, place),
Retag { fn_entry, ref place } =>
write!(fmt, "Retag({}{:?})", if fn_entry { "[fn entry] " } else { "" }, place),
Retag { fn_entry, two_phase, ref place } =>
write!(fmt, "Retag({}{}{:?})",
if fn_entry { "[fn entry] " } else { "" },
if two_phase { "[2phase] " } else { "" },
place,
),
EscapeToRaw(ref place) => write!(fmt, "EscapeToRaw({:?})", place),
StorageLive(ref place) => write!(fmt, "StorageLive({:?})", place),
StorageDead(ref place) => write!(fmt, "StorageDead({:?})", place),
Expand Down Expand Up @@ -3019,7 +3027,7 @@ EnumTypeFoldableImpl! {
(StatementKind::StorageLive)(a),
(StatementKind::StorageDead)(a),
(StatementKind::InlineAsm) { asm, outputs, inputs },
(StatementKind::Retag) { fn_entry, place },
(StatementKind::Retag) { fn_entry, two_phase, place },
(StatementKind::EscapeToRaw)(place),
(StatementKind::AscribeUserType)(a, v, b),
(StatementKind::Nop),
Expand Down
7 changes: 5 additions & 2 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,10 @@ macro_rules! make_mir_visitor {

fn visit_retag(&mut self,
fn_entry: & $($mutability)* bool,
two_phase: & $($mutability)* bool,
place: & $($mutability)* Place<'tcx>,
location: Location) {
self.super_retag(fn_entry, place, location);
self.super_retag(fn_entry, two_phase, place, location);
}

fn visit_place(&mut self,
Expand Down Expand Up @@ -417,8 +418,9 @@ macro_rules! make_mir_visitor {
}
}
StatementKind::Retag { ref $($mutability)* fn_entry,
ref $($mutability)* two_phase,
ref $($mutability)* place } => {
self.visit_retag(fn_entry, place, location);
self.visit_retag(fn_entry, two_phase, place, location);
}
StatementKind::AscribeUserType(
ref $($mutability)* place,
Expand Down Expand Up @@ -724,6 +726,7 @@ macro_rules! make_mir_visitor {

fn super_retag(&mut self,
_fn_entry: & $($mutability)* bool,
_two_phase: & $($mutability)* bool,
place: & $($mutability)* Place<'tcx>,
location: Location) {
self.visit_place(
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/interpret/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
fn retag(
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
_fn_entry: bool,
_two_phase: bool,
_place: PlaceTy<'tcx, Self::PointerTag>,
) -> EvalResult<'tcx> {
Ok(())
Expand Down
20 changes: 20 additions & 0 deletions src/librustc_mir/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ impl<Tag> MemPlace<Tag> {
}
}

#[inline]
pub fn with_tag(self, new_tag: Tag) -> Self
{
MemPlace {
ptr: self.ptr.with_tag(new_tag),
align: self.align,
meta: self.meta,
}
}

#[inline(always)]
pub fn from_scalar_ptr(ptr: Scalar<Tag>, align: Align) -> Self {
MemPlace {
Expand Down Expand Up @@ -187,6 +197,16 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> {
}
}

#[inline]
pub fn with_tag(self, new_tag: Tag) -> Self
{
MPlaceTy {
mplace: self.mplace.with_tag(new_tag),
layout: self.layout,
}
}

#[inline]
pub fn offset(
self,
offset: Size,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/interpret/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
FakeRead(..) => {}

// Stacked Borrows.
Retag { fn_entry, ref place } => {
Retag { fn_entry, two_phase, ref place } => {
let dest = self.eval_place(place)?;
M::retag(self, fn_entry, dest)?;
M::retag(self, fn_entry, two_phase, dest)?;
}
EscapeToRaw(ref op) => {
let op = self.eval_operand(op, None)?;
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_mir/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,11 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Function arguments should be retagged
mir.basic_blocks_mut()[START_BLOCK].statements.insert(0, Statement {
source_info,
kind: StatementKind::Retag { fn_entry: true, place: dropee_ptr.clone() },
kind: StatementKind::Retag {
fn_entry: true,
two_phase: false,
place: dropee_ptr.clone(),
},
});
// We use raw ptr operations, better prepare the alias tracking for that
mir.basic_blocks_mut()[START_BLOCK].statements.insert(1, Statement {
Expand Down
17 changes: 13 additions & 4 deletions src/librustc_mir/transform/add_retag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ impl MirPass for AddRetag {
basic_blocks[START_BLOCK].statements.splice(0..0,
places.into_iter().map(|place| Statement {
source_info,
kind: StatementKind::Retag { fn_entry: true, place },
kind: StatementKind::Retag { fn_entry: true, two_phase: false, place },
})
);
}
Expand Down Expand Up @@ -154,7 +154,7 @@ impl MirPass for AddRetag {
for (source_info, dest_place, dest_block) in returns {
basic_blocks[dest_block].statements.insert(0, Statement {
source_info,
kind: StatementKind::Retag { fn_entry: false, place: dest_place },
kind: StatementKind::Retag { fn_entry: false, two_phase: false, place: dest_place },
});
}

Expand Down Expand Up @@ -191,12 +191,21 @@ impl MirPass for AddRetag {
// Assignments of reference or ptr type are the ones where we may have
// to update tags. This includes `x = &[mut] ...` and hence
// we also retag after taking a reference!
StatementKind::Assign(ref place, _) if needs_retag(place) => {
StatementKind::Assign(ref place, box ref rvalue) if needs_retag(place) => {
let two_phase = match rvalue {
Rvalue::Ref(_, borrow_kind, _) =>
borrow_kind.allows_two_phase_borrow(),
_ => false
};
// Insert a retag after the assignment.
let source_info = block_data.statements[i].source_info;
block_data.statements.insert(i+1, Statement {
source_info,
kind: StatementKind::Retag { fn_entry: false, place: place.clone() },
kind: StatementKind::Retag {
fn_entry: false,
two_phase,
place: place.clone(),
},
});
}
// Do nothing for the rest
Expand Down
10 changes: 8 additions & 2 deletions src/librustc_mir/transform/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -707,8 +707,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
self.in_cleanup_block = false;
}

fn visit_retag(&mut self, fn_entry: &mut bool, place: &mut Place<'tcx>, loc: Location) {
self.super_retag(fn_entry, place, loc);
fn visit_retag(
&mut self,
fn_entry: &mut bool,
two_phase: &mut bool,
place: &mut Place<'tcx>,
loc: Location,
) {
self.super_retag(fn_entry, two_phase, place, loc);

// We have to patch all inlined retags to be aware that they are no longer
// happening on function entry.
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri
Submodule miri updated from 8d2bc9 to 61f207