Skip to content

Commit 888b02c

Browse files
committed
Replace hashbrown raw api by HashTable
1 parent 0c1077e commit 888b02c

File tree

2 files changed

+32
-34
lines changed

2 files changed

+32
-34
lines changed

Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ members = ["xtask"]
1515
[dependencies]
1616
rustc-hash = "2.1.1"
1717
hashbrown = { version = "0.15.2", features = [
18-
"inline-more",
19-
"raw-entry",
18+
"inline-more",
2019
], default-features = false }
2120
text-size = "1.1.1"
2221
countme = "3.0.1"

src/green/node_cache.rs

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use hashbrown::hash_map::RawEntryMut;
1+
use hashbrown::{HashTable, hash_table::Entry};
22
use rustc_hash::FxHasher;
3-
use std::hash::{BuildHasherDefault, Hash, Hasher};
3+
use std::hash::{Hash, Hasher};
44

55
use crate::{
66
GreenNode, GreenNodeData, GreenToken, GreenTokenData, NodeOrToken, SyntaxKind,
@@ -9,11 +9,6 @@ use crate::{
99

1010
use super::element::GreenElement;
1111

12-
type HashMap<K, V> = hashbrown::HashMap<K, V, BuildHasherDefault<FxHasher>>;
13-
14-
#[derive(Debug)]
15-
struct NoHash<T>(T);
16-
1712
/// Interner for GreenTokens and GreenNodes
1813
// XXX: the impl is a bit tricky. As usual when writing interners, we want to
1914
// store all values in one HashSet.
@@ -25,18 +20,17 @@ struct NoHash<T>(T);
2520
// That means that computing the hash naively is wasteful -- we just *know*
2621
// hashes of children, and we can re-use those.
2722
//
28-
// So here we use *raw* API of hashbrown and provide the hashes manually,
23+
// So here we use `HashTable` of hashbrown and provide the hashes manually,
2924
// instead of going via a `Hash` impl. Our manual `Hash` and the
3025
// `#[derive(Hash)]` are actually different! At some point we had a fun bug,
3126
// where we accidentally mixed the two hashes, which made the cache much less
3227
// efficient.
3328
//
34-
// To fix that, we additionally wrap the data in `NoHash` wrapper, to make sure
35-
// we don't accidentally use the wrong hash!
29+
// `HashTable` prevents us to accidentally use the wrong hash!
3630
#[derive(Default, Debug)]
3731
pub struct NodeCache {
38-
nodes: HashMap<NoHash<GreenNode>, ()>,
39-
tokens: HashMap<NoHash<GreenToken>, ()>,
32+
nodes: HashTable<GreenNode>,
33+
tokens: HashTable<GreenToken>,
4034
}
4135

4236
fn token_hash(token: &GreenTokenData) -> u64 {
@@ -103,26 +97,30 @@ impl NodeCache {
10397
// For example, all `#[inline]` in this file share the same green node!
10498
// For `libsyntax/parse/parser.rs`, measurements show that deduping saves
10599
// 17% of the memory for green nodes!
106-
let entry = self.nodes.raw_entry_mut().from_hash(hash, |node| {
107-
node.0.kind() == kind && node.0.children().len() == children_ref.len() && {
108-
let lhs = node.0.children();
109-
let rhs = children_ref.iter().map(|(_, it)| it.as_deref());
100+
let entry = self.nodes.entry(
101+
hash,
102+
|node| {
103+
node.kind() == kind && node.children().len() == children_ref.len() && {
104+
let lhs = node.children();
105+
let rhs = children_ref.iter().map(|(_, it)| it.as_deref());
110106

111-
let lhs = lhs.map(element_id);
112-
let rhs = rhs.map(element_id);
107+
let lhs = lhs.map(element_id);
108+
let rhs = rhs.map(element_id);
113109

114-
lhs.eq(rhs)
115-
}
116-
});
110+
lhs.eq(rhs)
111+
}
112+
},
113+
|node| node_hash(node),
114+
);
117115

118116
let node = match entry {
119-
RawEntryMut::Occupied(entry) => {
117+
Entry::Occupied(entry) => {
120118
drop(children.drain(first_child..));
121-
entry.key().0.clone()
119+
entry.get().clone()
122120
}
123-
RawEntryMut::Vacant(entry) => {
121+
Entry::Vacant(entry) => {
124122
let node = build_node(children);
125-
entry.insert_with_hasher(hash, NoHash(node.clone()), (), |n| node_hash(&n.0));
123+
entry.insert(node.clone());
126124
node
127125
}
128126
};
@@ -138,16 +136,17 @@ impl NodeCache {
138136
h.finish()
139137
};
140138

141-
let entry = self
142-
.tokens
143-
.raw_entry_mut()
144-
.from_hash(hash, |token| token.0.kind() == kind && token.0.text() == text);
139+
let entry = self.tokens.entry(
140+
hash,
141+
|token| token.kind() == kind && token.text() == text,
142+
|token| token_hash(token),
143+
);
145144

146145
let token = match entry {
147-
RawEntryMut::Occupied(entry) => entry.key().0.clone(),
148-
RawEntryMut::Vacant(entry) => {
146+
Entry::Occupied(entry) => entry.get().clone(),
147+
Entry::Vacant(entry) => {
149148
let token = GreenToken::new(kind, text);
150-
entry.insert_with_hasher(hash, NoHash(token.clone()), (), |t| token_hash(&t.0));
149+
entry.insert(token.clone());
151150
token
152151
}
153152
};

0 commit comments

Comments
 (0)