]> git.lizzy.rs Git - rust.git/commitdiff
Merge `locals` and `local_layouts` fields
authorOliver Scherer <github35764891676564198441@oli-obk.de>
Wed, 30 Jan 2019 13:16:18 +0000 (14:16 +0100)
committerOliver Scherer <github35764891676564198441@oli-obk.de>
Wed, 30 Jan 2019 13:16:18 +0000 (14:16 +0100)
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/snapshot.rs

index 34443bb353e0e4f1dfb54b2d8df884747713d789..d2cabde986345b746c125693d2cd959dbeba227f 100644 (file)
@@ -76,8 +76,7 @@ pub struct Frame<'mir, 'tcx: 'mir, Tag=(), Extra=()> {
     /// The locals are stored as `Option<Value>`s.
     /// `None` represents a local that is currently dead, while a live local
     /// can either directly contain `Scalar` or refer to some part of an `Allocation`.
-    pub locals: IndexVec<mir::Local, LocalValue<Tag>>,
-    pub local_layouts: IndexVec<mir::Local, Cell<Option<TyLayout<'tcx>>>>,
+    pub locals: IndexVec<mir::Local, LocalValue<'tcx, Tag>>,
 
     ////////////////////////////////////////////////////////////////////////////////
     // Current position within the function
@@ -106,9 +105,17 @@ pub enum StackPopCleanup {
     None { cleanup: bool },
 }
 
