Skip to content

Commit 8a5761a

Browse files
committed
Auto merge of #50959 - Zoxc:int-map, r=<try>
[WIP] Use a custom hash set for interning r? @michaelwoerister
2 parents cdc193d + c124143 commit 8a5761a

File tree

4 files changed

+370
-117
lines changed

4 files changed

+370
-117
lines changed

src/librustc/ty/context.rs

+73-117
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ use ty::BindingMode;
5252
use ty::CanonicalTy;
5353
use util::nodemap::{DefIdSet, ItemLocalMap};
5454
use util::nodemap::{FxHashMap, FxHashSet};
55+
use rustc_data_structures::fx::FxInterner;
5556
use rustc_data_structures::accumulate_vec::AccumulateVec;
5657
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
5758
StableHasher, StableHasherResult,
@@ -124,15 +125,15 @@ impl<'tcx> GlobalArenas<'tcx> {
124125
}
125126
}
126127

127-
type InternedSet<'tcx, T> = Lock<FxHashSet<Interned<'tcx, T>>>;
128+
type InternedSet<'tcx, T> = Lock<FxInterner<Interned<'tcx, T>>>;
128129

129130
pub struct CtxtInterners<'tcx> {
130131
/// The arena that types, regions, etc are allocated from
131132
arena: &'tcx SyncDroplessArena,
132133

133134
/// Specifically use a speedy hash algorithm for these hash sets,
134135
/// they're accessed quite often.
135-
type_: InternedSet<'tcx, TyS<'tcx>>,
136+
type_: Lock<FxInterner<Interned<'tcx, TyS<'tcx>>>>,
136137
type_list: InternedSet<'tcx, Slice<Ty<'tcx>>>,
137138
substs: InternedSet<'tcx, Substs<'tcx>>,
138139
canonical_var_infos: InternedSet<'tcx, Slice<CanonicalVarInfo>>,
@@ -173,51 +174,39 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
173174
// determine that all contents are in the global tcx.
174175
// See comments on Lift for why we can't use that.
175176
if flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) {
176-
let mut interner = local.type_.borrow_mut();
177-
if let Some(&Interned(ty)) = interner.get(&st) {
178-
return ty;
179-
}
180-
181-
let ty_struct = TyS {
182-
sty: st,
183-
flags: flags.flags,
184-
outer_exclusive_binder: flags.outer_exclusive_binder,
185-
};
177+
local.type_.borrow_mut().intern(st, |st| {
178+
let ty_struct = TyS {
179+
sty: st,
180+
flags: flags.flags,
181+
outer_exclusive_binder: flags.outer_exclusive_binder,
182+
};
186183

187-
// Make sure we don't end up with inference
188-
// types/regions in the global interner
189-
if local as *const _ as usize == global as *const _ as usize {
190-
bug!("Attempted to intern `{:?}` which contains \
191-
inference types/regions in the global type context",
192-
&ty_struct);
193-
}
184+
// Make sure we don't end up with inference
185+
// types/regions in the global interner
186+
if local as *const _ as usize == global as *const _ as usize {
187+
bug!("Attempted to intern `{:?}` which contains \
188+
inference types/regions in the global type context",
189+
&ty_struct);
190+
}
194191

195-
// Don't be &mut TyS.
196-
let ty: Ty<'tcx> = local.arena.alloc(ty_struct);
197-
interner.insert(Interned(ty));
198-
ty
192+
Interned(local.arena.alloc(ty_struct))
193+
}).0
199194
} else {
200-
let mut interner = global.type_.borrow_mut();
201-
if let Some(&Interned(ty)) = interner.get(&st) {
202-
return ty;
203-
}
204-
205-
let ty_struct = TyS {
206-
sty: st,
207-
flags: flags.flags,
208-
outer_exclusive_binder: flags.outer_exclusive_binder,
209-
};
195+
global.type_.borrow_mut().intern(st, |st| {
196+
let ty_struct = TyS {
197+
sty: st,
198+
flags: flags.flags,
199+
outer_exclusive_binder: flags.outer_exclusive_binder,
200+
};
210201

211-
// This is safe because all the types the ty_struct can point to
212-
// already is in the global arena
213-
let ty_struct: TyS<'gcx> = unsafe {
214-
mem::transmute(ty_struct)
215-
};
202+
// This is safe because all the types the ty_struct can point to
203+
// already is in the global arena
204+
let ty_struct: TyS<'gcx> = unsafe {
205+
mem::transmute(ty_struct)
206+
};
216207

217-
// Don't be &mut TyS.
218-
let ty: Ty<'gcx> = global.arena.alloc(ty_struct);
219-
interner.insert(Interned(ty));
220-
ty
208+
Interned(global.arena.alloc(ty_struct))
209+
}).0
221210
}
222211
}
223212
}
@@ -800,12 +789,9 @@ impl<'tcx> CommonTypes<'tcx> {
800789

801790
let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
802791
let mk_region = |r| {
803-
if let Some(r) = interners.region.borrow().get(&r) {
804-
return r.0;
805-
}
806-
let r = interners.arena.alloc(r);
807-
interners.region.borrow_mut().insert(Interned(r));
808-
&*r
792+
interners.region.borrow_mut().intern(r, |r| {
793+
Interned(interners.arena.alloc(r))
794+
}).0
809795
};
810796
CommonTypes {
811797
bool: mk(TyBool),
@@ -916,14 +902,14 @@ pub struct GlobalCtxt<'tcx> {
916902
/// Data layout specification for the current target.
917903
pub data_layout: TargetDataLayout,
918904

919-
stability_interner: Lock<FxHashSet<&'tcx attr::Stability>>,
905+
stability_interner: Lock<FxInterner<&'tcx attr::Stability>>,
920906

921907
/// Stores the value of constants (and deduplicates the actual memory)
922-
allocation_interner: Lock<FxHashSet<&'tcx Allocation>>,
908+
allocation_interner: Lock<FxInterner<&'tcx Allocation>>,
923909

924910
pub alloc_map: Lock<interpret::AllocMap<'tcx, &'tcx Allocation>>,
925911

926-
layout_interner: Lock<FxHashSet<&'tcx LayoutDetails>>,
912+
layout_interner: Lock<FxInterner<&'tcx LayoutDetails>>,
927913

928914
/// A general purpose channel to throw data out the back towards LLVM worker
929915
/// threads.
@@ -1006,16 +992,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
1006992
self,
1007993
alloc: Allocation,
1008994
) -> &'gcx Allocation {
1009-
let allocs = &mut self.allocation_interner.borrow_mut();
1010-
if let Some(alloc) = allocs.get(&alloc) {
1011-
return alloc;
1012-
}
1013-
1014-
let interned = self.global_arenas.const_allocs.alloc(alloc);
1015-
if let Some(prev) = allocs.replace(interned) {
1016-
bug!("Tried to overwrite interned Allocation: {:#?}", prev)
1017-
}
1018-
interned
995+
self.allocation_interner.borrow_mut().intern(alloc, |alloc| {
996+
self.global_arenas.const_allocs.alloc(alloc)
997+
})
1019998
}
1020999

