|
| 1 | +use std::cell::RefCell; |
| 2 | +use std::collections::hash_map::Entry; |
| 3 | + |
1 | 4 | use either::{Left, Right}; |
2 | 5 | use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; |
| 6 | +use rustc_data_structures::fx::FxHashMap; |
3 | 7 | use rustc_hir::def_id::DefId; |
4 | 8 | use rustc_hir::limit::Limit; |
5 | 9 | use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; |
@@ -38,6 +42,9 @@ pub struct InterpCx<'tcx, M: Machine<'tcx>> { |
38 | 42 | /// polymorphic context. This always uses `ty::TypingMode::PostAnalysis`. |
39 | 43 | pub(super) typing_env: ty::TypingEnv<'tcx>, |
40 | 44 |
|
| 45 | + /// The query cache is slow so we have our own cache in front of it. |
| 46 | + pub(super) layout_cache: RefCell<FxHashMap<Ty<'tcx>, rustc_abi::Layout<'tcx>>>, |
| 47 | + |
41 | 48 | /// The virtual memory system. |
42 | 49 | pub memory: Memory<'tcx, M>, |
43 | 50 |
|
@@ -130,10 +137,19 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { |
130 | 137 | /// This inherent method takes priority over the trait method with the same name in LayoutOf, |
131 | 138 | /// and allows wrapping the actual [LayoutOf::layout_of] with a tracing span. |
132 | 139 | /// See [LayoutOf::layout_of] for the original documentation. |
133 | | - #[inline(always)] |
| 140 | + #[inline] |
134 | 141 | pub fn layout_of(&self, ty: Ty<'tcx>) -> Result<TyAndLayout<'tcx>, InterpErrorKind<'tcx>> { |
135 | | - let _trace = enter_trace_span!(M, layouting::layout_of, ty = ?ty.kind()); |
136 | | - LayoutOf::layout_of(self, ty) |
| 142 | + match self.layout_cache.borrow_mut().entry(ty) { |
| 143 | + Entry::Occupied(occupied_entry) => { |
| 144 | + Ok(TyAndLayout { ty, layout: *occupied_entry.get() }) |
| 145 | + } |
| 146 | + Entry::Vacant(vacant_entry) => { |
| 147 | + let _trace = enter_trace_span!(M, layouting::layout_of, ty = ?ty.kind()); |
| 148 | + let layout = LayoutOf::layout_of(self, ty)?; |
| 149 | + vacant_entry.insert(layout.layout); |
| 150 | + Ok(layout) |
| 151 | + } |
| 152 | + } |
137 | 153 | } |
138 | 154 |
|
139 | 155 | /// This inherent method takes priority over the trait method with the same name in FnAbiOf, |
@@ -248,6 +264,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { |
248 | 264 | machine, |
249 | 265 | tcx: tcx.at(root_span), |
250 | 266 | typing_env, |
| 267 | + layout_cache: RefCell::new(FxHashMap::default()), |
251 | 268 | memory: Memory::new(), |
252 | 269 | recursion_limit: tcx.recursion_limit(), |
253 | 270 | } |
|
0 commit comments