about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2018-10-12 16:10:16 +0200
committerOliver Scherer <github35764891676564198441@oli-obk.de>2018-10-15 20:54:23 +0200
commit80feed380d478a14e5acd99fc8721ed0e6de19ba (patch)
tree90611f491e78fa83a4ae15821250aa293da2eb84
parent4f9b581f71810744069228f86242e6ba00b7d09c (diff)
downloadrust-80feed380d478a14e5acd99fc8721ed0e6de19ba.tar.gz
rust-80feed380d478a14e5acd99fc8721ed0e6de19ba.zip
Deduplicate vtables within a single evaluation
-rw-r--r--src/librustc_mir/interpret/eval_context.rs5
-rw-r--r--src/librustc_mir/interpret/traits.rs5
2 files changed, 9 insertions, 1 deletions
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 85a8376134a..be9f2b8f658 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -27,6 +27,7 @@ use rustc::mir::interpret::{
     EvalResult, EvalErrorKind,
     truncate, sign_extend,
 };
+use rustc_data_structures::fx::FxHashMap;
 
 use syntax::source_map::{self, Span};
 
@@ -50,6 +51,9 @@ pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
 
     /// The virtual call stack.
     pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag>>,
+
+    /// A cache for deduplicating vtables
+    pub(super) vtables: FxHashMap<(Ty<'tcx>, ty::PolyTraitRef<'tcx>), AllocId>,
 }
 
 /// A stack frame.
@@ -209,6 +213,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
             param_env,
             memory: Memory::new(tcx, memory_data),
             stack: Vec::new(),
+            vtables: FxHashMap(),
         }
     }
 
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index 227c85772d2..b4c73ad02c3 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -28,7 +28,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
     ) -> EvalResult<'tcx, Pointer<M::PointerTag>> {
         debug!("get_vtable(trait_ref={:?})", trait_ref);
 
-        // FIXME: Cache this!
+        if let Some(&vtable) = self.vtables.get(&(ty, trait_ref)) {
+            return Ok(Pointer::from(vtable).with_default_tag());
+        }
 
         let layout = self.layout_of(trait_ref.self_ty())?;
         assert!(!layout.is_unsized(), "can't create a vtable for an unsized type");
@@ -64,6 +66,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
         }
 
         self.memory.mark_immutable(vtable.alloc_id)?;
+        assert!(self.vtables.insert((ty, trait_ref), vtable.alloc_id).is_none());
 
         Ok(vtable)
     }