10211000
/// Allocates a byte or string literal for `mir::interpret`
@@ -1027,29 +1006,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
10271006
}
10281007

10291008
pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
1030-
let mut stability_interner = self.stability_interner.borrow_mut();
1031-
if let Some(st) = stability_interner.get(&stab) {
1032-
return st;
1033-
}
1034-
1035-
let interned = self.global_interners.arena.alloc(stab);
1036-
if let Some(prev) = stability_interner.replace(interned) {
1037-
bug!("Tried to overwrite interned Stability: {:?}", prev)
1038-
}
1039-
interned
1009+
self.stability_interner.borrow_mut().intern(stab, |stab| {
1010+
self.global_interners.arena.alloc(stab)
1011+
})
10401012
}
10411013

10421014
pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
1043-
let mut layout_interner = self.layout_interner.borrow_mut();
1044-
if let Some(layout) = layout_interner.get(&layout) {
1045-
return layout;
1046-
}
1047-
1048-
let interned = self.global_arenas.layout.alloc(layout);
1049-
if let Some(prev) = layout_interner.replace(interned) {
1050-
bug!("Tried to overwrite interned Layout: {:?}", prev)
1051-
}
1052-
interned
1015+
self.layout_interner.borrow_mut().intern(layout, |layout| {
1016+
self.global_arenas.layout.alloc(layout)
1017+
})
10531018
}
10541019

