Skip to content

Commit

Permalink
Compute symbol names more lazily.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelwoerister committed Mar 6, 2018
1 parent 33d5da1 commit aec6c85
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 48 deletions.
53 changes: 53 additions & 0 deletions src/librustc/middle/exported_symbols.rs
Expand Up @@ -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.
Expand All @@ -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)
});
4 changes: 2 additions & 2 deletions src/librustc/ty/maps/mod.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -358,7 +358,7 @@ define_maps! { <'tcx>
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,

[] fn exported_symbols: ExportedSymbols(CrateNum)
-> Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
-> Arc<Vec<(ExportedSymbol, SymbolExportLevel)>>,
[] fn collect_and_partition_translation_items:
collect_and_partition_translation_items_node(CrateNum)
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
Expand Down
16 changes: 15 additions & 1 deletion src/librustc/ty/mod.rs
Expand Up @@ -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`.
Expand All @@ -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;

Expand All @@ -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)
}
}
8 changes: 4 additions & 4 deletions src/librustc_trans/back/linker.rs
Expand Up @@ -768,9 +768,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
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());
}
}

Expand All @@ -782,9 +782,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
// 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());
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/back/lto.rs
Expand Up @@ -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());
Expand Down
63 changes: 36 additions & 27 deletions src/librustc_trans/back/symbol_export.rs
Expand Up @@ -15,17 +15,17 @@ 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;
use syntax::attr;

pub type ExportedSymbols = FxHashMap<
CrateNum,
Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
Arc<Vec<(String, SymbolExportLevel)>>,
>;

pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel {
Expand Down Expand Up @@ -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)
}
}
Expand All @@ -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<Vec<(String,
Option<DefId>,
-> Arc<Vec<(ExportedSymbol,
SymbolExportLevel)>>
{
assert_eq!(cnum, LOCAL_CRATE);
Expand Down Expand Up @@ -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)
Expand All @@ -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<Vec<(String,
Option<DefId>,
-> Arc<Vec<(ExportedSymbol,
SymbolExportLevel)>>
{
// If this crate is a plugin and/or a custom derive crate, then
Expand All @@ -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
Expand All @@ -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)
Expand Down
37 changes: 24 additions & 13 deletions src/librustc_trans/back/write.rs
Expand Up @@ -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))
}
};

Expand Down

0 comments on commit aec6c85

Please sign in to comment.