Skip to content

Commit

Permalink
Auto merge of #16329 - Veykril:perfperf, r=Veykril
Browse files Browse the repository at this point in the history
internal: Some minor perf/memory improvements
  • Loading branch information
bors committed Jan 9, 2024
2 parents 51ac6de + f8b130a commit ae6e737
Show file tree
Hide file tree
Showing 16 changed files with 315 additions and 267 deletions.
1 change: 1 addition & 0 deletions crates/base-db/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub trait Upcast<T: ?Sized> {
}

pub const DEFAULT_PARSE_LRU_CAP: usize = 128;
pub const DEFAULT_BORROWCK_LRU_CAP: usize = 256;

pub trait FileLoader {
/// Text of the file.
Expand Down
2 changes: 1 addition & 1 deletion crates/hir-def/src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ fn parse_comma_sep<S>(subtree: &tt::Subtree<S>) -> Vec<SmolStr> {
}

impl AttrsWithOwner {
pub(crate) fn attrs_with_owner(db: &dyn DefDatabase, owner: AttrDefId) -> Self {
pub fn attrs_with_owner(db: &dyn DefDatabase, owner: AttrDefId) -> Self {
Self { attrs: db.attrs(owner), owner }
}

Expand Down
7 changes: 2 additions & 5 deletions crates/hir-def/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,10 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
#[salsa::invoke(AttrsWithOwner::attrs_query)]
fn attrs(&self, def: AttrDefId) -> Attrs;

#[salsa::transparent]
#[salsa::invoke(lang_item::lang_attr_query)]
fn lang_attr(&self, def: AttrDefId) -> Option<LangItem>;

#[salsa::transparent]
#[salsa::invoke(AttrsWithOwner::attrs_with_owner)]
fn attrs_with_owner(&self, def: AttrDefId) -> AttrsWithOwner;

// endregion:attrs

#[salsa::invoke(LangItems::lang_item_query)]
Expand All @@ -240,7 +237,7 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
// endregion:visibilities

#[salsa::invoke(LangItems::crate_lang_items_query)]
fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>;
fn crate_lang_items(&self, krate: CrateId) -> Option<Arc<LangItems>>;

fn crate_supports_no_std(&self, crate_id: CrateId) -> bool;
}
Expand Down
241 changes: 133 additions & 108 deletions crates/hir-def/src/generics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ impl TypeOrConstParamData {
impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);

/// Data about the generic parameters of a function, struct, impl, etc.
#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct GenericParams {
pub type_or_consts: Arena<TypeOrConstParamData>,
pub lifetimes: Arena<LifetimeParamData>,
pub where_predicates: Vec<WherePredicate>,
pub where_predicates: Box<[WherePredicate]>,
}

/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined
Expand Down Expand Up @@ -142,109 +142,14 @@ pub enum WherePredicateTypeTarget {
TypeOrConstParam(LocalTypeOrConstParamId),
}

impl GenericParams {
/// Iterator of type_or_consts field
pub fn iter(
&self,
) -> impl DoubleEndedIterator<Item = (Idx<TypeOrConstParamData>, &TypeOrConstParamData)> {
self.type_or_consts.iter()
}

pub(crate) fn generic_params_query(
db: &dyn DefDatabase,
def: GenericDefId,
) -> Interned<GenericParams> {
let _p = profile::span("generic_params_query");

let krate = def.module(db).krate;
let cfg_options = db.crate_graph();
let cfg_options = &cfg_options[krate].cfg_options;

// Returns the generic parameters that are enabled under the current `#[cfg]` options
let enabled_params = |params: &Interned<GenericParams>, item_tree: &ItemTree| {
let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);

// In the common case, no parameters will by disabled by `#[cfg]` attributes.
// Therefore, make a first pass to check if all parameters are enabled and, if so,
// clone the `Interned<GenericParams>` instead of recreating an identical copy.
let all_type_or_consts_enabled =
params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into()));
let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into()));

if all_type_or_consts_enabled && all_lifetimes_enabled {
params.clone()
} else {
Interned::new(GenericParams {
type_or_consts: all_type_or_consts_enabled
.then(|| params.type_or_consts.clone())
.unwrap_or_else(|| {
params
.type_or_consts
.iter()
.filter_map(|(idx, param)| {
enabled(idx.into()).then(|| param.clone())
})
.collect()
}),
lifetimes: all_lifetimes_enabled
.then(|| params.lifetimes.clone())
.unwrap_or_else(|| {
params
.lifetimes
.iter()
.filter_map(|(idx, param)| {
enabled(idx.into()).then(|| param.clone())
})
.collect()
}),
where_predicates: params.where_predicates.clone(),
})
}
};
macro_rules! id_to_generics {
($id:ident) => {{
let id = $id.lookup(db).id;
let tree = id.item_tree(db);
let item = &tree[id.value];
enabled_params(&item.generic_params, &tree)
}};
}

