Skip to content

Commit f5b8f44

Browse files
committed
Auto merge of #109333 - Zoxc:erase-query-cache-values, r=cjgillot
Erase query cache values This replaces most concrete query values `V` with `MaybeUninit<[u8; { size_of::<V>() }]>` without introducing dynamic dispatch like #108638 does. This is split out of #108638 so the performance impact of only this change can be measured. r? `@cjgillot`
2 parents 0534655 + 0110073 commit f5b8f44

File tree

11 files changed

+465
-61
lines changed

11 files changed

+465
-61
lines changed

Diff for: compiler/rustc_middle/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#![feature(generators)]
3434
#![feature(get_mut_unchecked)]
3535
#![feature(if_let_guard)]
36+
#![feature(inline_const)]
3637
#![feature(iter_from_generator)]
3738
#![feature(local_key_cell_methods)]
3839
#![feature(negative_impls)]

Diff for: compiler/rustc_middle/src/query/erase.rs

+337
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
use crate::mir;
2+
use crate::traits;
3+
use crate::ty::{self, Ty};
4+
use std::mem::{size_of, transmute_copy, MaybeUninit};
5+
6+
#[derive(Copy, Clone)]
7+
pub struct Erased<T: Copy> {
8+
// We use `MaybeUninit` here so we can store any value
9+
// in `data` since we aren't actually storing a `T`.
10+
data: MaybeUninit<T>,
11+
}
12+
13+
pub trait EraseType: Copy {
14+
type Result: Copy;
15+
}
16+
17+
// Allow `type_alias_bounds` since compilation will fail without `EraseType`.
18+
#[allow(type_alias_bounds)]
19+
pub type Erase<T: EraseType> = Erased<impl Copy>;
20+
21+
#[inline(always)]
22+
pub fn erase<T: EraseType>(src: T) -> Erase<T> {
23+
// Ensure the sizes match
24+
const {
25+
if std::mem::size_of::<T>() != std::mem::size_of::<T::Result>() {
26+
panic!("size of T must match erased type T::Result")
27+
}
28+
};
29+
30+
Erased::<<T as EraseType>::Result> {
31+
// SAFETY: Is it safe to transmute to MaybeUninit for types with the same sizes.
32+
data: unsafe { transmute_copy(&src) },
33+
}
34+
}
35+
36+
/// Restores an erased value.
37+
#[inline(always)]
38+
pub fn restore<T: EraseType>(value: Erase<T>) -> T {
39+
let value: Erased<<T as EraseType>::Result> = value;
40+
// SAFETY: Due to the use of impl Trait in `Erase` the only way to safetly create an instance
41+
// of `Erase` is to call `erase`, so we know that `value.data` is a valid instance of `T` of
42+
// the right size.
43+
unsafe { transmute_copy(&value.data) }
44+
}
45+
46+
impl<T> EraseType for &'_ T {
47+
type Result = [u8; size_of::<*const ()>()];
48+
}
49+
50+
impl<T> EraseType for &'_ [T] {
51+
type Result = [u8; size_of::<*const [()]>()];
52+
}
53+
54+
impl<T> EraseType for &'_ ty::List<T> {
55+
type Result = [u8; size_of::<*const ()>()];
56+
}
57+
58+
impl<T> EraseType for Result<&'_ T, traits::query::NoSolution> {
59+
type Result = [u8; size_of::<Result<&'static (), traits::query::NoSolution>>()];
60+
}
61+
62+
impl<T> EraseType for Result<&'_ T, rustc_errors::ErrorGuaranteed> {
63+
type Result = [u8; size_of::<Result<&'static (), rustc_errors::ErrorGuaranteed>>()];
64+
}
65+
66+
impl<T> EraseType for Result<&'_ T, traits::CodegenObligationError> {
67+
type Result = [u8; size_of::<Result<&'static (), traits::CodegenObligationError>>()];
68+
}
69+
70+
impl<T> EraseType for Result<&'_ T, ty::layout::FnAbiError<'_>> {
71+
type Result = [u8; size_of::<Result<&'static (), ty::layout::FnAbiError<'static>>>()];
72+
}
73+
74+
impl<T> EraseType for Result<(&'_ T, rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed> {
75+
type Result = [u8; size_of::<
76+
Result<(&'static (), rustc_middle::thir::ExprId), rustc_errors::ErrorGuaranteed>,
77+
>()];
78+
}
79+
80+
impl EraseType for Result<Option<ty::Instance<'_>>, rustc_errors::ErrorGuaranteed> {
81+
type Result =
82+
[u8; size_of::<Result<Option<ty::Instance<'static>>, rustc_errors::ErrorGuaranteed>>()];
83+
}
84+
85+
impl EraseType for Result<Option<ty::Const<'_>>, rustc_errors::ErrorGuaranteed> {
86+
type Result =
87+
[u8; size_of::<Result<Option<ty::Const<'static>>, rustc_errors::ErrorGuaranteed>>()];
88+
}
89+
90+
impl EraseType for Result<ty::GenericArg<'_>, traits::query::NoSolution> {
91+
type Result = [u8; size_of::<Result<ty::GenericArg<'static>, traits::query::NoSolution>>()];
92+
}
93+
94+
impl EraseType for Result<bool, ty::layout::LayoutError<'_>> {
95+
type Result = [u8; size_of::<Result<bool, ty::layout::LayoutError<'static>>>()];
96+
}
97+
98+
impl EraseType for Result<rustc_target::abi::TyAndLayout<'_, Ty<'_>>, ty::layout::LayoutError<'_>> {
99+
type Result = [u8; size_of::<
100+
Result<
101+
rustc_target::abi::TyAndLayout<'static, Ty<'static>>,
102+
ty::layout::LayoutError<'static>,
103+
>,
104+
>()];
105+
}
106+
107+
impl EraseType for Result<ty::Const<'_>, mir::interpret::LitToConstError> {
108+
type Result = [u8; size_of::<Result<ty::Const<'static>, mir::interpret::LitToConstError>>()];
109+
}
110+
111+
impl EraseType for Result<mir::ConstantKind<'_>, mir::interpret::LitToConstError> {
112+
type Result =
113+
[u8; size_of::<Result<mir::ConstantKind<'static>, mir::interpret::LitToConstError>>()];
114+
}
115+
116+
impl EraseType for Result<mir::interpret::ConstAlloc<'_>, mir::interpret::ErrorHandled> {
117+
type Result = [u8; size_of::<
118+
Result<mir::interpret::ConstAlloc<'static>, mir::interpret::ErrorHandled>,
119+
>()];
120+
}
121+
122+
impl EraseType for Result<mir::interpret::ConstValue<'_>, mir::interpret::ErrorHandled> {
123+
type Result = [u8; size_of::<
124+
Result<mir::interpret::ConstValue<'static>, mir::interpret::ErrorHandled>,
125+
>()];
126+
}
127+
128+
impl EraseType for Result<Option<ty::ValTree<'_>>, mir::interpret::ErrorHandled> {
129+
type Result =
130+
[u8; size_of::<Result<Option<ty::ValTree<'static>>, mir::interpret::ErrorHandled>>()];
131+
}
132+
133+
impl EraseType for Result<&'_ ty::List<Ty<'_>>, ty::util::AlwaysRequiresDrop> {
134+
type Result =
135+
[u8; size_of::<Result<&'static ty::List<Ty<'static>>, ty::util::AlwaysRequiresDrop>>()];
136+
}
137+
138+
impl<T> EraseType for Option<&'_ T> {
139+
type Result = [u8; size_of::<Option<&'static ()>>()];
140+
}
141+
142+
impl<T> EraseType for Option<&'_ [T]> {
143+
type Result = [u8; size_of::<Option<&'static [()]>>()];
144+
}
145+
146+
impl EraseType for Option<rustc_middle::hir::Owner<'_>> {
147+
type Result = [u8; size_of::<Option<rustc_middle::hir::Owner<'static>>>()];
148+
}
149+
150+
impl EraseType for Option<mir::DestructuredConstant<'_>> {
151+
type Result = [u8; size_of::<Option<mir::DestructuredConstant<'static>>>()];
152+
}
153+
154+
impl EraseType for Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
155+
type Result = [u8; size_of::<Option<ty::EarlyBinder<ty::TraitRef<'static>>>>()];
156+
}
157+
158+
impl EraseType for Option<ty::EarlyBinder<Ty<'_>>> {
159+
type Result = [u8; size_of::<Option<ty::EarlyBinder<Ty<'static>>>>()];
160+
}
161+
162+
impl<T> EraseType for rustc_hir::MaybeOwner<&'_ T> {
163+
type Result = [u8; size_of::<rustc_hir::MaybeOwner<&'static ()>>()];
164+
}
165+
166+
impl<T: EraseType> EraseType for ty::EarlyBinder<T> {
167+
type Result = T::Result;
168+
}
169+
170+
impl EraseType for ty::Binder<'_, ty::FnSig<'_>> {
171+
type Result = [u8; size_of::<ty::Binder<'static, ty::FnSig<'static>>>()];
172+
}
173+
174+
impl<T0, T1> EraseType for (&'_ T0, &'_ T1) {
175+
type Result = [u8; size_of::<(&'static (), &'static ())>()];
176+
}
177+
178+
impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
179+
type Result = [u8; size_of::<(&'static (), &'static [()])>()];
180+
}
181+
182+
macro_rules! trivial {
183+
($($ty:ty),+ $(,)?) => {
184+
$(
185+
impl EraseType for $ty {
186+
type Result = [u8; size_of::<$ty>()];
187+
}
188+
)*
189+
}
190+
}
191+
192+
trivial! {
193+
(),
194+
bool,
195+
Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>,
196+
Option<rustc_ast::expand::allocator::AllocatorKind>,
197+
Option<rustc_attr::ConstStability>,
198+
Option<rustc_attr::DefaultBodyStability>,
199+
Option<rustc_attr::Stability>,
200+
Option<rustc_data_structures::svh::Svh>,
201+
Option<rustc_hir::def::DefKind>,
202+
Option<rustc_hir::GeneratorKind>,
203+
Option<rustc_hir::HirId>,
204+
Option<rustc_middle::middle::stability::DeprecationEntry>,
205+
Option<rustc_middle::ty::Destructor>,
206+
Option<rustc_middle::ty::ImplTraitInTraitData>,
207+
Option<rustc_span::def_id::CrateNum>,
208+
Option<rustc_span::def_id::DefId>,
209+
Option<rustc_span::def_id::LocalDefId>,
210+
Option<rustc_span::Span>,
211+
Option<rustc_target::spec::PanicStrategy>,
212+
Option<usize>,
213+
Result<(), rustc_errors::ErrorGuaranteed>,
214+
Result<(), rustc_middle::traits::query::NoSolution>,
215+
Result<rustc_middle::traits::EvaluationResult, rustc_middle::traits::OverflowError>,
216+
rustc_ast::expand::allocator::AllocatorKind,
217+
rustc_attr::ConstStability,
218+
rustc_attr::DefaultBodyStability,
219+
rustc_attr::Deprecation,
220+
rustc_attr::Stability,
221+
rustc_data_structures::svh::Svh,
222+
rustc_errors::ErrorGuaranteed,
223+
rustc_hir::Constness,
224+
rustc_hir::def_id::DefId,
225+
rustc_hir::def_id::DefIndex,
226+
rustc_hir::def_id::LocalDefId,
227+
rustc_hir::def::DefKind,
228+
rustc_hir::Defaultness,
229+
rustc_hir::definitions::DefKey,
230+
rustc_hir::GeneratorKind,
231+
rustc_hir::HirId,
232+
rustc_hir::IsAsync,
233+
rustc_hir::ItemLocalId,
234+
rustc_hir::LangItem,
235+
rustc_hir::OwnerId,
236+
rustc_hir::Upvar,
237+
rustc_index::bit_set::FiniteBitSet<u32>,
238+
rustc_middle::metadata::ModChild,
239+
rustc_middle::middle::dependency_format::Linkage,
240+
rustc_middle::middle::exported_symbols::SymbolExportInfo,
241+
rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault,
242+
rustc_middle::middle::resolve_bound_vars::ResolvedArg,
243+
rustc_middle::middle::stability::DeprecationEntry,
244+
rustc_middle::mir::ConstQualifs,
245+
rustc_middle::mir::interpret::AllocId,
246+
rustc_middle::mir::interpret::ErrorHandled,
247+
rustc_middle::mir::interpret::LitToConstError,
248+
rustc_middle::thir::ExprId,
249+
rustc_middle::traits::CodegenObligationError,
250+
rustc_middle::traits::EvaluationResult,
251+
rustc_middle::traits::OverflowError,
252+
rustc_middle::traits::query::NoSolution,
253+
rustc_middle::traits::WellFormedLoc,
254+
rustc_middle::ty::adjustment::CoerceUnsizedInfo,
255+
rustc_middle::ty::AssocItem,
256+
rustc_middle::ty::AssocItemContainer,
257+
rustc_middle::ty::BoundVariableKind,
258+
rustc_middle::ty::DeducedParamAttrs,
259+
rustc_middle::ty::Destructor,
260+
rustc_middle::ty::fast_reject::SimplifiedType,
261+
rustc_middle::ty::ImplPolarity,
262+
rustc_middle::ty::Representability,
263+
rustc_middle::ty::ReprOptions,
264+
rustc_middle::ty::UnusedGenericParams,
265+
rustc_middle::ty::util::AlwaysRequiresDrop,
266+
rustc_middle::ty::Visibility<rustc_span::def_id::DefId>,
267+
rustc_session::config::CrateType,
268+
rustc_session::config::EntryFnType,
269+
rustc_session::config::OptLevel,
270+
rustc_session::config::SymbolManglingVersion,
271+
rustc_session::cstore::CrateDepKind,
272+
rustc_session::cstore::ExternCrate,
273+
rustc_session::cstore::LinkagePreference,
274+
rustc_session::Limits,
275+
rustc_session::lint::LintExpectationId,
276+
rustc_span::def_id::CrateNum,
277+
rustc_span::def_id::DefPathHash,
278+
rustc_span::ExpnHash,
279+
rustc_span::ExpnId,
280+
rustc_span::Span,
281+
rustc_span::Symbol,
282+
rustc_span::symbol::Ident,
283+
rustc_target::spec::PanicStrategy,
284+
rustc_type_ir::Variance,
285+
u32,
286+
usize,
287+
}
288+
289+
macro_rules! tcx_lifetime {
290+
($($($fake_path:ident)::+),+ $(,)?) => {
291+
$(
292+
impl<'tcx> EraseType for $($fake_path)::+<'tcx> {
293+
type Result = [u8; size_of::<$($fake_path)::+<'static>>()];
294+
}
295+
)*
296+
}
297+
}
298+
299+
tcx_lifetime! {
300+
rustc_middle::hir::Owner,
301+
rustc_middle::middle::exported_symbols::ExportedSymbol,
302+
rustc_middle::mir::ConstantKind,
303+
rustc_middle::mir::DestructuredConstant,
304+
rustc_middle::mir::interpret::ConstAlloc,
305+
rustc_middle::mir::interpret::ConstValue,
306+
rustc_middle::mir::interpret::GlobalId,
307+
rustc_middle::mir::interpret::LitToConstInput,
308+
rustc_middle::traits::ChalkEnvironmentAndGoal,
309+
rustc_middle::traits::query::MethodAutoderefStepsResult,
310+
rustc_middle::traits::query::type_op::AscribeUserType,
311+
rustc_middle::traits::query::type_op::Eq,
312+
rustc_middle::traits::query::type_op::ProvePredicate,
313+
rustc_middle::traits::query::type_op::Subtype,
314+
rustc_middle::ty::AdtDef,
315+
rustc_middle::ty::AliasTy,
316+
rustc_middle::ty::Clause,
317+
rustc_middle::ty::ClosureTypeInfo,
318+
rustc_middle::ty::Const,
319+
rustc_middle::ty::DestructuredConst,
320+
rustc_middle::ty::ExistentialTraitRef,
321+
rustc_middle::ty::FnSig,
322+
rustc_middle::ty::GenericArg,
323+
rustc_middle::ty::GenericPredicates,
324+
rustc_middle::ty::inhabitedness::InhabitedPredicate,
325+
rustc_middle::ty::Instance,
326+
rustc_middle::ty::InstanceDef,
327+
rustc_middle::ty::layout::FnAbiError,
328+
rustc_middle::ty::layout::LayoutError,
329+
rustc_middle::ty::ParamEnv,
330+
rustc_middle::ty::Predicate,
331+
rustc_middle::ty::SymbolName,
332+
rustc_middle::ty::TraitRef,
333+
rustc_middle::ty::Ty,
334+
rustc_middle::ty::UnevaluatedConst,
335+
rustc_middle::ty::ValTree,
336+
rustc_middle::ty::VtblEntry,
337+
}

Diff for: compiler/rustc_middle/src/query/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use crate::ty::{self, print::describe_as_module, TyCtxt};
88
use rustc_span::def_id::LOCAL_CRATE;
99

10+
pub mod erase;
1011
mod keys;
1112
pub use keys::{AsLocalKey, Key, LocalCrate};
1213

0 commit comments

Comments
 (0)