From 80feed380d478a14e5acd99fc8721ed0e6de19ba Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 12 Oct 2018 16:10:16 +0200 Subject: [PATCH] Deduplicate vtables within a single evaluation --- src/librustc_mir/interpret/eval_context.rs | 5 +++++ src/librustc_mir/interpret/traits.rs | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) 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) }