match def {
GenericDefId::FunctionId(id) => {
let loc = id.lookup(db);
let tree = loc.id.item_tree(db);
let item = &tree[loc.id.value];

let enabled_params = enabled_params(&item.explicit_generic_params, &tree);
let mut generic_params = GenericParams::clone(&enabled_params);

let module = loc.container.module(db);
let func_data = db.function_data(id);

// Don't create an `Expander` if not needed since this
// could cause a reparse after the `ItemTree` has been created due to the spanmap.
let mut expander =
Lazy::new(|| (module.def_map(db), Expander::new(db, loc.id.file_id(), module)));
for param in func_data.params.iter() {
generic_params.fill_implicit_impl_trait_args(db, &mut expander, param);
}

Interned::new(generic_params)
}
GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id),
GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id),
GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id),
GenericDefId::TraitId(id) => id_to_generics!(id),
GenericDefId::TraitAliasId(id) => id_to_generics!(id),
GenericDefId::TypeAliasId(id) => id_to_generics!(id),
GenericDefId::ImplId(id) => id_to_generics!(id),
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
Interned::new(GenericParams::default())
}
}
}
#[derive(Clone, Default)]
pub(crate) struct GenericParamsCollector {
pub(crate) type_or_consts: Arena<TypeOrConstParamData>,
lifetimes: Arena<LifetimeParamData>,
where_predicates: Vec<WherePredicate>,
}

impl GenericParamsCollector {
pub(crate) fn fill(
&mut self,
lower_ctx: &LowerCtx<'_>,
Expand Down Expand Up @@ -444,11 +349,131 @@ impl GenericParams {
});
}

pub(crate) fn shrink_to_fit(&mut self) {
let Self { lifetimes, type_or_consts: types, where_predicates } = self;
pub(crate) fn finish(self) -> GenericParams {
let Self { mut lifetimes, mut type_or_consts, where_predicates } = self;
lifetimes.shrink_to_fit();
types.shrink_to_fit();
where_predicates.shrink_to_fit();
type_or_consts.shrink_to_fit();
GenericParams {
type_or_consts,
lifetimes,
where_predicates: where_predicates.into_boxed_slice(),
}
}
}

impl GenericParams {
/// Iterator of type_or_consts field
pub fn iter(
&self,
) -> impl DoubleEndedIterator<Item = (Idx<TypeOrConstParamData>, &TypeOrConstParamData)> {
self.type_or_consts.iter()
}

pub(crate) fn generic_params_query(
db: &dyn DefDatabase,
def: GenericDefId,
) -> Interned<GenericParams> {
let _p = profile::span("generic_params_query");

let krate = def.module(db).krate;
let cfg_options = db.crate_graph();
let cfg_options = &cfg_options[krate].cfg_options;

// Returns the generic parameters that are enabled under the current `#[cfg]` options
let enabled_params = |params: &Interned<GenericParams>, item_tree: &ItemTree| {
let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);

// In the common case, no parameters will by disabled by `#[cfg]` attributes.
// Therefore, make a first pass to check if all parameters are enabled and, if so,
// clone the `Interned<GenericParams>` instead of recreating an identical copy.
let all_type_or_consts_enabled =
params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into()));
let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into()));

if all_type_or_consts_enabled && all_lifetimes_enabled {
params.clone()
} else {
Interned::new(GenericParams {
type_or_consts: all_type_or_consts_enabled
.then(|| params.type_or_consts.clone())
.unwrap_or_else(|| {
params
.type_or_consts
.iter()
.filter_map(|(idx, param)| {
enabled(idx.into()).then(|| param.clone())
})
.collect()
}),
lifetimes: all_lifetimes_enabled
.then(|| params.lifetimes.clone())
.unwrap_or_else(|| {
params
.lifetimes
.iter()
.filter_map(|(idx, param)| {
enabled(idx.into()).then(|| param.clone())
})
.collect()
}),
where_predicates: params.where_predicates.clone(),
})
}
};
macro_rules! id_to_generics {
($id:ident) => {{
let id = $id.lookup(db).id;
let tree = id.item_tree(db);
let item = &tree[id.value];
enabled_params(&item.generic_params, &tree)
}};
}

