Skip to content

Commit aa10411

Browse files
committed
Split exported_symbols for generic and non-generic symbols
This reduces metadata decoder overhead during the monomorphization collector.
1 parent a17780d commit aa10411

File tree

10 files changed

+83
-48
lines changed

10 files changed

+83
-48
lines changed

compiler/rustc_codegen_ssa/src/back/linker.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1794,7 +1794,10 @@ fn for_each_exported_symbols_include_dep<'tcx>(
17941794
for (cnum, dep_format) in deps.iter_enumerated() {
17951795
// For each dependency that we are linking to statically ...
17961796
if *dep_format == Linkage::Static {
1797-
for &(symbol, info) in tcx.exported_symbols(cnum).iter() {
1797+
for &(symbol, info) in tcx.exported_non_generic_symbols(cnum).iter() {
1798+
callback(symbol, info, cnum);
1799+
}
1800+
for &(symbol, info) in tcx.exported_generic_symbols(cnum).iter() {
17981801
callback(symbol, info, cnum);
17991802
}
18001803
}

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,8 @@ fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> b
164164
tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
165165
}
166166

167-
fn exported_symbols_provider_local<'tcx>(
167+
// FIXME maybe split into two functions
168+
fn exported_symbols_provider_local<'tcx, const GENERIC: bool>(
168169
tcx: TyCtxt<'tcx>,
169170
_: LocalCrate,
170171
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
@@ -174,15 +175,19 @@ fn exported_symbols_provider_local<'tcx>(
174175

175176
// FIXME: Sorting this is unnecessary since we are sorting later anyway.
176177
// Can we skip the later sorting?
177-
let sorted = tcx.with_stable_hashing_context(|hcx| {
178-
tcx.reachable_non_generics(LOCAL_CRATE).to_sorted(&hcx, true)
179-
});
178+
let sorted = if GENERIC {
179+
vec![]
180+
} else {
181+
tcx.with_stable_hashing_context(|hcx| {
182+
tcx.reachable_non_generics(LOCAL_CRATE).to_sorted(&hcx, true)
183+
})
184+
};
180185

181186
let mut symbols: Vec<_> =
182187
sorted.iter().map(|&(&def_id, &info)| (ExportedSymbol::NonGeneric(def_id), info)).collect();
183188

184189
// Export TLS shims
185-
if !tcx.sess.target.dll_tls_export {
190+
if !GENERIC && !tcx.sess.target.dll_tls_export {
186191
symbols.extend(sorted.iter().filter_map(|&(&def_id, &info)| {
187192
tcx.needs_thread_local_shim(def_id).then(|| {
188193
(
@@ -197,7 +202,7 @@ fn exported_symbols_provider_local<'tcx>(
197202
}))
198203
}
199204

200-
if tcx.entry_fn(()).is_some() {
205+
if !GENERIC && tcx.entry_fn(()).is_some() {
201206
let exported_symbol =
202207
ExportedSymbol::NoDefId(SymbolName::new(tcx, tcx.sess.target.entry_name.as_ref()));
203208

@@ -212,7 +217,7 @@ fn exported_symbols_provider_local<'tcx>(
212217
}
213218

214219
// Mark allocator shim symbols as exported only if they were generated.
215-
if allocator_kind_for_codegen(tcx).is_some() {
220+
if !GENERIC && allocator_kind_for_codegen(tcx).is_some() {
216221
for symbol_name in ALLOCATOR_METHODS
217222
.iter()
218223
.map(|method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
@@ -235,7 +240,7 @@ fn exported_symbols_provider_local<'tcx>(
235240
}
236241
}
237242

238-
if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() {
243+
if !GENERIC && tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() {
239244
// These are weak symbols that point to the profile version and the
240245
// profile name, which need to be treated as exported so LTO doesn't nix
241246
// them.
@@ -255,7 +260,7 @@ fn exported_symbols_provider_local<'tcx>(
255260
}));
256261
}
257262

258-
if tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
263+
if !GENERIC && tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) {
259264
let mut msan_weak_symbols = Vec::new();
260265

261266
// Similar to profiling, preserve weak msan symbol during LTO.
@@ -280,8 +285,9 @@ fn exported_symbols_provider_local<'tcx>(
280285
}));
281286
}
282287

283-
if tcx.crate_types().contains(&CrateType::Dylib)
284-
|| tcx.crate_types().contains(&CrateType::ProcMacro)
288+
if !GENERIC
289+
&& (tcx.crate_types().contains(&CrateType::Dylib)
290+
|| tcx.crate_types().contains(&CrateType::ProcMacro))
285291
{
286292
let symbol_name = metadata_symbol_name(tcx);
287293
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(tcx, &symbol_name));
@@ -296,7 +302,7 @@ fn exported_symbols_provider_local<'tcx>(
296302
));
297303
}
298304