-// State of a local variable
+/// State of a local variable including a memoized layout
+#[derive(Clone, PartialEq, Eq)]
+pub struct LocalValue<'tcx, Tag=(), Id=AllocId> {
+    pub state: LocalState<Tag, Id>,
+    /// Don't modify if `Some`, this is only used to prevent computing the layout twice
+    pub layout: Cell<Option<TyLayout<'tcx>>>,
+}
+
+/// State of a local variable
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
-pub enum LocalValue<Tag=(), Id=AllocId> {
+pub enum LocalState<Tag=(), Id=AllocId> {
     Dead,
     // Mostly for convenience, we re-use the `Operand` type here.
     // This is an optimization over just always having a pointer here;
@@ -117,18 +124,18 @@ pub enum LocalValue<Tag=(), Id=AllocId> {
     Live(Operand<Tag, Id>),
 }
 
-impl<'tcx, Tag> LocalValue<Tag> {
+impl<'tcx, Tag> LocalValue<'tcx, Tag> {
     pub fn access(&self) -> EvalResult<'tcx, &Operand<Tag>> {
-        match self {
-            LocalValue::Dead => err!(DeadLocal),
-            LocalValue::Live(ref val) => Ok(val),
+        match self.state {
+            LocalState::Dead => err!(DeadLocal),
+            LocalState::Live(ref val) => Ok(val),
         }
     }
 
     pub fn access_mut(&mut self) -> EvalResult<'tcx, &mut Operand<Tag>> {
-        match self {
-            LocalValue::Dead => err!(DeadLocal),
-            LocalValue::Live(ref mut val) => Ok(val),
+        match self.state {
+            LocalState::Dead => err!(DeadLocal),
+            LocalState::Live(ref mut val) => Ok(val),
         }
     }
 }
@@ -312,7 +319,7 @@ pub fn layout_of_local(
         frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         local: mir::Local
     ) -> EvalResult<'tcx, TyLayout<'tcx>> {
-        let cell = &frame.local_layouts[local];
+        let cell = &frame.locals[local].layout;
         if cell.get().is_none() {
             let local_ty = frame.mir.local_decls[local].ty;
             let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
@@ -454,7 +461,6 @@ pub fn push_stack_frame(
             // empty local array, we fill it in below, after we are inside the stack frame and
             // all methods actually know about the frame
             locals: IndexVec::new(),
-            local_layouts: IndexVec::from_elem_n(Default::default(), mir.local_decls.len()),
             span,
             instance,
             stmt: 0,
@@ -464,14 +470,18 @@ pub fn push_stack_frame(
         // don't allocate at all for trivial constants
         if mir.local_decls.len() > 1 {
             // We put some marker immediate into the locals that we later want to initialize.
-            // This can be anything except for LocalValue::Dead -- because *that* is the
+            // This can be anything except for LocalState::Dead -- because *that* is the
             // value we use for things that we know are initially dead.
-            let dummy =
-                LocalValue::Live(Operand::Immediate(Immediate::Scalar(ScalarMaybeUndef::Undef)));
+            let dummy = LocalValue {
+                state: LocalState::Live(Operand::Immediate(Immediate::Scalar(
+                    ScalarMaybeUndef::Undef,
+                ))),
+                layout: Cell::new(None),
+            };
             let mut locals = IndexVec::from_elem(dummy, &mir.local_decls);
             // Return place is handled specially by the `eval_place` functions, and the
             // entry in `locals` should never be used. Make it dead, to be sure.
-            locals[mir::RETURN_PLACE] = LocalValue::Dead;
+            locals[mir::RETURN_PLACE].state = LocalState::Dead;
             // Now mark those locals as dead that we do not want to initialize
             match self.tcx.describe_def(instance.def_id()) {
                 // statics and constants don't have `Storage*` statements, no need to look for them
@@ -484,7 +494,7 @@ pub fn push_stack_frame(
                             match stmt.kind {
                                 StorageLive(local) |
                                 StorageDead(local) => {
-                                    locals[local] = LocalValue::Dead;
+                                    locals[local].state = LocalState::Dead;
                                 }
                                 _ => {}
                             }
@@ -494,13 +504,13 @@ pub fn push_stack_frame(
             }
             // Finally, properly initialize all those that still have the dummy value
             for (idx, local) in locals.iter_enumerated_mut() {
-                match *local {
-                    LocalValue::Live(_) => {
+                match local.state {
+                    LocalState::Live(_) => {
                         // This needs to be peoperly initialized.
                         let layout = self.layout_of_local(self.frame(), idx)?;
-                        *local = LocalValue::Live(self.uninit_operand(layout)?);
+                        local.state = LocalState::Live(self.uninit_operand(layout)?);
                     }
-                    LocalValue::Dead => {
+                    LocalState::Dead => {
                         // Nothing to do
                     }
                 }
@@ -543,7 +553,7 @@ pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
         }
         // Deallocate all locals that are backed by an allocation.
         for local in frame.locals {
-            self.deallocate_local(local)?;
+            self.deallocate_local(local.state)?;
         }
         // Validate the return value. Do this after deallocating so that we catch dangling
         // references.
@@ -587,31 +597,31 @@ pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> {
     pub fn storage_live(
         &mut self,
         local: mir::Local
-    ) -> EvalResult<'tcx, LocalValue<M::PointerTag>> {
+    ) -> EvalResult<'tcx, LocalState<M::PointerTag>> {
         assert!(local != mir::RETURN_PLACE, "Cannot make return place live");
         trace!("{:?} is now live", local);
 
         let layout = self.layout_of_local(self.frame(), local)?;
-        let init = LocalValue::Live(self.uninit_operand(layout)?);
+        let init = LocalState::Live(self.uninit_operand(layout)?);
         // StorageLive *always* kills the value that's currently stored
-        Ok(mem::replace(&mut self.frame_mut().locals[local], init))
+        Ok(mem::replace(&mut self.frame_mut().locals[local].state, init))
     }
 
     /// Returns the old value of the local.
     /// Remember to deallocate that!
-    pub fn storage_dead(&mut self, local: mir::Local) -> LocalValue<M::PointerTag> {
+    pub fn storage_dead(&mut self, local: mir::Local) -> LocalState<M::PointerTag> {
         assert!(local != mir::RETURN_PLACE, "Cannot make return place dead");
         trace!("{:?} is now dead", local);
 
-        mem::replace(&mut self.frame_mut().locals[local], LocalValue::Dead)
+        mem::replace(&mut self.frame_mut().locals[local].state, LocalState::Dead)
     }
 
     pub(super) fn deallocate_local(
         &mut self,
-        local: LocalValue<M::PointerTag>,
+        local: LocalState<M::PointerTag>,
     ) -> EvalResult<'tcx> {
         // FIXME: should we tell the user that there was a local which was never written to?
-        if let LocalValue::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
+        if let LocalState::Live(Operand::Indirect(MemPlace { ptr, .. })) = local {
             trace!("deallocating local");
             let ptr = ptr.to_ptr()?;
             self.memory.dump_alloc(ptr.alloc_id);
index e3ab90a602040f06326cb1ef4f811725a0c6c71a..6ee7d3309f464789e96a5b848661c706682c73bd 100644 (file)
@@ -18,7 +18,7 @@
 pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here
 
 pub use self::eval_context::{
-    EvalContext, Frame, StackPopCleanup, LocalValue,
+    EvalContext, Frame, StackPopCleanup, LocalValue, LocalState,
 };
 
 pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
index 53105266b39284372354d84860652e4d2adf97ac..0b5dc9446921a896ee1caf354e48e0bec22d039c 100644 (file)
@@ -7,7 +7,7 @@
 
 use std::hash::{Hash, Hasher};
 
-use rustc::ich::StableHashingContextProvider;
+use rustc::ich::{StableHashingContextProvider, StableHashingContext};
 use rustc::mir;
 use rustc::mir::interpret::{
     AllocId, Pointer, Scalar,
 use rustc::ty::layout::Align;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
 use syntax::ast::Mutability;
 use syntax::source_map::Span;
 
 use super::eval_context::{LocalValue, StackPopCleanup};
-use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef};
+use super::{Frame, Memory, Operand, MemPlace, Place, Immediate, ScalarMaybeUndef, LocalState};
 use const_eval::CompileTimeInterpreter;
 
 #[derive(Default)]
@@ -250,11 +250,11 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
     Indirect(m),
 });
 
-impl_stable_hash_for!(enum ::interpret::LocalValue {
+impl_stable_hash_for!(enum ::interpret::LocalState {
     Dead,
     Live(x),
 });
-impl_snapshot_for!(enum LocalValue {
+impl_snapshot_for!(enum LocalState {
     Live(v),
     Dead,
 });
@@ -309,7 +309,7 @@ struct FrameSnapshot<'a, 'tcx: 'a> {
     span: &'a Span,
     return_to_block: &'a StackPopCleanup,
     return_place: Option<Place<(), AllocIdSnapshot<'a>>>,
-    locals: IndexVec<mir::Local, LocalValue<(), AllocIdSnapshot<'a>>>,
+    locals: IndexVec<mir::Local, LocalState<(), AllocIdSnapshot<'a>>>,
     block: &'a mir::BasicBlock,
     stmt: usize,
 }
@@ -321,7 +321,6 @@ struct FrameSnapshot<'a, 'tcx: 'a> {
     return_to_block,
     return_place -> (return_place.as_ref().map(|r| &**r)),
     locals,
-    local_layouts -> _,
     block,
     stmt,
     extra,
@@ -340,7 +339,6 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
             return_to_block,
             return_place,
             locals,
-            local_layouts: _,
             block,
             stmt,
             extra: _,
@@ -358,6 +356,27 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
     }
 }
 
+impl<'a, 'tcx, Ctx> Snapshot<'a, Ctx> for &'a LocalValue<'tcx>
+    where Ctx: SnapshotContext<'a>,
+{
+    type Item = LocalState<(), AllocIdSnapshot<'a>>;
+
+    fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
+        self.state.snapshot(ctx)
+    }
+}
+
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for LocalValue<'gcx> {
+    fn hash_stable<W: StableHasherResult>(
+        &self,
+        hcx: &mut StableHashingContext<'a>,
+        hasher: &mut StableHasher<W>,
+    ) {
+        self.state.hash_stable(hcx, hasher);
+    }
+}
+
 impl<'a, 'b, 'mir, 'tcx: 'a+'mir> SnapshotContext<'b>
     for Memory<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>
 {