Skip to content

Commit b6d5448

Browse files
Compute symbol names more lazily.
1 parent a9614f9 commit b6d5448

File tree

7 files changed

+135
-48
lines changed

7 files changed

+135
-48
lines changed

src/librustc/middle/exported_symbols.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use hir::def_id::DefId;
12+
use std::cmp;
13+
use ty;
14+
1115
/// The SymbolExportLevel of a symbols specifies from which kinds of crates
1216
/// the symbol will be exported. `C` symbols will be exported from any
1317
/// kind of crate, including cdylibs which export very few things.
@@ -34,3 +38,52 @@ impl SymbolExportLevel {
3438
}
3539
}
3640
}
41+
42+
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
43+
pub enum ExportedSymbol {
44+
NonGeneric(DefId),
45+
NoDefId(ty::SymbolName),
46+
}
47+
48+
impl ExportedSymbol {
49+
pub fn symbol_name(&self, tcx: ty::TyCtxt) -> ty::SymbolName {
50+
match *self {
51+
ExportedSymbol::NonGeneric(def_id) => {
52+
tcx.symbol_name(ty::Instance::mono(tcx, def_id))
53+
}
54+
ExportedSymbol::NoDefId(symbol_name) => {
55+
symbol_name
56+
}
57+
}
58+
}
59+
60+
pub fn compare_stable(&self, tcx: ty::TyCtxt, other: &ExportedSymbol) -> cmp::Ordering {
61+
match *self {
62+
ExportedSymbol::NonGeneric(self_def_id) => {
63+
match *other {
64+
ExportedSymbol::NonGeneric(other_def_id) => {
65+
tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id))
66+
}
67+
ExportedSymbol::NoDefId(_) => {
68+
cmp::Ordering::Less
69+
}
70+
}
71+
}
72+
ExportedSymbol::NoDefId(self_symbol_name) => {
73+
match *other {
74+
ExportedSymbol::NonGeneric(_) => {
75+
cmp::Ordering::Greater
76+
}
77+
ExportedSymbol::NoDefId(ref other_symbol_name) => {
78+
self_symbol_name.cmp(other_symbol_name)
79+
}
80+
}
81+
}
82+
}
83+
}
84+
}
85+
86+
impl_stable_hash_for!(enum self::ExportedSymbol {
87+
NonGeneric(def_id),
88+
NoDefId(symbol_name)
89+
});

src/librustc/ty/maps/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use middle::region;
2626
use middle::resolve_lifetime::{ResolveLifetimes, Region, ObjectLifetimeDefault};
2727
use middle::stability::{self, DeprecationEntry};
2828
use middle::lang_items::{LanguageItems, LangItem};
29-
use middle::exported_symbols::SymbolExportLevel;
29+
use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
3030
use mir::mono::{CodegenUnit, Stats};
3131
use mir;
3232
use session::{CompileResult, CrateDisambiguator};
@@ -359,7 +359,7 @@ define_maps! { <'tcx>
359359
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Rc<Vec<CrateNum>>,
360360

361361
[] fn exported_symbols: ExportedSymbols(CrateNum)
362-
-> Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
362+
-> Arc<Vec<(ExportedSymbol, SymbolExportLevel)>>,
363363
[] fn collect_and_partition_translation_items:
364364
collect_and_partition_translation_items_node(CrateNum)
365365
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),

src/librustc/ty/mod.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2712,7 +2712,7 @@ impl<'tcx> DtorckConstraint<'tcx> {
27122712
}
27132713
}
27142714

2715-
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
2715+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
27162716
pub struct SymbolName {
27172717
// FIXME: we don't rely on interning or equality here - better have
27182718
// this be a `&'tcx str`.
@@ -2723,6 +2723,14 @@ impl_stable_hash_for!(struct self::SymbolName {
27232723
name
27242724
});
27252725

2726+
impl SymbolName {
2727+
pub fn new(name: &str) -> SymbolName {
2728+
SymbolName {
2729+
name: Symbol::intern(name).as_str()
2730+
}
2731+
}
2732+
}
2733+
27262734
impl Deref for SymbolName {
27272735
type Target = str;
27282736

@@ -2734,3 +2742,9 @@ impl fmt::Display for SymbolName {
27342742
fmt::Display::fmt(&self.name, fmt)
27352743
}
27362744
}
2745+
2746+
impl fmt::Debug for SymbolName {
2747+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2748+
fmt::Display::fmt(&self.name, fmt)
2749+
}
2750+
}

