Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only lookup types in one interner #50332

Merged
merged 1 commit into from
May 11, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 68 additions & 77 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,66 +162,65 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
}
}

/// Intern a type. global_interners is Some only if this is
/// a local interner and global_interners is its counterpart.
fn intern_ty(&self, st: TypeVariants<'tcx>,
global_interners: Option<&CtxtInterners<'gcx>>)
-> Ty<'tcx> {
let ty = {
let mut interner = self.type_.borrow_mut();
/// Intern a type
fn intern_ty(
local: &CtxtInterners<'tcx>,
global: &CtxtInterners<'gcx>,
st: TypeVariants<'tcx>
) -> Ty<'tcx> {
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) {
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 {
sty: st,
flags: flags.flags,
region_depth: flags.depth,
};

// 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) {
if let Some((mut type_, arena)) = global_interner {
let ty_struct: TyS<'gcx> = unsafe {
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);
}
// Make sure we don't end up with inference
// types/regions in the global interner
if local as *const _ as usize == global as *const _ as usize {
bug!("Attempted to intern `{:?}` which contains \
inference types/regions in the global type context",
&ty_struct);
}

// 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));
ty
};
} else {
let mut interner = global.type_.borrow_mut();
if let Some(&Interned(ty)) = interner.get(&st) {
return ty;
}

debug!("Interned type: {:?} Pointer: {:?}",
ty, ty as *const TyS);
ty
}
let ty_struct = TyS {
sty: st,
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> {
Expand Down Expand Up @@ -796,7 +795,7 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for TypeckTables<'gcx> {

impl<'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| {
if let Some(r) = interners.region.borrow().get(&r) {
return r.0;
Expand Down Expand Up @@ -2130,43 +2129,42 @@ macro_rules! intern_method {
$keep_in_local_tcx:expr) -> $ty:ty) => {
impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> {
pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
{
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;
}
}
}
let key = ($alloc_to_key)(&v);

// 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 !($keep_in_local_tcx)(&v) {
if !self.is_global() {
let v = unsafe {
mem::transmute(v)
};
let i = ($alloc_to_ret)(self.global_interners.arena.$alloc_method(v));
self.global_interners.$name.borrow_mut().insert(Interned(i));
return i;
if ($keep_in_local_tcx)(&v) {
let mut interner = self.interners.$name.borrow_mut();
if let Some(&Interned(v)) = interner.get(key) {
return v;
}
} else {

// Make sure we don't end up with inference
// types/regions in the global tcx.
if self.is_global() {
bug!("Attempted to intern `{:?}` which contains \
inference types/regions in the global type context",
v);
}
}

let i = ($alloc_to_ret)(self.interners.arena.$alloc_method(v));
self.interners.$name.borrow_mut().insert(Interned(i));
i
let i = ($alloc_to_ret)(self.interners.arena.$alloc_method(v));
interner.insert(Interned(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
}
}
}
}
Expand Down Expand Up @@ -2274,15 +2272,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self.mk_fn_ptr(converted_sig)
}

// Interns a type/name combination, stores the resulting box in cx.interners,
// and returns the box as cast to an unsafe ptr (see comments for Ty above).
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_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
CtxtInterners::intern_ty(&self.interners, &self.global_interners, st)
}

pub fn mk_mach_int(self, tm: ast::IntTy) -> Ty<'tcx> {
Expand Down