Skip to content

Commit b977e04

Browse files
committed
Auto merge of #48611 - michaelwoerister:share-generics2, r=alexcrichton
Don't recompute SymbolExportLevel for upstream crates. The data collected in #48373 suggests that we can avoid generating up to 30% of the LLVM definitions by only instantiating function monomorphizations once with a given crate graph. Some more data, collected with a [proof-of-concept implementation](https://github.com/michaelwoerister/rust/commits/share-generics) of re-using monomorphizations, which is less efficient than the MIR-only RLIB approach, suggests that it's still around 25% LLVM definitions that we can save. So far, this PR only cleans up handling of symbol export status. Too early to review still.
2 parents 6f2100b + f5ab4d4 commit b977e04

File tree

26 files changed

+413
-271
lines changed

26 files changed

+413
-271
lines changed

src/librustc/dep_graph/dep_node.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ define_dep_nodes!( <'tcx>
556556
[] RvaluePromotableMap(DefId),
557557
[] ImplParent(DefId),
558558
[] TraitOfItem(DefId),
559-
[] IsExportedSymbol(DefId),
559+
[] IsReachableNonGeneric(DefId),
560560
[] IsMirAvailable(DefId),
561561
[] ItemAttrs(DefId),
562562
[] FnArgNames(DefId),
@@ -574,7 +574,7 @@ define_dep_nodes!( <'tcx>
574574
[] GetPanicStrategy(CrateNum),
575575
[] IsNoBuiltins(CrateNum),
576576
[] ImplDefaultness(DefId),
577-
[] ExportedSymbolIds(CrateNum),
577+
[] ReachableNonGenerics(CrateNum),
578578
[] NativeLibraries(CrateNum),
579579
[] PluginRegistrarFn(CrateNum),
580580
[] DeriveRegistrarFn(CrateNum),

src/librustc/middle/cstore.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ use ich;
3232
use ty::{self, TyCtxt};
3333
use session::{Session, CrateDisambiguator};
3434
use session::search_paths::PathKind;
35-
use util::nodemap::NodeSet;
3635

3736
use std::any::Any;
3837
use std::collections::BTreeMap;
@@ -258,8 +257,7 @@ pub trait CrateStore {
258257
// utility functions
259258
fn encode_metadata<'a, 'tcx>(&self,
260259
tcx: TyCtxt<'a, 'tcx, 'tcx>,
261-
link_meta: &LinkMeta,
262-
reachable: &NodeSet)
260+
link_meta: &LinkMeta)
263261
-> EncodedMetadata;
264262
fn metadata_encoding_version(&self) -> &[u8];
265263
}
@@ -342,8 +340,7 @@ impl CrateStore for DummyCrateStore {
342340
fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
343341
fn encode_metadata<'a, 'tcx>(&self,
344342
tcx: TyCtxt<'a, 'tcx, 'tcx>,
345-
link_meta: &LinkMeta,
346-
reachable: &NodeSet)
343+
link_meta: &LinkMeta)
347344
-> EncodedMetadata {
348345
bug!("encode_metadata")
349346
}

src/librustc/middle/exported_symbols.rs

+60-1
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use hir::def_id::{DefId, LOCAL_CRATE};
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.
1418
/// `Rust` will only be exported if the crate produced is a Rust
1519
/// dylib.
16-
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
20+
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
1721
pub enum SymbolExportLevel {
1822
C,
1923
Rust,
@@ -34,3 +38,58 @@ impl SymbolExportLevel {
3438
}
3539
}
3640
}
41+
42+
#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)]
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+
});
90+
91+
pub fn metadata_symbol_name(tcx: ty::TyCtxt) -> String {
92+
format!("rust_metadata_{}_{}",
93+
tcx.original_crate_name(LOCAL_CRATE),
94+
tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex())
95+
}

src/librustc/ty/context.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use ty::layout::{LayoutDetails, TargetDataLayout};
4646
use ty::maps;
4747
use ty::steal::Steal;
4848
use ty::BindingMode;
49-
use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap};
49+
use util::nodemap::{NodeMap, DefIdSet, ItemLocalMap};
5050
use util::nodemap::{FxHashMap, FxHashSet};
5151
use rustc_data_structures::accumulate_vec::AccumulateVec;
5252
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
@@ -1417,10 +1417,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
14171417
}
14181418

14191419
impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
1420-
pub fn encode_metadata(self, link_meta: &LinkMeta, reachable: &NodeSet)
1420+
pub fn encode_metadata(self, link_meta: &LinkMeta)
14211421
-> EncodedMetadata
14221422
{
1423-
self.cstore.encode_metadata(self, link_meta, reachable)
1423+
self.cstore.encode_metadata(self, link_meta)
14241424
}
14251425
}
14261426

