Skip to content

Commit 7cfb05f

Browse files
committed
Merge locals and local_layouts fields
1 parent 43b4c4a commit 7cfb05f

File tree

3 files changed

+68
-39
lines changed

3 files changed

+68
-39
lines changed

src/librustc_mir/interpret/eval_context.rs

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,7 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
7676
/// The locals are stored as `Option<Value>`s.
7777
/// `None` represents a local that is currently dead, while a live local
7878
/// can either directly contain `Scalar` or refer to some part of an `Allocation`.
79-
pub locals: IndexVec<mir::Local, LocalValue<Tag>>,
80-
pub local_layouts: IndexVec<mir::Local, Cell<Option<TyLayout<'tcx>>>>,
79+
pub locals: IndexVec<mir::Local, LocalValue<'tcx, Tag>>,
8180

8281
////////////////////////////////////////////////////////////////////////////////
8382
// Current position within the function
@@ -106,9 +105,17 @@ pub enum StackPopCleanup {
106105
None { cleanup: bool },
107106
}
108107

109-
// State of a local variable
108+
/// State of a local variable including a memoized layout
109+
#[derive(Clone, PartialEq, Eq)]
110+
pub struct LocalValue<'tcx, Tag=(), Id=AllocId> {
111+
pub state: LocalState<Tag, Id>,
112+
/// Don't modify if `Some`, this is only used to prevent computing the layout twice
113+
pub layout: Cell<Option<TyLayout<'tcx>>>,
114+
}
115+
116+
/// State of a local variable
110117
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
111-
pub enum LocalValue<Tag=(), Id=AllocId> {
118+
pub enum LocalState<Tag=(), Id=AllocId> {
112119
Dead,
113120
// Mostly for convenience, we re-use the `Operand` type here.
114121
// This is an optimization over just always having a pointer here;
@@ -117,18 +124,18 @@ pub enum LocalValue<Tag=(), Id=AllocId> {
117124
Live(Operand<Tag, Id>),
118125
}
119126

120-
impl<'tcx, Tag> LocalValue<Tag> {
127+
impl<'tcx, Tag> LocalValue<'tcx, Tag> {
121128
pub fn access(&self) -> EvalResult<'tcx, &Operand<Tag>> {
122-
match self {
123-
LocalValue::Dead => err!(DeadLocal),
124-
LocalValue::Live(ref val) => Ok(val),
129+
match self.state {
130+
LocalState::Dead => err!(DeadLocal),
131+
LocalState::Live(ref val) => Ok(val),
125132
}
126133
}
127134

128135
pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand<Tag>> {
129-
match self {
130-
LocalValue::Dead => err!(DeadLocal),
131-
LocalValue::Live(ref mut val) => Ok(val),
136+
match self.state {
137+
LocalState::Dead => err!(DeadLocal),
138+
LocalState::Live(ref mut val) => Ok(val),
132139
}
133140
}
134141
}
@@ -312,7 +319,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
312319
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
313320
local: mir::Local
314321
) -> EvalResult<'tcx, TyLayout<'tcx>> {
315-
let cell = &frame.local_layouts[local];
322+
let cell = &frame.locals[local].layout;
316323
if cell.get().is_none() {
317324
let local_ty = frame.mir.local_decls[local].ty;
318325
let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
@@ -454,7 +461,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
454461
// empty local array, we fill it in below, after we are inside the stack frame and
455462
// all methods actually know about the frame
456463
locals: IndexVec::new(),
457-
local_layouts: IndexVec::from_elem_n(Default::default(), mir.local_decls.len()),
458464
span,
459465
instance,
460466
stmt: 0,
@@ -464,14 +470,18 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
464470
// don't allocate at all for trivial constants
465471
if mir.local_decls.len() > 1 {
466472
// We put some marker immediate into the locals that we later want to initialize.
467-
// This can be anything except for LocalValue::Dead -- because *that* is the
473+
// This can be anything except for LocalState::Dead -- because *that* is the
468474
// value we use for things that we know are initially dead.
469-
let dummy =
470-
LocalValue::Live(Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef)));
475+
let dummy = LocalValue {
476+
state: LocalState::Live(Operand::Immediate(Immediate::Scalar(
477+
ScalarMaybeUndef::Undef,
478+
))),
479+
layout: Cell::new(None),
480+
};
471481
let mut locals = IndexVec::from_elem(dummy, &mir.local_decls);
472482
// Return place is handled specially by the `eval_place` functions, and the
473483
// entry in `locals` should never be used. Make it dead, to be sure.
474-
locals[mir::RETURN_PLACE] = LocalValue::Dead;
484+
locals[mir::RETURN_PLACE].state = LocalState::Dead;
475485
// Now mark those locals as dead that we do not want to initialize
476486
match self.tcx.describe_def(instance.def_id()) {
477487
// statics and constants don't have `Storage*` statements, no need to look for them
@@ -484,7 +494,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
484494
match stmt.kind {
485495
StorageLive(local) |
486496
StorageDead(local) => {
487-
locals[local] = LocalValue::Dead;
497+
locals[local].state = LocalState::Dead;
488498
}
489499
_ => {}
490500
}
@@ -494,13 +504,13 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
494504
}
495505
// Finally, properly initialize all those that still have the dummy value
496506
for (idx, local) in locals.iter_enumerated_mut() {
497-
match *local {
498-
LocalValue::Live(_) => {
507+
match local.state {
508+
LocalState::Live(_) => {
499509
// This needs to be peoperly initialized.
500510
let layout = self.layout_of_local(self.frame(), idx)?;
501-
*local = LocalValue::Live(self.uninit_operand(layout)?);
511+
local.state = LocalState::Live(self.uninit_operand(layout)?);
502512
}
503-
LocalValue::Dead => {
513+
LocalState::Dead => {
504514
// Nothing to do
505515
}
506516
}
@@ -543,7 +553,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
543553
}
544554
// Deallocate all locals that are backed by an allocation.
545555
for local in frame.locals {
546-
self.deallocate_local(local)?;
556+
self.deallocate_local(local.state)?;
547557
}
548558
// Validate the return value. Do this after deallocating so that we catch dangling
549559
// references.
@@ -587,31 +597,31 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
587597
pub fn storage_live(
588598
&mut self,
589599
local: mir::Local
590-
) -> EvalResult<'tcx, LocalValue<M::PointerTag>> {
600+
) -> EvalResult<'tcx, LocalState<M::PointerTag>> {
591601
assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
592602
trace!("{:?} is now live", local);
593603

594604
let layout = self.layout_of_local(self.frame(), local)?;
595-
let init = LocalValue::Live(self.uninit_operand(layout)?);
605+
let init = LocalState::Live(self.uninit_operand(layout)?);
596606
// StorageLive *always* kills the value that's currently stored
597-
Ok(mem::replace(&mut self.frame_mut().locals[local], init))
607+
Ok(mem::replace(&mut self.frame_mut().locals[local].state, init))
598608
}
599609

600610
/// Returns the old value of the local.
601611
/// Remember to deallocate that!
602-
pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue<M::PointerTag> {
612+
pub fn storage_dead(&mut self, local: mir::Local) -> LocalState<M::PointerTag> {
603613
assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
604614
trace!("{:?} is now dead", local);
605615

606-
mem::replace(&mut self.frame_mut().locals[local], LocalValue::Dead)
616+
mem::replace(&mut self.frame_mut().locals[local].state, LocalState::Dead)
607617
}
608618

609619
pub(super) fn deallocate_local(
610620
&mut self,
611-
local: LocalValue<M::PointerTag>,
621+
local: LocalState<M::PointerTag>,
612622
) -> EvalResult<'tcx> {
613623
// FIXME: should we tell the user that there was a local which was never written to?
614-
if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
624+
if let LocalState::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
615625
trace!("deallocating local");
616626
let ptr = ptr.to_ptr()?;
617627
self.memory.dump_alloc(ptr.alloc_id);

src/librustc_mir/interpret/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ mod visitor;
1818
pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here
1919

2020
pub use self::eval_context::{
21-
EvalContext, Frame, StackPopCleanup, LocalValue,
21+
EvalContext, Frame, StackPopCleanup, LocalValue, LocalState,
2222
};
2323

2424
pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};

src/librustc_mir/interpret/snapshot.rs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use std::hash::{Hash, Hasher};
99

10-
use rustc::ich::StableHashingContextProvider;
10+
use rustc::ich::{StableHashingContextProvider, StableHashingContext};
1111
use rustc::mir;
1212
use rustc::mir::interpret::{
1313
AllocId, Pointer, Scalar,
@@ -19,12 +19,12 @@ use rustc::ty::{self, TyCtxt};
1919
use rustc::ty::layout::Align;
2020
use rustc_data_structures::fx::FxHashSet;
2121
use rustc_data_structures::indexed_vec::IndexVec;
22-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
22+
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
2323
use syntax::ast::Mutability;
2424
use syntax::source_map::Span;
2525

2626
use super::eval_context::{LocalValue, StackPopCleanup};
27-
use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef};
27+
use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef, LocalState};
2828
use const_eval::CompileTimeInterpreter;
2929

3030
#[derive(Default)]
@@ -250,11 +250,11 @@ impl_snapshot_for!(enum Operand {
250250
Indirect(m),
251251
});
252252

253-
impl_stable_hash_for!(enum ::interpret::LocalValue {
253+
impl_stable_hash_for!(enum ::interpret::LocalState {
254254
Dead,
255255
Live(x),
256256
});
257-
impl_snapshot_for!(enum LocalValue {
257+
impl_snapshot_for!(enum LocalState {
258258
Live(v),
259259
Dead,
260260
});
@@ -309,7 +309,7 @@ struct FrameSnapshot<'a, 'tcx: 'a> {
309309
span: &'a Span,
310310
return_to_block: &'a StackPopCleanup,
311311
return_place: Option<Place<(), AllocIdSnapshot<'a>>>,
312-
locals: IndexVec<mir::Local, LocalValue<(), AllocIdSnapshot<'a>>>,
312+
locals: IndexVec<mir::Local, LocalState<(), AllocIdSnapshot<'a>>>,
313313
block: &'a mir::BasicBlock,
314314
stmt: usize,
315315
}
@@ -321,7 +321,6 @@ impl_stable_hash_for!(impl<'mir, 'tcx: 'mir> for struct Frame<'mir, 'tcx> {
321321
return_to_block,
322322
return_place -> (return_place.as_ref().map(|r| &**r)),
323323
locals,
324-
local_layouts -> _,
325324
block,
326325
stmt,
327326
extra,
@@ -340,7 +339,6 @@ impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
340339
return_to_block,
341340
return_place,
342341
locals,
343-
local_layouts: _,
344342
block,
345343
stmt,
346344
extra: _,
@@ -358,6 +356,27 @@ impl<'a, 'mir, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a Frame<'mir, 'tcx>
358356
}
359357
}
360358

359+
impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalValue<'tcx>
360+
where Ctx: SnapshotContext<'a>,
361+
{
362+
type Item = LocalState<(), AllocIdSnapshot<'a>>;
363+
364+
fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
365+
self.state.snapshot(ctx)
366+
}
367+
}
368+
369+
370+
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for LocalValue<'gcx> {
371+
fn hash_stable<W: StableHasherResult>(
372+
&self,
373+
hcx: &mut StableHashingContext<'a>,
374+
hasher: &mut StableHasher<W>,
375+
) {
376+
self.state.hash_stable(hcx, hasher);
377+
}
378+
}
379+
361380
impl<'a, 'b, 'mir, 'tcx: 'a+'mir> SnapshotContext<'b>
362381
for Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>
363382
{

0 commit comments

Comments
 (0)