match def {
GenericDefId::FunctionId(id) => {
let loc = id.lookup(db);
let tree = loc.id.item_tree(db);
let item = &tree[loc.id.value];

let enabled_params = enabled_params(&item.explicit_generic_params, &tree);

let module = loc.container.module(db);
let func_data = db.function_data(id);
if func_data.params.is_empty() {
enabled_params
} else {
let mut generic_params = GenericParamsCollector {
type_or_consts: enabled_params.type_or_consts.clone(),
lifetimes: enabled_params.lifetimes.clone(),
where_predicates: enabled_params.where_predicates.clone().into(),
};

// Don't create an `Expander` if not needed since this
// could cause a reparse after the `ItemTree` has been created due to the spanmap.
let mut expander = Lazy::new(|| {
(module.def_map(db), Expander::new(db, loc.id.file_id(), module))
});
for param in func_data.params.iter() {
generic_params.fill_implicit_impl_trait_args(db, &mut expander, param);
}
Interned::new(generic_params.finish())
}
}
GenericDefId::AdtId(AdtId::StructId(id)) => id_to_generics!(id),
GenericDefId::AdtId(AdtId::EnumId(id)) => id_to_generics!(id),
GenericDefId::AdtId(AdtId::UnionId(id)) => id_to_generics!(id),
GenericDefId::TraitId(id) => id_to_generics!(id),
GenericDefId::TraitAliasId(id) => id_to_generics!(id),
GenericDefId::TypeAliasId(id) => id_to_generics!(id),
GenericDefId::ImplId(id) => id_to_generics!(id),
GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
Interned::new(GenericParams {
type_or_consts: Default::default(),
lifetimes: Default::default(),
where_predicates: Default::default(),
})
}
}
}

pub fn find_type_by_name(&self, name: &Name, parent: GenericDefId) -> Option<TypeParamId> {
Expand Down
3 changes: 1 addition & 2 deletions crates/hir-def/src/hir/type_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,7 @@ pub enum TypeRef {
Path(Path),
RawPtr(Box<TypeRef>, Mutability),
Reference(Box<TypeRef>, Option<LifetimeRef>, Mutability),
// FIXME: for full const generics, the latter element (length) here is going to have to be an
// expression that is further lowered later in hir_ty.
// FIXME: This should be Array(Box<TypeRef>, Ast<ConstArg>),
Array(Box<TypeRef>, ConstRef),
Slice(Box<TypeRef>),
/// A fn pointer. Last element of the vector is the return type.
Expand Down
12 changes: 5 additions & 7 deletions crates/hir-def/src/item_tree/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use hir_expand::{ast_id_map::AstIdMap, span_map::SpanMapRef, HirFileId};
use syntax::ast::{self, HasModuleItem, HasTypeBounds};

use crate::{
generics::{GenericParams, TypeParamData, TypeParamProvenance},
generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
type_ref::{LifetimeRef, TraitBoundModifier, TraitRef},
LocalLifetimeParamId, LocalTypeOrConstParamId,
};
Expand Down Expand Up @@ -386,17 +386,16 @@ impl<'a> Ctx<'a> {
flags |= FnFlags::HAS_UNSAFE_KW;
}

let mut res = Function {
let res = Function {
name,
visibility,
explicit_generic_params: Interned::new(GenericParams::default()),
explicit_generic_params: self.lower_generic_params(HasImplicitSelf::No, func),
abi,
params,
ret_type: Interned::new(ret_type),
ast_id,
flags,
};
res.explicit_generic_params = self.lower_generic_params(HasImplicitSelf::No, func);

Some(id(self.data().functions.alloc(res)))
}
Expand Down Expand Up @@ -604,7 +603,7 @@ impl<'a> Ctx<'a> {
has_implicit_self: HasImplicitSelf,
node: &dyn ast::HasGenericParams,
) -> Interned<GenericParams> {
let mut generics = GenericParams::default();
let mut generics = GenericParamsCollector::default();

if let HasImplicitSelf::Yes(bounds) = has_implicit_self {
// Traits and trait aliases get the Self type as an implicit first type parameter.
Expand Down Expand Up @@ -642,8 +641,7 @@ impl<'a> Ctx<'a> {
};
generics.fill(&self.body_ctx, node, add_param_attrs);

generics.shrink_to_fit();
Interned::new(generics)
Interned::new(generics.finish())
}

fn lower_type_bounds(&mut self, node: &dyn ast::HasTypeBounds) -> Box<[Interned<TypeBound>]> {
Expand Down
Loading

0 comments on commit ae6e737

Please sign in to comment.