Add caching of external MIR in trans::collector
This commit is contained in:
parent
862911df9a
commit
9e969808e2
@ -25,7 +25,7 @@
|
||||
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 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// BasicBlock and Terminator
|
||||
|
||||
#[derive(Debug, RustcEncodable, RustcDecodable)]
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct BasicBlockData<'tcx> {
|
||||
pub statements: Vec<Statement<'tcx>>,
|
||||
pub terminator: Option<Terminator<'tcx>>,
|
||||
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 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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>),
|
||||
|
@ -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()
|
||||
|
@ -217,6 +217,7 @@
|
||||
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<mir::Mir<'tcx>>)
|
||||
}
|
||||
|
||||
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<TransItem<'tcx>>,
|
||||
recursion_depths: &mut DefIdMap<usize>) {
|
||||
recursion_depths: &mut DefIdMap<usize>,
|
||||
mir_cache: &mut DefIdMap<CachedMir<'a, 'tcx>>) {
|
||||
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>>)
|
||||
-> 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<usize>)
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
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<ValueRef, ConstEvalErr> {
|
||||
|
||||
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");
|
||||
|
@ -28,7 +28,7 @@
|
||||
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.
|
||||
|
Loading…
Reference in New Issue
Block a user