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:
bors 2017-01-01 02:39:40 +00:00
commit 08babdb412
9 changed files with 228 additions and 100 deletions

View File

@ -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;

View File

@ -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()),

View File

@ -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
}

View File

@ -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};

View File

@ -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,

View File

@ -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);

View 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, _, _, _| {

View File

@ -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,

View File

@ -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| {