about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2019-11-15 18:36:20 +0900
committerGitHub <noreply@github.com>2019-11-15 18:36:20 +0900
commit22c0f628df2353e121650b7618dd4bd71535c2bf (patch)
treea25a20bdd2fe1a8ab7d79bf64d84d01a22cf8d36
parent00c0c31554bec14a05f38e15fa698bcb839e998c (diff)
parent1aceaaa969d85195966e453590cbfc68771bf904 (diff)
downloadrust-22c0f628df2353e121650b7618dd4bd71535c2bf.tar.gz
rust-22c0f628df2353e121650b7618dd4bd71535c2bf.zip
Rollup merge of #66013 - nnethercote:avoid-hashing-twice-in-get_query, r=Zoxc
Avoid hashing the key twice in `get_query()`.

For a single-threaded parallel compiler, this reduces instruction counts
across several benchmarks, by up to 2.8%.

The commit also adds documentation about `Sharded`'s use of `FxHasher`.

r? @Zoxc
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/ty/query/plumbing.rs16
-rw-r--r--src/librustc_data_structures/sharded.rs6
3 files changed, 20 insertions, 3 deletions
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 82994f9170f..38877dee711 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -59,6 +59,7 @@
 #![feature(log_syntax)]
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
+#![feature(hash_raw_entry)]
 
 #![recursion_limit="512"]
 
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 214de35b6d0..52a784d3fc0 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -14,12 +14,13 @@ use errors::Level;
 use errors::Diagnostic;
 use errors::FatalError;
 use errors::Handler;
-use rustc_data_structures::fx::{FxHashMap};
+use rustc_data_structures::fx::{FxHasher, FxHashMap};
 use rustc_data_structures::sync::{Lrc, Lock};
 use rustc_data_structures::sharded::Sharded;
 use rustc_data_structures::thin_vec::ThinVec;
 #[cfg(not(parallel_compiler))]
 use rustc_data_structures::cold_path;
+use std::hash::{Hash, Hasher};
 use std::mem;
 use std::ptr;
 use std::collections::hash_map::Entry;
@@ -82,8 +83,17 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> {
     pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> {
         let cache = Q::query_cache(tcx);
         loop {
-            let mut lock = cache.get_shard_by_value(key).lock();
-            if let Some(value) = lock.results.get(key) {
+            // We compute the key's hash once and then use it for both the
+            // shard lookup and the hashmap lookup. This relies on the fact
+            // that both of them use `FxHasher`.
+            let mut state = FxHasher::default();
+            key.hash(&mut state);
+            let key_hash = state.finish();
+
+            let mut lock = cache.get_shard_by_hash(key_hash).lock();
+            if let Some((_, value)) =
+                lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key)
+            {
                 tcx.prof.query_cache_hit(Q::NAME);
                 let result = (value.value.clone(), value.index);
                 #[cfg(debug_assertions)]
diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs
index 2f972eeccdc..a28a5e0f041 100644
--- a/src/librustc_data_structures/sharded.rs
+++ b/src/librustc_data_structures/sharded.rs
@@ -60,6 +60,7 @@ impl<T> Sharded<T> {
         }
     }
 
+    /// The shard is selected by hashing `val` with `FxHasher`.
     #[inline]
     pub fn get_shard_by_value<K: Hash + ?Sized>(&self, val: &K) -> &Lock<T> {
         if SHARDS == 1 {
@@ -69,6 +70,11 @@ impl<T> Sharded<T> {
         }
     }
 
+    /// Get a shard with a pre-computed hash value. If `get_shard_by_value` is
+    /// ever used in combination with `get_shard_by_hash` on a single `Sharded`
+    /// instance, then `hash` must be computed with `FxHasher`. Otherwise,
+    /// `hash` can be computed with any hasher, so long as that hasher is used
+    /// consistently for each `Sharded` instance.
     #[inline]
     pub fn get_shard_by_hash(&self, hash: u64) -> &Lock<T> {
         let hash_len = mem::size_of::<usize>();