1
Fork 0

Auto merge of #89030 - nbdd0121:box2, r=jonas-schievink

Introduce `Rvalue::ShallowInitBox`

Polished version of #88700.

Implements MCP rust-lang/compiler-team#460, and should allow #43596 to go forward.

In short, creating an empty box is split from a nullary-op `NullOp::Box` into two steps, first a call to `exchange_malloc`, then a `Rvalue::ShallowInitBox` which transmutes `*mut u8` to a shallow-initialized `Box<T>`. This allows the `exchange_malloc` call to unwind. Details can be found in the MCP.

`NullOp::Box` is not yet removed, purely to make reverting easier in case anything goes wrong as the result of this PR. If revert is needed a reversion of "Use Rvalue::ShallowInitBox for box expression" commit followed by a test bless should be sufficient.

Experiments in #88700 showed a very slight compile-time perf regression due to (supposedly) slightly more time spent in LLVM. We could omit unwind edge generation (in non-`oom=panic` case) in box expression MIR construction to restore perf; but I don't think it's necessary since runtime perf isn't affected and perf difference is rather small.
This commit is contained in:
bors 2021-09-25 11:01:13 +00:00
commit e9f29a8519
31 changed files with 478 additions and 237 deletions

View file

@ -2200,6 +2200,12 @@ pub enum Rvalue<'tcx> {
/// that `Foo` has a destructor. These rvalues can be optimized
/// away after type-checking and before lowering.
Aggregate(Box<AggregateKind<'tcx>>, Vec<Operand<'tcx>>),
/// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
///
/// This is different a normal transmute because dataflow analysis will treat the box
/// as initialized but its content as uninitialized.
ShallowInitBox(Operand<'tcx>, Ty<'tcx>),
}
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
@ -2450,6 +2456,10 @@ impl<'tcx> Debug for Rvalue<'tcx> {
}),
}
}
ShallowInitBox(ref place, ref ty) => {
write!(fmt, "ShallowInitBox({:?}, {:?})", place, ty)
}
}
}
}

View file

@ -206,6 +206,7 @@ impl<'tcx> Rvalue<'tcx> {
tcx.mk_generator(did, substs, movability)
}
},
Rvalue::ShallowInitBox(_, ty) => tcx.mk_box(ty),
}
}
@ -214,7 +215,9 @@ impl<'tcx> Rvalue<'tcx> {
/// whether its only shallowly initialized (`Rvalue::Box`).
pub fn initialization_state(&self) -> RvalueInitializationState {
match *self {
Rvalue::NullaryOp(NullOp::Box, _) => RvalueInitializationState::Shallow,
Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::ShallowInitBox(_, _) => {
RvalueInitializationState::Shallow
}
_ => RvalueInitializationState::Deep,
}
}

View file

@ -210,6 +210,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
});
Aggregate(kind, fields.fold_with(folder))
}
ShallowInitBox(op, ty) => ShallowInitBox(op.fold_with(folder), ty.fold_with(folder)),
}
}
@ -255,6 +256,10 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> {
}
fields.visit_with(visitor)
}
ShallowInitBox(ref op, ty) => {
op.visit_with(visitor)?;
ty.visit_with(visitor)
}
}
}
}

View file

@ -753,6 +753,11 @@ macro_rules! make_mir_visitor {
self.visit_operand(operand, location);
}
}
Rvalue::ShallowInitBox(operand, ty) => {
self.visit_operand(operand, location);
self.visit_ty(ty, TyContext::Location(location));
}
}
}