src/librustc_trans/back/linker.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -761,9 +761,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
761761
let mut symbols = Vec::new();
762762

763763
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
764-
for &(ref name, _, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
764+
for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
765765
if level.is_below_threshold(export_threshold) {
766-
symbols.push(name.clone());
766+
symbols.push(symbol.symbol_name(tcx).to_string());
767767
}
768768
}
769769

@@ -775,9 +775,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
775775
// For each dependency that we are linking to statically ...
776776
if *dep_format == Linkage::Static {
777777
// ... we add its symbol list to our export list.
778-
for &(ref name, _, level) in tcx.exported_symbols(cnum).iter() {
778+
for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
779779
if level.is_below_threshold(export_threshold) {
780-
symbols.push(name.clone());
780+
symbols.push(symbol.symbol_name(tcx).to_string());
781781
}
782782
}
783783
}

src/librustc_trans/back/lto.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ pub(crate) fn run(cgcx: &CodegenContext,
113113
Lto::No => panic!("didn't request LTO but we're doing LTO"),
114114
};
115115

116-
let symbol_filter = &|&(ref name, _, level): &(String, _, SymbolExportLevel)| {
116+
let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| {
117117
if level.is_below_threshold(export_threshold) {
118118
let mut bytes = Vec::with_capacity(name.len() + 1);
119119
bytes.extend(name.bytes());

src/librustc_trans/back/symbol_export.rs

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ use monomorphize::Instance;
1515
use rustc::hir;
1616
use rustc::hir::def_id::CrateNum;
1717
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
18-
use rustc::middle::exported_symbols::SymbolExportLevel;
18+
use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
1919
use rustc::session::config;
20-
use rustc::ty::TyCtxt;
20+
use rustc::ty::{TyCtxt, SymbolName};
2121
use rustc::ty::maps::Providers;
2222
use rustc::util::nodemap::{FxHashMap, DefIdSet};
2323
use rustc_allocator::ALLOCATOR_METHODS;
@@ -26,7 +26,7 @@ use syntax::attr;
2626

2727
pub type ExportedSymbols = FxHashMap<
2828
CrateNum,
29-
Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
29+
Arc<Vec<(String, SymbolExportLevel)>>,
3030
>;
3131

3232
pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel {
@@ -79,9 +79,10 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
7979
let reachable_non_generics = tcx
8080
.exported_symbols(LOCAL_CRATE)
8181
.iter()
82-
.filter_map(|&(_, opt_def_id, level)| {
83-
if let Some(def_id) = opt_def_id {
84-
if level.is_below_threshold(export_threshold) {
82+
.filter_map(|&(exported_symbol, _)| {
83+
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
84+
if tcx.symbol_export_level(def_id)
85+
.is_below_threshold(export_threshold) {
8586
return Some(def_id)
8687
}
8788
}
@@ -101,8 +102,7 @@ fn is_reachable_non_generic_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
101102

102103
fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
103104
cnum: CrateNum)
104-
-> Arc<Vec<(String,
105-
Option<DefId>,
105+
-> Arc<Vec<(ExportedSymbol,
106106
SymbolExportLevel)>>
107107
{
108108
assert_eq!(cnum, LOCAL_CRATE);
@@ -177,34 +177,40 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
177177
let mut symbols: Vec<_> = reachable_non_generics
178178
.iter()
179179
.map(|&def_id| {
180-
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
181180
let export_level = tcx.symbol_export_level(def_id);
182-
debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level);
183-
(str::to_owned(&name), Some(def_id), export_level)
181+
debug!("EXPORTED SYMBOL (local): {} ({:?})",
182+
tcx.symbol_name(Instance::mono(tcx, def_id)),
183+
export_level);
184+
(ExportedSymbol::NonGeneric(def_id), export_level)
184185
})
185186
.collect();
186187

187188
if let Some(_) = *tcx.sess.entry_fn.borrow() {
188-
symbols.push(("main".to_string(), None, SymbolExportLevel::C));
189+
let symbol_name = "main".to_string();
190+
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
191+
192+
symbols.push((exported_symbol, SymbolExportLevel::C));
189193
}
190194

191195
if tcx.sess.allocator_kind.get().is_some() {
192196
for method in ALLOCATOR_METHODS {
193-
symbols.push((format!("__rust_{}", method.name),
194-
None,
195-
SymbolExportLevel::Rust));
197+
let symbol_name = format!("__rust_{}", method.name);
198+
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
199+
200+
symbols.push((exported_symbol, SymbolExportLevel::Rust));
196201
}
197202
}
198203

199204
if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) {
200-
symbols.push((metadata_symbol_name(tcx),
201-
None,
202-
SymbolExportLevel::Rust));
205+
let symbol_name = metadata_symbol_name(tcx);
206+
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name));
207+
208+
symbols.push((exported_symbol, SymbolExportLevel::Rust));
203209
}
204210

205211
// Sort so we get a stable incr. comp. hash.
206-
symbols.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
207-
name1.cmp(name2)
212+
symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
213+
symbol1.compare_stable(tcx, symbol2)
208214
});
209215

210216
Arc::new(symbols)
@@ -219,8 +225,7 @@ pub fn provide(providers: &mut Providers) {
219225

220226
fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
221227
cnum: CrateNum)
222-
-> Arc<Vec<(String,
223-
Option<DefId>,
228+
-> Arc<Vec<(ExportedSymbol,
224229
SymbolExportLevel)>>
225230
{
226231
// If this crate is a plugin and/or a custom derive crate, then
@@ -255,11 +260,11 @@ fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
255260
.reachable_non_generics(cnum)
256261
.iter()
257262
.map(|&def_id| {
258-
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
259263
let export_level = if compiler_builtins_and_binaryen &&
260264
tcx.contains_extern_indicator(def_id) {
261265
SymbolExportLevel::C
262266
} else if special_runtime_crate {
267+
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
263268
// We can probably do better here by just ensuring that
264269
// it has hidden visibility rather than public
265270
// visibility, as this is primarily here to ensure it's
@@ -277,14 +282,18 @@ fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
277282
} else {
278283
tcx.symbol_export_level(def_id)
279284
};
280-
debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
281-
(str::to_owned(&name), Some(def_id), export_level)
285+
286+
debug!("EXPORTED SYMBOL (re-export): {} ({:?})",
287+
tcx.symbol_name(Instance::mono(tcx, def_id)),
288+
export_level);
289+
290+
(ExportedSymbol::NonGeneric(def_id), export_level)
282291
})
283292
.collect();
284293

285294
// Sort so we get a stable incr. comp. hash.
286-
crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
287-
name1.cmp(name2)
295+
crate_exports.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
296+
symbol1.compare_stable(tcx, symbol2)
288297
});
289298

290299
Arc::new(crate_exports)

src/librustc_trans/back/write.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,20 +1396,31 @@ fn start_executing_work(tcx: TyCtxt,
13961396
let coordinator_send = tcx.tx_to_llvm_workers.clone();
13971397
let sess = tcx.sess;
13981398

1399-
let exported_symbols = match sess.lto() {
1400-
Lto::No => None,
1401-
Lto::ThinLocal => {
1402-
let mut exported_symbols = FxHashMap();
1403-
exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE));
1404-
Some(Arc::new(exported_symbols))
1405-
}
1406-
Lto::Yes | Lto::Fat | Lto::Thin => {
1407-
let mut exported_symbols = FxHashMap();
1408-
exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE));
1409-
for &cnum in tcx.crates().iter() {
1410-
exported_symbols.insert(cnum, tcx.exported_symbols(cnum));
1399+
// Compute the set of symbols we need to retain when doing LTO (if we need to)
1400+
let exported_symbols = {
1401+
let mut exported_symbols = FxHashMap();
1402+
1403+
let copy_symbols = |cnum| {
1404+
let symbols = tcx.exported_symbols(cnum)
1405+
.iter()
1406+
.map(|&(s, lvl)| (s.symbol_name(tcx).to_string(), lvl))
1407+
.collect();
1408+
Arc::new(symbols)
1409+
};
1410+
1411+
match sess.lto() {
1412+
Lto::No => None,
1413+
Lto::ThinLocal => {
1414+
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
1415+
Some(Arc::new(exported_symbols))
1416+
}
1417+
Lto::Yes | Lto::Fat | Lto::Thin => {
1418+
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
1419+
for &cnum in tcx.crates().iter() {
1420+
exported_symbols.insert(cnum, copy_symbols(cnum));
1421+
}
1422+
Some(Arc::new(exported_symbols))
14111423
}
1412-
Some(Arc::new(exported_symbols))
14131424
}
14141425
};
14151426

0 commit comments

Comments
 (0)