Skip to content

Commit

Permalink
Auto merge of #81398 - bugadani:rustdoc-perf, r=GuillaumeGomez
Browse files Browse the repository at this point in the history
rustdoc tweaking

* Reuse memory
* simplify `next_def_id`, avoid multiple hashing and unnecessary lookups
* remove `all_fake_def_ids`, use the global map instead (probably not a good step toward parallelization, though...)
* convert `add_deref_target` to iterative implementation
* use `ArrayVec` where we know the max number of elements
* minor touchups here and there
* avoid building temporary vectors that get appended to other vectors

At most places I may or may not be doing the compiler's job is this PR.
  • Loading branch information
bors committed Jan 30, 2021
2 parents 9fa9b58 + 4b80687 commit 0248c6f
Show file tree
Hide file tree
Showing 16 changed files with 521 additions and 512 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4386,6 +4386,7 @@ dependencies = [
name = "rustdoc"
version = "0.0.0"
dependencies = [
"arrayvec",
"expect-test",
"itertools 0.9.0",
"minifier",
Expand Down
1 change: 1 addition & 0 deletions src/librustdoc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2018"
path = "lib.rs"

[dependencies]
arrayvec = { version = "0.5.1", default-features = false }
pulldown-cmark = { version = "0.8", default-features = false }
minifier = "0.0.33"
rayon = { version = "0.3.0", package = "rustc-rayon" }
Expand Down
25 changes: 10 additions & 15 deletions src/librustdoc/clean/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ crate fn try_inline(
let kind = match res {
Res::Def(DefKind::Trait, did) => {
record_extern_fqn(cx, did, clean::TypeKind::Trait);
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
clean::TraitItem(build_external_trait(cx, did))
}
Res::Def(DefKind::Fn, did) => {
Expand All @@ -65,27 +65,27 @@ crate fn try_inline(
}
Res::Def(DefKind::Struct, did) => {
record_extern_fqn(cx, did, clean::TypeKind::Struct);
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
clean::StructItem(build_struct(cx, did))
}
Res::Def(DefKind::Union, did) => {
record_extern_fqn(cx, did, clean::TypeKind::Union);
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
clean::UnionItem(build_union(cx, did))
}
Res::Def(DefKind::TyAlias, did) => {
record_extern_fqn(cx, did, clean::TypeKind::Typedef);
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
clean::TypedefItem(build_type_alias(cx, did), false)
}
Res::Def(DefKind::Enum, did) => {
record_extern_fqn(cx, did, clean::TypeKind::Enum);
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
clean::EnumItem(build_enum(cx, did))
}
Res::Def(DefKind::ForeignTy, did) => {
record_extern_fqn(cx, did, clean::TypeKind::Foreign);
ret.extend(build_impls(cx, Some(parent_module), did, attrs));
build_impls(cx, Some(parent_module), did, attrs, &mut ret);
clean::ForeignTypeItem
}
// Never inline enum variants but leave them shown as re-exports.
Expand Down Expand Up @@ -133,10 +133,7 @@ crate fn try_inline_glob(
res: Res,
visited: &mut FxHashSet<DefId>,
) -> Option<Vec<clean::Item>> {
if res == Res::Err {
return None;
}
let did = res.def_id();
let did = res.opt_def_id()?;
if did.is_local() {
return None;
}
Expand Down Expand Up @@ -280,16 +277,14 @@ crate fn build_impls(
parent_module: Option<DefId>,
did: DefId,
attrs: Option<Attrs<'_>>,
) -> Vec<clean::Item> {
ret: &mut Vec<clean::Item>,
) {
let tcx = cx.tcx;
let mut impls = Vec::new();

// for each implementation of an item represented by `did`, build the clean::Item for that impl
for &did in tcx.inherent_impls(did).iter() {
build_impl(cx, parent_module, did, attrs, &mut impls);
build_impl(cx, parent_module, did, attrs, ret);
}

impls
}

/// `parent_module` refers to the parent of the re-export, not the original item
Expand Down
28 changes: 14 additions & 14 deletions src/librustdoc/clean/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::rc::Rc;
use std::sync::Arc;
use std::{slice, vec};

use arrayvec::ArrayVec;
use rustc_ast::attr;
use rustc_ast::util::comments::beautify_doc_string;
use rustc_ast::{self as ast, AttrStyle};
Expand All @@ -16,7 +17,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_feature::UnstableFeatures;
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, Res};
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
use rustc_hir::lang_items::LangItem;
use rustc_hir::Mutability;
use rustc_index::vec::IndexVec;
Expand All @@ -28,7 +29,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol, SymbolStr};
use rustc_span::{self, FileName, Loc};
use rustc_target::abi::VariantIdx;
use rustc_target::spec::abi::Abi;
use smallvec::{smallvec, SmallVec};

use crate::clean::cfg::Cfg;
use crate::clean::external_path;
Expand All @@ -45,7 +45,7 @@ use self::ItemKind::*;
use self::SelfTy::*;
use self::Type::*;

thread_local!(crate static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = Default::default());
thread_local!(crate static MAX_DEF_IDX: RefCell<FxHashMap<CrateNum, DefIndex>> = Default::default());

#[derive(Clone, Debug)]
crate struct Crate {
Expand Down Expand Up @@ -293,8 +293,8 @@ impl Item {
///
/// [`next_def_id()`]: DocContext::next_def_id()
crate fn is_fake(&self) -> bool {
MAX_DEF_ID.with(|m| {
m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false)
MAX_DEF_IDX.with(|m| {
m.borrow().get(&self.def_id.krate).map(|&idx| idx <= self.def_id.index).unwrap_or(false)
})
}
}
Expand Down Expand Up @@ -1539,12 +1539,12 @@ impl PrimitiveType {
}
}

crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static SmallVec<[DefId; 4]> {
crate fn impls(&self, tcx: TyCtxt<'_>) -> &'static ArrayVec<[DefId; 4]> {
Self::all_impls(tcx).get(self).expect("missing impl for primitive type")
}

crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>> {
static CELL: OnceCell<FxHashMap<PrimitiveType, SmallVec<[DefId; 4]>>> = OnceCell::new();
crate fn all_impls(tcx: TyCtxt<'_>) -> &'static FxHashMap<PrimitiveType, ArrayVec<[DefId; 4]>> {
static CELL: OnceCell<FxHashMap<PrimitiveType, ArrayVec<[DefId; 4]>>> = OnceCell::new();

CELL.get_or_init(move || {
use self::PrimitiveType::*;
Expand All @@ -1568,7 +1568,7 @@ impl PrimitiveType {
}

let single = |a: Option<DefId>| a.into_iter().collect();
let both = |a: Option<DefId>, b: Option<DefId>| -> SmallVec<_> {
let both = |a: Option<DefId>, b: Option<DefId>| -> ArrayVec<_> {
a.into_iter().chain(b).collect()
};

Expand Down Expand Up @@ -1601,8 +1601,8 @@ impl PrimitiveType {
.collect()
},
Array => single(lang_items.array_impl()),
Tuple => smallvec![],
Unit => smallvec![],
Tuple => ArrayVec::new(),
Unit => ArrayVec::new(),
RawPointer => {
lang_items
.const_ptr_impl()
Expand All @@ -1612,9 +1612,9 @@ impl PrimitiveType {
.chain(lang_items.mut_slice_ptr_impl())
.collect()
},
Reference => smallvec![],
Fn => smallvec![],
Never => smallvec![],
Reference => ArrayVec::new(),
Fn => ArrayVec::new(),
Never => ArrayVec::new(),
}
})
}
Expand Down
18 changes: 6 additions & 12 deletions src/librustdoc/clean/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,20 +322,14 @@ crate fn build_deref_target_impls(cx: &DocContext<'_>, items: &[Item], ret: &mut
ItemKind::TypedefItem(ref t, true) => &t.type_,
_ => continue,
};
let primitive = match *target {
ResolvedPath { did, .. } if did.is_local() => continue,
ResolvedPath { did, .. } => {
ret.extend(inline::build_impls(cx, None, did, None));
continue;

if let Some(prim) = target.primitive_type() {
for &did in prim.impls(tcx).iter().filter(|did| !did.is_local()) {
inline::build_impl(cx, None, did, None, ret);
}
_ => match target.primitive_type() {
Some(prim) => prim,
None => continue,
},
};
for &did in primitive.impls(tcx) {
} else if let ResolvedPath { did, .. } = *target {
if !did.is_local() {
inline::build_impl(cx, None, did, None, ret);
inline::build_impls(cx, None, did, None, ret);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ impl Options {
};

let mut id_map = html::markdown::IdMap::new();
id_map.populate(html::render::initial_ids());
id_map.populate(&html::render::INITIAL_IDS);
let external_html = match ExternalHtml::load(
&matches.opt_strs("html-in-header"),
&matches.opt_strs("html-before-content"),
Expand Down
58 changes: 30 additions & 28 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,15 @@ use rustc_span::source_map;
use rustc_span::symbol::sym;
use rustc_span::DUMMY_SP;

use std::cell::{Cell, RefCell};
use std::mem;
use std::rc::Rc;
use std::{
cell::{Cell, RefCell},
collections::hash_map::Entry,
};

use crate::clean;
use crate::clean::{AttributesExt, MAX_DEF_ID};
use crate::clean::{AttributesExt, MAX_DEF_IDX};
use crate::config::{Options as RustdocOptions, RenderOptions};
use crate::config::{OutputFormat, RenderInfo};
use crate::formats::cache::Cache;
Expand Down Expand Up @@ -63,8 +66,7 @@ crate struct DocContext<'tcx> {
crate ct_substs: RefCell<FxHashMap<DefId, clean::Constant>>,
/// Table synthetic type parameter for `impl Trait` in argument position -> bounds
crate impl_trait_bounds: RefCell<FxHashMap<ImplTraitParam, Vec<clean::GenericBound>>>,
crate fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
crate all_fake_def_ids: RefCell<FxHashSet<DefId>>,
crate fake_def_ids: RefCell<FxHashMap<CrateNum, DefIndex>>,
/// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`.
// FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set.
crate generated_synthetics: RefCell<FxHashSet<(Ty<'tcx>, DefId)>>,
Expand Down Expand Up @@ -138,37 +140,38 @@ impl<'tcx> DocContext<'tcx> {
/// [`Debug`]: std::fmt::Debug
/// [`clean::Item`]: crate::clean::types::Item
crate fn next_def_id(&self, crate_num: CrateNum) -> DefId {
let start_def_id = {
let num_def_ids = if crate_num == LOCAL_CRATE {
self.tcx.hir().definitions().def_path_table().num_def_ids()
} else {
self.enter_resolver(|r| r.cstore().num_def_ids(crate_num))
};

DefId { krate: crate_num, index: DefIndex::from_usize(num_def_ids) }
};

let mut fake_ids = self.fake_def_ids.borrow_mut();

let def_id = *fake_ids.entry(crate_num).or_insert(start_def_id);
fake_ids.insert(
crate_num,
DefId { krate: crate_num, index: DefIndex::from(def_id.index.index() + 1) },
);

MAX_DEF_ID.with(|m| {
m.borrow_mut().entry(def_id.krate).or_insert(start_def_id);
});

self.all_fake_def_ids.borrow_mut().insert(def_id);
let def_index = match fake_ids.entry(crate_num) {
Entry::Vacant(e) => {
let num_def_idx = {
let num_def_idx = if crate_num == LOCAL_CRATE {
self.tcx.hir().definitions().def_path_table().num_def_ids()
} else {
self.enter_resolver(|r| r.cstore().num_def_ids(crate_num))
};

DefIndex::from_usize(num_def_idx)
};

MAX_DEF_IDX.with(|m| {
m.borrow_mut().insert(crate_num, num_def_idx);
});
e.insert(num_def_idx)
}
Entry::Occupied(e) => e.into_mut(),
};
*def_index = DefIndex::from(*def_index + 1);

def_id
DefId { krate: crate_num, index: *def_index }
}

/// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
/// (This avoids a slice-index-out-of-bounds panic.)
crate fn as_local_hir_id(&self, def_id: DefId) -> Option<HirId> {
if self.all_fake_def_ids.borrow().contains(&def_id) {
if MAX_DEF_IDX.with(|m| {
m.borrow().get(&def_id.krate).map(|&idx| idx <= def_id.index).unwrap_or(false)
}) {
None
} else {
def_id.as_local().map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
Expand Down Expand Up @@ -517,7 +520,6 @@ crate fn run_global_ctxt(
ct_substs: Default::default(),
impl_trait_bounds: Default::default(),
fake_def_ids: Default::default(),
all_fake_def_ids: Default::default(),
generated_synthetics: Default::default(),
auto_traits: tcx
.all_traits(LOCAL_CRATE)
Expand Down
2 changes: 1 addition & 1 deletion src/librustdoc/formats/item_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,6 @@ impl ItemType {

impl fmt::Display for ItemType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
f.write_str(self.as_str())
}
}
31 changes: 14 additions & 17 deletions src/librustdoc/html/escape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,20 @@ impl<'a> fmt::Display for Escape<'a> {
let Escape(s) = *self;
let pile_o_bits = s;
let mut last = 0;
for (i, ch) in s.bytes().enumerate() {
match ch as char {
'<' | '>' | '&' | '\'' | '"' => {
fmt.write_str(&pile_o_bits[last..i])?;
let s = match ch as char {
'>' => "&gt;",
'<' => "&lt;",
'&' => "&amp;",
'\'' => "&#39;",
'"' => "&quot;",
_ => unreachable!(),
};
fmt.write_str(s)?;
last = i + 1;
}
_ => {}
}
for (i, ch) in s.char_indices() {
let s = match ch {
'>' => "&gt;",
'<' => "&lt;",
'&' => "&amp;",
'\'' => "&#39;",
'"' => "&quot;",
_ => continue,
};
fmt.write_str(&pile_o_bits[last..i])?;
fmt.write_str(s)?;
// NOTE: we only expect single byte characters here - which is fine as long as we
// only match single byte characters
last = i + 1;
}

if last < s.len() {
Expand Down
Loading

0 comments on commit 0248c6f

Please sign in to comment.