Only lookup types in one interner

This commit is contained in:
John Kåre Alsaker 2018-04-30 08:59:23 +02:00
parent 9b97705f9e
commit e245d69322

View file

@ -162,66 +162,65 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
} }
} }
/// Intern a type. global_interners is Some only if this is /// Intern a type
/// a local interner and global_interners is its counterpart. fn intern_ty(
fn intern_ty(&self, st: TypeVariants<'tcx>, local: &CtxtInterners<'tcx>,
global_interners: Option<&CtxtInterners<'gcx>>) global: &CtxtInterners<'gcx>,
-> Ty<'tcx> { st: TypeVariants<'tcx>
let ty = { ) -> Ty<'tcx> {
let mut interner = self.type_.borrow_mut(); let flags = super::flags::FlagComputation::for_sty(&st);
// HACK(eddyb) Depend on flags being accurate to
// determine that all contents are in the global tcx.
// See comments on Lift for why we can't use that.
if flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) {
let mut interner = local.type_.borrow_mut();
if let Some(&Interned(ty)) = interner.get(&st) { if let Some(&Interned(ty)) = interner.get(&st) {
return ty; return ty;
} }
let global_interner = global_interners.map(|interners| {
(interners.type_.borrow_mut(), &interners.arena)
});
if let Some((ref type_, _)) = global_interner {
if let Some(&Interned(ty)) = type_.get(&st) {
return ty;
}
}
let flags = super::flags::FlagComputation::for_sty(&st);
let ty_struct = TyS { let ty_struct = TyS {
sty: st, sty: st,
flags: flags.flags, flags: flags.flags,
region_depth: flags.depth, region_depth: flags.depth,
}; };
// HACK(eddyb) Depend on flags being accurate to // Make sure we don't end up with inference
// determine that all contents are in the global tcx. // types/regions in the global interner
// See comments on Lift for why we can't use that. if local as *const _ as usize == global as *const _ as usize {
if !flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) { bug!("Attempted to intern `{:?}` which contains \
if let Some((mut type_, arena)) = global_interner { inference types/regions in the global type context",
let ty_struct: TyS<'gcx> = unsafe { &ty_struct);
mem::transmute(ty_struct)
};
let ty: Ty<'gcx> = arena.alloc(ty_struct);
type_.insert(Interned(ty));
return ty;
}
} else {
// Make sure we don't end up with inference
// types/regions in the global tcx.
if global_interner.is_none() {
drop(interner);
bug!("Attempted to intern `{:?}` which contains \
inference types/regions in the global type context",
&ty_struct);
}
} }
// Don't be &mut TyS. // Don't be &mut TyS.
let ty: Ty<'tcx> = self.arena.alloc(ty_struct); let ty: Ty<'tcx> = local.arena.alloc(ty_struct);
interner.insert(Interned(ty)); interner.insert(Interned(ty));
ty ty
}; } else {
let mut interner = global.type_.borrow_mut();
if let Some(&Interned(ty)) = interner.get(&st) {
return ty;
}
debug!("Interned type: {:?} Pointer: {:?}", let ty_struct = TyS {
ty, ty as *const TyS); sty: st,
ty flags: flags.flags,
region_depth: flags.depth,
};
// This is safe because all the types the ty_struct can point to
// already is in the global arena
let ty_struct: TyS<'gcx> = unsafe {
mem::transmute(ty_struct)
};
// Don't be &mut TyS.
let ty: Ty<'gcx> = global.arena.alloc(ty_struct);
interner.insert(Interned(ty));
ty
}
} }
} }
pub struct CommonTypes<'tcx> { pub struct CommonTypes<'tcx> {
@ -796,7 +795,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {
impl<'tcx> CommonTypes<'tcx> { impl<'tcx> CommonTypes<'tcx> {
fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
let mk = |sty| interners.intern_ty(sty, None); let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
let mk_region = |r| { let mk_region = |r| {
if let Some(r) = interners.region.borrow().get(&r) { if let Some(r) = interners.region.borrow().get(&r) {
return r.0; return r.0;
@ -2130,31 +2129,17 @@ macro_rules! intern_method {
$keep_in_local_tcx:expr) -> $ty:ty) => { $keep_in_local_tcx:expr) -> $ty:ty) => {
impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> { impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> {
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);
if let Some(i) = self.interners.$name.borrow().get(key) {
return i.0;
}
if !self.is_global() {
if let Some(i) = self.global_interners.$name.borrow().get(key) {
return i.0;
}
}
}
// 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.
if !($keep_in_local_tcx)(&v) { if ($keep_in_local_tcx)(&v) {
if !self.is_global() { let mut interner = self.interners.$name.borrow_mut();
let v = unsafe { if let Some(&Interned(v)) = interner.get(key) {
mem::transmute(v) return v;
};
let i = ($alloc_to_ret)(self.global_interners.arena.$alloc_method(v));
self.global_interners.$name.borrow_mut().insert(Interned(i));
return i;
} }
} else {
// Make sure we don't end up with inference // Make sure we don't end up with inference
// types/regions in the global tcx. // types/regions in the global tcx.
if self.is_global() { if self.is_global() {
@ -2162,11 +2147,24 @@ macro_rules! intern_method {
inference types/regions in the global type context", inference types/regions in the global type context",
v); v);
} }
}
let i = ($alloc_to_ret)(self.interners.arena.$alloc_method(v)); let i = ($alloc_to_ret)(self.interners.arena.$alloc_method(v));
self.interners.$name.borrow_mut().insert(Interned(i)); interner.insert(Interned(i));
i i
} else {
let mut interner = self.global_interners.$name.borrow_mut();
if let Some(&Interned(v)) = interner.get(key) {
return v;
}
// This transmutes $alloc<'tcx> to $alloc<'gcx>
let v = unsafe {
mem::transmute(v)
};
let i = ($alloc_to_ret)(self.global_interners.arena.$alloc_method(v));
interner.insert(Interned(i));
i
}
} }
} }
} }
@ -2274,15 +2272,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.mk_fn_ptr(converted_sig) self.mk_fn_ptr(converted_sig)
} }
// Interns a type/name combination, stores the resulting box in cx.interners, pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
// and returns the box as cast to an unsafe ptr (see comments for Ty above). CtxtInterners::intern_ty(&self.interners, &self.global_interners, st)
pub fn mk_ty(self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
let global_interners = if !self.is_global() {
Some(&self.global_interners)
} else {
None
};
self.interners.intern_ty(st, global_interners)
} }
pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> { pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {