Skip to content

Commit d31d71e

Browse files
committed
[perf] WIP
1 parent c8e6a9e commit d31d71e

File tree

7 files changed

+124
-32
lines changed

7 files changed

+124
-32
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
12401240
}
12411241
}
12421242

1243+
fn get_rustdoc_reachable(self) -> impl Iterator<Item = DefId> + 'a {
1244+
self.root.rustdoc_reachable.decode(self)
1245+
}
1246+
12431247
fn get_native_libraries(self, sess: &'a Session) -> impl Iterator<Item = NativeLib> + 'a {
12441248
self.root.native_libraries.decode((self, sess))
12451249
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,10 @@ impl CStore {
624624
self.get_crate_data(cnum).get_all_incoherent_impls()
625625
}
626626

627+
pub fn rustdoc_reachable_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ {
628+
self.get_crate_data(cnum).get_rustdoc_reachable()
629+
}
630+
627631
pub fn associated_item_def_ids_untracked<'a>(
628632
&'a self,
629633
def_id: DefId,

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 107 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::rmeta::*;
55

66
use rustc_ast::Attribute;
77
use rustc_data_structures::fingerprint::Fingerprint;
8-
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
8+
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
99
use rustc_data_structures::memmap::{Mmap, MmapMut};
1010
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1111
use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
@@ -598,6 +598,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
598598

599599
let incoherent_impls = stat!("incoherent-impls", || self.encode_incoherent_impls());
600600

601+
let rustdoc_reachable = stat!("rustdoc-reachable", || self.encode_rustdoc_reachable());
602+
601603
_ = stat!("mir", || self.encode_mir());
602604

603605
_ = stat!("items", || {
@@ -698,6 +700,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
698700
traits,
699701
impls,
700702
incoherent_impls,
703+
rustdoc_reachable,
701704
exported_symbols,
702705
interpret_alloc_index,
703706
tables,
@@ -1256,7 +1259,40 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
12561259
}
12571260
}
12581261

1259-
fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) {
1262+
fn module_children(
1263+
tcx: TyCtxt<'tcx>,
1264+
md: &'tcx hir::Mod<'tcx>,
1265+
) -> impl Iterator<Item = DefIndex> + 'tcx {
1266+
iter::from_generator(move || {
1267+
for item_id in md.item_ids {
1268+
match tcx.hir().item(*item_id).kind {
1269+
// Foreign items are planted into their parent modules
1270+
// from name resolution point of view.
1271+
hir::ItemKind::ForeignMod { items, .. } => {
1272+
for foreign_item in items {
1273+
yield foreign_item.id.owner_id.def_id.local_def_index;
1274+
}
1275+
}
1276+
// Only encode named non-reexport children, reexports are encoded
1277+
// separately and unnamed items are not used by name resolution.
1278+
hir::ItemKind::ExternCrate(..) => continue,
1279+
hir::ItemKind::Struct(ref vdata, _) => {
1280+
yield item_id.owner_id.def_id.local_def_index;
1281+
// Encode constructors which take a separate slot in value namespace.
1282+
if let Some(ctor_hir_id) = vdata.ctor_hir_id() {
1283+
yield tcx.hir().local_def_id(ctor_hir_id).local_def_index;
1284+
}
1285+
}
1286+
_ if tcx.def_key(item_id.owner_id.to_def_id()).get_opt_name().is_some() => {
1287+
yield item_id.owner_id.def_id.local_def_index;
1288+
}
1289+
_ => continue,
1290+
}
1291+
}
1292+
})
1293+
}
1294+
1295+
fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &'tcx hir::Mod<'tcx>) {
12601296
let tcx = self.tcx;
12611297
let def_id = local_def_id.to_def_id();
12621298
debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
@@ -1270,33 +1306,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
12701306
// Encode this here because we don't do it in encode_def_ids.
12711307
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
12721308
} else {
1273-
record_array!(self.tables.children[def_id] <- iter::from_generator(|| {
1274-
for item_id in md.item_ids {
1275-
match tcx.hir().item(*item_id).kind {
1276-
// Foreign items are planted into their parent modules
1277-
// from name resolution point of view.
1278-
hir::ItemKind::ForeignMod { items, .. } => {
1279-
for foreign_item in items {
1280-
yield foreign_item.id.owner_id.def_id.local_def_index;
1281-
}
1282-
}
1283-
// Only encode named non-reexport children, reexports are encoded
1284-
// separately and unnamed items are not used by name resolution.
1285-
hir::ItemKind::ExternCrate(..) => continue,
1286-
hir::ItemKind::Struct(ref vdata, _) => {
1287-
yield item_id.owner_id.def_id.local_def_index;
1288-
// Encode constructors which take a separate slot in value namespace.
1289-
if let Some(ctor_hir_id) = vdata.ctor_hir_id() {
1290-
yield tcx.hir().local_def_id(ctor_hir_id).local_def_index;
1291-
}
1292-
}
1293-
_ if tcx.def_key(item_id.owner_id.to_def_id()).get_opt_name().is_some() => {
1294-
yield item_id.owner_id.def_id.local_def_index;
1295-
}
1296-
_ => continue,
1297-
}
1298-
}
1299-
}));
1309+
record_array!(self.tables.children[def_id] <- Self::module_children(tcx, md));
13001310

13011311
if let Some(reexports) = tcx.module_reexports(local_def_id) {
13021312
assert!(!reexports.is_empty());
@@ -1974,6 +1984,74 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
19741984
self.lazy_array(&all_impls)
19751985
}
19761986

1987+
fn encode_rustdoc_reachable(&mut self) -> LazyArray<DefId> {
1988+
struct LibEmbargoVisitor<'tcx> {
1989+
tcx: TyCtxt<'tcx>,
1990+
extern_public: FxHashSet<DefId>,
1991+
visited_mods: FxHashSet<DefId>,
1992+
}
1993+
1994+
impl LibEmbargoVisitor<'_> {
1995+
fn visit_mod(&mut self, def_id: DefId) {
1996+
if !self.visited_mods.insert(def_id) {
1997+
return;
1998+
}
1999+
2000+
let tcx = self.tcx;
2001+
match def_id.as_local() {
2002+
Some(def_id) => {
2003+
let (md, ..) = tcx.hir().get_module(def_id);
2004+
for local_def_index in EncodeContext::module_children(tcx, md) {
2005+
let def_id = LocalDefId { local_def_index }.to_def_id();
2006+
if tcx.visibility(def_id).is_public() {
2007+
self.visit_item(def_id);
2008+
}
2009+
}
2010+
if let Some(reexports) = tcx.module_reexports(def_id) {
2011+
for item in reexports {
2012+
if let Some(def_id) = item.res.opt_def_id() {
2013+
if item.vis.is_public() {
2014+
self.visit_item(def_id);
2015+
}
2016+
}
2017+
}
2018+
}
2019+
}
2020+
None => {
2021+
for item in tcx.module_children(def_id).iter() {
2022+
if let Some(def_id) = item.res.opt_def_id() {
2023+
if item.vis.is_public() {
2024+
self.visit_item(def_id);
2025+
}
2026+
}
2027+
}
2028+
}
2029+
}
2030+
}
2031+
2032+
fn visit_item(&mut self, def_id: DefId) {
2033+
if !self.tcx.is_doc_hidden(def_id) {
2034+
self.extern_public.insert(def_id);
2035+
if self.tcx.def_kind(def_id) == DefKind::Mod {
2036+
self.visit_mod(def_id);
2037+
}
2038+
}
2039+
}
2040+
}
2041+
2042+
let mut visitor = LibEmbargoVisitor {
2043+
tcx: self.tcx,
2044+
extern_public: Default::default(),
2045+
visited_mods: Default::default(),
2046+
};
2047+
visitor.visit_item(CRATE_DEF_ID.to_def_id());
2048+
2049+
let mut rustdoc_reachable: Vec<_> = visitor.extern_public.into_iter().collect();
2050+
rustdoc_reachable.sort_by_cached_key(|&def_id| self.tcx.def_path_hash(def_id));
2051+
2052+
self.lazy_array(rustdoc_reachable)
2053+
}
2054+
19772055
// Encodes all symbols exported from this crate into the metadata.
19782056
//
19792057
// This pass is seeded off the reachability list calculated in the

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ pub(crate) struct CrateRoot {
239239
traits: LazyArray<DefIndex>,
240240
impls: LazyArray<TraitImpls>,
241241
incoherent_impls: LazyArray<IncoherentImpls>,
242+
rustdoc_reachable: LazyArray<DefId>,
242243
interpret_alloc_index: LazyArray<u32>,
243244
proc_macro_data: Option<ProcMacroData>,
244245

compiler/rustc_middle/src/ty/parameterized.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ trivially_parameterized_over_tcx! {
8181
rustc_hir::IsAsync,
8282
rustc_hir::LangItem,
8383
rustc_hir::def::DefKind,
84+
rustc_hir::def_id::DefId,
8485
rustc_hir::def_id::DefIndex,
8586
rustc_hir::definitions::DefKey,
8687
rustc_index::bit_set::BitSet<u32>,

src/librustdoc/clean/utils.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_ast::tokenstream::TokenTree;
1414
use rustc_hir as hir;
1515
use rustc_hir::def::{DefKind, Res};
1616
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
17+
use rustc_metadata::creader::CStore;
1718
use rustc_middle::mir;
1819
use rustc_middle::mir::interpret::ConstValue;
1920
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
@@ -29,9 +30,12 @@ mod tests;
2930
pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
3031
let module = crate::visit_ast::RustdocVisitor::new(cx).visit();
3132

33+
let cstore = CStore::from_tcx(cx.tcx);
3234
for &cnum in cx.tcx.crates(()) {
33-
// Analyze doc-reachability for extern items
34-
crate::visit_lib::lib_embargo_visit_item(cx, cnum.as_def_id());
35+
Extend::extend(
36+
&mut cx.cache.effective_visibilities.extern_public,
37+
cstore.rustdoc_reachable_untracked(cnum),
38+
);
3539
}
3640

3741
// Clean the crate, translating the entire librustc_ast AST to one that is

src/librustdoc/visit_lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_middle::ty::TyCtxt;
77

88
#[derive(Default)]
99
pub(crate) struct RustdocEffectiveVisibilities {
10-
extern_public: DefIdSet,
10+
pub extern_public: DefIdSet,
1111
}
1212

1313
macro_rules! define_method {

0 commit comments

Comments
 (0)