rustc: Remove another global map from trans

This commit removes the `crate_trans_items` field from the `CrateContext` of
trans. This field, a big map, was calculated during partioning and was a set of
all translation items. This isn't quite incremental-friendly because the map may
change a lot but not have much effect on downstream consumers.

Instead a new query was added for the one location this map was needed, along
with a new comment explaining what the location is doing!
This commit is contained in:
Alex Crichton 2017-09-13 15:24:13 -07:00
parent 19727c84dd
commit 2eada58706
6 changed files with 76 additions and 31 deletions

View File

@ -579,6 +579,7 @@ define_dep_nodes!( <'tcx>
[] CollectAndPartitionTranslationItems, [] CollectAndPartitionTranslationItems,
[] ExportName(DefId), [] ExportName(DefId),
[] ContainsExternIndicator(DefId), [] ContainsExternIndicator(DefId),
[] IsTranslatedFunction(DefId),
); );
trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {

View File

@ -24,7 +24,7 @@ use middle::resolve_lifetime::{Region, ObjectLifetimeDefault};
use middle::stability::{self, DeprecationEntry}; use middle::stability::{self, DeprecationEntry};
use middle::lang_items::{LanguageItems, LangItem}; use middle::lang_items::{LanguageItems, LangItem};
use middle::exported_symbols::SymbolExportLevel; use middle::exported_symbols::SymbolExportLevel;
use middle::trans::{TransItem, CodegenUnit}; use middle::trans::CodegenUnit;
use mir; use mir;
use mir::transform::{MirSuite, MirPassIndex}; use mir::transform::{MirSuite, MirPassIndex};
use session::CompileResult; use session::CompileResult;
@ -1391,9 +1391,10 @@ define_maps! { <'tcx>
-> Arc<Vec<(String, DefId, SymbolExportLevel)>>, -> Arc<Vec<(String, DefId, SymbolExportLevel)>>,
[] fn collect_and_partition_translation_items: [] fn collect_and_partition_translation_items:
collect_and_partition_translation_items_node(CrateNum) collect_and_partition_translation_items_node(CrateNum)
-> (Arc<FxHashSet<TransItem<'tcx>>>, Vec<Arc<CodegenUnit<'tcx>>>), -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
[] fn export_name: ExportName(DefId) -> Option<Symbol>, [] fn export_name: ExportName(DefId) -> Option<Symbol>,
[] fn contains_extern_indicator: ContainsExternIndicator(DefId) -> bool, [] fn contains_extern_indicator: ContainsExternIndicator(DefId) -> bool,
[] fn is_translated_function: IsTranslatedFunction(DefId) -> bool,
} }
fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> { fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {

View File

@ -35,7 +35,7 @@ use back::write::{self, OngoingCrateTranslation};
use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param}; use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param};
use llvm; use llvm;
use metadata; use metadata;
use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::lang_items::StartFnLangItem;
use rustc::middle::trans::{Linkage, Visibility}; use rustc::middle::trans::{Linkage, Visibility};
use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes}; use rustc::middle::cstore::{EncodedMetadata, EncodedMetadataHashes};
@ -75,7 +75,7 @@ use trans_item::{TransItem, TransItemExt, DefPathBasedNames};
use type_::Type; use type_::Type;
use type_of; use type_of;
use value::Value; use value::Value;
use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet}; use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet, DefIdSet};
use CrateInfo; use CrateInfo;
use libc::c_uint; use libc::c_uint;
@ -990,8 +990,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Run the translation item collector and partition the collected items into // Run the translation item collector and partition the collected items into
// codegen units. // codegen units.
let (translation_items, codegen_units) = let codegen_units =
shared_ccx.tcx().collect_and_partition_translation_items(LOCAL_CRATE); shared_ccx.tcx().collect_and_partition_translation_items(LOCAL_CRATE).1;
let codegen_units = (*codegen_units).clone();
assert!(codegen_units.len() <= 1 || !tcx.sess.lto()); assert!(codegen_units.len() <= 1 || !tcx.sess.lto());
@ -1076,8 +1077,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let ((stats, module), _) = let ((stats, module), _) =
tcx.dep_graph.with_task(dep_node, tcx.dep_graph.with_task(dep_node,
AssertDepGraphSafe(&shared_ccx), AssertDepGraphSafe(&shared_ccx),
AssertDepGraphSafe((cgu, AssertDepGraphSafe(cgu),
translation_items.clone())),
module_translation); module_translation);
all_stats.extend(stats); all_stats.extend(stats);
@ -1118,13 +1118,12 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn module_translation<'a, 'tcx>( fn module_translation<'a, 'tcx>(
scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>, scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>,
args: AssertDepGraphSafe<(Arc<CodegenUnit<'tcx>>, args: AssertDepGraphSafe<Arc<CodegenUnit<'tcx>>>)
Arc<FxHashSet<TransItem<'tcx>>>)>)
-> (Stats, ModuleTranslation) -> (Stats, ModuleTranslation)
{ {
// FIXME(#40304): We ought to be using the id as a key and some queries, I think. // FIXME(#40304): We ought to be using the id as a key and some queries, I think.
let AssertDepGraphSafe(scx) = scx; let AssertDepGraphSafe(scx) = scx;
let AssertDepGraphSafe((cgu, crate_trans_items)) = args; let AssertDepGraphSafe(cgu) = args;
let cgu_name = cgu.name().to_string(); let cgu_name = cgu.name().to_string();
let cgu_id = cgu.work_product_id(); let cgu_id = cgu.work_product_id();
@ -1164,7 +1163,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
} }
// Instantiate translation items without filling out definitions yet... // Instantiate translation items without filling out definitions yet...
let lcx = LocalCrateContext::new(scx, cgu, crate_trans_items); let lcx = LocalCrateContext::new(scx, cgu);
let module = { let module = {
let ccx = CrateContext::new(scx, &lcx); let ccx = CrateContext::new(scx, &lcx);
let trans_items = ccx.codegen_unit() let trans_items = ccx.codegen_unit()
@ -1353,7 +1352,7 @@ fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trans_i
fn collect_and_partition_translation_items<'a, 'tcx>( fn collect_and_partition_translation_items<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
cnum: CrateNum, cnum: CrateNum,
) -> (Arc<FxHashSet<TransItem<'tcx>>>, Vec<Arc<CodegenUnit<'tcx>>>) ) -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>)
{ {
assert_eq!(cnum, LOCAL_CRATE); assert_eq!(cnum, LOCAL_CRATE);
let time_passes = tcx.sess.time_passes(); let time_passes = tcx.sess.time_passes();
@ -1404,7 +1403,12 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
assert!(tcx.sess.opts.cg.codegen_units == codegen_units.len() || assert!(tcx.sess.opts.cg.codegen_units == codegen_units.len() ||
tcx.sess.opts.debugging_opts.incremental.is_some()); tcx.sess.opts.debugging_opts.incremental.is_some());
let translation_items: FxHashSet<TransItem<'tcx>> = items.iter().cloned().collect(); let translation_items: DefIdSet = items.iter().filter_map(|trans_item| {
match *trans_item {
TransItem::Fn(ref instance) => Some(instance.def_id()),
_ => None,
}
}).collect();
if tcx.sess.opts.debugging_opts.print_trans_items.is_some() { if tcx.sess.opts.debugging_opts.print_trans_items.is_some() {
let mut item_to_cgus = FxHashMap(); let mut item_to_cgus = FxHashMap();
@ -1459,7 +1463,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(
} }
} }
(Arc::new(translation_items), codegen_units) (Arc::new(translation_items), Arc::new(codegen_units))
} }
impl CrateInfo { impl CrateInfo {
@ -1505,9 +1509,25 @@ impl CrateInfo {
} }
} }
pub fn provide(providers: &mut Providers) { fn is_translated_function(tcx: TyCtxt, id: DefId) -> bool {
// FIXME(#42293) needs red/green tracking to avoid failing a bunch of
// existing tests
tcx.dep_graph.with_ignore(|| {
let (all_trans_items, _) =
tcx.collect_and_partition_translation_items(LOCAL_CRATE);
all_trans_items.contains(&id)
})
}
pub fn provide_local(providers: &mut Providers) {
providers.collect_and_partition_translation_items = providers.collect_and_partition_translation_items =
collect_and_partition_translation_items; collect_and_partition_translation_items;
providers.is_translated_function = is_translated_function;
}
pub fn provide_extern(providers: &mut Providers) {
providers.is_translated_function = is_translated_function;
} }
pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { pub fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage {

View File

@ -23,7 +23,6 @@ use monomorphize::{self, Instance};
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::ty::TypeFoldable; use rustc::ty::TypeFoldable;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use trans_item::TransItem;
use type_of; use type_of;
/// Translates a reference to a fn/method item, monomorphizing and /// Translates a reference to a fn/method item, monomorphizing and
@ -109,10 +108,43 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
attributes::unwind(llfn, true); attributes::unwind(llfn, true);
} }
// Apply an appropriate linkage/visibility value to our item that we
// just declared.
//
// This is sort of subtle. Inside our codegen unit we started off
// compilation by predefining all our own `TransItem` instances. That
// is, everything we're translating ourselves is already defined. That
// means that anything we're actually translating ourselves will have
// hit the above branch in `get_declared_value`. As a result, we're
// guaranteed here that we're declaring a symbol that won't get defined,
// or in other words we're referencing a foreign value.
//
// So because this is a foreign value we blanket apply an external
// linkage directive because it's coming from a different object file.
// The visibility here is where it gets tricky. This symbol could be
// referencing some foreign crate or foreign library (an `extern`
// block) in which case we want to leave the default visibility. We may
// also, though, have multiple codegen units.
//
// In the situation of multiple codegen units this function may be
// referencing a function from another codegen unit. If we're
// indeed referencing a symbol in another codegen unit then we're in one
// of two cases:
//
// * This is a symbol defined in a foreign crate and we're just
// monomorphizing in another codegen unit. In this case this symbols
// is for sure not exported, so both codegen units will be using
// hidden visibility. Hence, we apply a hidden visibility here.
//
// * This is a symbol defined in our local crate. If the symbol in the
// other codegen unit is also not exported then like with the foreign
// case we apply a hidden visibility. If the symbol is exported from
// the foreign object file, however, then we leave this at the
// default visibility as we'll just import it naturally.
unsafe { unsafe {
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage); llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
if ccx.crate_trans_items().contains(&TransItem::Fn(instance)) { if ccx.tcx().is_translated_function(instance_def_id) {
if instance_def_id.is_local() { if instance_def_id.is_local() {
if !ccx.tcx().is_exported_symbol(instance_def_id) { if !ccx.tcx().is_exported_symbol(instance_def_id) {
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);

View File

@ -22,14 +22,13 @@ use declare;
use monomorphize::Instance; use monomorphize::Instance;
use partitioning::CodegenUnit; use partitioning::CodegenUnit;
use trans_item::TransItem;
use type_::Type; use type_::Type;
use rustc_data_structures::base_n; use rustc_data_structures::base_n;
use rustc::session::config::{self, NoDebugInfo, OutputFilenames}; use rustc::session::config::{self, NoDebugInfo, OutputFilenames};
use rustc::session::Session; use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout}; use rustc::ty::layout::{LayoutCx, LayoutError, LayoutTyper, TyLayout};
use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc::util::nodemap::FxHashMap;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
@ -94,9 +93,6 @@ pub struct LocalCrateContext<'a, 'tcx: 'a> {
stats: Stats, stats: Stats,
codegen_unit: Arc<CodegenUnit<'tcx>>, codegen_unit: Arc<CodegenUnit<'tcx>>,
/// The translation items of the whole crate.
crate_trans_items: Arc<FxHashSet<TransItem<'tcx>>>,
/// Cache instances of monomorphic and polymorphic items /// Cache instances of monomorphic and polymorphic items
instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>, instances: RefCell<FxHashMap<Instance<'tcx>, ValueRef>>,
/// Cache generated vtables /// Cache generated vtables
@ -349,8 +345,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> { impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
pub fn new(shared: &SharedCrateContext<'a, 'tcx>, pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
codegen_unit: Arc<CodegenUnit<'tcx>>, codegen_unit: Arc<CodegenUnit<'tcx>>)
crate_trans_items: Arc<FxHashSet<TransItem<'tcx>>>)
-> LocalCrateContext<'a, 'tcx> { -> LocalCrateContext<'a, 'tcx> {
unsafe { unsafe {
// Append ".rs" to LLVM module identifier. // Append ".rs" to LLVM module identifier.
@ -382,7 +377,6 @@ impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
llcx, llcx,
stats: Stats::default(), stats: Stats::default(),
codegen_unit, codegen_unit,
crate_trans_items,
instances: RefCell::new(FxHashMap()), instances: RefCell::new(FxHashMap()),
vtables: RefCell::new(FxHashMap()), vtables: RefCell::new(FxHashMap()),
const_cstr_cache: RefCell::new(FxHashMap()), const_cstr_cache: RefCell::new(FxHashMap()),
@ -489,10 +483,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.local().codegen_unit &self.local().codegen_unit
} }
pub fn crate_trans_items(&self) -> &FxHashSet<TransItem<'tcx>> {
&self.local().crate_trans_items
}
pub fn td(&self) -> llvm::TargetDataRef { pub fn td(&self) -> llvm::TargetDataRef {
unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) } unsafe { llvm::LLVMRustGetModuleDataLayout(self.llmod()) }
} }

View File

@ -251,10 +251,11 @@ __build_diagnostic_array! { librustc_trans, DIAGNOSTICS }
pub fn provide_local(providers: &mut Providers) { pub fn provide_local(providers: &mut Providers) {
back::symbol_names::provide(providers); back::symbol_names::provide(providers);
back::symbol_export::provide_local(providers); back::symbol_export::provide_local(providers);
base::provide(providers); base::provide_local(providers);
} }
pub fn provide_extern(providers: &mut Providers) { pub fn provide_extern(providers: &mut Providers) {
back::symbol_names::provide(providers); back::symbol_names::provide(providers);
back::symbol_export::provide_extern(providers); back::symbol_export::provide_extern(providers);
base::provide_extern(providers);
} }