From 9e969808e291cb85c6870972264b29708e33a531 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 26 Jan 2016 08:36:34 -0500 Subject: [PATCH] Add caching of external MIR in trans::collector --- src/librustc/mir/repr.rs | 16 ++--- src/librustc_trans/trans/base.rs | 4 ++ src/librustc_trans/trans/collector.rs | 97 ++++++++++++++++++--------- src/librustc_trans/trans/consts.rs | 6 +- src/librustc_trans/trans/glue.rs | 10 +-- 5 files changed, 87 insertions(+), 46 deletions(-) diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs index de7a694a646..0fe39dcb7f9 100644 --- a/src/librustc/mir/repr.rs +++ b/src/librustc/mir/repr.rs @@ -25,7 +25,7 @@ use std::{iter, u32}; use std::ops::{Index, IndexMut}; /// Lowered representation of a single function. -#[derive(RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Mir<'tcx> { /// List of basic blocks. References to basic block use a newtyped index type `BasicBlock` /// that indexes into this vector. @@ -146,7 +146,7 @@ pub enum BorrowKind { // A "variable" is a binding declared by the user as part of the fn // decl, a let, etc. -#[derive(RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct VarDecl<'tcx> { pub mutability: Mutability, pub name: Name, @@ -155,7 +155,7 @@ pub struct VarDecl<'tcx> { // A "temp" is a temporary that we place on the stack. They are // anonymous, always mutable, and have only a type. -#[derive(RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct TempDecl<'tcx> { pub ty: Ty<'tcx>, } @@ -171,7 +171,7 @@ pub struct TempDecl<'tcx> { // // there is only one argument, of type `(i32, u32)`, but two bindings // (`x` and `y`). -#[derive(RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct ArgDecl<'tcx> { pub ty: Ty<'tcx>, } @@ -207,14 +207,14 @@ impl Debug for BasicBlock { /////////////////////////////////////////////////////////////////////////// // BasicBlock and Terminator -#[derive(Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct BasicBlockData<'tcx> { pub statements: Vec>, pub terminator: Option>, pub is_cleanup: bool, } -#[derive(RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub enum Terminator<'tcx> { /// block should have one successor in the graph; we jump there Goto { @@ -481,13 +481,13 @@ impl<'tcx> Terminator<'tcx> { /////////////////////////////////////////////////////////////////////////// // Statements -#[derive(RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable)] pub struct Statement<'tcx> { pub span: Span, pub kind: StatementKind<'tcx>, } -#[derive(Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub enum StatementKind<'tcx> { Assign(Lvalue<'tcx>, Rvalue<'tcx>), Drop(DropKind, Lvalue<'tcx>), diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 68f8d9d2adb..76b1bad1214 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2110,6 +2110,10 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn record_translation_item_as_generated<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, node_id: ast::NodeId, param_substs: &'tcx Substs<'tcx>) { + if !collector::collecting_debug_information(ccx) { + return; + } + let def_id = match ccx.tcx().node_id_to_type(node_id).sty { ty::TyClosure(def_id, _) => def_id, _ => ccx.external_srcs() diff --git a/src/librustc_trans/trans/collector.rs b/src/librustc_trans/trans/collector.rs index 574cba2f0ee..f8aaa2fcdca 100644 --- a/src/librustc_trans/trans/collector.rs +++ b/src/librustc_trans/trans/collector.rs @@ -217,6 +217,7 @@ use trans::monomorphize; use util::nodemap::{FnvHashSet, FnvHashMap, DefIdMap}; use std::hash::{Hash, Hasher}; +use std::rc::Rc; #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] pub enum TransItemCollectionMode { @@ -281,9 +282,14 @@ pub fn collect_crate_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, debug!("Building translation item graph, beginning at roots"); let mut visited = FnvHashSet(); let mut recursion_depths = DefIdMap(); + let mut mir_cache = DefIdMap(); for root in roots { - collect_items_rec(ccx, root, &mut visited, &mut recursion_depths); + collect_items_rec(ccx, + root, + &mut visited, + &mut recursion_depths, + &mut mir_cache); } visited @@ -313,11 +319,27 @@ fn collect_roots<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, roots } +#[derive(Clone)] +enum CachedMir<'mir, 'tcx: 'mir> { + Ref(&'mir mir::Mir<'tcx>), + Owned(Rc>) +} + +impl<'mir, 'tcx: 'mir> CachedMir<'mir, 'tcx> { + fn get_ref<'a>(&'a self) -> &'a mir::Mir<'tcx> { + match *self { + CachedMir::Ref(r) => r, + CachedMir::Owned(ref rc) => &**rc, + } + } +} + // Collect all monomorphized translation items reachable from `starting_point` fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, starting_point: TransItem<'tcx>, visited: &mut FnvHashSet>, - recursion_depths: &mut DefIdMap) { + recursion_depths: &mut DefIdMap, + mir_cache: &mut DefIdMap>) { if !visited.insert(starting_point.clone()) { // We've been here already, no need to search again. return; @@ -343,42 +365,21 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, // Scan the MIR in order to find function calls, closures, and // drop-glue - let mir_not_found_error_message = || { - format!("Could not find MIR for function: {}", - ccx.tcx().item_path_str(def_id)) - }; - - let external_mir = if !def_id.is_local() { - ccx.sess().cstore.maybe_get_item_mir(ccx.tcx(), def_id) - } else { - None - }; - - let mir_opt = match external_mir { - Some(ref mir) => Some(mir), - None => { - let node_id = ccx.tcx().map.as_local_node_id(def_id).unwrap(); - ccx.mir_map().get(&node_id) - } - }; - - let mir = errors::expect(ccx.sess().diagnostic(), - mir_opt, - mir_not_found_error_message); + let mir = load_mir(ccx, def_id, mir_cache); let mut visitor = MirNeighborCollector { ccx: ccx, - mir: mir, + mir: mir.get_ref(), output: &mut neighbors, param_substs: param_substs }; - visitor.visit_mir(mir); + visitor.visit_mir(mir.get_ref()); } } for neighbour in neighbors { - collect_items_rec(ccx, neighbour, visited, recursion_depths); + collect_items_rec(ccx, neighbour, visited, recursion_depths, mir_cache); } if let Some((def_id, depth)) = recursion_depth_reset { @@ -388,6 +389,37 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, debug!("END collect_items_rec({})", starting_point.to_string(ccx)); } +fn load_mir<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, + def_id: DefId, + mir_cache: &mut DefIdMap>) + -> CachedMir<'a, 'tcx> { + let mir_not_found_error_message = || { + format!("Could not find MIR for function: {}", + ccx.tcx().item_path_str(def_id)) + }; + + if def_id.is_local() { + let node_id = ccx.tcx().map.as_local_node_id(def_id).unwrap(); + let mir_opt = ccx.mir_map().get(&node_id); + let mir = errors::expect(ccx.sess().diagnostic(), + mir_opt, + mir_not_found_error_message); + CachedMir::Ref(mir) + } else { + if let Some(mir) = mir_cache.get(&def_id) { + return mir.clone(); + } + + let mir_opt = ccx.sess().cstore.maybe_get_item_mir(ccx.tcx(), def_id); + let mir = errors::expect(ccx.sess().diagnostic(), + mir_opt, + mir_not_found_error_message); + let cached = CachedMir::Owned(Rc::new(mir)); + mir_cache.insert(def_id, cached.clone()); + cached + } +} + fn check_recursion_limit<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId, recursion_depths: &mut DefIdMap) @@ -1488,14 +1520,15 @@ pub enum TransItemState { NotPredictedButGenerated, } +pub fn collecting_debug_information(ccx: &CrateContext) -> bool { + return cfg!(debug_assertions) && + ccx.sess().opts.debugging_opts.print_trans_items.is_some(); +} + pub fn print_collection_results<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) { use std::hash::{Hash, SipHasher, Hasher}; - if !cfg!(debug_assertions) { - return; - } - - if ccx.sess().opts.debugging_opts.print_trans_items.is_none() { + if !collecting_debug_information(ccx) { return; } diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index daf36bf8693..0d6324f3e89 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -30,7 +30,7 @@ use middle::def::Def; use middle::def_id::DefId; use trans::{adt, closure, debuginfo, expr, inline, machine}; use trans::base::{self, push_ctxt}; -use trans::collector::TransItem; +use trans::collector::{self, TransItem}; use trans::common::{self, type_is_sized, ExprOrMethodCall, node_id_substs, C_nil, const_get_elt}; use trans::common::{CrateContext, C_integral, C_floating, C_bool, C_str_slice, C_bytes, val_ty}; use trans::common::{C_struct, C_undef, const_to_opt_int, const_to_opt_uint, VariantInfo, C_uint}; @@ -1018,7 +1018,9 @@ pub fn trans_static(ccx: &CrateContext, attrs: &[ast::Attribute]) -> Result { - ccx.record_translation_item_as_generated(TransItem::Static(id)); + if collector::collecting_debug_information(ccx) { + ccx.record_translation_item_as_generated(TransItem::Static(id)); + } unsafe { let _icx = push_ctxt("trans_static"); diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 9073846e2ae..de4867398b9 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -28,7 +28,7 @@ use trans::build::*; use trans::callee; use trans::cleanup; use trans::cleanup::CleanupMethods; -use trans::collector::TransItem; +use trans::collector::{self, TransItem}; use trans::common::*; use trans::debuginfo::DebugLoc; use trans::declare; @@ -498,9 +498,11 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK -> Block<'blk, 'tcx> { let t = g.ty(); - bcx.ccx() - .record_translation_item_as_generated(TransItem::DropGlue(bcx.tcx() - .erase_regions(&t))); + if collector::collecting_debug_information(bcx.ccx()) { + bcx.ccx() + .record_translation_item_as_generated(TransItem::DropGlue(bcx.tcx() + .erase_regions(&t))); + } let skip_dtor = match g { DropGlueKind::Ty(_) => false, DropGlueKind::TyContents(_) => true }; // NB: v0 is an *alias* of type t here, not a direct value.