Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Jun 3, 2018
1 parent 235ea68 commit 3ee5405
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 79 deletions.
111 changes: 39 additions & 72 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ impl<'tcx> GlobalArenas<'tcx> {
}
}

type InternedSet<'tcx, T> = Lock<FxHashSet<Interned<'tcx, T>>>;
type InternedSet<'tcx, T> = Lock<FxInterner<Interned<'tcx, T>>>;

pub struct CtxtInterners<'tcx> {
/// The arena that types, regions, etc are allocated from
Expand Down Expand Up @@ -789,12 +789,9 @@ impl<'tcx> CommonTypes<'tcx> {

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;
}
let r = interners.arena.alloc(r);
interners.region.borrow_mut().insert(Interned(r));
&*r
interners.region.borrow_mut().intern(r, |r| {
Interned(interners.arena.alloc(r))
}).0
};
CommonTypes {
bool: mk(TyBool),
Expand Down Expand Up @@ -905,14 +902,14 @@ pub struct GlobalCtxt<'tcx> {
/// Data layout specification for the current target.
pub data_layout: TargetDataLayout,

stability_interner: Lock<FxHashSet<&'tcx attr::Stability>>,
stability_interner: Lock<FxInterner<&'tcx attr::Stability>>,

/// Stores the value of constants (and deduplicates the actual memory)
allocation_interner: Lock<FxHashSet<&'tcx Allocation>>,

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

layout_interner: Lock<FxHashSet<&'tcx LayoutDetails>>,
layout_interner: Lock<FxInterner<&'tcx LayoutDetails>>,

/// A general purpose channel to throw data out the back towards LLVM worker
/// threads.
Expand Down Expand Up @@ -995,16 +992,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
self,
alloc: Allocation,
) -> &'gcx Allocation {
let allocs = &mut self.allocation_interner.borrow_mut();
if let Some(alloc) = allocs.get(&alloc) {
return alloc;
}

let interned = self.global_arenas.const_allocs.alloc(alloc);
if let Some(prev) = allocs.replace(interned) {
bug!("Tried to overwrite interned Allocation: {:#?}", prev)
}
interned
self.allocation_interner.borrow_mut().intern(alloc, |alloc| {
self.global_arenas.const_allocs.alloc(alloc)
})
}

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

pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
let mut stability_interner = self.stability_interner.borrow_mut();
if let Some(st) = stability_interner.get(&stab) {
return st;
}

let interned = self.global_interners.arena.alloc(stab);
if let Some(prev) = stability_interner.replace(interned) {
bug!("Tried to overwrite interned Stability: {:?}", prev)
}
interned
self.stability_interner.borrow_mut().intern(stab, |stab| {
self.global_interners.arena.alloc(stab)
})
}

pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
let mut layout_interner = self.layout_interner.borrow_mut();
if let Some(layout) = layout_interner.get(&layout) {
return layout;
}

let interned = self.global_arenas.layout.alloc(layout);
if let Some(prev) = layout_interner.replace(interned) {
bug!("Tried to overwrite interned Layout: {:?}", prev)
}
interned
self.layout_interner.borrow_mut().intern(layout, |layout| {
self.global_arenas.layout.alloc(layout)
})
}

pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
Expand Down Expand Up @@ -1160,8 +1136,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
evaluation_cache: traits::EvaluationCache::new(),
crate_name: Symbol::intern(crate_name),
data_layout,
layout_interner: Lock::new(FxHashSet()),
stability_interner: Lock::new(FxHashSet()),
layout_interner: Default::default(),
stability_interner: Default::default(),
allocation_interner: Lock::new(FxHashSet()),
alloc_map: Lock::new(interpret::AllocMap::new()),
tx_to_llvm_workers: Lock::new(tx),
Expand Down Expand Up @@ -1898,7 +1874,7 @@ macro_rules! sty_debug_print {
($ctxt: expr, $($variant: ident),*) => {{
// curious inner module to allow variant names to be used as
// variable names.
#[allow(non_snake_case)]
#[allow(non_snake_case, warnings)]
mod inner {
use ty::{self, TyCtxt};
use ty::context::Interned;
Expand Down Expand Up @@ -2085,37 +2061,28 @@ macro_rules! intern_method {
// 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) {
let mut interner = self.interners.$name.borrow_mut();
if let Some(&Interned(v)) = interner.get(key) {
return v;
}

// 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_method(&self.interners.arena, v);
interner.insert(Interned(i));
i
self.interners.$name.borrow_mut().intern_ref(key, || {
// 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);
}

Interned($alloc_method(&self.interners.arena, v))
}).0
} 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: &$lt_tcx $ty = $alloc_method(&self.global_interners.arena, v);
// Cast to 'gcx
let i = unsafe { mem::transmute(i) };
interner.insert(Interned(i));
i
self.global_interners.$name.borrow_mut().intern_ref(key, || {
// This transmutes $alloc<'tcx> to $alloc<'gcx>
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
}
}
}
Expand Down
48 changes: 41 additions & 7 deletions src/librustc_data_structures/interner.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::marker::PhantomData;
use std::hash::Hash;
use std::hash::Hasher;
Expand All @@ -7,6 +17,7 @@ use std::ptr::{Unique, NonNull};
use std::alloc::{Global, Alloc};
use std::collections::hash_map::RandomState;
use std::borrow::Borrow;
use std::fmt;

const ENTRIES_PER_GROUP: usize = 5;

Expand Down Expand Up @@ -88,7 +99,7 @@ impl Drop for Table {
}

impl Table {
unsafe fn new_uninitialized(group_count: usize) -> Table {
fn new(group_count: usize) -> Table {
assert!(size_of::<Group>() == 64);
let groups: NonNull<Group> = Global.alloc_array(group_count).unwrap();
let capacity2 = group_count * ENTRIES_PER_GROUP;
Expand All @@ -110,7 +121,7 @@ impl Table {
group_mask: group_count.wrapping_sub(1),
size: 0,
capacity,
groups: Unique::new_unchecked(groups.as_ptr()),
groups: unsafe { Unique::new_unchecked(groups.as_ptr()) },
}
}

Expand All @@ -126,7 +137,7 @@ impl Table {
let group = unsafe {
&(*group_ptr)
};
match unsafe { group.search_for_empty() } {
match group.search_for_empty() {
Some(pos) => return RawEntry {
group: group_ptr,
pos,
Expand All @@ -150,7 +161,7 @@ impl Table {
let group = unsafe {
&(*group_ptr)
};
let r = unsafe { group.search_with(&mut eq, hash as u32) } ;
let r = group.search_with(&mut eq, hash as u32);
match r {
Some((pos, empty)) => return RawEntry {
group: group_ptr,
Expand Down Expand Up @@ -182,6 +193,12 @@ pub struct Interner<K: Eq + Hash, S = RandomState> {
marker: PhantomData<K>,
}

impl<K: Eq + Hash, S> fmt::Debug for Interner<K, S> {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
"Interner".fmt(f)
}
}

impl<K: Eq + Hash, S: Default> Default for Interner<K, S> {
fn default() -> Self {
assert!(size_of::<K>() == 8);
Expand Down Expand Up @@ -211,9 +228,7 @@ impl<K: Eq + Hash, S: BuildHasher> Interner<K, S> {
#[inline(never)]
#[cold]
fn expand(&mut self) {
let mut new_table = unsafe {
Table::new_uninitialized((self.table.group_mask + 1) << 1)
};
let mut new_table = Table::new((self.table.group_mask + 1) << 1);
new_table.size = self.table.size;
self.table.iter(|h, v| {
let spot = new_table.search_for_empty(h as u64);
Expand All @@ -236,6 +251,25 @@ impl<K: Eq + Hash, S: BuildHasher> Interner<K, S> {
self.table.size
}

#[inline]
pub fn intern_ref<Q: ?Sized, F: FnOnce() -> K>(&mut self, value: &Q, make: F) -> &K
where K: Borrow<Q>,
Q: Hash + Eq
{
self.incr();
let hash = make_hash(&self.hash_builder, value);
let spot = self.table.search_with::<K, _>(|k| value.eq(k.borrow()), hash);
unsafe {
if spot.empty {
self.table.size += 1;
(*spot.group).size += 1;
let key = make();
(*spot.group).set(spot.pos, hash as u32, *(&key as *const _ as *const u64));
}
&*((*spot.group).values.get_unchecked(spot.pos) as *const _ as *const K)
}
}

#[inline]
pub fn intern<Q, F: FnOnce(Q) -> K>(&mut self, value: Q, make: F) -> &K
where K: Borrow<Q>,
Expand Down

0 comments on commit 3ee5405

Please sign in to comment.