Skip to content

Commit aec6c85

Browse files
Compute symbol names more lazily.
1 parent 33d5da1 commit aec6c85

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};
@@ -358,7 +358,7 @@ define_maps! { <'tcx>
358358
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
359359

360360
[] fn exported_symbols: ExportedSymbols(CrateNum)
361-
-> Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
361+
-> Arc<Vec<(ExportedSymbol, SymbolExportLevel)>>,
362362
[] fn collect_and_partition_translation_items:
363363
collect_and_partition_translation_items_node(CrateNum)
364364
-> (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
@@ -2806,7 +2806,7 @@ impl<'tcx> DtorckConstraint<'tcx> {
28062806
}
28072807
}
28082808

2809-
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
2809+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
28102810
pub struct SymbolName {
28112811
// FIXME: we don't rely on interning or equality here - better have
28122812
// this be a `&'tcx str`.
@@ -2817,6 +2817,14 @@ impl_stable_hash_for!(struct self::SymbolName {
28172817
name
28182818
});
28192819

2820+
impl SymbolName {
2821+
pub fn new(name: &str) -> SymbolName {
2822+
SymbolName {
2823+
name: Symbol::intern(name).as_str()
2824+
}
2825+
}
2826+
}
2827+
28202828
impl Deref for SymbolName {
28212829
type Target = str;
28222830

@@ -2828,3 +2836,9 @@ impl fmt::Display for SymbolName {
28282836
fmt::Display::fmt(&self.name, fmt)
28292837
}
28302838
}
2839+
2840+
impl fmt::Debug for SymbolName {
2841+
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2842+
fmt::Display::fmt(&self.name, fmt)
2843+
}
2844+
}

src/librustc_trans/back/linker.rs

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

770770
let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
771-
for &(ref name, _, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
771+
for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
772772
if level.is_below_threshold(export_threshold) {
773-
symbols.push(name.clone());
773+
symbols.push(symbol.symbol_name(tcx).to_string());
774774
}
775775
}
776776

@@ -782,9 +782,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
782782
// For each dependency that we are linking to statically ...
783783
if *dep_format == Linkage::Static {
784784
// ... we add its symbol list to our export list.
785-
for &(ref name, _, level) in tcx.exported_symbols(cnum).iter() {
785+
for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
786786
if level.is_below_threshold(export_threshold) {
787-
symbols.push(name.clone());
787+
symbols.push(symbol.symbol_name(tcx).to_string());
788788
}
789789
}
790790
}

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,17 +15,17 @@ 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;
2424
use syntax::attr;
2525

2626
pub type ExportedSymbols = FxHashMap<
2727
CrateNum,
28-
Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
28+
Arc<Vec<(String, SymbolExportLevel)>>,
2929
>;
3030

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

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

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

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

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

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

209215
Arc::new(symbols)
@@ -218,8 +224,7 @@ pub fn provide(providers: &mut Providers) {
218224

219225
fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
220226
cnum: CrateNum)
221-
-> Arc<Vec<(String,
222-
Option<DefId>,
227+
-> Arc<Vec<(ExportedSymbol,
223228
SymbolExportLevel)>>
224229
{
225230
// 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>,
243248
.reachable_non_generics(cnum)
244249
.iter()
245250
.map(|&def_id| {
246-
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
247251
let export_level = if special_runtime_crate {
252+
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
248253
// We can probably do better here by just ensuring that
249254
// it has hidden visibility rather than public
250255
// 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>,
262267
} else {
263268
tcx.symbol_export_level(def_id)
264269
};
265-
debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level);
266-
(str::to_owned(&name), Some(def_id), export_level)
270+
271+
debug!("EXPORTED SYMBOL (re-export): {} ({:?})",
272+
tcx.symbol_name(Instance::mono(tcx, def_id)),
273+
export_level);
274+
275+
(ExportedSymbol::NonGeneric(def_id), export_level)
267276
})
268277
.collect();
269278

270279
// Sort so we get a stable incr. comp. hash.
271-
crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| {
272-
name1.cmp(name2)
280+
crate_exports.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| {
281+
symbol1.compare_stable(tcx, symbol2)
273282
});
274283

275284
Arc::new(crate_exports)

src/librustc_trans/back/write.rs

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

1335-
let exported_symbols = match sess.lto() {
1336-
Lto::No => None,
1337-
Lto::ThinLocal => {
1338-
let mut exported_symbols = FxHashMap();
1339-
exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE));
1340-
Some(Arc::new(exported_symbols))
1341-
}
1342-
Lto::Yes | Lto::Fat | Lto::Thin => {
1343-
let mut exported_symbols = FxHashMap();
1344-
exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE));
1345-
for &cnum in tcx.crates().iter() {
1346-
exported_symbols.insert(cnum, tcx.exported_symbols(cnum));
1335+
// Compute the set of symbols we need to retain when doing LTO (if we need to)
1336+
let exported_symbols = {
1337+
let mut exported_symbols = FxHashMap();
1338+
1339+
let copy_symbols = |cnum| {
1340+
let symbols = tcx.exported_symbols(cnum)
1341+
.iter()
1342+
.map(|&(s, lvl)| (s.symbol_name(tcx).to_string(), lvl))
1343+
.collect();
1344+
Arc::new(symbols)
1345+
};
1346+
1347+
match sess.lto() {
1348+
Lto::No => None,
1349+
Lto::ThinLocal => {
1350+
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
1351+
Some(Arc::new(exported_symbols))
1352+
}
1353+
Lto::Yes | Lto::Fat | Lto::Thin => {
1354+
exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE));
1355+
for &cnum in tcx.crates().iter() {
1356+
exported_symbols.insert(cnum, copy_symbols(cnum));
1357+
}
1358+
Some(Arc::new(exported_symbols))
13471359
}
1348-
Some(Arc::new(exported_symbols))
13491360
}
13501361
};
13511362

0 commit comments

Comments
 (0)