Auto merge of #37764 - nnethercote:shrink-scope_auxiliary, r=nikomatsakis

Remove `scope_auxiliary`.

`scope_auxiliary` is a big part of the high memory usage in #36799. It's only used for MIR dumping. I have taken a hubristic approach: I have assumed that particular use is unimportant and removed `scope_auxiliary` and related things. This reduces peak RSS by ~10% for a cut-down version of the program in #36799.

If that assumption is wrong perhaps we can avoid building `scope_auxiliary` unless MIR dumping is enabled.
This commit is contained in:
bors 2016-11-15 20:43:53 -08:00 committed by GitHub
commit c19cb9c12d
7 changed files with 30 additions and 129 deletions

View File

@ -54,7 +54,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
let tcx = this.hir.tcx();
// Enter the remainder scope, i.e. the bindings' destruction scope.
this.push_scope(remainder_scope, block);
this.push_scope(remainder_scope);
let_extent_stack.push(remainder_scope);
// Declare the bindings, which may create a visibility scope.

View File

@ -40,11 +40,6 @@ impl<'tcx> CFG<'tcx> {
self.block_data_mut(block).statements.push(statement);
}
pub fn current_location(&mut self, block: BasicBlock) -> Location {
let index = self.block_data(block).statements.len();
Location { block: block, statement_index: index }
}
pub fn push_assign(&mut self,
block: BasicBlock,
source_info: SourceInfo,

View File

@ -36,13 +36,6 @@ pub struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
/// see the `scope` module for more details
scopes: Vec<scope::Scope<'tcx>>,
/// for each scope, a span of blocks that defines it;
/// we track these for use in region and borrow checking,
/// but these are liable to get out of date once optimization
/// begins. They are also hopefully temporary, and will be
/// no longer needed when we adopt graph-based regions.
scope_auxiliary: IndexVec<ScopeId, ScopeAuxiliary>,
/// the current set of loops; see the `scope` module for more
/// details
loop_scopes: Vec<scope::LoopScope>,
@ -82,30 +75,6 @@ impl Idx for ScopeId {
}
}
/// For each scope, we track the extent (from the HIR) and a
/// single-entry-multiple-exit subgraph that contains all the
/// statements/terminators within it.
///
/// This information is separated out from the main `ScopeData`
/// because it is short-lived. First, the extent contains node-ids,
/// so it cannot be saved and re-loaded. Second, any optimization will mess up
/// the dominator/postdominator information.
///
/// The intention is basically to use this information to do
/// regionck/borrowck and then throw it away once we are done.
pub struct ScopeAuxiliary {
/// extent of this scope from the MIR.
pub extent: CodeExtent,
/// "entry point": dominator of all nodes in the scope
pub dom: Location,
/// "exit points": mutual postdominators of all nodes in the scope
pub postdoms: Vec<Location>,
}
pub type ScopeAuxiliaryVec = IndexVec<ScopeId, ScopeAuxiliary>;
///////////////////////////////////////////////////////////////////////////
/// The `BlockAnd` "monad" packages up the new basic block along with a
/// produced value (sometimes just unit, of course). The `unpack!`
@ -158,7 +127,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
abi: Abi,
return_ty: Ty<'gcx>,
ast_body: &'gcx hir::Expr)
-> (Mir<'tcx>, ScopeAuxiliaryVec)
-> Mir<'tcx>
where A: Iterator<Item=(Ty<'gcx>, Option<&'gcx hir::Pat>)>
{
let arguments: Vec<_> = arguments.collect();
@ -221,15 +190,15 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
}).collect()
});
let (mut mir, aux) = builder.finish(upvar_decls, return_ty);
let mut mir = builder.finish(upvar_decls, return_ty);
mir.spread_arg = spread_arg;
(mir, aux)
mir
}
pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>,
item_id: ast::NodeId,
ast_expr: &'tcx hir::Expr)
-> (Mir<'tcx>, ScopeAuxiliaryVec) {
-> Mir<'tcx> {
let tcx = hir.tcx();
let ty = tcx.tables().expr_ty_adjusted(ast_expr);
let span = tcx.map.span(item_id);
@ -269,7 +238,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
scopes: vec![],
visibility_scopes: IndexVec::new(),
visibility_scope: ARGUMENT_VISIBILITY_SCOPE,
scope_auxiliary: IndexVec::new(),
loop_scopes: vec![],
local_decls: IndexVec::from_elem_n(LocalDecl::new_return_pointer(return_ty), 1),
var_indices: NodeMap(),
@ -288,14 +256,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
fn finish(self,
upvar_decls: Vec<UpvarDecl>,
return_ty: Ty<'tcx>)
-> (Mir<'tcx>, ScopeAuxiliaryVec) {
-> Mir<'tcx> {
for (index, block) in self.cfg.basic_blocks.iter().enumerate() {
if block.terminator.is_none() {
span_bug!(self.fn_span, "no terminator on block {:?}", index);
}
}
(Mir::new(self.cfg.basic_blocks,
Mir::new(self.cfg.basic_blocks,
self.visibility_scopes,
IndexVec::new(),
return_ty,
@ -303,7 +271,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
self.arg_count,
upvar_decls,
self.fn_span
), self.scope_auxiliary)
)
}
fn args_and_body(&mut self,

View File

@ -86,7 +86,7 @@ should go to.
*/
use build::{BlockAnd, BlockAndExtension, Builder, CFG, ScopeAuxiliary, ScopeId};
use build::{BlockAnd, BlockAndExtension, Builder, CFG};
use rustc::middle::region::{CodeExtent, CodeExtentData};
use rustc::middle::lang_items;
use rustc::ty::subst::{Kind, Subst};
@ -97,14 +97,10 @@ use rustc_data_structures::indexed_vec::Idx;
use rustc_data_structures::fx::FxHashMap;
pub struct Scope<'tcx> {
/// the scope-id within the scope_auxiliary
id: ScopeId,
/// The visibility scope this scope was created in.
visibility_scope: VisibilityScope,
/// the extent of this scope within source code; also stored in
/// `ScopeAuxiliary`, but kept here for convenience
/// the extent of this scope within source code.
extent: CodeExtent,
/// Whether there's anything to do for the cleanup path, that is,
@ -276,7 +272,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
{
debug!("in_scope(extent={:?}, block={:?})", extent, block);
self.push_scope(extent, block);
self.push_scope(extent);
let rv = unpack!(block = f(self));
unpack!(block = self.pop_scope(extent, block));
debug!("in_scope: exiting extent={:?} block={:?}", extent, block);
@ -287,12 +283,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
/// scope and call `pop_scope` afterwards. Note that these two
/// calls must be paired; using `in_scope` as a convenience
/// wrapper maybe preferable.
pub fn push_scope(&mut self, extent: CodeExtent, entry: BasicBlock) {
pub fn push_scope(&mut self, extent: CodeExtent) {
debug!("push_scope({:?})", extent);
let id = ScopeId::new(self.scope_auxiliary.len());
let vis_scope = self.visibility_scope;
self.scopes.push(Scope {
id: id,
visibility_scope: vis_scope,
extent: extent,
needs_cleanup: false,
@ -300,11 +294,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
free: None,
cached_exits: FxHashMap()
});
self.scope_auxiliary.push(ScopeAuxiliary {
extent: extent,
dom: self.cfg.current_location(entry),
postdoms: vec![]
});
}
/// Pops a scope, which should have extent `extent`, adding any
@ -325,9 +314,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
&self.scopes,
block,
self.arg_count));
self.scope_auxiliary[scope.id]
.postdoms
.push(self.cfg.current_location(block));
block.unit()
}
@ -375,9 +361,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
self.cfg.terminate(block, scope.source_info(span), free);
block = next;
}
self.scope_auxiliary[scope.id]
.postdoms
.push(self.cfg.current_location(block));
}
}
let scope = &self.scopes[len - scope_count];

