mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-06 08:36:52 -04:00
Auto merge of #155329 - nnethercote:rm-WithCachedTypeInfo-stable_hash, r=oli-obk
Remove `WithCachedTypeInfo::stable_hash`. We store a stable hash value in the most common interned values (e.g. types, predicates, regions). This is 16 bytes of data. - In non-incremental builds it's a straightforward performance loss: the stable hash isn't computed or used, and the 16 bytes of space goes to waste (but it still gets hashed when interning). - In incremental builds it avoids some hashing but doesn't seem to actually be a genuine performance win, and the complexity doesn't seem worth it. r? @oli-obk
This commit is contained in:
@@ -18,13 +18,12 @@ use std::{fmt, iter, mem};
|
||||
use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx};
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::defer;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_data_structures::jobserver::Proxy;
|
||||
use rustc_data_structures::profiling::SelfProfilerRef;
|
||||
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_data_structures::stable_hasher::HashStable;
|
||||
use rustc_data_structures::steal::Steal;
|
||||
use rustc_data_structures::sync::{
|
||||
self, DynSend, DynSync, FreezeReadGuard, Lock, RwLock, WorkerLocal,
|
||||
@@ -47,9 +46,7 @@ use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_type_ir::TyKind::*;
|
||||
pub use rustc_type_ir::lift::Lift;
|
||||
use rustc_type_ir::{
|
||||
CollectAndApply, FnSigKind, TypeFlags, WithCachedTypeInfo, elaborate, search_graph,
|
||||
};
|
||||
use rustc_type_ir::{CollectAndApply, FnSigKind, WithCachedTypeInfo, elaborate, search_graph};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::arena::Arena;
|
||||
@@ -247,16 +244,13 @@ impl<'tcx> CtxtInterners<'tcx> {
|
||||
/// Interns a type. (Use `mk_*` functions instead, where possible.)
|
||||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
#[inline(never)]
|
||||
fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
|
||||
fn intern_ty(&self, kind: TyKind<'tcx>) -> Ty<'tcx> {
|
||||
Ty(Interned::new_unchecked(
|
||||
self.type_
|
||||
.intern(kind, |kind| {
|
||||
let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_kind(&kind);
|
||||
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
|
||||
|
||||
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
|
||||
internee: kind,
|
||||
stable_hash,
|
||||
flags: flags.flags,
|
||||
outer_exclusive_binder: flags.outer_exclusive_binder,
|
||||
}))
|
||||
@@ -268,21 +262,13 @@ impl<'tcx> CtxtInterners<'tcx> {
|
||||
/// Interns a const. (Use `mk_*` functions instead, where possible.)
|
||||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
#[inline(never)]
|
||||
fn intern_const(
|
||||
&self,
|
||||
kind: ty::ConstKind<'tcx>,
|
||||
sess: &Session,
|
||||
untracked: &Untracked,
|
||||
) -> Const<'tcx> {
|
||||
fn intern_const(&self, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
|
||||
Const(Interned::new_unchecked(
|
||||
self.const_
|
||||
.intern(kind, |kind: ty::ConstKind<'_>| {
|
||||
let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_const_kind(&kind);
|
||||
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
|
||||
|
||||
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
|
||||
internee: kind,
|
||||
stable_hash,
|
||||
flags: flags.flags,
|
||||
outer_exclusive_binder: flags.outer_exclusive_binder,
|
||||
}))
|
||||
@@ -291,43 +277,15 @@ impl<'tcx> CtxtInterners<'tcx> {
|
||||
))
|
||||
}
|
||||
|
||||
fn stable_hash<'a, T: HashStable<StableHashingContext<'a>>>(
|
||||
&self,
|
||||
flags: &ty::FlagComputation<TyCtxt<'tcx>>,
|
||||
sess: &'a Session,
|
||||
untracked: &'a Untracked,
|
||||
val: &T,
|
||||
) -> Fingerprint {
|
||||
// It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
|
||||
// Without incremental, we rarely stable-hash types, so let's not do it proactively.
|
||||
if flags.flags.intersects(TypeFlags::HAS_INFER) || sess.opts.incremental.is_none() {
|
||||
Fingerprint::ZERO
|
||||
} else {
|
||||
let mut hasher = StableHasher::new();
|
||||
let mut hcx = StableHashingContext::new(sess, untracked);
|
||||
val.hash_stable(&mut hcx, &mut hasher);
|
||||
hasher.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Interns a predicate. (Use `mk_predicate` instead, where possible.)
|
||||
#[inline(never)]
|
||||
fn intern_predicate(
|
||||
&self,
|
||||
kind: Binder<'tcx, PredicateKind<'tcx>>,
|
||||
sess: &Session,
|
||||
untracked: &Untracked,
|
||||
) -> Predicate<'tcx> {
|
||||
fn intern_predicate(&self, kind: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
|
||||
Predicate(Interned::new_unchecked(
|
||||
self.predicate
|
||||
.intern(kind, |kind| {
|
||||
let flags = ty::FlagComputation::<TyCtxt<'tcx>>::for_predicate(kind);
|
||||
|
||||
let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
|
||||
|
||||
InternedInSet(self.arena.alloc(WithCachedTypeInfo {
|
||||
internee: kind,
|
||||
stable_hash,
|
||||
flags: flags.flags,
|
||||
outer_exclusive_binder: flags.outer_exclusive_binder,
|
||||
}))
|
||||
@@ -463,12 +421,8 @@ pub struct CommonConsts<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> CommonTypes<'tcx> {
|
||||
fn new(
|
||||
interners: &CtxtInterners<'tcx>,
|
||||
sess: &Session,
|
||||
untracked: &Untracked,
|
||||
) -> CommonTypes<'tcx> {
|
||||
let mk = |ty| interners.intern_ty(ty, sess, untracked);
|
||||
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
|
||||
let mk = |ty| interners.intern_ty(ty);
|
||||
|
||||
let ty_vars =
|
||||
(0..NUM_PREINTERNED_TY_VARS).map(|n| mk(Infer(ty::TyVar(TyVid::from(n))))).collect();
|
||||
@@ -584,18 +538,8 @@ impl<'tcx> CommonLifetimes<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> CommonConsts<'tcx> {
|
||||
fn new(
|
||||
interners: &CtxtInterners<'tcx>,
|
||||
types: &CommonTypes<'tcx>,
|
||||
sess: &Session,
|
||||
untracked: &Untracked,
|
||||
) -> CommonConsts<'tcx> {
|
||||
let mk_const = |c| {
|
||||
interners.intern_const(
|
||||
c, sess, // This is only used to create a stable hashing context.
|
||||
untracked,
|
||||
)
|
||||
};
|
||||
fn new(interners: &CtxtInterners<'tcx>, types: &CommonTypes<'tcx>) -> CommonConsts<'tcx> {
|
||||
let mk_const = |c| interners.intern_const(c);
|
||||
|
||||
let mk_valtree = |v| {
|
||||
ty::ValTree(Interned::new_unchecked(
|
||||
@@ -1088,9 +1032,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
s.dcx().emit_fatal(err);
|
||||
});
|
||||
let interners = CtxtInterners::new(arena);
|
||||
let common_types = CommonTypes::new(&interners, s, &untracked);
|
||||
let common_types = CommonTypes::new(&interners);
|
||||
let common_lifetimes = CommonLifetimes::new(&interners);
|
||||
let common_consts = CommonConsts::new(&interners, &common_types, s, &untracked);
|
||||
let common_consts = CommonConsts::new(&interners, &common_types);
|
||||
|
||||
let gcx = gcx_cell.get_or_init(|| GlobalCtxt {
|
||||
sess: s,
|
||||
@@ -2221,12 +2165,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn mk_predicate(self, binder: Binder<'tcx, PredicateKind<'tcx>>) -> Predicate<'tcx> {
|
||||
self.interners.intern_predicate(
|
||||
binder,
|
||||
self.sess,
|
||||
// This is only used to create a stable hashing context.
|
||||
&self.untracked,
|
||||
)
|
||||
self.interners.intern_predicate(binder)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -2347,24 +2286,14 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
|
||||
#[inline]
|
||||
pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>) -> Const<'tcx> {
|
||||
self.interners.intern_const(
|
||||
kind,
|
||||
self.sess,
|
||||
// This is only used to create a stable hashing context.
|
||||
&self.untracked,
|
||||
)
|
||||
self.interners.intern_const(kind)
|
||||
}
|
||||
|
||||
// Avoid this in favour of more specific `Ty::new_*` methods, where possible.
|
||||
#[allow(rustc::usage_of_ty_tykind)]
|
||||
#[inline]
|
||||
pub fn mk_ty_from_kind(self, st: TyKind<'tcx>) -> Ty<'tcx> {
|
||||
self.interners.intern_ty(
|
||||
st,
|
||||
self.sess,
|
||||
// This is only used to create a stable hashing context.
|
||||
&self.untracked,
|
||||
)
|
||||
self.interners.intern_ty(st)
|
||||
}
|
||||
|
||||
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> GenericArg<'tcx> {
|
||||
|
||||
@@ -644,6 +644,6 @@ mod size_asserts {
|
||||
use super::*;
|
||||
// tidy-alphabetical-start
|
||||
static_assert_size!(PredicateKind<'_>, 40);
|
||||
static_assert_size!(WithCachedTypeInfo<PredicateKind<'_>>, 64);
|
||||
static_assert_size!(WithCachedTypeInfo<PredicateKind<'_>>, 48);
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
@@ -460,6 +460,6 @@ mod size_asserts {
|
||||
use super::*;
|
||||
// tidy-alphabetical-start
|
||||
static_assert_size!(RegionKind<'_>, 20);
|
||||
static_assert_size!(ty::WithCachedTypeInfo<RegionKind<'_>>, 48);
|
||||
static_assert_size!(ty::WithCachedTypeInfo<RegionKind<'_>>, 28);
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
@@ -2167,6 +2167,6 @@ mod size_asserts {
|
||||
use super::*;
|
||||
// tidy-alphabetical-start
|
||||
static_assert_size!(TyKind<'_>, 32);
|
||||
static_assert_size!(ty::WithCachedTypeInfo<TyKind<'_>>, 56);
|
||||
static_assert_size!(ty::WithCachedTypeInfo<TyKind<'_>>, 40);
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ use std::cmp::Ordering;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_type_ir_macros::GenericTypeVisitable;
|
||||
@@ -11,19 +9,12 @@ use rustc_type_ir_macros::GenericTypeVisitable;
|
||||
use crate::{DebruijnIndex, TypeFlags};
|
||||
|
||||
/// A helper type that you can wrap round your own type in order to automatically
|
||||
/// cache the stable hash, type flags and debruijn index on creation and
|
||||
/// not recompute it whenever the information is needed.
|
||||
/// This is only done in incremental mode. You can also opt out of caching by using
|
||||
/// StableHash::ZERO for the hash, in which case the hash gets computed each time.
|
||||
/// This is useful if you have values that you intern but never (can?) use for stable
|
||||
/// hashing.
|
||||
/// cache the type flags and debruijn index on creation and not recompute it
|
||||
/// whenever the information is needed.
|
||||
#[derive(Copy, Clone, GenericTypeVisitable)]
|
||||
pub struct WithCachedTypeInfo<T> {
|
||||
pub internee: T,
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
pub stable_hash: Fingerprint,
|
||||
|
||||
/// This field provides fast access to information that is also contained
|
||||
/// in `kind`.
|
||||
///
|
||||
@@ -87,11 +78,6 @@ impl<T> Deref for WithCachedTypeInfo<T> {
|
||||
impl<T: Hash> Hash for WithCachedTypeInfo<T> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||
#[cfg(feature = "nightly")]
|
||||
if self.stable_hash != Fingerprint::ZERO {
|
||||
return self.stable_hash.hash(s);
|
||||
}
|
||||
|
||||
self.internee.hash(s)
|
||||
}
|
||||
}
|
||||
@@ -99,27 +85,6 @@ impl<T: Hash> Hash for WithCachedTypeInfo<T> {
|
||||
#[cfg(feature = "nightly")]
|
||||
impl<T: HashStable<Hcx>, Hcx> HashStable<Hcx> for WithCachedTypeInfo<T> {
|
||||
fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
|
||||
if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {
|
||||
// No cached hash available. This can only mean that incremental is disabled.
|
||||
// We don't cache stable hashes in non-incremental mode, because they are used
|
||||
// so rarely that the performance actually suffers.
|
||||
|
||||
// We need to build the hash as if we cached it and then hash that hash, as
|
||||
// otherwise the hashes will differ between cached and non-cached mode.
|
||||
let stable_hash: Fingerprint = {
|
||||
let mut hasher = StableHasher::new();
|
||||
self.internee.hash_stable(hcx, &mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
if cfg!(debug_assertions) && self.stable_hash != Fingerprint::ZERO {
|
||||
assert_eq!(
|
||||
stable_hash, self.stable_hash,
|
||||
"cached stable hash does not match freshly computed stable hash"
|
||||
);
|
||||
}
|
||||
stable_hash.hash_stable(hcx, hasher);
|
||||
} else {
|
||||
self.stable_hash.hash_stable(hcx, hasher);
|
||||
}
|
||||
self.internee.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
// Const generic parameter
|
||||
//@ gdb-command:info functions -q function_names::const_generic_fn.*
|
||||
//@ gdb-check:[...]static fn function_names::const_generic_fn_bool<false>();
|
||||
//@ gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#6dd80cc0c950c171}>();
|
||||
//@ gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#68cf9e429c783d36}>();
|
||||
//@ gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>();
|
||||
//@ gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>();
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
error: symbol-name(_ZN5basic4main17h947b7a9ed2b2bf56E)
|
||||
error: symbol-name(_ZN5basic4main17h27f62b2d0b2beac6E)
|
||||
--> $DIR/basic.rs:8:1
|
||||
|
|
||||
LL | #[rustc_dump_symbol_name]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: demangling(basic::main::h947b7a9ed2b2bf56)
|
||||
error: demangling(basic::main::h27f62b2d0b2beac6)
|
||||
--> $DIR/basic.rs:8:1
|
||||
|
|
||||
LL | #[rustc_dump_symbol_name]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hba5ac046b858f549E)
|
||||
error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h1eb769490ff06e77E)
|
||||
--> $DIR/issue-60925.rs:21:9
|
||||
|
|
||||
LL | #[rustc_dump_symbol_name]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::hba5ac046b858f549)
|
||||
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h1eb769490ff06e77)
|
||||
--> $DIR/issue-60925.rs:21:9
|
||||
|
|
||||
LL | #[rustc_dump_symbol_name]
|
||||
|
||||
Reference in New Issue
Block a user