299-
if tcx.local_crate_exports_generics() {
305+
if GENERIC && tcx.local_crate_exports_generics() {
300306
use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
301307
use rustc_middle::ty::InstanceKind;
302308

@@ -458,7 +464,7 @@ fn upstream_monomorphizations_provider(
458464
let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn();
459465

460466
for &cnum in cnums.iter() {
461-
for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
467+
for (exported_symbol, _) in tcx.exported_generic_symbols(cnum).iter() {
462468
let (def_id, args) = match *exported_symbol {
463469
ExportedSymbol::Generic(def_id, args) => (def_id, args),
464470
ExportedSymbol::DropGlue(ty) => {
@@ -480,10 +486,7 @@ fn upstream_monomorphizations_provider(
480486
ExportedSymbol::AsyncDropGlue(def_id, ty) => (def_id, tcx.mk_args(&[ty.into()])),
481487
ExportedSymbol::NonGeneric(..)
482488
| ExportedSymbol::ThreadLocalShim(..)
483-
| ExportedSymbol::NoDefId(..) => {
484-
// These are no monomorphizations
485-
continue;
486-
}
489+
| ExportedSymbol::NoDefId(..) => unreachable!(),
487490
};
488491

489492
let args_map = instances.entry(def_id).or_default();
@@ -538,7 +541,8 @@ fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId)
538541
pub(crate) fn provide(providers: &mut Providers) {
539542
providers.reachable_non_generics = reachable_non_generics_provider;
540543
providers.is_reachable_non_generic = is_reachable_non_generic_provider_local;
541-
providers.exported_symbols = exported_symbols_provider_local;
544+
providers.exported_non_generic_symbols = exported_symbols_provider_local::<false>;
545+
providers.exported_generic_symbols = exported_symbols_provider_local::<true>;
542546
providers.upstream_monomorphizations = upstream_monomorphizations_provider;
543547
providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
544548
providers.upstream_drop_glue_for = upstream_drop_glue_for_provider;

compiler/rustc_codegen_ssa/src/back/write.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1124,8 +1124,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
11241124

11251125
let copy_symbols = |cnum| {
11261126
let symbols = tcx
1127-
.exported_symbols(cnum)
1127+
.exported_non_generic_symbols(cnum)
11281128
.iter()
1129+
.chain(tcx.exported_generic_symbols(cnum))
11291130
.map(|&(s, lvl)| (symbol_name_for_instance_in_crate(tcx, s, cnum), lvl))
11301131
.collect();
11311132
Arc::new(symbols)

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1496,11 +1496,18 @@ impl<'a> CrateMetadataRef<'a> {
14961496
.map(move |v| (self.local_def_id(v.0), v.1))
14971497
}
14981498

1499-
fn exported_symbols<'tcx>(
1499+
fn exported_non_generic_symbols<'tcx>(
15001500
self,
15011501
tcx: TyCtxt<'tcx>,
15021502
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
1503-
tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx)))
1503+
tcx.arena.alloc_from_iter(self.root.exported_non_generic_symbols.decode((self, tcx)))
1504+
}
1505+
1506+
fn exported_generic_symbols<'tcx>(
1507+
self,
1508+
tcx: TyCtxt<'tcx>,
1509+
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
1510+
tcx.arena.alloc_from_iter(self.root.exported_generic_symbols.decode((self, tcx)))
15041511
}
15051512

15061513
fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ provide! { tcx, def_id, other, cdata,
358358
specialization_enabled_in => { cdata.root.specialization_enabled_in }
359359
reachable_non_generics => {
360360
let reachable_non_generics = tcx
361-
.exported_symbols(cdata.cnum)
361+
.exported_non_generic_symbols(cdata.cnum)
362362
.iter()
363363
.filter_map(|&(exported_symbol, export_info)| {
364364
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
@@ -408,15 +408,8 @@ provide! { tcx, def_id, other, cdata,
408408

409409
exportable_items => { tcx.arena.alloc_from_iter(cdata.get_exportable_items()) }
410410
stable_order_of_exportable_impls => { tcx.arena.alloc(cdata.get_stable_order_of_exportable_impls().collect()) }
411-
exported_symbols => {
412-
let syms = cdata.exported_symbols(tcx);
413-
414-
// FIXME rust-lang/rust#64319, rust-lang/rust#64872: We want
415-
// to block export of generics from dylibs, but we must fix
416-
// rust-lang/rust#65890 before we can do that robustly.
417-
418-
syms
419-
}
411+
exported_non_generic_symbols => { cdata.exported_non_generic_symbols(tcx) }
412+
exported_generic_symbols => { cdata.exported_generic_symbols(tcx) }
420413

421414
crate_extern_paths => { cdata.source().paths().cloned().collect() }
422415
expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -677,9 +677,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
677677
stat!("exportable-items", || self.encode_stable_order_of_exportable_impls());
678678

679679
// Encode exported symbols info. This is prefetched in `encode_metadata`.
680-
let exported_symbols = stat!("exported-symbols", || {
681-
self.encode_exported_symbols(tcx.exported_symbols(LOCAL_CRATE))
682-
});
680+
let (exported_non_generic_symbols, exported_generic_symbols) =
681+
stat!("exported-symbols", || {
682+
(
683+
self.encode_exported_symbols(tcx.exported_non_generic_symbols(LOCAL_CRATE)),
684+
self.encode_exported_symbols(tcx.exported_generic_symbols(LOCAL_CRATE)),
685+
)
686+
});
683687

684688
// Encode the hygiene data.
685689
// IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The
@@ -745,7 +749,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
745749
incoherent_impls,
746750
exportable_items,
747751
stable_order_of_exportable_impls,
748-
exported_symbols,
752+
exported_non_generic_symbols,
753+
exported_generic_symbols,
749754
interpret_alloc_index,
750755
tables,
751756
syntax_contexts,
@@ -2356,7 +2361,13 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
23562361
// Prefetch some queries used by metadata encoding.
23572362
// This is not necessary for correctness, but is only done for performance reasons.
23582363
// It can be removed if it turns out to cause trouble or be detrimental to performance.
2359-
join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
2364+
join(
2365+
|| prefetch_mir(tcx),
2366+
|| {
2367+
let _ = tcx.exported_non_generic_symbols(LOCAL_CRATE);
2368+
let _ = tcx.exported_generic_symbols(LOCAL_CRATE);
2369+
},
2370+
);
23602371
}
23612372

23622373
with_encode_metadata_header(tcx, path, |ecx| {

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,8 @@ pub(crate) struct CrateRoot {
282282

283283
exportable_items: LazyArray<DefIndex>,
284284
stable_order_of_exportable_impls: LazyArray<(DefIndex, usize)>,
285-
exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
285+
exported_non_generic_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
286+
exported_generic_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
286287

287288
syntax_contexts: SyntaxContextTable,
288289
expn_data: ExpnDataTable,

compiler/rustc_middle/src/query/mod.rs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2312,13 +2312,28 @@ rustc_queries! {
23122312
separate_provide_extern
23132313
}
23142314

2315-
/// The list of symbols exported from the given crate.
2315+
/// The list of non-generic symbols exported from the given crate.
2316+
///
2317+
/// - All names contained in `exported_non_generic_symbols(cnum)` are
2318+
/// guaranteed to correspond to a publicly visible symbol in `cnum`
2319+
/// machine code.
2320+
/// - The `exported_non_generic_symbols` and `exported_generic_symbols`
2321+
/// sets of different crates do not intersect.
2322+
query exported_non_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
2323+
desc { "collecting exported non-generic symbols for crate `{}`", cnum}
2324+
cache_on_disk_if { *cnum == LOCAL_CRATE }
2325+
separate_provide_extern
2326+
}
2327+
2328+
/// The list of generic symbols exported from the given crate.
23162329
///
2317-
/// - All names contained in `exported_symbols(cnum)` are guaranteed to
2318-
/// correspond to a publicly visible symbol in `cnum` machine code.
2319-
/// - The `exported_symbols` sets of different crates do not intersect.
2320-
query exported_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
2321-
desc { "collecting exported symbols for crate `{}`", cnum}
2330+
/// - All names contained in `exported_generic_symbols(cnum)` are
2331+
/// guaranteed to correspond to a publicly visible symbol in `cnum`
2332+
/// machine code.
2333+
/// - The `exported_non_generic_symbols` and `exported_generic_symbols`
2334+
/// sets of different crates do not intersect.
2335+
query exported_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
2336+
desc { "collecting exported generic symbols for crate `{}`", cnum}
23222337
cache_on_disk_if { *cnum == LOCAL_CRATE }
23232338
separate_provide_extern
23242339
}

src/tools/miri/src/bin/miri.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
8585
return (def_id, MiriEntryFnType::Rustc(entry_type));
8686
}
8787
// Look for a symbol in the local crate named `miri_start`, and treat that as the entry point.
88-
let sym = tcx.exported_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| {
88+
let sym = tcx.exported_non_generic_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| {
8989
if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None }
9090
});
9191
if let Some(ExportedSymbol::NonGeneric(id)) = sym {
@@ -249,10 +249,10 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
249249
// Queries overridden here affect the data stored in `rmeta` files of dependencies,
250250
// which will be used later in non-`MIRI_BE_RUSTC` mode.
251251
config.override_queries = Some(|_, local_providers| {
252-
// `exported_symbols` and `reachable_non_generics` provided by rustc always returns
252+
// `exported_non_generic_symbols` and `reachable_non_generics` provided by rustc always returns
253253
// an empty result if `tcx.sess.opts.output_types.should_codegen()` is false.
254254
// In addition we need to add #[used] symbols to exported_symbols for `lookup_link_section`.
255-
local_providers.exported_symbols = |tcx, LocalCrate| {
255+
local_providers.exported_non_generic_symbols = |tcx, LocalCrate| {
256256
let reachable_set = tcx.with_stable_hashing_context(|hcx| {
257257
tcx.reachable_set(()).to_sorted(&hcx, true)
258258
});

src/tools/miri/src/helpers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ pub fn iter_exported_symbols<'tcx>(
162162

163163
// We can ignore `_export_info` here: we are a Rust crate, and everything is exported
164164
// from a Rust crate.
165-
for &(symbol, _export_info) in tcx.exported_symbols(cnum) {
165+
for &(symbol, _export_info) in tcx.exported_non_generic_symbols(cnum) {
166166
if let ExportedSymbol::NonGeneric(def_id) = symbol {
167167
f(cnum, def_id)?;
168168
}

0 commit comments

Comments
 (0)