View File

@ -103,11 +103,11 @@ impl<'a, 'gcx, 'tcx> BuildMir<'a, 'gcx> {
impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> {
fn build<F>(&'tcx mut self, f: F)
where F: for<'b> FnOnce(Cx<'b, 'gcx, 'tcx>) -> (Mir<'tcx>, build::ScopeAuxiliaryVec)
where F: for<'b> FnOnce(Cx<'b, 'gcx, 'tcx>) -> Mir<'tcx>
{
let (src, def_id) = (self.src, self.def_id);
self.infcx.enter(|infcx| {
let (mut mir, scope_auxiliary) = f(Cx::new(&infcx, src));
let mut mir = f(Cx::new(&infcx, src));
// Convert the Mir to global types.
let tcx = infcx.tcx.global_tcx();
@ -120,7 +120,7 @@ impl<'a, 'gcx, 'tcx> CxBuilder<'a, 'gcx, 'tcx> {
mem::transmute::<Mir, Mir<'gcx>>(mir)
};
pretty::dump_mir(tcx, "mir_map", &0, src, &mir, Some(&scope_auxiliary));
pretty::dump_mir(tcx, "mir_map", &0, src, &mir);
let mir = tcx.alloc_mir(mir);
assert!(tcx.mir_map.borrow_mut().insert(def_id, mir).is_none());

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use build::{ScopeAuxiliaryVec, ScopeId};
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::mir::*;
@ -43,8 +42,7 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
pass_name: &str,
disambiguator: &Display,
src: MirSource,
mir: &Mir<'tcx>,
auxiliary: Option<&ScopeAuxiliaryVec>) {
mir: &Mir<'tcx>) {
let filters = match tcx.sess.opts.debugging_opts.dump_mir {
None => return,
Some(ref filters) => filters,
@ -81,7 +79,7 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
writeln!(file, "// pass_name = {}", pass_name)?;
writeln!(file, "// disambiguator = {}", disambiguator)?;
writeln!(file, "")?;
write_mir_fn(tcx, src, mir, &mut file, auxiliary)?;
write_mir_fn(tcx, src, mir, &mut file)?;
Ok(())
});
}
@ -106,52 +104,24 @@ pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
let id = tcx.map.as_local_node_id(def_id).unwrap();
let src = MirSource::from_node(tcx, id);
write_mir_fn(tcx, src, mir, w, None)?;
write_mir_fn(tcx, src, mir, w)?;
for (i, mir) in mir.promoted.iter_enumerated() {
writeln!(w, "")?;
write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w, None)?;
write_mir_fn(tcx, MirSource::Promoted(id, i), mir, w)?;
}
}
Ok(())
}
enum Annotation {
EnterScope(ScopeId),
ExitScope(ScopeId),
}
fn scope_entry_exit_annotations(auxiliary: Option<&ScopeAuxiliaryVec>)
-> FxHashMap<Location, Vec<Annotation>>
{
// compute scope/entry exit annotations
let mut annotations = FxHashMap();
if let Some(auxiliary) = auxiliary {
for (scope_id, auxiliary) in auxiliary.iter_enumerated() {
annotations.entry(auxiliary.dom)
.or_insert(vec![])
.push(Annotation::EnterScope(scope_id));
for &loc in &auxiliary.postdoms {
annotations.entry(loc)
.or_insert(vec![])
.push(Annotation::ExitScope(scope_id));
}
}
}
return annotations;
}
pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
src: MirSource,
mir: &Mir<'tcx>,
w: &mut Write,
auxiliary: Option<&ScopeAuxiliaryVec>)
w: &mut Write)
-> io::Result<()> {
let annotations = scope_entry_exit_annotations(auxiliary);
write_mir_intro(tcx, src, mir, w)?;
for block in mir.basic_blocks().indices() {
write_basic_block(tcx, block, mir, w, &annotations)?;
write_basic_block(tcx, block, mir, w)?;
if block.index() + 1 != mir.basic_blocks().len() {
writeln!(w, "")?;
}
@ -165,8 +135,7 @@ pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn write_basic_block(tcx: TyCtxt,
block: BasicBlock,
mir: &Mir,
w: &mut Write,
annotations: &FxHashMap<Location, Vec<Annotation>>)
w: &mut Write)
-> io::Result<()> {
let data = &mir[block];
@ -176,19 +145,6 @@ fn write_basic_block(tcx: TyCtxt,
// List of statements in the middle.
let mut current_location = Location { block: block, statement_index: 0 };
for statement in &data.statements {
if let Some(ref annotations) = annotations.get(&current_location) {
for annotation in annotations.iter() {
match *annotation {
Annotation::EnterScope(id) =>
writeln!(w, "{0}{0}// Enter Scope({1})",
INDENT, id.index())?,
Annotation::ExitScope(id) =>
writeln!(w, "{0}{0}// Exit Scope({1})",
INDENT, id.index())?,
}
}
}
let indented_mir = format!("{0}{0}{1:?};", INDENT, statement);
writeln!(w, "{0:1$} // {2}",
indented_mir,

View File

@ -64,8 +64,7 @@ impl<'tcx> MirPassHook<'tcx> for DumpMir {
is_after: is_after
},
src,
mir,
None
mir
);
}
}