From 9327272d0203deb60def6719b4f890d886653f1c Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 23 Feb 2022 18:02:06 +0000 Subject: [PATCH 1/4] Try out caching the stable hash of Ty within itself --- compiler/rustc_middle/src/ty/context.rs | 40 ++++++++++++++++--- compiler/rustc_middle/src/ty/mod.rs | 15 +++++-- src/test/ui/symbol-names/basic.legacy.stderr | 4 +- .../ui/symbol-names/issue-60925.legacy.stderr | 4 +- 4 files changed, 51 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 7a6a6a00cc7..0416ed17977 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -24,6 +24,7 @@ use crate::ty::{ RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, }; use rustc_ast as ast; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::memmap::Mmap; @@ -58,6 +59,7 @@ use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{Layout, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; +use rustc_type_ir::TypeFlags; use smallvec::SmallVec; use std::any::Any; use std::borrow::Borrow; @@ -140,16 +142,40 @@ impl<'tcx> CtxtInterners<'tcx> { /// Interns a type. #[allow(rustc::usage_of_ty_tykind)] #[inline(never)] - fn intern_ty(&self, kind: TyKind<'tcx>) -> Ty<'tcx> { + fn intern_ty( + &self, + kind: TyKind<'tcx>, + sess: &Session, + resolutions: &ty::ResolverOutputs, + ) -> Ty<'tcx> { Ty(Interned::new_unchecked( self.type_ .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_kind(&kind); + let stable_hash = if flags.flags.intersects(TypeFlags::HAS_RE_INFER) { + Fingerprint::ZERO + } else { + let mut hasher = StableHasher::new(); + let mut hcx = StableHashingContext::new( + sess, + &resolutions.definitions, + &*resolutions.cstore, + ); + + hcx.while_hashing_spans(false, |hcx| { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + kind.hash_stable(hcx, &mut hasher); + }); + }); + hasher.finish() + }; + let ty_struct = TyS { kind, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, + stable_hash, }; InternedInSet(self.arena.alloc(ty_struct)) @@ -887,8 +913,12 @@ pub enum UserType<'tcx> { } impl<'tcx> CommonTypes<'tcx> { - fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { - let mk = |ty| interners.intern_ty(ty); + fn new( + interners: &CtxtInterners<'tcx>, + sess: &Session, + resolutions: &ty::ResolverOutputs, + ) -> CommonTypes<'tcx> { + let mk = |ty| interners.intern_ty(ty, sess, resolutions); CommonTypes { unit: mk(Tuple(List::empty())), @@ -1162,7 +1192,7 @@ impl<'tcx> TyCtxt<'tcx> { s.fatal(&err); }); let interners = CtxtInterners::new(arena); - let common_types = CommonTypes::new(&interners); + let common_types = CommonTypes::new(&interners, s, &resolutions); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); @@ -2276,7 +2306,7 @@ impl<'tcx> TyCtxt<'tcx> { #[allow(rustc::usage_of_ty_tykind)] #[inline] pub fn mk_ty(self, st: TyKind<'tcx>) -> Ty<'tcx> { - self.interners.intern_ty(st) + self.interners.intern_ty(st, self.sess, &self.gcx.untracked_resolutions) } #[inline] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f0b7f2a653f..7a14a568c1c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -17,6 +17,7 @@ pub use self::Variance::*; pub use adt::*; pub use assoc::*; pub use generics::*; +use rustc_data_structures::fingerprint::Fingerprint; pub use vtable::*; use crate::metadata::ModChild; @@ -424,11 +425,15 @@ crate struct TyS<'tcx> { /// De Bruijn indices within the type are contained within `0..D` /// (exclusive). outer_exclusive_binder: ty::DebruijnIndex, + + /// The stable hash of the type. This way hashing of types will not have to work + /// on the address of the type anymore, but can instead just read this field + stable_hash: Fingerprint, } // `TyS` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -static_assert_size!(TyS<'_>, 40); +static_assert_size!(TyS<'_>, 56); /// Use this rather than `TyS`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -442,21 +447,25 @@ static BOOL_TYS: TyS<'static> = TyS { kind: ty::Bool, flags: TypeFlags::empty(), outer_exclusive_binder: DebruijnIndex::from_usize(0), + stable_hash: Fingerprint::ZERO, }; impl<'a, 'tcx> HashStable> for Ty<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let TyS { - ref kind, + kind, // The other fields just provide fast access to information that is // also contained in `kind`, so no need to hash them. flags: _, outer_exclusive_binder: _, + + stable_hash, } = self.0.0; - kind.hash_stable(hcx, hasher); + assert_ne!(*stable_hash, Fingerprint::ZERO, "{:#?}", kind); + stable_hash.hash_stable(hcx, hasher); } } diff --git a/src/test/ui/symbol-names/basic.legacy.stderr b/src/test/ui/symbol-names/basic.legacy.stderr index 429e28e5241..e4d58d3ccdb 100644 --- a/src/test/ui/symbol-names/basic.legacy.stderr +++ b/src/test/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h611df9c6948c15f7E) +error: symbol-name(_ZN5basic4main17h87acd86b3a6f1754E) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h611df9c6948c15f7) +error: demangling(basic::main::h87acd86b3a6f1754) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/src/test/ui/symbol-names/issue-60925.legacy.stderr b/src/test/ui/symbol-names/issue-60925.legacy.stderr index 0e36747fb80..c987ebc5343 100644 --- a/src/test/ui/symbol-names/issue-60925.legacy.stderr +++ b/src/test/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h5425dadb5b1e5fb6E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h8d22952c45e20d65E) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h5425dadb5b1e5fb6) +error: demangling(issue_60925::foo::Foo::foo::h8d22952c45e20d65) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] From 8d4f4e42afc74be02cd3dc040a164a493b41a1bf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 24 Feb 2022 12:58:48 +0000 Subject: [PATCH 2/4] Remove redundant hashing configuration logic in type interner --- compiler/rustc_middle/src/ty/context.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0416ed17977..6c0582a240e 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -157,17 +157,12 @@ impl<'tcx> CtxtInterners<'tcx> { Fingerprint::ZERO } else { let mut hasher = StableHasher::new(); - let mut hcx = StableHashingContext::new( + let mut hcx = StableHashingContext::ignore_spans( sess, &resolutions.definitions, &*resolutions.cstore, ); - - hcx.while_hashing_spans(false, |hcx| { - hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { - kind.hash_stable(hcx, &mut hasher); - }); - }); + kind.hash_stable(&mut hcx, &mut hasher); hasher.finish() }; From 8b0440a66942ac1f14707ae25a1efbbe7f24a686 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 24 Feb 2022 13:43:23 +0000 Subject: [PATCH 3/4] Don't cache stable hashes in types outside of incremental mode --- compiler/rustc_middle/src/ty/context.rs | 6 +++++- compiler/rustc_middle/src/ty/mod.rs | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6c0582a240e..2d43724d418 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -153,7 +153,11 @@ impl<'tcx> CtxtInterners<'tcx> { .intern(kind, |kind| { let flags = super::flags::FlagComputation::for_kind(&kind); - let stable_hash = if flags.flags.intersects(TypeFlags::HAS_RE_INFER) { + // It's impossible to hash inference regions (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. + let stable_hash = if flags.flags.intersects(TypeFlags::HAS_RE_INFER) + || sess.opts.incremental.is_none() + { Fingerprint::ZERO } else { let mut hasher = StableHasher::new(); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 7a14a568c1c..8f067de3665 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -464,8 +464,20 @@ impl<'a, 'tcx> HashStable> for Ty<'tcx> { stable_hash, } = self.0.0; - assert_ne!(*stable_hash, Fingerprint::ZERO, "{:#?}", kind); - stable_hash.hash_stable(hcx, hasher); + if *stable_hash == Fingerprint::ZERO { + // 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. + + let stable_hash: Fingerprint = { + let mut hasher = StableHasher::new(); + kind.hash_stable(hcx, &mut hasher); + hasher.finish() + }; + stable_hash.hash_stable(hcx, hasher); + } else { + stable_hash.hash_stable(hcx, hasher); + } } } From 5875d7b03c4dba91be95cacd3f02bdb7ccc90a0e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 25 Feb 2022 17:51:28 +0000 Subject: [PATCH 4/4] "Reset" the hashing context before stable hashing the types --- compiler/rustc_middle/src/ty/mod.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8f067de3665..34d18281c59 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -31,7 +31,7 @@ use rustc_ast as ast; use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::intern::Interned; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, NodeIdHashingMode, StableHasher}; use rustc_data_structures::tagged_ptr::CopyTaggedPtr; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; @@ -471,7 +471,11 @@ impl<'a, 'tcx> HashStable> for Ty<'tcx> { let stable_hash: Fingerprint = { let mut hasher = StableHasher::new(); - kind.hash_stable(hcx, &mut hasher); + hcx.while_hashing_spans(false, |hcx| { + hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { + kind.hash_stable(hcx, &mut hasher) + }) + }); hasher.finish() }; stable_hash.hash_stable(hcx, hasher);