Auto merge of #38653 - Mark-Simulacrum:dropless-arena, r=eddyb
Add a DroplessArena and utilize it as a more efficient arena when possible I will collect performance (probably just `-Ztime-passes`, and more if that shows significant differences, perhaps). 6feba98 also fixes a potential infinite loop if inplace reallocation failed for `TypedArena` (and `DroplessArena` via copied code). r? @eddyb
This commit is contained in:
commit
08babdb412
@ -196,9 +196,9 @@ impl<T> TypedArena<T> {
|
||||
self.end.set(last_chunk.end());
|
||||
return;
|
||||
} else {
|
||||
let prev_capacity = last_chunk.storage.cap();
|
||||
new_capacity = last_chunk.storage.cap();
|
||||
loop {
|
||||
new_capacity = prev_capacity.checked_mul(2).unwrap();
|
||||
new_capacity = new_capacity.checked_mul(2).unwrap();
|
||||
if new_capacity >= currently_used_cap + n {
|
||||
break;
|
||||
}
|
||||
@ -280,6 +280,133 @@ impl<T> Drop for TypedArena<T> {
|
||||
|
||||
unsafe impl<T: Send> Send for TypedArena<T> {}
|
||||
|
||||
pub struct DroplessArena {
|
||||
/// A pointer to the next object to be allocated.
|
||||
ptr: Cell<*mut u8>,
|
||||
|
||||
/// A pointer to the end of the allocated area. When this pointer is
|
||||
/// reached, a new chunk is allocated.
|
||||
end: Cell<*mut u8>,
|
||||
|
||||
/// A vector of arena chunks.
|
||||
chunks: RefCell<Vec<TypedArenaChunk<u8>>>,
|
||||
}
|
||||
|
||||
impl DroplessArena {
|
||||
pub fn new() -> DroplessArena {
|
||||
DroplessArena {
|
||||
ptr: Cell::new(0 as *mut u8),
|
||||
end: Cell::new(0 as *mut u8),
|
||||
chunks: RefCell::new(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
|
||||
let ptr = ptr as *const u8 as *mut u8;
|
||||
for chunk in &*self.chunks.borrow() {
|
||||
if chunk.start() <= ptr && ptr < chunk.end() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn align_for<T>(&self) {
|
||||
let align = mem::align_of::<T>();
|
||||
let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1);
|
||||
self.ptr.set(final_address as *mut u8);
|
||||
assert!(self.ptr <= self.end);
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[cold]
|
||||
fn grow<T>(&self, n: usize) {
|
||||
let needed_bytes = n * mem::size_of::<T>();
|
||||
unsafe {
|
||||
let mut chunks = self.chunks.borrow_mut();
|
||||
let (chunk, mut new_capacity);
|
||||
if let Some(last_chunk) = chunks.last_mut() {
|
||||
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
|
||||
if last_chunk.storage.reserve_in_place(used_bytes, needed_bytes) {
|
||||
self.end.set(last_chunk.end());
|
||||
return;
|
||||
} else {
|
||||
new_capacity = last_chunk.storage.cap();
|
||||
loop {
|
||||
new_capacity = new_capacity.checked_mul(2).unwrap();
|
||||
if new_capacity >= used_bytes + needed_bytes {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
new_capacity = cmp::max(needed_bytes, PAGE);
|
||||
}
|
||||
chunk = TypedArenaChunk::<u8>::new(new_capacity);
|
||||
self.ptr.set(chunk.start());
|
||||
self.end.set(chunk.end());
|
||||
chunks.push(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn alloc<T>(&self, object: T) -> &mut T {
|
||||
unsafe {
|
||||
assert!(!intrinsics::needs_drop::<T>());
|
||||
assert!(mem::size_of::<T>() != 0);
|
||||
|
||||
self.align_for::<T>();
|
||||
let future_end = intrinsics::arith_offset(self.ptr.get(), mem::size_of::<T>() as isize);
|
||||
if (future_end as *mut u8) >= self.end.get() {
|
||||
self.grow::<T>(1)
|
||||
}
|
||||
|
||||
let ptr = self.ptr.get();
|
||||
// Set the pointer past ourselves
|
||||
self.ptr.set(intrinsics::arith_offset(
|
||||
self.ptr.get(), mem::size_of::<T>() as isize
|
||||
) as *mut u8);
|
||||
// Write into uninitialized memory.
|
||||
ptr::write(ptr as *mut T, object);
|
||||
&mut *(ptr as *mut T)
|
||||
}
|
||||
}
|
||||
|
||||
/// Allocates a slice of objects that are copied into the `DroplessArena`, returning a mutable
|
||||
/// reference to it. Will panic if passed a zero-sized type.
|
||||
///
|
||||
/// Panics:
|
||||
/// - Zero-sized types
|
||||
/// - Zero-length slices
|
||||
#[inline]
|
||||
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
|
||||
where T: Copy {
|
||||
unsafe {
|
||||
assert!(!intrinsics::needs_drop::<T>());
|
||||
}
|
||||
assert!(mem::size_of::<T>() != 0);
|
||||
assert!(slice.len() != 0);
|
||||
self.align_for::<T>();
|
||||
|
||||
let future_end = unsafe {
|
||||
intrinsics::arith_offset(self.ptr.get(), (slice.len() * mem::size_of::<T>()) as isize)
|
||||
};
|
||||
if (future_end as *mut u8) >= self.end.get() {
|
||||
self.grow::<T>(slice.len());
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let arena_slice = slice::from_raw_parts_mut(self.ptr.get() as *mut T, slice.len());
|
||||
self.ptr.set(intrinsics::arith_offset(
|
||||
self.ptr.get(), (slice.len() * mem::size_of::<T>()) as isize
|
||||
) as *mut u8);
|
||||
arena_slice.copy_from_slice(slice);
|
||||
arena_slice
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
extern crate test;
|
||||
|
@ -41,6 +41,7 @@ use syntax::ast;
|
||||
use errors::DiagnosticBuilder;
|
||||
use syntax_pos::{self, Span, DUMMY_SP};
|
||||
use util::nodemap::{FxHashMap, FxHashSet, NodeMap};
|
||||
use arena::DroplessArena;
|
||||
|
||||
use self::combine::CombineFields;
|
||||
use self::higher_ranked::HrMatchResult;
|
||||
@ -374,7 +375,7 @@ impl fmt::Display for FixupError {
|
||||
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
|
||||
pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
||||
arenas: ty::CtxtArenas<'tcx>,
|
||||
arena: DroplessArena,
|
||||
tables: Option<RefCell<ty::Tables<'tcx>>>,
|
||||
param_env: Option<ty::ParameterEnvironment<'gcx>>,
|
||||
projection_mode: Reveal,
|
||||
@ -388,7 +389,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
|
||||
-> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
InferCtxtBuilder {
|
||||
global_tcx: self,
|
||||
arenas: ty::CtxtArenas::new(),
|
||||
arena: DroplessArena::new(),
|
||||
tables: tables.map(RefCell::new),
|
||||
param_env: param_env,
|
||||
projection_mode: projection_mode,
|
||||
@ -426,7 +427,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
{
|
||||
let InferCtxtBuilder {
|
||||
global_tcx,
|
||||
ref arenas,
|
||||
ref arena,
|
||||
ref tables,
|
||||
ref mut param_env,
|
||||
projection_mode,
|
||||
@ -439,7 +440,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
|
||||
let param_env = param_env.take().unwrap_or_else(|| {
|
||||
global_tcx.empty_parameter_environment()
|
||||
});
|
||||
global_tcx.enter_local(arenas, |tcx| f(InferCtxt {
|
||||
global_tcx.enter_local(arena, |tcx| f(InferCtxt {
|
||||
tcx: tcx,
|
||||
tables: tables,
|
||||
projection_cache: RefCell::new(traits::ProjectionCache::new()),
|
||||
|
@ -39,7 +39,7 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||
|
||||
use arena::TypedArena;
|
||||
use arena::{TypedArena, DroplessArena};
|
||||
use std::borrow::Borrow;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::hash::{Hash, Hasher};
|
||||
@ -55,16 +55,9 @@ use syntax::symbol::{Symbol, keywords};
|
||||
use hir;
|
||||
|
||||
/// Internal storage
|
||||
pub struct CtxtArenas<'tcx> {
|
||||
pub struct GlobalArenas<'tcx> {
|
||||
// internings
|
||||
type_: TypedArena<TyS<'tcx>>,
|
||||
type_list: TypedArena<Ty<'tcx>>,
|
||||
substs: TypedArena<Kind<'tcx>>,
|
||||
bare_fn: TypedArena<BareFnTy<'tcx>>,
|
||||
region: TypedArena<Region>,
|
||||
stability: TypedArena<attr::Stability>,
|
||||
layout: TypedArena<Layout>,
|
||||
existential_predicates: TypedArena<ExistentialPredicate<'tcx>>,
|
||||
|
||||
// references
|
||||
generics: TypedArena<ty::Generics<'tcx>>,
|
||||
@ -73,29 +66,21 @@ pub struct CtxtArenas<'tcx> {
|
||||
mir: TypedArena<RefCell<Mir<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'tcx> CtxtArenas<'tcx> {
|
||||
pub fn new() -> CtxtArenas<'tcx> {
|
||||
CtxtArenas {
|
||||
type_: TypedArena::new(),
|
||||
type_list: TypedArena::new(),
|
||||
substs: TypedArena::new(),
|
||||
bare_fn: TypedArena::new(),
|
||||
region: TypedArena::new(),
|
||||
stability: TypedArena::new(),
|
||||
impl<'tcx> GlobalArenas<'tcx> {
|
||||
pub fn new() -> GlobalArenas<'tcx> {
|
||||
GlobalArenas {
|
||||
layout: TypedArena::new(),
|
||||
existential_predicates: TypedArena::new(),
|
||||
|
||||
generics: TypedArena::new(),
|
||||
trait_def: TypedArena::new(),
|
||||
adt_def: TypedArena::new(),
|
||||
mir: TypedArena::new()
|
||||
mir: TypedArena::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CtxtInterners<'tcx> {
|
||||
/// The arenas that types etc are allocated from.
|
||||
arenas: &'tcx CtxtArenas<'tcx>,
|
||||
/// The arena that types, regions, etc are allocated from
|
||||
arena: &'tcx DroplessArena,
|
||||
|
||||
/// Specifically use a speedy hash algorithm for these hash sets,
|
||||
/// they're accessed quite often.
|
||||
@ -104,22 +89,18 @@ pub struct CtxtInterners<'tcx> {
|
||||
substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
|
||||
bare_fn: RefCell<FxHashSet<Interned<'tcx, BareFnTy<'tcx>>>>,
|
||||
region: RefCell<FxHashSet<Interned<'tcx, Region>>>,
|
||||
stability: RefCell<FxHashSet<&'tcx attr::Stability>>,
|
||||
layout: RefCell<FxHashSet<&'tcx Layout>>,
|
||||
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
|
||||
}
|
||||
|
||||
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
fn new(arenas: &'tcx CtxtArenas<'tcx>) -> CtxtInterners<'tcx> {
|
||||
fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
|
||||
CtxtInterners {
|
||||
arenas: arenas,
|
||||
arena: arena,
|
||||
type_: RefCell::new(FxHashSet()),
|
||||
type_list: RefCell::new(FxHashSet()),
|
||||
substs: RefCell::new(FxHashSet()),
|
||||
bare_fn: RefCell::new(FxHashSet()),
|
||||
region: RefCell::new(FxHashSet()),
|
||||
stability: RefCell::new(FxHashSet()),
|
||||
layout: RefCell::new(FxHashSet()),
|
||||
existential_predicates: RefCell::new(FxHashSet()),
|
||||
}
|
||||
}
|
||||
@ -158,7 +139,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
let ty_struct: TyS<'gcx> = unsafe {
|
||||
mem::transmute(ty_struct)
|
||||
};
|
||||
let ty: Ty<'gcx> = interner.arenas.type_.alloc(ty_struct);
|
||||
let ty: Ty<'gcx> = interner.arena.alloc(ty_struct);
|
||||
global_interner.unwrap().insert(Interned(ty));
|
||||
return ty;
|
||||
}
|
||||
@ -174,7 +155,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
|
||||
}
|
||||
|
||||
// Don't be &mut TyS.
|
||||
let ty: Ty<'tcx> = self.arenas.type_.alloc(ty_struct);
|
||||
let ty: Ty<'tcx> = self.arena.alloc(ty_struct);
|
||||
interner.insert(Interned(ty));
|
||||
ty
|
||||
};
|
||||
@ -391,6 +372,7 @@ impl<'a, 'gcx, 'tcx> Deref for TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
pub struct GlobalCtxt<'tcx> {
|
||||
global_arenas: &'tcx GlobalArenas<'tcx>,
|
||||
global_interners: CtxtInterners<'tcx>,
|
||||
|
||||
pub specializes_cache: RefCell<traits::SpecializesCache>,
|
||||
@ -586,6 +568,10 @@ pub struct GlobalCtxt<'tcx> {
|
||||
/// Map from function to the `#[derive]` mode that it's defining. Only used
|
||||
/// by `proc-macro` crates.
|
||||
pub derive_macros: RefCell<NodeMap<Symbol>>,
|
||||
|
||||
stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>,
|
||||
|
||||
layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
|
||||
}
|
||||
|
||||
impl<'tcx> GlobalCtxt<'tcx> {
|
||||
@ -649,15 +635,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
pub fn alloc_generics(self, generics: ty::Generics<'gcx>)
|
||||
-> &'gcx ty::Generics<'gcx> {
|
||||
self.global_interners.arenas.generics.alloc(generics)
|
||||
self.global_arenas.generics.alloc(generics)
|
||||
}
|
||||
|
||||
pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx RefCell<Mir<'gcx>> {
|
||||
self.global_interners.arenas.mir.alloc(RefCell::new(mir))
|
||||
self.global_arenas.mir.alloc(RefCell::new(mir))
|
||||
}
|
||||
|
||||
pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
|
||||
self.global_interners.arenas.trait_def.alloc(def)
|
||||
self.global_arenas.trait_def.alloc(def)
|
||||
}
|
||||
|
||||
pub fn alloc_adt_def(self,
|
||||
@ -666,32 +652,28 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
variants: Vec<ty::VariantDef>)
|
||||
-> &'gcx ty::AdtDef {
|
||||
let def = ty::AdtDef::new(self, did, kind, variants);
|
||||
self.global_interners.arenas.adt_def.alloc(def)
|
||||
self.global_arenas.adt_def.alloc(def)
|
||||
}
|
||||
|
||||
pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
|
||||
if let Some(st) = self.global_interners.stability.borrow().get(&stab) {
|
||||
if let Some(st) = self.stability_interner.borrow().get(&stab) {
|
||||
return st;
|
||||
}
|
||||
|
||||
let interned = self.global_interners.arenas.stability.alloc(stab);
|
||||
if let Some(prev) = self.global_interners.stability
|
||||
.borrow_mut()
|
||||
.replace(interned) {
|
||||
let interned = self.global_interners.arena.alloc(stab);
|
||||
if let Some(prev) = self.stability_interner.borrow_mut().replace(interned) {
|
||||
bug!("Tried to overwrite interned Stability: {:?}", prev)
|
||||
}
|
||||
interned
|
||||
}
|
||||
|
||||
pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
|
||||
if let Some(layout) = self.global_interners.layout.borrow().get(&layout) {
|
||||
if let Some(layout) = self.layout_interner.borrow().get(&layout) {
|
||||
return layout;
|
||||
}
|
||||
|
||||
let interned = self.global_interners.arenas.layout.alloc(layout);
|
||||
if let Some(prev) = self.global_interners.layout
|
||||
.borrow_mut()
|
||||
.replace(interned) {
|
||||
let interned = self.global_arenas.layout.alloc(layout);
|
||||
if let Some(prev) = self.layout_interner.borrow_mut().replace(interned) {
|
||||
bug!("Tried to overwrite interned Layout: {:?}", prev)
|
||||
}
|
||||
interned
|
||||
@ -728,24 +710,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
|
||||
/// reference to the context, to allow formatting values that need it.
|
||||
pub fn create_and_enter<F, R>(s: &'tcx Session,
|
||||
arenas: &'tcx CtxtArenas<'tcx>,
|
||||
arenas: &'tcx GlobalArenas<'tcx>,
|
||||
arena: &'tcx DroplessArena,
|
||||
resolutions: ty::Resolutions,
|
||||
named_region_map: resolve_lifetime::NamedRegionMap,
|
||||
map: ast_map::Map<'tcx>,
|
||||
region_maps: RegionMaps,
|
||||
lang_items: middle::lang_items::LanguageItems,
|
||||
stability: stability::Index<'tcx>,
|
||||
crate_name: &str,
|
||||
crate_name: &str,
|
||||
f: F) -> R
|
||||
where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R
|
||||
{
|
||||
let data_layout = TargetDataLayout::parse(s);
|
||||
let interners = CtxtInterners::new(arenas);
|
||||
let interners = CtxtInterners::new(arena);
|
||||
let common_types = CommonTypes::new(&interners);
|
||||
let dep_graph = map.dep_graph.clone();
|
||||
let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone());
|
||||
tls::enter_global(GlobalCtxt {
|
||||
specializes_cache: RefCell::new(traits::SpecializesCache::new()),
|
||||
global_arenas: arenas,
|
||||
global_interners: interners,
|
||||
dep_graph: dep_graph.clone(),
|
||||
types: common_types,
|
||||
@ -794,18 +778,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
crate_name: Symbol::intern(crate_name),
|
||||
data_layout: data_layout,
|
||||
layout_cache: RefCell::new(FxHashMap()),
|
||||
layout_interner: RefCell::new(FxHashSet()),
|
||||
layout_depth: Cell::new(0),
|
||||
derive_macros: RefCell::new(NodeMap()),
|
||||
stability_interner: RefCell::new(FxHashSet()),
|
||||
}, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
|
||||
/// Call the closure with a local `TyCtxt` using the given arenas.
|
||||
pub fn enter_local<F, R>(&self, arenas: &'tcx CtxtArenas<'tcx>, f: F) -> R
|
||||
/// Call the closure with a local `TyCtxt` using the given arena.
|
||||
pub fn enter_local<F, R>(&self, arena: &'tcx DroplessArena, f: F) -> R
|
||||
where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
|
||||
{
|
||||
let interners = CtxtInterners::new(arenas);
|
||||
let interners = CtxtInterners::new(arena);
|
||||
tls::enter(self, &interners, f)
|
||||
}
|
||||
}
|
||||
@ -835,10 +821,8 @@ pub trait Lift<'tcx> {
|
||||
impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
|
||||
type Lifted = Ty<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
|
||||
if let Some(&Interned(ty)) = tcx.interners.type_.borrow().get(&self.sty) {
|
||||
if *self as *const _ == ty as *const _ {
|
||||
return Some(ty);
|
||||
}
|
||||
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||
return Some(unsafe { mem::transmute(*self) });
|
||||
}
|
||||
// Also try in the global tcx if we're not that.
|
||||
if !tcx.is_global() {
|
||||
@ -855,10 +839,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
|
||||
if self.len() == 0 {
|
||||
return Some(Slice::empty());
|
||||
}
|
||||
if let Some(&Interned(substs)) = tcx.interners.substs.borrow().get(&self[..]) {
|
||||
if *self as *const _ == substs as *const _ {
|
||||
return Some(substs);
|
||||
}
|
||||
if tcx.interners.arena.in_arena(&self[..] as *const _) {
|
||||
return Some(unsafe { mem::transmute(*self) });
|
||||
}
|
||||
// Also try in the global tcx if we're not that.
|
||||
if !tcx.is_global() {
|
||||
@ -872,10 +854,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
|
||||
impl<'a, 'tcx> Lift<'tcx> for &'a Region {
|
||||
type Lifted = &'tcx Region;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Region> {
|
||||
if let Some(&Interned(region)) = tcx.interners.region.borrow().get(*self) {
|
||||
if *self as *const _ == region as *const _ {
|
||||
return Some(region);
|
||||
}
|
||||
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||
return Some(unsafe { mem::transmute(*self) });
|
||||
}
|
||||
// Also try in the global tcx if we're not that.
|
||||
if !tcx.is_global() {
|
||||
@ -893,10 +873,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Ty<'a>> {
|
||||
if self.len() == 0 {
|
||||
return Some(Slice::empty());
|
||||
}
|
||||
if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(&self[..]) {
|
||||
if *self as *const _ == list as *const _ {
|
||||
return Some(list);
|
||||
}
|
||||
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||
return Some(unsafe { mem::transmute(*self) });
|
||||
}
|
||||
// Also try in the global tcx if we're not that.
|
||||
if !tcx.is_global() {
|
||||
@ -914,10 +892,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<ExistentialPredicate<'a>> {
|
||||
if self.is_empty() {
|
||||
return Some(Slice::empty());
|
||||
}
|
||||
if let Some(&Interned(eps)) = tcx.interners.existential_predicates.borrow().get(&self[..]) {
|
||||
if *self as *const _ == eps as *const _ {
|
||||
return Some(eps);
|
||||
}
|
||||
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||
return Some(unsafe { mem::transmute(*self) });
|
||||
}
|
||||
// Also try in the global tcx if we're not that.
|
||||
if !tcx.is_global() {
|
||||
@ -932,10 +908,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> {
|
||||
type Lifted = &'tcx BareFnTy<'tcx>;
|
||||
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
|
||||
-> Option<&'tcx BareFnTy<'tcx>> {
|
||||
if let Some(&Interned(fty)) = tcx.interners.bare_fn.borrow().get(*self) {
|
||||
if *self as *const _ == fty as *const _ {
|
||||
return Some(fty);
|
||||
}
|
||||
if tcx.interners.arena.in_arena(*self as *const _) {
|
||||
return Some(unsafe { mem::transmute(*self) });
|
||||
}
|
||||
// Also try in the global tcx if we're not that.
|
||||
if !tcx.is_global() {
|
||||
@ -1101,8 +1075,8 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
println!("Substs interner: #{}", self.interners.substs.borrow().len());
|
||||
println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
|
||||
println!("Region interner: #{}", self.interners.region.borrow().len());
|
||||
println!("Stability interner: #{}", self.interners.stability.borrow().len());
|
||||
println!("Layout interner: #{}", self.interners.layout.borrow().len());
|
||||
println!("Stability interner: #{}", self.stability_interner.borrow().len());
|
||||
println!("Layout interner: #{}", self.layout_interner.borrow().len());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1205,8 +1179,7 @@ macro_rules! intern_method {
|
||||
let v = unsafe {
|
||||
mem::transmute(v)
|
||||
};
|
||||
let i = ($alloc_to_ret)(self.global_interners.arenas.$name
|
||||
.$alloc_method(v));
|
||||
let i = ($alloc_to_ret)(self.global_interners.arena.$alloc_method(v));
|
||||
self.global_interners.$name.borrow_mut().insert(Interned(i));
|
||||
return i;
|
||||
}
|
||||
@ -1220,7 +1193,7 @@ macro_rules! intern_method {
|
||||
}
|
||||
}
|
||||
|
||||
let i = ($alloc_to_ret)(self.interners.arenas.$name.$alloc_method(v));
|
||||
let i = ($alloc_to_ret)(self.interners.arena.$alloc_method(v));
|
||||
self.interners.$name.borrow_mut().insert(Interned(i));
|
||||
i
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ pub use self::sty::Region::*;
|
||||
pub use self::sty::TypeVariants::*;
|
||||
|
||||
pub use self::contents::TypeContents;
|
||||
pub use self::context::{TyCtxt, tls};
|
||||
pub use self::context::{CtxtArenas, Lift, Tables};
|
||||
pub use self::context::{TyCtxt, GlobalArenas, tls};
|
||||
pub use self::context::{Lift, Tables};
|
||||
|
||||
pub use self::trait_def::{TraitDef, TraitFlags};
|
||||
|
||||
|
@ -19,7 +19,7 @@ use rustc::session::search_paths::PathKind;
|
||||
use rustc::lint;
|
||||
use rustc::middle::{self, dependency_format, stability, reachable};
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::ty::{self, TyCtxt, Resolutions};
|
||||
use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
|
||||
use rustc::util::common::time;
|
||||
use rustc::util::nodemap::{NodeSet, NodeMap};
|
||||
use rustc_borrowck as borrowck;
|
||||
@ -55,6 +55,7 @@ use syntax::symbol::Symbol;
|
||||
use syntax::util::node_count::NodeCounter;
|
||||
use syntax;
|
||||
use syntax_ext;
|
||||
use arena::DroplessArena;
|
||||
|
||||
use derive_registrar;
|
||||
|
||||
@ -123,7 +124,8 @@ pub fn compile_input(sess: &Session,
|
||||
|
||||
write_out_deps(sess, &outputs, &crate_name);
|
||||
|
||||
let arenas = ty::CtxtArenas::new();
|
||||
let arena = DroplessArena::new();
|
||||
let arenas = GlobalArenas::new();
|
||||
|
||||
// Construct the HIR map
|
||||
let hir_map = time(sess.time_passes(),
|
||||
@ -138,6 +140,7 @@ pub fn compile_input(sess: &Session,
|
||||
sess,
|
||||
outdir,
|
||||
output,
|
||||
&arena,
|
||||
&arenas,
|
||||
&cstore,
|
||||
&hir_map,
|
||||
@ -164,6 +167,7 @@ pub fn compile_input(sess: &Session,
|
||||
hir_map,
|
||||
analysis,
|
||||
resolutions,
|
||||
&arena,
|
||||
&arenas,
|
||||
&crate_name,
|
||||
|tcx, analysis, incremental_hashes_map, result| {
|
||||
@ -331,7 +335,8 @@ pub struct CompileState<'a, 'tcx: 'a> {
|
||||
pub output_filenames: Option<&'a OutputFilenames>,
|
||||
pub out_dir: Option<&'a Path>,
|
||||
pub out_file: Option<&'a Path>,
|
||||
pub arenas: Option<&'tcx ty::CtxtArenas<'tcx>>,
|
||||
pub arena: Option<&'tcx DroplessArena>,
|
||||
pub arenas: Option<&'tcx GlobalArenas<'tcx>>,
|
||||
pub expanded_crate: Option<&'a ast::Crate>,
|
||||
pub hir_crate: Option<&'a hir::Crate>,
|
||||
pub ast_map: Option<&'a hir_map::Map<'tcx>>,
|
||||
@ -351,6 +356,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
|
||||
session: session,
|
||||
out_dir: out_dir.as_ref().map(|s| &**s),
|
||||
out_file: None,
|
||||
arena: None,
|
||||
arenas: None,
|
||||
krate: None,
|
||||
registry: None,
|
||||
@ -405,7 +411,8 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
|
||||
session: &'tcx Session,
|
||||
out_dir: &'a Option<PathBuf>,
|
||||
out_file: &'a Option<PathBuf>,
|
||||
arenas: &'tcx ty::CtxtArenas<'tcx>,
|
||||
arena: &'tcx DroplessArena,
|
||||
arenas: &'tcx GlobalArenas<'tcx>,
|
||||
cstore: &'a CStore,
|
||||
hir_map: &'a hir_map::Map<'tcx>,
|
||||
analysis: &'a ty::CrateAnalysis<'static>,
|
||||
@ -416,6 +423,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
|
||||
-> Self {
|
||||
CompileState {
|
||||
crate_name: Some(crate_name),
|
||||
arena: Some(arena),
|
||||
arenas: Some(arenas),
|
||||
cstore: Some(cstore),
|
||||
ast_map: Some(hir_map),
|
||||
@ -800,7 +808,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
hir_map: hir_map::Map<'tcx>,
|
||||
mut analysis: ty::CrateAnalysis<'tcx>,
|
||||
resolutions: Resolutions,
|
||||
arenas: &'tcx ty::CtxtArenas<'tcx>,
|
||||
arena: &'tcx DroplessArena,
|
||||
arenas: &'tcx GlobalArenas<'tcx>,
|
||||
name: &str,
|
||||
f: F)
|
||||
-> Result<R, usize>
|
||||
@ -858,6 +867,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|
||||
TyCtxt::create_and_enter(sess,
|
||||
arenas,
|
||||
arena,
|
||||
resolutions,
|
||||
named_region_map,
|
||||
hir_map,
|
||||
|
@ -462,6 +462,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
||||
&state.expanded_crate.take().unwrap(),
|
||||
state.crate_name.unwrap(),
|
||||
ppm,
|
||||
state.arena.unwrap(),
|
||||
state.arenas.unwrap(),
|
||||
opt_uii.clone(),
|
||||
state.out_file);
|
||||
|
@ -17,7 +17,7 @@ use self::NodesMatchingUII::*;
|
||||
|
||||
use {abort_on_err, driver};
|
||||
|
||||
use rustc::ty::{self, TyCtxt, Resolutions};
|
||||
use rustc::ty::{self, TyCtxt, GlobalArenas, Resolutions};
|
||||
use rustc::cfg;
|
||||
use rustc::cfg::graphviz::LabelledCFG;
|
||||
use rustc::dep_graph::DepGraph;
|
||||
@ -51,6 +51,8 @@ use rustc::hir::map::blocks;
|
||||
use rustc::hir;
|
||||
use rustc::hir::print as pprust_hir;
|
||||
|
||||
use arena::DroplessArena;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum PpSourceMode {
|
||||
PpmNormal,
|
||||
@ -201,7 +203,8 @@ impl PpSourceMode {
|
||||
ast_map: &hir_map::Map<'tcx>,
|
||||
analysis: &ty::CrateAnalysis<'tcx>,
|
||||
resolutions: &Resolutions,
|
||||
arenas: &'tcx ty::CtxtArenas<'tcx>,
|
||||
arena: &'tcx DroplessArena,
|
||||
arenas: &'tcx GlobalArenas<'tcx>,
|
||||
id: &str,
|
||||
payload: B,
|
||||
f: F)
|
||||
@ -229,6 +232,7 @@ impl PpSourceMode {
|
||||
ast_map.clone(),
|
||||
analysis.clone(),
|
||||
resolutions.clone(),
|
||||
arena,
|
||||
arenas,
|
||||
id,
|
||||
|tcx, _, _, _| {
|
||||
@ -846,7 +850,8 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
krate: &ast::Crate,
|
||||
crate_name: &str,
|
||||
ppm: PpMode,
|
||||
arenas: &'tcx ty::CtxtArenas<'tcx>,
|
||||
arena: &'tcx DroplessArena,
|
||||
arenas: &'tcx GlobalArenas<'tcx>,
|
||||
opt_uii: Option<UserIdentifiedItem>,
|
||||
ofile: Option<&Path>) {
|
||||
let dep_graph = DepGraph::new(false);
|
||||
@ -858,6 +863,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
analysis,
|
||||
resolutions,
|
||||
crate_name,
|
||||
arena,
|
||||
arenas,
|
||||
ppm,
|
||||
opt_uii,
|
||||
@ -894,6 +900,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
ast_map,
|
||||
analysis,
|
||||
resolutions,
|
||||
arena,
|
||||
arenas,
|
||||
crate_name,
|
||||
box out,
|
||||
@ -917,6 +924,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
ast_map,
|
||||
analysis,
|
||||
resolutions,
|
||||
arena,
|
||||
arenas,
|
||||
crate_name,
|
||||
(out, uii),
|
||||
@ -959,7 +967,8 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
analysis: &ty::CrateAnalysis<'tcx>,
|
||||
resolutions: &Resolutions,
|
||||
crate_name: &str,
|
||||
arenas: &'tcx ty::CtxtArenas<'tcx>,
|
||||
arena: &'tcx DroplessArena,
|
||||
arenas: &'tcx GlobalArenas<'tcx>,
|
||||
ppm: PpMode,
|
||||
uii: Option<UserIdentifiedItem>,
|
||||
ofile: Option<&Path>) {
|
||||
@ -977,6 +986,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
|
||||
ast_map.clone(),
|
||||
analysis.clone(),
|
||||
resolutions.clone(),
|
||||
arena,
|
||||
arenas,
|
||||
crate_name,
|
||||
|tcx, _, _, _| {
|
||||
|
@ -38,6 +38,7 @@ use errors::{Level, DiagnosticBuilder};
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::DUMMY_SP;
|
||||
use arena::DroplessArena;
|
||||
|
||||
use rustc::hir;
|
||||
|
||||
@ -128,7 +129,8 @@ fn test_env<F>(source_string: &str,
|
||||
};
|
||||
let _ignore = dep_graph.in_ignore();
|
||||
|
||||
let arenas = ty::CtxtArenas::new();
|
||||
let arena = DroplessArena::new();
|
||||
let arenas = ty::GlobalArenas::new();
|
||||
let ast_map = hir_map::map_crate(&mut hir_forest, defs);
|
||||
|
||||
// run just enough stuff to build a tcx:
|
||||
@ -138,6 +140,7 @@ fn test_env<F>(source_string: &str,
|
||||
let index = stability::Index::new(&ast_map);
|
||||
TyCtxt::create_and_enter(&sess,
|
||||
&arenas,
|
||||
&arena,
|
||||
resolutions,
|
||||
named_region_map.unwrap(),
|
||||
ast_map,
|
||||
|
@ -15,7 +15,7 @@ use rustc::session::{self, config};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::def::{Def, ExportMap};
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::ty::{self, TyCtxt, Ty};
|
||||
use rustc::ty::{self, TyCtxt, GlobalArenas, Ty};
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::lint;
|
||||
use rustc::util::nodemap::{FxHashMap, NodeMap};
|
||||
@ -37,6 +37,7 @@ use visit_ast::RustdocVisitor;
|
||||
use clean;
|
||||
use clean::Clean;
|
||||
use html::render::RenderInfo;
|
||||
use arena::DroplessArena;
|
||||
|
||||
pub use rustc::session::config::Input;
|
||||
pub use rustc::session::search_paths::SearchPaths;
|
||||
@ -160,13 +161,15 @@ pub fn run_core(search_paths: SearchPaths,
|
||||
).expect("phase_2_configure_and_expand aborted in rustdoc!")
|
||||
};
|
||||
|
||||
let arenas = ty::CtxtArenas::new();
|
||||
let arena = DroplessArena::new();
|
||||
let arenas = GlobalArenas::new();
|
||||
let hir_map = hir_map::map_crate(&mut hir_forest, defs);
|
||||
|
||||
abort_on_err(driver::phase_3_run_analysis_passes(&sess,
|
||||
hir_map,
|
||||
analysis,
|
||||
resolutions,
|
||||
&arena,
|
||||
&arenas,
|
||||
&name,
|
||||
|tcx, analysis, _, result| {
|
||||
|
Loading…
Reference in New Issue
Block a user