Skip to content

Commit

Permalink
rustc: Mostly remove ExportedSymbols
Browse files Browse the repository at this point in the history
This is a big map that ends up inside of a `CrateContext` during translation for
all codegen units. This means that any change to the map may end up causing an
incremental recompilation of a codegen unit! In order to reduce the amount of
dependencies here between codegen units and the actual input crate this commit
refactors dealing with exported symbols and such into various queries.

The new queries are largely based on existing queries with filled out
implementations for the local crate in addition to external crates, but the main
idea is that while translating codegen untis no unit needs the entire set of
exported symbols, instead they only need queries about particulare `DefId`
instances every now and then.

The linking stage, however, still generates a full list of all exported symbols
from all crates, but that's going to always happen unconditionally anyway, so no
news there!
  • Loading branch information
alexcrichton committed Sep 17, 2017
1 parent 8821aff commit afb85cf
Show file tree
Hide file tree
Showing 18 changed files with 233 additions and 313 deletions.
2 changes: 1 addition & 1 deletion src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ define_dep_nodes!( <'tcx>
[] MaybeUnusedExternCrates,
[] StabilityIndex,
[] AllCrateNums,
[] ExportedSymbols,
[] ExportedSymbols(CrateNum),
[] CollectAndPartitionTranslationItems,
[] ExportName(DefId),
[] ContainsExternIndicator(DefId),
Expand Down
5 changes: 3 additions & 2 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,9 @@ pub trait CrateLoader {
// In order to get this left-to-right dependency ordering, we perform a
// topological sort of all crates putting the leaves at the right-most
// positions.
pub fn used_crates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> {
pub fn used_crates(tcx: TyCtxt, prefer: LinkagePreference)
-> Vec<(CrateNum, LibSource)>
{
let mut libs = tcx.crates()
.iter()
.cloned()
Expand Down
60 changes: 7 additions & 53 deletions src/librustc/middle/exported_symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use util::nodemap::{FxHashMap, NodeSet};
use hir::def_id::{DefId, CrateNum};

/// The SymbolExportLevel of a symbols specifies from which kinds of crates
/// the symbol will be exported. `C` symbols will be exported from any
/// kind of crate, including cdylibs which export very few things.
Expand All @@ -22,56 +19,13 @@ pub enum SymbolExportLevel {
Rust,
}

/// The set of symbols exported from each crate in the crate graph.
#[derive(Debug)]
pub struct ExportedSymbols {
pub export_threshold: SymbolExportLevel,
exports: FxHashMap<CrateNum, Vec<(String, DefId, SymbolExportLevel)>>,
local_exports: NodeSet,
}

impl ExportedSymbols {
pub fn new(export_threshold: SymbolExportLevel,
exports: FxHashMap<CrateNum, Vec<(String, DefId, SymbolExportLevel)>>,
local_exports: NodeSet) -> ExportedSymbols {
ExportedSymbols {
export_threshold,
exports,
local_exports,
}
}

pub fn local_exports(&self) -> &NodeSet {
&self.local_exports
}

pub fn exported_symbols(&self, cnum: CrateNum)
-> &[(String, DefId, SymbolExportLevel)]
{
match self.exports.get(&cnum) {
Some(exports) => exports,
None => &[]
}
}

pub fn for_each_exported_symbol<F>(&self, cnum: CrateNum, mut f: F)
where F: FnMut(&str, DefId, SymbolExportLevel)
{
for &(ref name, def_id, export_level) in self.exported_symbols(cnum) {
if is_below_threshold(export_level, self.export_threshold) {
f(&name, def_id, export_level)
}
impl SymbolExportLevel {
pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool {
if threshold == SymbolExportLevel::Rust {
// We export everything from Rust dylibs
true
} else {
self == SymbolExportLevel::C
}
}
}

pub fn is_below_threshold(level: SymbolExportLevel,
threshold: SymbolExportLevel)
-> bool {
if threshold == SymbolExportLevel::Rust {
// We export everything from Rust dylibs
true
} else {
level == SymbolExportLevel::C
}
}
6 changes: 0 additions & 6 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use middle::cstore::EncodedMetadata;
use middle::free_region::FreeRegionMap;
use middle::lang_items;
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
use middle::exported_symbols::ExportedSymbols;
use middle::stability;
use mir::Mir;
use mir::transform::Passes;
Expand Down Expand Up @@ -65,7 +64,6 @@ use std::mem;
use std::ops::Deref;
use std::iter;
use std::rc::Rc;
use std::sync::Arc;
use syntax::abi;
use syntax::ast::{self, Name, NodeId};
use syntax::attr;
Expand Down Expand Up @@ -1220,10 +1218,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn crate_data_as_rc_any(self, cnum: CrateNum) -> Rc<Any> {
self.cstore.crate_data_as_rc_any(cnum)
}

pub fn exported_symbols(self) -> Arc<ExportedSymbols> {
self.exported_symbol_set(LOCAL_CRATE)
}
}

impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
Expand Down
16 changes: 6 additions & 10 deletions src/librustc/ty/maps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use middle::region;
use middle::resolve_lifetime::{Region, ObjectLifetimeDefault};
use middle::stability::{self, DeprecationEntry};
use middle::lang_items::{LanguageItems, LangItem};
use middle::exported_symbols::ExportedSymbols;
use middle::exported_symbols::SymbolExportLevel;
use middle::trans::{TransItem, CodegenUnit};
use mir;
use mir::transform::{MirSuite, MirPassIndex};
Expand Down Expand Up @@ -748,9 +748,9 @@ impl<'tcx> QueryDescription for queries::all_crate_nums<'tcx> {
}
}

impl<'tcx> QueryDescription for queries::exported_symbol_set<'tcx> {
impl<'tcx> QueryDescription for queries::exported_symbols<'tcx> {
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
format!("exported symbol set")
format!("exported_symbols")
}
}

Expand Down Expand Up @@ -1337,7 +1337,7 @@ define_maps! { <'tcx>
[] fn lint_levels: lint_levels_node(CrateNum) -> Rc<lint::LintLevelMap>,

[] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness,
[] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Rc<Vec<DefId>>,
[] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Rc<DefIdSet>,
[] fn native_libraries: NativeLibraries(CrateNum) -> Rc<Vec<NativeLibrary>>,
[] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
[] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option<DefId>,
Expand Down Expand Up @@ -1387,8 +1387,8 @@ define_maps! { <'tcx>
[] fn stability_index: stability_index_node(CrateNum) -> Rc<stability::Index<'tcx>>,
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Rc<Vec<CrateNum>>,

[] fn exported_symbol_set: exported_symbol_set_node(CrateNum)
-> Arc<ExportedSymbols>,
[] fn exported_symbols: ExportedSymbols(CrateNum)
-> Arc<Vec<(String, DefId, SymbolExportLevel)>>,
[] fn collect_and_partition_translation_items:
collect_and_partition_translation_items_node(CrateNum)
-> (Arc<FxHashSet<TransItem<'tcx>>>, Vec<Arc<CodegenUnit<'tcx>>>),
Expand Down Expand Up @@ -1508,10 +1508,6 @@ fn all_crate_nums_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::AllCrateNums
}

fn exported_symbol_set_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::ExportedSymbols
}

fn collect_and_partition_translation_items_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
DepConstructor::CollectAndPartitionTranslationItems
}
3 changes: 2 additions & 1 deletion src/librustc_metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use rustc::middle::lang_items;
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::Substs;
use rustc::util::nodemap::DefIdSet;

use rustc::mir::Mir;

Expand Down Expand Up @@ -1017,7 +1018,7 @@ impl<'a, 'tcx> CrateMetadata {
arg_names.decode(self).collect()
}

pub fn get_exported_symbols(&self) -> Vec<DefId> {
pub fn get_exported_symbols(&self) -> DefIdSet {
self.exported_symbols
.iter()
.map(|&index| self.local_def_id(index))
Expand Down
49 changes: 25 additions & 24 deletions src/librustc_trans/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,15 @@ use std::io::prelude::*;
use std::io::{self, BufWriter};
use std::path::{Path, PathBuf};

use context::SharedCrateContext;

use back::archive;
use back::command::Command;
use rustc::middle::dependency_format::Linkage;
use rustc::middle::exported_symbols::ExportedSymbols;
use back::symbol_export;
use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
use rustc_back::LinkerFlavor;
use rustc::middle::dependency_format::Linkage;
use rustc::session::Session;
use rustc::session::config::{self, CrateType, OptLevel, DebugInfoLevel};
use rustc::ty::TyCtxt;
use rustc_back::LinkerFlavor;
use serialize::{json, Encoder};

/// For all the linkers we support, and information they might
Expand All @@ -33,19 +32,18 @@ pub struct LinkerInfo {
exports: HashMap<CrateType, Vec<String>>,
}

impl<'a, 'tcx> LinkerInfo {
pub fn new(scx: &SharedCrateContext<'a, 'tcx>) -> LinkerInfo {
let exports = scx.tcx().exported_symbols();
impl LinkerInfo {
pub fn new(tcx: TyCtxt) -> LinkerInfo {
LinkerInfo {
exports: scx.sess().crate_types.borrow().iter().map(|&c| {
(c, exported_symbols(scx, &exports, c))
exports: tcx.sess.crate_types.borrow().iter().map(|&c| {
(c, exported_symbols(tcx, c))
}).collect(),
}
}

pub fn to_linker(&'a self,
cmd: Command,
sess: &'a Session) -> Box<Linker+'a> {
pub fn to_linker<'a>(&'a self,
cmd: Command,
sess: &'a Session) -> Box<Linker+'a> {
match sess.linker_flavor() {
LinkerFlavor::Msvc => {
Box::new(MsvcLinker {
Expand Down Expand Up @@ -734,26 +732,29 @@ impl<'a> Linker for EmLinker<'a> {
}
}

fn exported_symbols(scx: &SharedCrateContext,
exported_symbols: &ExportedSymbols,
crate_type: CrateType)
-> Vec<String> {
fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
let mut symbols = Vec::new();
exported_symbols.for_each_exported_symbol(LOCAL_CRATE, |name, _, _| {
symbols.push(name.to_owned());
});

let formats = scx.sess().dependency_formats.borrow();
let export_threshold = symbol_export::threshold(tcx);
for &(ref name, _, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
if level.is_below_threshold(export_threshold) {
symbols.push(name.clone());
}
}

let formats = tcx.sess.dependency_formats.borrow();
let deps = formats[&crate_type].iter();

for (index, dep_format) in deps.enumerate() {
let cnum = CrateNum::new(index + 1);
// For each dependency that we are linking to statically ...
if *dep_format == Linkage::Static {
// ... we add its symbol list to our export list.
exported_symbols.for_each_exported_symbol(cnum, |name, _, _| {
symbols.push(name.to_owned());
})
for &(ref name, _, level) in tcx.exported_symbols(cnum).iter() {
if level.is_below_threshold(export_threshold) {
symbols.push(name.clone());
}
}
}
}

Expand Down
15 changes: 7 additions & 8 deletions src/librustc_trans/back/lto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use errors::{FatalError, Handler};
use llvm;
use llvm::archive_ro::ArchiveRO;
use llvm::{ModuleRef, TargetMachineRef, True, False};
use rustc::middle::exported_symbols;
use rustc::middle::exported_symbols::SymbolExportLevel;
use rustc::util::common::time;
use rustc::util::common::path2cstr;
use rustc::hir::def_id::LOCAL_CRATE;
Expand Down Expand Up @@ -68,8 +68,8 @@ pub fn run(cgcx: &CodegenContext,
let export_threshold =
symbol_export::crates_export_threshold(&cgcx.crate_types);

let symbol_filter = &|&(ref name, _, level): &(String, _, _)| {
if exported_symbols::is_below_threshold(level, export_threshold) {
let symbol_filter = &|&(ref name, _, level): &(String, _, SymbolExportLevel)| {
if level.is_below_threshold(export_threshold) {
let mut bytes = Vec::with_capacity(name.len() + 1);
bytes.extend(name.bytes());
Some(CString::new(bytes).unwrap())
Expand All @@ -78,8 +78,7 @@ pub fn run(cgcx: &CodegenContext,
}
};

let mut symbol_white_list: Vec<CString> = cgcx.exported_symbols
.exported_symbols(LOCAL_CRATE)
let mut symbol_white_list: Vec<CString> = cgcx.exported_symbols[&LOCAL_CRATE]
.iter()
.filter_map(symbol_filter)
.collect();
Expand All @@ -89,9 +88,9 @@ pub fn run(cgcx: &CodegenContext,
// module that we've got.
for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() {
symbol_white_list.extend(
cgcx.exported_symbols.exported_symbols(cnum)
.iter()
.filter_map(symbol_filter));
cgcx.exported_symbols[&cnum]
.iter()
.filter_map(symbol_filter));

let archive = ArchiveRO::open(&path).expect("wanted an rlib");
let bytecodes = archive.iter().filter_map(|child| {
Expand Down
Loading

0 comments on commit afb85cf

Please sign in to comment.