From 8bc005c8bb26f8d84066a096780c765ba431d721 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 27 Feb 2018 19:28:21 +0100 Subject: [PATCH] Don't recompute SymbolExportLevel for upstream crates. --- src/librustc/middle/exported_symbols.rs | 4 +- src/librustc/ty/context.rs | 8 ++ src/librustc_metadata/cstore_impl.rs | 32 +++++++- src/librustc_metadata/decoder.rs | 7 +- src/librustc_metadata/encoder.rs | 28 ++++--- src/librustc_metadata/schema.rs | 4 +- src/librustc_trans/back/symbol_export.rs | 98 ++++++++---------------- 7 files changed, 91 insertions(+), 90 deletions(-) diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs index c9b3acdd836ec..fb971dd2515cd 100644 --- a/src/librustc/middle/exported_symbols.rs +++ b/src/librustc/middle/exported_symbols.rs @@ -17,7 +17,7 @@ use ty; /// kind of crate, including cdylibs which export very few things. /// `Rust` will only be exported if the crate produced is a Rust /// dylib. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)] pub enum SymbolExportLevel { C, Rust, @@ -39,7 +39,7 @@ impl SymbolExportLevel { } } -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)] pub enum ExportedSymbol { NonGeneric(DefId), NoDefId(ty::SymbolName), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index aac6b3dc08a78..47a3580e86769 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2460,4 +2460,12 @@ pub fn provide(providers: &mut ty::maps::Providers) { assert_eq!(cnum, LOCAL_CRATE); Lrc::new(tcx.sess.features_untracked().clone()) }; + providers.is_panic_runtime = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + attr::contains_name(tcx.hir.krate_attrs(), "panic_runtime") + }; + providers.is_compiler_builtins = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + attr::contains_name(tcx.hir.krate_attrs(), "compiler_builtins") + }; } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 00862816d57b4..0a2270571f3fc 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -18,6 +18,7 @@ use rustc::ty::maps::QueryConfig; use rustc::middle::cstore::{CrateStore, DepKind, MetadataLoader, LinkMeta, LoadedMacro, EncodedMetadata, NativeLibraryKind}; +use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; use rustc::hir::def; use rustc::session::{CrateDisambiguator, Session}; @@ -31,6 +32,7 @@ use rustc::util::nodemap::DefIdMap; use std::any::Any; use rustc_data_structures::sync::Lrc; +use std::sync::Arc; use syntax::ast; use syntax::attr; @@ -176,7 +178,21 @@ provide! { <'tcx> tcx, def_id, other, cdata, extern_crate => { Lrc::new(cdata.extern_crate.get()) } is_no_builtins => { cdata.is_no_builtins(tcx.sess) } impl_defaultness => { cdata.get_impl_defaultness(def_id.index) } - reachable_non_generics => { Lrc::new(cdata.reachable_non_generics()) } + reachable_non_generics => { + let reachable_non_generics = tcx + .exported_symbols(cdata.cnum) + .iter() + .filter_map(|&(exported_symbol, _)| { + if let ExportedSymbol::NonGeneric(def_id) = exported_symbol { + return Some(def_id) + } else { + None + } + }) + .collect(); + + Lrc::new(reachable_non_generics) + } native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) } plugin_registrar_fn => { cdata.root.plugin_registrar_fn.map(|index| { @@ -235,6 +251,20 @@ provide! { <'tcx> tcx, def_id, other, cdata, has_copy_closures => { cdata.has_copy_closures(tcx.sess) } has_clone_closures => { cdata.has_clone_closures(tcx.sess) } + + exported_symbols => { + let cnum = cdata.cnum; + assert!(cnum != LOCAL_CRATE); + + // If this crate is a plugin and/or a custom derive crate, then + // we're not even going to link those in so we skip those crates. + if cdata.root.plugin_registrar_fn.is_some() || + cdata.root.macro_derive_registrar.is_some() { + return Arc::new(Vec::new()) + } + + Arc::new(cdata.exported_symbols()) + } } pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 2831b63bbac59..60a0d4e03b54a 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -18,6 +18,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir; use rustc::middle::cstore::{LinkagePreference, ExternConstBody, ExternBodyNestedBodies}; +use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -27,7 +28,6 @@ use rustc::mir; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::codec::TyDecoder; -use rustc::util::nodemap::DefIdSet; use rustc::mir::Mir; use std::cell::Ref; @@ -1006,11 +1006,10 @@ impl<'a, 'tcx> CrateMetadata { arg_names.decode(self).collect() } - pub fn reachable_non_generics(&self) -> DefIdSet { + pub fn exported_symbols(&self) -> Vec<(ExportedSymbol, SymbolExportLevel)> { self.root - .reachable_non_generics + .exported_symbols .decode(self) - .map(|index| self.local_def_id(index)) .collect() } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c649cf62dc5d3..1c54b7aa1333b 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -20,6 +20,7 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE use rustc::hir::map::definitions::DefPathTable; use rustc::ich::Fingerprint; use rustc::middle::dependency_format::Linkage; +use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::lang_items; use rustc::mir; use rustc::traits::specialization_graph; @@ -27,7 +28,7 @@ use rustc::ty::{self, Ty, TyCtxt, ReprOptions}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::session::config::{self, CrateTypeProcMacro}; -use rustc::util::nodemap::{FxHashMap, DefIdSet}; +use rustc::util::nodemap::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; @@ -394,11 +395,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode exported symbols info. i = self.position(); - let reachable_non_generics = self.tcx.reachable_non_generics(LOCAL_CRATE); - let reachable_non_generics = self.tracked( - IsolatedEncoder::encode_reachable_non_generics, - &reachable_non_generics); - let reachable_non_generics_bytes = self.position() - i; + let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); + let exported_symbols = self.tracked( + IsolatedEncoder::encode_exported_symbols, + &exported_symbols); + let exported_symbols_bytes = self.position() - i; // Encode and index the items. i = self.position(); @@ -442,7 +443,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { codemap, def_path_table, impls, - reachable_non_generics, + exported_symbols, index, }); @@ -462,7 +463,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" native bytes: {}", native_lib_bytes); println!(" codemap bytes: {}", codemap_bytes); println!(" impl bytes: {}", impl_bytes); - println!(" exp. symbols bytes: {}", reachable_non_generics_bytes); + println!(" exp. symbols bytes: {}", exported_symbols_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); println!(" index bytes: {}", index_bytes); @@ -1388,13 +1389,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // middle::reachable module but filters out items that either don't have a // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). - fn encode_reachable_non_generics(&mut self, - reachable_non_generics: &DefIdSet) - -> LazySeq { - self.lazy_seq(reachable_non_generics.iter().map(|def_id| { - debug_assert!(def_id.is_local()); - def_id.index - })) + fn encode_exported_symbols(&mut self, + exported_symbols: &[(ExportedSymbol, SymbolExportLevel)]) + -> LazySeq<(ExportedSymbol, SymbolExportLevel)> { + self.lazy_seq(exported_symbols.iter().cloned()) } fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 3e7d31513a22d..ce94e4f912f4f 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -16,6 +16,7 @@ use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId, CrateNum}; use rustc::ich::StableHashingContext; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; +use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::lang_items; use rustc::mir; use rustc::session::CrateDisambiguator; @@ -202,7 +203,8 @@ pub struct CrateRoot { pub codemap: LazySeq, pub def_path_table: Lazy, pub impls: LazySeq, - pub reachable_non_generics: LazySeq, + pub exported_symbols: LazySeq<(ExportedSymbol, SymbolExportLevel)>, + pub index: LazySeq, } diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 4e3a37104886b..0873c1632f58f 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -78,10 +78,9 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let reachable_non_generics = tcx .exported_symbols(LOCAL_CRATE) .iter() - .filter_map(|&(exported_symbol, _)| { + .filter_map(|&(exported_symbol, level)| { if let ExportedSymbol::NonGeneric(def_id) = exported_symbol { - if tcx.symbol_export_level(def_id) - .is_below_threshold(export_threshold) { + if level.is_below_threshold(export_threshold) { return Some(def_id) } } @@ -110,6 +109,16 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return Arc::new(vec![]) } + // Check to see if this crate is a "special runtime crate". These + // crates, implementation details of the standard library, typically + // have a bunch of `pub extern` and `#[no_mangle]` functions as the + // ABI between them. We don't want their symbols to have a `C` + // export level, however, as they're just implementation details. + // Down below we'll hardwire all of the symbols to the `Rust` export + // level instead. + let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) || + tcx.is_compiler_builtins(LOCAL_CRATE); + let mut reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0 .iter() .filter_map(|&node_id| { @@ -176,7 +185,25 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut symbols: Vec<_> = reachable_non_generics .iter() .map(|&def_id| { - let export_level = tcx.symbol_export_level(def_id); + let export_level = if special_runtime_crate { + let name = tcx.symbol_name(Instance::mono(tcx, def_id)); + // We can probably do better here by just ensuring that + // it has hidden visibility rather than public + // visibility, as this is primarily here to ensure it's + // not stripped during LTO. + // + // In general though we won't link right if these + // symbols are stripped, and LTO currently strips them. + if &*name == "rust_eh_personality" || + &*name == "rust_eh_register_frames" || + &*name == "rust_eh_unregister_frames" { + SymbolExportLevel::C + } else { + SymbolExportLevel::Rust + } + } else { + tcx.symbol_export_level(def_id) + }; debug!("EXPORTED SYMBOL (local): {} ({:?})", tcx.symbol_name(Instance::mono(tcx, def_id)), export_level); @@ -222,70 +249,7 @@ pub fn provide(providers: &mut Providers) { providers.symbol_export_level = symbol_export_level_provider; } -fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - cnum: CrateNum) - -> Arc> -{ - // If this crate is a plugin and/or a custom derive crate, then - // we're not even going to link those in so we skip those crates. - if tcx.plugin_registrar_fn(cnum).is_some() || - tcx.derive_registrar_fn(cnum).is_some() { - return Arc::new(Vec::new()) - } - - // Check to see if this crate is a "special runtime crate". These - // crates, implementation details of the standard library, typically - // have a bunch of `pub extern` and `#[no_mangle]` functions as the - // ABI between them. We don't want their symbols to have a `C` - // export level, however, as they're just implementation details. - // Down below we'll hardwire all of the symbols to the `Rust` export - // level instead. - let special_runtime_crate = - tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum); - - let mut crate_exports: Vec<_> = tcx - .reachable_non_generics(cnum) - .iter() - .map(|&def_id| { - let export_level = if special_runtime_crate { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); - // We can probably do better here by just ensuring that - // it has hidden visibility rather than public - // visibility, as this is primarily here to ensure it's - // not stripped during LTO. - // - // In general though we won't link right if these - // symbols are stripped, and LTO currently strips them. - if &*name == "rust_eh_personality" || - &*name == "rust_eh_register_frames" || - &*name == "rust_eh_unregister_frames" { - SymbolExportLevel::C - } else { - SymbolExportLevel::Rust - } - } else { - tcx.symbol_export_level(def_id) - }; - - debug!("EXPORTED SYMBOL (re-export): {} ({:?})", - tcx.symbol_name(Instance::mono(tcx, def_id)), - export_level); - - (ExportedSymbol::NonGeneric(def_id), export_level) - }) - .collect(); - - // Sort so we get a stable incr. comp. hash. - crate_exports.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| { - symbol1.compare_stable(tcx, symbol2) - }); - - Arc::new(crate_exports) -} - pub fn provide_extern(providers: &mut Providers) { - providers.exported_symbols = exported_symbols_provider_extern; providers.is_reachable_non_generic = is_reachable_non_generic_provider; providers.symbol_export_level = symbol_export_level_provider; }