Skip to content

Commit

Permalink
Auto merge of #94299 - oli-obk:stable_hash_ty, r=michaelwoerister
Browse files Browse the repository at this point in the history
Caching the stable hash of Ty within itself

Instead of computing stable hashes on types as needed, we compute it during interning.

This way we can, when a hash is requested, just hash that hash, which is significantly faster than traversing the type itself.

We only do this for incremental for now, as incremental is the only frequent user of stable hashing.

As a next step we can try out

* moving the hash and TypeFlags to Interner, so projections and regions get the same benefit (tho regions are not nested, so maybe that's not a good idea? Would be nice for dedup tho)
* start comparing types via their stable hash instead of their address?
  • Loading branch information
bors committed Feb 28, 2022
2 parents 4ce3749 + 5875d7b commit 8d6f527
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 13 deletions.
39 changes: 34 additions & 5 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -140,16 +142,39 @@ 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);

// 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();
let mut hcx = StableHashingContext::ignore_spans(
sess,
&resolutions.definitions,
&*resolutions.cstore,
);
kind.hash_stable(&mut 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))
Expand Down Expand Up @@ -887,8 +912,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())),
Expand Down Expand Up @@ -1162,7 +1191,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);

Expand Down Expand Up @@ -2276,7 +2305,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]
Expand Down
33 changes: 29 additions & 4 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -30,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};
Expand Down Expand Up @@ -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)]
Expand All @@ -442,21 +447,41 @@ 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<StableHashingContext<'a>> 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);
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();
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);
} else {
stable_hash.hash_stable(hcx, hasher);
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/symbol-names/basic.legacy.stderr
Original file line number Diff line number Diff line change
@@ -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]
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/symbol-names/issue-60925.legacy.stderr
Original file line number Diff line number Diff line change
@@ -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<issue_60925::llvm::Foo>::foo::h5425dadb5b1e5fb6)
error: demangling(issue_60925::foo::Foo<issue_60925::llvm::Foo>::foo::h8d22952c45e20d65)
--> $DIR/issue-60925.rs:21:9
|
LL | #[rustc_symbol_name]
Expand Down

0 comments on commit 8d6f527

Please sign in to comment.