@@ -2460,4 +2460,12 @@ pub fn provide(providers: &mut ty::maps::Providers) {
24602460
assert_eq!(cnum, LOCAL_CRATE);
24612461
Lrc::new(tcx.sess.features_untracked().clone())
24622462
};
2463+
providers.is_panic_runtime = |tcx, cnum| {
2464+
assert_eq!(cnum, LOCAL_CRATE);
2465+
attr::contains_name(tcx.hir.krate_attrs(), "panic_runtime")
2466+
};
2467+
providers.is_compiler_builtins = |tcx, cnum| {
2468+
assert_eq!(cnum, LOCAL_CRATE);
2469+
attr::contains_name(tcx.hir.krate_attrs(), "compiler_builtins")
2470+
};
24632471
}

src/librustc/ty/maps/config.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,9 @@ impl<'tcx> QueryDescription<'tcx> for queries::item_attrs<'tcx> {
212212
}
213213
}
214214

215-
impl<'tcx> QueryDescription<'tcx> for queries::is_exported_symbol<'tcx> {
215+
impl<'tcx> QueryDescription<'tcx> for queries::is_reachable_non_generic<'tcx> {
216216
fn describe(_: TyCtxt, _: DefId) -> String {
217-
bug!("is_exported_symbol")
217+
bug!("is_reachable_non_generic")
218218
}
219219
}
220220

@@ -383,7 +383,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::is_sanitizer_runtime<'tcx> {
383383
}
384384
}
385385

386-
impl<'tcx> QueryDescription<'tcx> for queries::exported_symbol_ids<'tcx> {
386+
impl<'tcx> QueryDescription<'tcx> for queries::reachable_non_generics<'tcx> {
387387
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
388388
format!("looking up the exported symbols of a crate")
389389
}

src/librustc/ty/maps/mod.rs

+19-4
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};
@@ -238,7 +238,6 @@ define_maps! { <'tcx>
238238
[] fn fn_arg_names: FnArgNames(DefId) -> Vec<ast::Name>,
239239
[] fn impl_parent: ImplParent(DefId) -> Option<DefId>,
240240
[] fn trait_of_item: TraitOfItem(DefId) -> Option<DefId>,
241-
[] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool,
242241
[] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies,
243242
[] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool,
244243
[] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc<ItemLocalSet>,
@@ -290,7 +289,23 @@ define_maps! { <'tcx>
290289
[] fn lint_levels: lint_levels_node(CrateNum) -> Lrc<lint::LintLevelMap>,
291290

292291
[] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
293-
[] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Lrc<DefIdSet>,
292+
293+
// The DefIds of all non-generic functions and statics in the given crate
294+
// that can be reached from outside the crate.
295+
//
296+
// We expect this items to be available for being linked to.
297+
//
298+
// This query can also be called for LOCAL_CRATE. In this case it will
299+
// compute which items will be reachable to other crates, taking into account
300+
// the kind of crate that is currently compiled. Crates with only a
301+
// C interface have fewer reachable things.
302+
//
303+
// Does not include external symbols that don't have a corresponding DefId,
304+
// like the compiler-generated `main` function and so on.
305+
[] fn reachable_non_generics: ReachableNonGenerics(CrateNum) -> Lrc<DefIdSet>,
306+
[] fn is_reachable_non_generic: IsReachableNonGeneric(DefId) -> bool,
307+
308+
294309
[] fn native_libraries: NativeLibraries(CrateNum) -> Lrc<Vec<NativeLibrary>>,
295310
[] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
296311
[] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option<DefId>,
@@ -343,7 +358,7 @@ define_maps! { <'tcx>
343358
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
344359

345360
[] fn exported_symbols: ExportedSymbols(CrateNum)
346-
-> Arc<Vec<(String, Option<DefId>, SymbolExportLevel)>>,
361+
-> Arc<Vec<(ExportedSymbol, SymbolExportLevel)>>,
347362
[] fn collect_and_partition_translation_items:
348363
collect_and_partition_translation_items_node(CrateNum)
349364
-> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),

src/librustc/ty/maps/plumbing.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
851851
DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); }
852852
DepKind::ImplParent => { force!(impl_parent, def_id!()); }
853853
DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); }
854-
DepKind::IsExportedSymbol => { force!(is_exported_symbol, def_id!()); }
854+
DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); }
855855
DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); }
856856
DepKind::ItemAttrs => { force!(item_attrs, def_id!()); }
857857
DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); }
@@ -868,7 +868,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
868868
DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); }
869869
DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); }
870870
DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); }
871-
DepKind::ExportedSymbolIds => { force!(exported_symbol_ids, krate!()); }
871+
DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
872872
DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
873873
DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
874874
DepKind::DeriveRegistrarFn => { force!(derive_registrar_fn, krate!()); }

src/librustc/ty/mod.rs

+15-1
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_metadata/creader.rs

-4
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,6 @@ impl<'a> CrateLoader<'a> {
225225
crate_root.def_path_table.decode((&metadata, self.sess))
226226
});
227227

