diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 85a8376134aa..be9f2b8f658d 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>,
+
+ /// 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 227c85772d22..b4c73ad02c31 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> {
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)
}