about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2018-02-27 17:52:07 +0100
committerMichael Woerister <michaelwoerister@posteo>2018-03-06 09:47:43 +0100
commitaec6c85b0c6281d938bdd80e98fa9473d8b27780 (patch)
tree7092d404bb5e66fc1462d6808272457a6c516724
parent33d5da1ee400e4b1b85a6a3f0c552ce68c665500 (diff)
downloadrust-aec6c85b0c6281d938bdd80e98fa9473d8b27780.tar.gz
rust-aec6c85b0c6281d938bdd80e98fa9473d8b27780.zip
Compute symbol names more lazily.
-rw-r--r--src/librustc/middle/exported_symbols.rs53
-rw-r--r--src/librustc/ty/maps/mod.rs4
-rw-r--r--src/librustc/ty/mod.rs16
-rw-r--r--src/librustc_trans/back/linker.rs8
-rw-r--r--src/librustc_trans/back/lto.rs2
-rw-r--r--src/librustc_trans/back/symbol_export.rs63
-rw-r--r--src/librustc_trans/back/write.rs37
7 files changed, 135 insertions, 48 deletions
diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs
index d650dbe88b5..c9b3acdd836 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 e91ccce8ffa..2ef97b2673d 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<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>>>>),
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index f6f4e1ceb15..a7c55880e2e 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 a3ff39a47a2..3fe667f1543 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<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());
         }
     }
 
@@ -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());
                 }
             }
         }
diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs
index 3f9e9191cf0..f79651cef3e 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 74f7a6e8d9c..4e3a3710488 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<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
+    Arc<Vec<(String, SymbolExportLevel)>>,
 >;
 
 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<Vec<(String,
-                                                         Option<DefId>,
+                                             -> Arc<Vec<(ExportedSymbol,
                                                          SymbolExportLevel)>>
 {
     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<Vec<(String,
-                                                          Option<DefId>,
+                                              -> Arc<Vec<(ExportedSymbol,
                                                           SymbolExportLevel)>>
 {
     // 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 78b26a37485..c0561ff0c17 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))
         }
     };