228-
let exported_symbols = crate_root.exported_symbols
229-
.decode((&metadata, self.sess))
230-
.collect();
231228
let trait_impls = crate_root
232229
.impls
233230
.decode((&metadata, self.sess))
@@ -238,7 +235,6 @@ impl<'a> CrateLoader<'a> {
238235
name,
239236
extern_crate: Cell::new(None),
240237
def_path_table: Lrc::new(def_path_table),
241-
exported_symbols,
242238
trait_impls,
243239
proc_macros: crate_root.macro_derive_registrar.map(|_| {
244240
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)

src/librustc_metadata/cstore.rs

-2
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@ pub struct CrateMetadata {
7878
/// compilation support.
7979
pub def_path_table: Lrc<DefPathTable>,
8080

81-
pub exported_symbols: FxHashSet<DefIndex>,
82-
8381
pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,
8482

8583
pub dep_kind: Cell<DepKind>,

src/librustc_metadata/cstore_impl.rs

+33-8
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc::ty::maps::QueryConfig;
1818
use rustc::middle::cstore::{CrateStore, DepKind,
1919
MetadataLoader, LinkMeta,
2020
LoadedMacro, EncodedMetadata, NativeLibraryKind};
21+
use rustc::middle::exported_symbols::ExportedSymbol;
2122
use rustc::middle::stability::DeprecationEntry;
2223
use rustc::hir::def;
2324
use rustc::session::{CrateDisambiguator, Session};
@@ -27,10 +28,11 @@ use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
2728
use rustc::hir::map::{DefKey, DefPath, DefPathHash};
2829
use rustc::hir::map::blocks::FnLikeNode;
2930
use rustc::hir::map::definitions::DefPathTable;
30-
use rustc::util::nodemap::{NodeSet, DefIdMap};
31+
use rustc::util::nodemap::DefIdMap;
3132

3233
use std::any::Any;
3334
use rustc_data_structures::sync::Lrc;
35+
use std::sync::Arc;
3436

3537
use syntax::ast;
3638
use syntax::attr;
@@ -160,9 +162,6 @@ provide! { <'tcx> tcx, def_id, other, cdata,
160162
fn_arg_names => { cdata.get_fn_arg_names(def_id.index) }
161163
impl_parent => { cdata.get_parent_impl(def_id.index) }
162164
trait_of_item => { cdata.get_trait_of_item(def_id.index) }
163-
is_exported_symbol => {
164-
cdata.exported_symbols.contains(&def_id.index)
165-
}
166165
item_body_nested_bodies => { cdata.item_body_nested_bodies(def_id.index) }
167166
const_is_rvalue_promotable_to_static => {
168167
cdata.const_is_rvalue_promotable_to_static(def_id.index)
@@ -179,7 +178,21 @@ provide! { <'tcx> tcx, def_id, other, cdata,
179178
extern_crate => { Lrc::new(cdata.extern_crate.get()) }
180179
is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
181180
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
182-
exported_symbol_ids => { Lrc::new(cdata.get_exported_symbols()) }
181+
reachable_non_generics => {
182+
let reachable_non_generics = tcx
183+
.exported_symbols(cdata.cnum)
184+
.iter()
185+
.filter_map(|&(exported_symbol, _)| {
186+
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
187+
return Some(def_id)
188+
} else {
189+
None
190+
}
191+
})
192+
.collect();
193+
194+
Lrc::new(reachable_non_generics)
195+
}
183196
native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) }
184197
plugin_registrar_fn => {
185198
cdata.root.plugin_registrar_fn.map(|index| {
@@ -238,6 +251,19 @@ provide! { <'tcx> tcx, def_id, other, cdata,
238251

239252
has_copy_closures => { cdata.has_copy_closures(tcx.sess) }
240253
has_clone_closures => { cdata.has_clone_closures(tcx.sess) }
254+
255+
exported_symbols => {
256+
let cnum = cdata.cnum;
257+
assert!(cnum != LOCAL_CRATE);
258+
259+
// If this crate is a custom derive crate, then we're not even going to
260+
// link those in so we skip those crates.
261+
if cdata.root.macro_derive_registrar.is_some() {
262+
return Arc::new(Vec::new())
263+
}
264+
265+
Arc::new(cdata.exported_symbols())
266+
}
241267
}
242268

243269
pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
@@ -520,11 +546,10 @@ impl CrateStore for cstore::CStore {
520546

521547
fn encode_metadata<'a, 'tcx>(&self,
522548
tcx: TyCtxt<'a, 'tcx, 'tcx>,
523-
link_meta: &LinkMeta,
524-
reachable: &NodeSet)
549+
link_meta: &LinkMeta)
525550
-> EncodedMetadata
526551
{
527-
encoder::encode_metadata(tcx, link_meta, reachable)
552+
encoder::encode_metadata(tcx, link_meta)
528553
}
529554

530555
fn metadata_encoding_version(&self) -> &[u8]

0 commit comments

Comments
 (0)