From aec6c85b0c6281d938bdd80e98fa9473d8b27780 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 27 Feb 2018 17:52:07 +0100 Subject: [PATCH] Compute symbol names more lazily. --- src/librustc/middle/exported_symbols.rs | 53 ++++++++++++++++++++ src/librustc/ty/maps/mod.rs | 4 +- src/librustc/ty/mod.rs | 16 +++++- src/librustc_trans/back/linker.rs | 8 +-- src/librustc_trans/back/lto.rs | 2 +- src/librustc_trans/back/symbol_export.rs | 63 ++++++++++++++---------- src/librustc_trans/back/write.rs | 37 +++++++++----- 7 files changed, 135 insertions(+), 48 deletions(-) diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs index d650dbe88b5c..c9b3acdd836e 100644 --- a/src/librustc/middle/exported_symbols.rs +++ b/src/librustc/middle/exported_symbols.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::def_id::DefId; +use std::cmp; +use ty; + /// The SymbolExportLevel of a symbols specifies from which kinds of crates /// the symbol will be exported. `C` symbols will be exported from any /// kind of crate, including cdylibs which export very few things. @@ -34,3 +38,52 @@ impl SymbolExportLevel { } } } + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum ExportedSymbol { + NonGeneric(DefId), + NoDefId(ty::SymbolName), +} + +impl ExportedSymbol { + pub fn symbol_name(&self, tcx: ty::TyCtxt) -> ty::SymbolName { + match *self { + ExportedSymbol::NonGeneric(def_id) => { + tcx.symbol_name(ty::Instance::mono(tcx, def_id)) + } + ExportedSymbol::NoDefId(symbol_name) => { + symbol_name + } + } + } + + pub fn compare_stable(&self, tcx: ty::TyCtxt, other: &ExportedSymbol) -> cmp::Ordering { + match *self { + ExportedSymbol::NonGeneric(self_def_id) => { + match *other { + ExportedSymbol::NonGeneric(other_def_id) => { + tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id)) + } + ExportedSymbol::NoDefId(_) => { + cmp::Ordering::Less + } + } + } + ExportedSymbol::NoDefId(self_symbol_name) => { + match *other { + ExportedSymbol::NonGeneric(_) => { + cmp::Ordering::Greater + } + ExportedSymbol::NoDefId(ref other_symbol_name) => { + self_symbol_name.cmp(other_symbol_name) + } + } + } + } + } +} + +impl_stable_hash_for!(enum self::ExportedSymbol { + NonGeneric(def_id), + NoDefId(symbol_name) +}); diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index e91ccce8ffa9..2ef97b2673d6 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -26,7 +26,7 @@ use middle::region; use middle::resolve_lifetime::{ResolveLifetimes, Region, ObjectLifetimeDefault}; use middle::stability::{self, DeprecationEntry}; use middle::lang_items::{LanguageItems, LangItem}; -use middle::exported_symbols::SymbolExportLevel; +use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol}; use mir::mono::{CodegenUnit, Stats}; use mir; use session::{CompileResult, CrateDisambiguator}; @@ -358,7 +358,7 @@ define_maps! { <'tcx> [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc>, [] fn exported_symbols: ExportedSymbols(CrateNum) - -> Arc, SymbolExportLevel)>>, + -> Arc>, [] fn collect_and_partition_translation_items: collect_and_partition_translation_items_node(CrateNum) -> (Arc, Arc>>>), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f6f4e1ceb156..a7c55880e2e1 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2806,7 +2806,7 @@ impl<'tcx> DtorckConstraint<'tcx> { } } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] pub struct SymbolName { // FIXME: we don't rely on interning or equality here - better have // this be a `&'tcx str`. @@ -2817,6 +2817,14 @@ impl_stable_hash_for!(struct self::SymbolName { name }); +impl SymbolName { + pub fn new(name: &str) -> SymbolName { + SymbolName { + name: Symbol::intern(name).as_str() + } + } +} + impl Deref for SymbolName { type Target = str; @@ -2828,3 +2836,9 @@ impl fmt::Display for SymbolName { fmt::Display::fmt(&self.name, fmt) } } + +impl fmt::Debug for SymbolName { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.name, fmt) + } +} diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index a3ff39a47a29..3fe667f15437 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -768,9 +768,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { let mut symbols = Vec::new(); let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); - for &(ref name, _, level) in tcx.exported_symbols(LOCAL_CRATE).iter() { + for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() { if level.is_below_threshold(export_threshold) { - symbols.push(name.clone()); + symbols.push(symbol.symbol_name(tcx).to_string()); } } @@ -782,9 +782,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { // For each dependency that we are linking to statically ... if *dep_format == Linkage::Static { // ... we add its symbol list to our export list. - for &(ref name, _, level) in tcx.exported_symbols(cnum).iter() { + for &(symbol, level) in tcx.exported_symbols(cnum).iter() { if level.is_below_threshold(export_threshold) { - symbols.push(name.clone()); + symbols.push(symbol.symbol_name(tcx).to_string()); } } } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 3f9e9191cf03..f79651cef3ec 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -113,7 +113,7 @@ pub(crate) fn run(cgcx: &CodegenContext, Lto::No => panic!("didn't request LTO but we're doing LTO"), }; - let symbol_filter = &|&(ref name, _, level): &(String, _, SymbolExportLevel)| { + let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| { if level.is_below_threshold(export_threshold) { let mut bytes = Vec::with_capacity(name.len() + 1); bytes.extend(name.bytes()); diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 74f7a6e8d9cd..4e3a37104886 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -15,9 +15,9 @@ use monomorphize::Instance; use rustc::hir; use rustc::hir::def_id::CrateNum; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::middle::exported_symbols::SymbolExportLevel; +use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol}; use rustc::session::config; -use rustc::ty::TyCtxt; +use rustc::ty::{TyCtxt, SymbolName}; use rustc::ty::maps::Providers; use rustc::util::nodemap::{FxHashMap, DefIdSet}; use rustc_allocator::ALLOCATOR_METHODS; @@ -25,7 +25,7 @@ use syntax::attr; pub type ExportedSymbols = FxHashMap< CrateNum, - Arc, SymbolExportLevel)>>, + Arc>, >; pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel { @@ -78,9 +78,10 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let reachable_non_generics = tcx .exported_symbols(LOCAL_CRATE) .iter() - .filter_map(|&(_, opt_def_id, level)| { - if let Some(def_id) = opt_def_id { - if level.is_below_threshold(export_threshold) { + .filter_map(|&(exported_symbol, _)| { + if let ExportedSymbol::NonGeneric(def_id) = exported_symbol { + if tcx.symbol_export_level(def_id) + .is_below_threshold(export_threshold) { return Some(def_id) } } @@ -100,8 +101,7 @@ fn is_reachable_non_generic_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) - -> Arc, + -> Arc> { assert_eq!(cnum, LOCAL_CRATE); @@ -176,34 +176,40 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut symbols: Vec<_> = reachable_non_generics .iter() .map(|&def_id| { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); let export_level = tcx.symbol_export_level(def_id); - debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level); - (str::to_owned(&name), Some(def_id), export_level) + debug!("EXPORTED SYMBOL (local): {} ({:?})", + tcx.symbol_name(Instance::mono(tcx, def_id)), + export_level); + (ExportedSymbol::NonGeneric(def_id), export_level) }) .collect(); if let Some(_) = *tcx.sess.entry_fn.borrow() { - symbols.push(("main".to_string(), None, SymbolExportLevel::C)); + let symbol_name = "main".to_string(); + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); + + symbols.push((exported_symbol, SymbolExportLevel::C)); } if tcx.sess.allocator_kind.get().is_some() { for method in ALLOCATOR_METHODS { - symbols.push((format!("__rust_{}", method.name), - None, - SymbolExportLevel::Rust)); + let symbol_name = format!("__rust_{}", method.name); + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); + + symbols.push((exported_symbol, SymbolExportLevel::Rust)); } } if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) { - symbols.push((metadata_symbol_name(tcx), - None, - SymbolExportLevel::Rust)); + let symbol_name = metadata_symbol_name(tcx); + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); + + symbols.push((exported_symbol, SymbolExportLevel::Rust)); } // Sort so we get a stable incr. comp. hash. - symbols.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| { - name1.cmp(name2) + symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| { + symbol1.compare_stable(tcx, symbol2) }); Arc::new(symbols) @@ -218,8 +224,7 @@ pub fn provide(providers: &mut Providers) { fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) - -> Arc, + -> Arc> { // If this crate is a plugin and/or a custom derive crate, then @@ -243,8 +248,8 @@ fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .reachable_non_generics(cnum) .iter() .map(|&def_id| { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); let export_level = if special_runtime_crate { + let name = tcx.symbol_name(Instance::mono(tcx, def_id)); // We can probably do better here by just ensuring that // it has hidden visibility rather than public // visibility, as this is primarily here to ensure it's @@ -262,14 +267,18 @@ fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } else { tcx.symbol_export_level(def_id) }; - debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level); - (str::to_owned(&name), Some(def_id), export_level) + + debug!("EXPORTED SYMBOL (re-export): {} ({:?})", + tcx.symbol_name(Instance::mono(tcx, def_id)), + export_level); + + (ExportedSymbol::NonGeneric(def_id), export_level) }) .collect(); // Sort so we get a stable incr. comp. hash. - crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| { - name1.cmp(name2) + crate_exports.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| { + symbol1.compare_stable(tcx, symbol2) }); Arc::new(crate_exports) diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 78b26a37485e..c0561ff0c173 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1332,20 +1332,31 @@ fn start_executing_work(tcx: TyCtxt, let coordinator_send = tcx.tx_to_llvm_workers.clone(); let sess = tcx.sess; - let exported_symbols = match sess.lto() { - Lto::No => None, - Lto::ThinLocal => { - let mut exported_symbols = FxHashMap(); - exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE)); - Some(Arc::new(exported_symbols)) - } - Lto::Yes | Lto::Fat | Lto::Thin => { - let mut exported_symbols = FxHashMap(); - exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE)); - for &cnum in tcx.crates().iter() { - exported_symbols.insert(cnum, tcx.exported_symbols(cnum)); + // Compute the set of symbols we need to retain when doing LTO (if we need to) + let exported_symbols = { + let mut exported_symbols = FxHashMap(); + + let copy_symbols = |cnum| { + let symbols = tcx.exported_symbols(cnum) + .iter() + .map(|&(s, lvl)| (s.symbol_name(tcx).to_string(), lvl)) + .collect(); + Arc::new(symbols) + }; + + match sess.lto() { + Lto::No => None, + Lto::ThinLocal => { + exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); + Some(Arc::new(exported_symbols)) + } + Lto::Yes | Lto::Fat | Lto::Thin => { + exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); + for &cnum in tcx.crates().iter() { + exported_symbols.insert(cnum, copy_symbols(cnum)); + } + Some(Arc::new(exported_symbols)) } - Some(Arc::new(exported_symbols)) } };