1
Fork 0

Store CtxtInterners for local values in AllArenas

This commit is contained in:
John Kåre Alsaker 2018-12-30 21:19:11 +01:00
parent 3ade426ede
commit 66a376ea4f
2 changed files with 30 additions and 27 deletions

View file

@ -21,11 +21,10 @@ use crate::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use crate::ty::fold::{TypeFolder, TypeFoldable}; use crate::ty::fold::{TypeFolder, TypeFoldable};
use crate::ty::relate::RelateResult; use crate::ty::relate::RelateResult;
use crate::ty::subst::{Kind, InternalSubsts, SubstsRef}; use crate::ty::subst::{Kind, InternalSubsts, SubstsRef};
use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners, InferConst}; use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, InferConst};
use crate::ty::{FloatVid, IntVid, TyVid, ConstVid}; use crate::ty::{FloatVid, IntVid, TyVid, ConstVid};
use crate::util::nodemap::FxHashMap; use crate::util::nodemap::FxHashMap;
use arena::SyncDroplessArena;
use errors::DiagnosticBuilder; use errors::DiagnosticBuilder;
use rustc_data_structures::unify as ut; use rustc_data_structures::unify as ut;
use std::cell::{Cell, Ref, RefCell, RefMut}; use std::cell::{Cell, Ref, RefCell, RefMut};
@ -468,8 +467,6 @@ impl<'tcx> fmt::Display for FixupError<'tcx> {
/// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>)`. /// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>)`.
pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
global_tcx: TyCtxt<'a, 'gcx, 'gcx>, global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
arena: SyncDroplessArena,
interners: Option<CtxtInterners<'tcx>>,
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>, fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
} }
@ -477,8 +474,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> { pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
InferCtxtBuilder { InferCtxtBuilder {
global_tcx: self, global_tcx: self,
arena: SyncDroplessArena::default(),
interners: None,
fresh_tables: None, fresh_tables: None,
} }
} }
@ -518,14 +513,10 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R { pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R {
let InferCtxtBuilder { let InferCtxtBuilder {
global_tcx, global_tcx,
ref arena,
ref mut interners,
ref fresh_tables, ref fresh_tables,
} = *self; } = *self;
let in_progress_tables = fresh_tables.as_ref(); let in_progress_tables = fresh_tables.as_ref();
// Check that we haven't entered before global_tcx.enter_local(|tcx| {
assert!(interners.is_none());
global_tcx.enter_local(arena, interners, |tcx| {
f(InferCtxt { f(InferCtxt {
tcx, tcx,
in_progress_tables, in_progress_tables,

View file

@ -82,6 +82,7 @@ use crate::hir;
pub struct AllArenas<'tcx> { pub struct AllArenas<'tcx> {
pub global: WorkerLocal<GlobalArenas<'tcx>>, pub global: WorkerLocal<GlobalArenas<'tcx>>,
pub interner: SyncDroplessArena, pub interner: SyncDroplessArena,
pub local_interner: SyncDroplessArena,
} }
impl<'tcx> AllArenas<'tcx> { impl<'tcx> AllArenas<'tcx> {
@ -89,6 +90,7 @@ impl<'tcx> AllArenas<'tcx> {
AllArenas { AllArenas {
global: WorkerLocal::new(|_| GlobalArenas::default()), global: WorkerLocal::new(|_| GlobalArenas::default()),
interner: SyncDroplessArena::default(), interner: SyncDroplessArena::default(),
local_interner: SyncDroplessArena::default(),
} }
} }
} }
@ -154,7 +156,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
/// Intern a type /// Intern a type
#[inline(never)] #[inline(never)]
fn intern_ty( fn intern_ty(
local: &CtxtInterners<'tcx>, local: &CtxtInterners<'gcx>,
global: &CtxtInterners<'gcx>, global: &CtxtInterners<'gcx>,
st: TyKind<'tcx> st: TyKind<'tcx>
) -> Ty<'tcx> { ) -> Ty<'tcx> {
@ -179,6 +181,12 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
&ty_struct); &ty_struct);
} }
// This is safe because all the types the ty_struct can point to
// already is in the local arena or the global arena
let ty_struct: TyS<'gcx> = unsafe {
mem::transmute(ty_struct)
};
Interned(local.arena.alloc(ty_struct)) Interned(local.arena.alloc(ty_struct))
}).0 }).0
} else { } else {
@ -1029,8 +1037,8 @@ pub struct FreeRegionInfo {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> { pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> {
gcx: &'gcx GlobalCtxt<'gcx>, gcx: &'gcx GlobalCtxt<'gcx>,
interners: &'tcx CtxtInterners<'tcx>, interners: &'gcx CtxtInterners<'gcx>,
dummy: PhantomData<&'a ()>, dummy: PhantomData<(&'a (), &'tcx ())>,
} }
impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> { impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> {
@ -1045,6 +1053,7 @@ pub struct GlobalCtxt<'tcx> {
pub arena: WorkerLocal<Arena<'tcx>>, pub arena: WorkerLocal<Arena<'tcx>>,
global_arenas: &'tcx WorkerLocal<GlobalArenas<'tcx>>, global_arenas: &'tcx WorkerLocal<GlobalArenas<'tcx>>,
global_interners: CtxtInterners<'tcx>, global_interners: CtxtInterners<'tcx>,
local_interners: CtxtInterners<'tcx>,
cstore: &'tcx CrateStoreDyn, cstore: &'tcx CrateStoreDyn,
@ -1262,6 +1271,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
s.fatal(&err); s.fatal(&err);
}); });
let interners = CtxtInterners::new(&arenas.interner); let interners = CtxtInterners::new(&arenas.interner);
let local_interners = CtxtInterners::new(&arenas.local_interner);
let common = Common { let common = Common {
empty_predicates: ty::GenericPredicates { empty_predicates: ty::GenericPredicates {
parent: None, parent: None,
@ -1321,6 +1331,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
arena: WorkerLocal::new(|_| Arena::default()), arena: WorkerLocal::new(|_| Arena::default()),
global_arenas: &arenas.global, global_arenas: &arenas.global,
global_interners: interners, global_interners: interners,
local_interners: local_interners,
dep_graph, dep_graph,
common, common,
types: common_types, types: common_types,
@ -1716,18 +1727,15 @@ impl<'gcx> GlobalCtxt<'gcx> {
/// with the same lifetime as `arena`. /// with the same lifetime as `arena`.
pub fn enter_local<'tcx, F, R>( pub fn enter_local<'tcx, F, R>(
&'gcx self, &'gcx self,
arena: &'tcx SyncDroplessArena,
interners: &'tcx mut Option<CtxtInterners<'tcx>>,
f: F f: F
) -> R ) -> R
where where
F: FnOnce(TyCtxt<'tcx, 'gcx, 'tcx>) -> R, F: FnOnce(TyCtxt<'tcx, 'gcx, 'tcx>) -> R,
'gcx: 'tcx, 'gcx: 'tcx,
{ {
*interners = Some(CtxtInterners::new(&arena));
let tcx = TyCtxt { let tcx = TyCtxt {
gcx: self, gcx: self,
interners: interners.as_ref().unwrap(), interners: &self.local_interners,
dummy: PhantomData, dummy: PhantomData,
}; };
ty::tls::with_related_context(tcx.global_tcx(), |icx| { ty::tls::with_related_context(tcx.global_tcx(), |icx| {
@ -2333,6 +2341,17 @@ macro_rules! intern_method {
pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
let key = ($alloc_to_key)(&v); let key = ($alloc_to_key)(&v);
let alloc = |v, interners: &'gcx CtxtInterners<'gcx>| {
// This transmutes $alloc<'tcx> to $alloc<'gcx>
let v = unsafe {
mem::transmute(v)
};
let i: &$lt_tcx $ty = $alloc_method(&interners.arena, v);
// Cast to 'gcx
let i = unsafe { mem::transmute(i) };
Interned(i)
};
// HACK(eddyb) Depend on flags being accurate to // HACK(eddyb) Depend on flags being accurate to
// determine that all contents are in the global tcx. // determine that all contents are in the global tcx.
// See comments on Lift for why we can't use that. // See comments on Lift for why we can't use that.
@ -2346,18 +2365,11 @@ macro_rules! intern_method {
v); v);
} }
Interned($alloc_method(&self.interners.arena, v)) alloc(v, &self.interners)
}).0 }).0
} else { } else {
self.global_interners.$name.borrow_mut().intern_ref(key, || { self.global_interners.$name.borrow_mut().intern_ref(key, || {
// This transmutes $alloc<'tcx> to $alloc<'gcx> alloc(v, &self.global_interners)
let v = unsafe {
mem::transmute(v)
};
let i: &$lt_tcx $ty = $alloc_method(&self.global_interners.arena, v);
// Cast to 'gcx
let i = unsafe { mem::transmute(i) };
Interned(i)
}).0 }).0
} }
} }