10551020
pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
@@ -1171,9 +1136,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
11711136
evaluation_cache: traits::EvaluationCache::new(),
11721137
crate_name: Symbol::intern(crate_name),
11731138
data_layout,
1174-
layout_interner: Lock::new(FxHashSet()),
1175-
stability_interner: Lock::new(FxHashSet()),
1176-
allocation_interner: Lock::new(FxHashSet()),
1139+
layout_interner: Default::default(),
1140+
stability_interner: Default::default(),
1141+
allocation_interner: Default::default(),
11771142
alloc_map: Lock::new(interpret::AllocMap::new()),
11781143
tx_to_llvm_workers: Lock::new(tx),
11791144
output_filenames: Arc::new(output_filenames.clone()),
@@ -1909,7 +1874,7 @@ macro_rules! sty_debug_print {
19091874
($ctxt: expr, $($variant: ident),*) => {{
19101875
// curious inner module to allow variant names to be used as
19111876
// variable names.
1912-
#[allow(non_snake_case)]
1877+
#[allow(non_snake_case, warnings)]
19131878
mod inner {
19141879
use ty::{self, TyCtxt};
19151880
use ty::context::Interned;
@@ -1929,7 +1894,7 @@ macro_rules! sty_debug_print {
19291894
};
19301895
$(let mut $variant = total;)*
19311896

1932-
1897+
/*
19331898
for &Interned(t) in tcx.interners.type_.borrow().iter() {
19341899
let variant = match t.sty {
19351900
ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) |
@@ -1945,7 +1910,7 @@ macro_rules! sty_debug_print {
19451910
if region { total.region_infer += 1; variant.region_infer += 1 }
19461911
if ty { total.ty_infer += 1; variant.ty_infer += 1 }
19471912
if region && ty { total.both_infer += 1; variant.both_infer += 1 }
1948-
}
1913+
}*/
19491914
println!("Ty interner total ty region both");
19501915
$(println!(" {:18}: {uses:6} {usespc:4.1}%, \
19511916
{ty:4.1}% {region:5.1}% {both:4.1}%",
@@ -2096,37 +2061,28 @@ macro_rules! intern_method {
20962061
// determine that all contents are in the global tcx.
20972062
// See comments on Lift for why we can't use that.
20982063
if ($keep_in_local_tcx)(&v) {
2099-
let mut interner = self.interners.$name.borrow_mut();
2100-
if let Some(&Interned(v)) = interner.get(key) {
2101-
return v;
2102-
}
2103-
2104-
// Make sure we don't end up with inference
2105-
// types/regions in the global tcx.
2106-
if self.is_global() {
2107-
bug!("Attempted to intern `{:?}` which contains \
2108-
inference types/regions in the global type context",
2109-
v);
2110-
}
2111-
2112-
let i = $alloc_method(&self.interners.arena, v);
2113-
interner.insert(Interned(i));
2114-
i
2064+
self.interners.$name.borrow_mut().intern_ref(key, || {
2065+
// Make sure we don't end up with inference
2066+
// types/regions in the global tcx.
2067+
if self.is_global() {
2068+
bug!("Attempted to intern `{:?}` which contains \
2069+
inference types/regions in the global type context",
2070+
v);
2071+
}
2072+
2073+
Interned($alloc_method(&self.interners.arena, v))
2074+
}).0
21152075
} else {
2116-
let mut interner = self.global_interners.$name.borrow_mut();
2117-
if let Some(&Interned(v)) = interner.get(key) {
2118-
return v;
2119-
}
2120-
2121-
// This transmutes $alloc<'tcx> to $alloc<'gcx>
2122-
let v = unsafe {
2123-
mem::transmute(v)
2124-
};
2125-
let i: &$lt_tcx $ty = $alloc_method(&self.global_interners.arena, v);
2126-
// Cast to 'gcx
2127-
let i = unsafe { mem::transmute(i) };
2128-
interner.insert(Interned(i));
2129-
i
2076+
self.global_interners.$name.borrow_mut().intern_ref(key, || {
2077+
// This transmutes $alloc<'tcx> to $alloc<'gcx>
2078+
let v = unsafe {
2079+
mem::transmute(v)
2080+
};
2081+
let i: &$lt_tcx $ty = $alloc_method(&self.global_interners.arena, v);
2082+
// Cast to 'gcx
2083+
let i = unsafe { mem::transmute(i) };
2084+
Interned(i)
2085+
}).0
21302086
}
21312087
}
21322088
}

src/librustc_data_structures/fx.rs

+3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@
1111
use std::collections::{HashMap, HashSet};
1212
use std::default::Default;
1313
use std::hash::Hash;
14+
use std::hash::BuildHasherDefault;
15+
use interner;
1416

1517
pub use rustc_hash::FxHashMap;
1618
pub use rustc_hash::FxHashSet;
1719
pub use rustc_hash::FxHasher;
20+
pub type FxInterner<V> = interner::Interner<V, BuildHasherDefault<FxHasher>>;
1821

1922
#[allow(non_snake_case)]
2023
pub fn FxHashMap<K: Hash + Eq, V>() -> FxHashMap<K, V> {

0 commit comments

Comments
 (0)