Split exported_symbols for generic and non-generic symbols
This reduces metadata decoder overhead during the monomorphization collector.
This commit is contained in:
@@ -1794,7 +1794,10 @@ fn for_each_exported_symbols_include_dep<'tcx>(
|
||||
for (cnum, dep_format) in deps.iter_enumerated() {
|
||||
// For each dependency that we are linking to statically ...
|
||||
if *dep_format == Linkage::Static {
|
||||
for &(symbol, info) in tcx.exported_symbols(cnum).iter() {
|
||||
for &(symbol, info) in tcx.exported_non_generic_symbols(cnum).iter() {
|
||||
callback(symbol, info, cnum);
|
||||
}
|
||||
for &(symbol, info) in tcx.exported_generic_symbols(cnum).iter() {
|
||||
callback(symbol, info, cnum);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ fn is_reachable_non_generic_provider_extern(tcx: TyCtxt<'_>, def_id: DefId) -> b
|
||||
tcx.reachable_non_generics(def_id.krate).contains_key(&def_id)
|
||||
}
|
||||
|
||||
fn exported_symbols_provider_local<'tcx>(
|
||||
fn exported_non_generic_symbols_provider_local<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
_: LocalCrate,
|
||||
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
@@ -296,6 +296,22 @@ fn exported_symbols_provider_local<'tcx>(
|
||||
));
|
||||
}
|
||||
|
||||
// Sort so we get a stable incr. comp. hash.
|
||||
symbols.sort_by_cached_key(|s| s.0.symbol_name_for_local_instance(tcx));
|
||||
|
||||
tcx.arena.alloc_from_iter(symbols)
|
||||
}
|
||||
|
||||
fn exported_generic_symbols_provider_local<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
_: LocalCrate,
|
||||
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
if !tcx.sess.opts.output_types.should_codegen() && !tcx.is_sdylib_interface_build() {
|
||||
return &[];
|
||||
}
|
||||
|
||||
let mut symbols: Vec<_> = vec![];
|
||||
|
||||
if tcx.local_crate_exports_generics() {
|
||||
use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
|
||||
use rustc_middle::ty::InstanceKind;
|
||||
@@ -458,7 +474,7 @@ fn upstream_monomorphizations_provider(
|
||||
let async_drop_in_place_fn_def_id = tcx.lang_items().async_drop_in_place_fn();
|
||||
|
||||
for &cnum in cnums.iter() {
|
||||
for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() {
|
||||
for (exported_symbol, _) in tcx.exported_generic_symbols(cnum).iter() {
|
||||
let (def_id, args) = match *exported_symbol {
|
||||
ExportedSymbol::Generic(def_id, args) => (def_id, args),
|
||||
ExportedSymbol::DropGlue(ty) => {
|
||||
@@ -480,10 +496,7 @@ fn upstream_monomorphizations_provider(
|
||||
ExportedSymbol::AsyncDropGlue(def_id, ty) => (def_id, tcx.mk_args(&[ty.into()])),
|
||||
ExportedSymbol::NonGeneric(..)
|
||||
| ExportedSymbol::ThreadLocalShim(..)
|
||||
| ExportedSymbol::NoDefId(..) => {
|
||||
// These are no monomorphizations
|
||||
continue;
|
||||
}
|
||||
| ExportedSymbol::NoDefId(..) => unreachable!("{exported_symbol:?}"),
|
||||
};
|
||||
|
||||
let args_map = instances.entry(def_id).or_default();
|
||||
@@ -538,7 +551,8 @@ fn is_unreachable_local_definition_provider(tcx: TyCtxt<'_>, def_id: LocalDefId)
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
providers.reachable_non_generics = reachable_non_generics_provider;
|
||||
providers.is_reachable_non_generic = is_reachable_non_generic_provider_local;
|
||||
providers.exported_symbols = exported_symbols_provider_local;
|
||||
providers.exported_non_generic_symbols = exported_non_generic_symbols_provider_local;
|
||||
providers.exported_generic_symbols = exported_generic_symbols_provider_local;
|
||||
providers.upstream_monomorphizations = upstream_monomorphizations_provider;
|
||||
providers.is_unreachable_local_definition = is_unreachable_local_definition_provider;
|
||||
providers.upstream_drop_glue_for = upstream_drop_glue_for_provider;
|
||||
|
||||
@@ -1124,8 +1124,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
||||
|
||||
let copy_symbols = |cnum| {
|
||||
let symbols = tcx
|
||||
.exported_symbols(cnum)
|
||||
.exported_non_generic_symbols(cnum)
|
||||
.iter()
|
||||
.chain(tcx.exported_generic_symbols(cnum))
|
||||
.map(|&(s, lvl)| (symbol_name_for_instance_in_crate(tcx, s, cnum), lvl))
|
||||
.collect();
|
||||
Arc::new(symbols)
|
||||
|
||||
@@ -1496,11 +1496,18 @@ impl<'a> CrateMetadataRef<'a> {
|
||||
.map(move |v| (self.local_def_id(v.0), v.1))
|
||||
}
|
||||
|
||||
fn exported_symbols<'tcx>(
|
||||
fn exported_non_generic_symbols<'tcx>(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
tcx.arena.alloc_from_iter(self.root.exported_symbols.decode((self, tcx)))
|
||||
tcx.arena.alloc_from_iter(self.root.exported_non_generic_symbols.decode((self, tcx)))
|
||||
}
|
||||
|
||||
fn exported_generic_symbols<'tcx>(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
tcx.arena.alloc_from_iter(self.root.exported_generic_symbols.decode((self, tcx)))
|
||||
}
|
||||
|
||||
fn get_macro(self, id: DefIndex, sess: &Session) -> ast::MacroDef {
|
||||
|
||||
@@ -358,7 +358,7 @@ provide! { tcx, def_id, other, cdata,
|
||||
specialization_enabled_in => { cdata.root.specialization_enabled_in }
|
||||
reachable_non_generics => {
|
||||
let reachable_non_generics = tcx
|
||||
.exported_symbols(cdata.cnum)
|
||||
.exported_non_generic_symbols(cdata.cnum)
|
||||
.iter()
|
||||
.filter_map(|&(exported_symbol, export_info)| {
|
||||
if let ExportedSymbol::NonGeneric(def_id) = exported_symbol {
|
||||
@@ -408,15 +408,8 @@ provide! { tcx, def_id, other, cdata,
|
||||
|
||||
exportable_items => { tcx.arena.alloc_from_iter(cdata.get_exportable_items()) }
|
||||
stable_order_of_exportable_impls => { tcx.arena.alloc(cdata.get_stable_order_of_exportable_impls().collect()) }
|
||||
exported_symbols => {
|
||||
let syms = cdata.exported_symbols(tcx);
|
||||
|
||||
// FIXME rust-lang/rust#64319, rust-lang/rust#64872: We want
|
||||
// to block export of generics from dylibs, but we must fix
|
||||
// rust-lang/rust#65890 before we can do that robustly.
|
||||
|
||||
syms
|
||||
}
|
||||
exported_non_generic_symbols => { cdata.exported_non_generic_symbols(tcx) }
|
||||
exported_generic_symbols => { cdata.exported_generic_symbols(tcx) }
|
||||
|
||||
crate_extern_paths => { cdata.source().paths().cloned().collect() }
|
||||
expn_that_defined => { cdata.get_expn_that_defined(def_id.index, tcx.sess) }
|
||||
|
||||
@@ -677,9 +677,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
stat!("exportable-items", || self.encode_stable_order_of_exportable_impls());
|
||||
|
||||
// Encode exported symbols info. This is prefetched in `encode_metadata`.
|
||||
let exported_symbols = stat!("exported-symbols", || {
|
||||
self.encode_exported_symbols(tcx.exported_symbols(LOCAL_CRATE))
|
||||
});
|
||||
let (exported_non_generic_symbols, exported_generic_symbols) =
|
||||
stat!("exported-symbols", || {
|
||||
(
|
||||
self.encode_exported_symbols(tcx.exported_non_generic_symbols(LOCAL_CRATE)),
|
||||
self.encode_exported_symbols(tcx.exported_generic_symbols(LOCAL_CRATE)),
|
||||
)
|
||||
});
|
||||
|
||||
// Encode the hygiene data.
|
||||
// IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The
|
||||
@@ -745,7 +749,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
incoherent_impls,
|
||||
exportable_items,
|
||||
stable_order_of_exportable_impls,
|
||||
exported_symbols,
|
||||
exported_non_generic_symbols,
|
||||
exported_generic_symbols,
|
||||
interpret_alloc_index,
|
||||
tables,
|
||||
syntax_contexts,
|
||||
@@ -2356,7 +2361,13 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) {
|
||||
// Prefetch some queries used by metadata encoding.
|
||||
// This is not necessary for correctness, but is only done for performance reasons.
|
||||
// It can be removed if it turns out to cause trouble or be detrimental to performance.
|
||||
join(|| prefetch_mir(tcx), || tcx.exported_symbols(LOCAL_CRATE));
|
||||
join(
|
||||
|| prefetch_mir(tcx),
|
||||
|| {
|
||||
let _ = tcx.exported_non_generic_symbols(LOCAL_CRATE);
|
||||
let _ = tcx.exported_generic_symbols(LOCAL_CRATE);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
with_encode_metadata_header(tcx, path, |ecx| {
|
||||
|
||||
@@ -282,7 +282,8 @@ pub(crate) struct CrateRoot {
|
||||
|
||||
exportable_items: LazyArray<DefIndex>,
|
||||
stable_order_of_exportable_impls: LazyArray<(DefIndex, usize)>,
|
||||
exported_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
|
||||
exported_non_generic_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
|
||||
exported_generic_symbols: LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)>,
|
||||
|
||||
syntax_contexts: SyntaxContextTable,
|
||||
expn_data: ExpnDataTable,
|
||||
|
||||
@@ -2312,13 +2312,32 @@ rustc_queries! {
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
/// The list of symbols exported from the given crate.
|
||||
/// The list of non-generic symbols exported from the given crate.
|
||||
///
|
||||
/// - All names contained in `exported_symbols(cnum)` are guaranteed to
|
||||
/// correspond to a publicly visible symbol in `cnum` machine code.
|
||||
/// - The `exported_symbols` sets of different crates do not intersect.
|
||||
query exported_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
desc { "collecting exported symbols for crate `{}`", cnum}
|
||||
/// This is separate from exported_generic_symbols to avoid having
|
||||
/// to deserialize all non-generic symbols too for upstream crates
|
||||
/// in the upstream_monomorphizations query.
|
||||
///
|
||||
/// - All names contained in `exported_non_generic_symbols(cnum)` are
|
||||
/// guaranteed to correspond to a publicly visible symbol in `cnum`
|
||||
/// machine code.
|
||||
/// - The `exported_non_generic_symbols` and `exported_generic_symbols`
|
||||
/// sets of different crates do not intersect.
|
||||
query exported_non_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
desc { "collecting exported non-generic symbols for crate `{}`", cnum}
|
||||
cache_on_disk_if { *cnum == LOCAL_CRATE }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
/// The list of generic symbols exported from the given crate.
|
||||
///
|
||||
/// - All names contained in `exported_generic_symbols(cnum)` are
|
||||
/// guaranteed to correspond to a publicly visible symbol in `cnum`
|
||||
/// machine code.
|
||||
/// - The `exported_non_generic_symbols` and `exported_generic_symbols`
|
||||
/// sets of different crates do not intersect.
|
||||
query exported_generic_symbols(cnum: CrateNum) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] {
|
||||
desc { "collecting exported generic symbols for crate `{}`", cnum}
|
||||
cache_on_disk_if { *cnum == LOCAL_CRATE }
|
||||
separate_provide_extern
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
|
||||
return (def_id, MiriEntryFnType::Rustc(entry_type));
|
||||
}
|
||||
// Look for a symbol in the local crate named `miri_start`, and treat that as the entry point.
|
||||
let sym = tcx.exported_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| {
|
||||
let sym = tcx.exported_non_generic_symbols(LOCAL_CRATE).iter().find_map(|(sym, _)| {
|
||||
if sym.symbol_name_for_local_instance(tcx).name == "miri_start" { Some(sym) } else { None }
|
||||
});
|
||||
if let Some(ExportedSymbol::NonGeneric(id)) = sym {
|
||||
@@ -249,10 +249,10 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
|
||||
// Queries overridden here affect the data stored in `rmeta` files of dependencies,
|
||||
// which will be used later in non-`MIRI_BE_RUSTC` mode.
|
||||
config.override_queries = Some(|_, local_providers| {
|
||||
// `exported_symbols` and `reachable_non_generics` provided by rustc always returns
|
||||
// `exported_non_generic_symbols` and `reachable_non_generics` provided by rustc always returns
|
||||
// an empty result if `tcx.sess.opts.output_types.should_codegen()` is false.
|
||||
// In addition we need to add #[used] symbols to exported_symbols for `lookup_link_section`.
|
||||
local_providers.exported_symbols = |tcx, LocalCrate| {
|
||||
local_providers.exported_non_generic_symbols = |tcx, LocalCrate| {
|
||||
let reachable_set = tcx.with_stable_hashing_context(|hcx| {
|
||||
tcx.reachable_set(()).to_sorted(&hcx, true)
|
||||
});
|
||||
|
||||
@@ -162,7 +162,7 @@ pub fn iter_exported_symbols<'tcx>(
|
||||
|
||||
// We can ignore `_export_info` here: we are a Rust crate, and everything is exported
|
||||
// from a Rust crate.
|
||||
for &(symbol, _export_info) in tcx.exported_symbols(cnum) {
|
||||
for &(symbol, _export_info) in tcx.exported_non_generic_symbols(cnum) {
|
||||
if let ExportedSymbol::NonGeneric(def_id) = symbol {
|
||||
f(cnum, def_id)?;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user