diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-04-02 17:43:16 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2021-04-02 17:43:16 +0100 |
commit | f4d56989b657b15aec6675cf1ba697e3f87eb088 (patch) | |
tree | 23e4d8265444257f2e4018a003659a711fde0414 /crates/hir_def/src/item_tree.rs | |
parent | 9bcdbefc7b657f34704439d068113180b14359dc (diff) | |
parent | 6e227b80a7686a7ea5bc039d54c307fda29c99ba (diff) |
Merge #8284
8284: Reduce memory usage by using global `Arc`-based interning r=jonas-schievink a=jonas-schievink
This saves around 50 mb when running `analysis-stats` on r-a itself. Not a lot, but this infra can be easily reused to intern more stuff.
Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/hir_def/src/item_tree.rs')
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 94 |
1 files changed, 10 insertions, 84 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 5449bbf5d..69a313c7e 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -30,6 +30,7 @@ use crate::{ | |||
30 | attr::{Attrs, RawAttrs}, | 30 | attr::{Attrs, RawAttrs}, |
31 | db::DefDatabase, | 31 | db::DefDatabase, |
32 | generics::GenericParams, | 32 | generics::GenericParams, |
33 | intern::Interned, | ||
33 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, | 34 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, |
34 | type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, | 35 | type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, |
35 | visibility::RawVisibility, | 36 | visibility::RawVisibility, |
@@ -146,8 +147,6 @@ impl ItemTree { | |||
146 | macro_defs, | 147 | macro_defs, |
147 | vis, | 148 | vis, |
148 | generics, | 149 | generics, |
149 | type_refs, | ||
150 | trait_refs, | ||
151 | inner_items, | 150 | inner_items, |
152 | } = &mut **data; | 151 | } = &mut **data; |
153 | 152 | ||
@@ -172,9 +171,6 @@ impl ItemTree { | |||
172 | 171 | ||
173 | vis.arena.shrink_to_fit(); | 172 | vis.arena.shrink_to_fit(); |
174 | generics.arena.shrink_to_fit(); | 173 | generics.arena.shrink_to_fit(); |
175 | type_refs.arena.shrink_to_fit(); | ||
176 | type_refs.map.shrink_to_fit(); | ||
177 | trait_refs.map.shrink_to_fit(); | ||
178 | 174 | ||
179 | inner_items.shrink_to_fit(); | 175 | inner_items.shrink_to_fit(); |
180 | } | 176 | } |
@@ -271,58 +267,6 @@ static EMPTY_GENERICS: GenericParams = GenericParams { | |||
271 | where_predicates: Vec::new(), | 267 | where_predicates: Vec::new(), |
272 | }; | 268 | }; |
273 | 269 | ||
274 | /// `TypeRef` interner. | ||
275 | #[derive(Default, Debug, Eq, PartialEq)] | ||
276 | struct TypeRefStorage { | ||
277 | arena: Arena<Arc<TypeRef>>, | ||
278 | map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>, | ||
279 | } | ||
280 | |||
281 | impl TypeRefStorage { | ||
282 | // Note: We lie about the `Idx<TypeRef>` to hide the interner details. | ||
283 | |||
284 | fn intern(&mut self, ty: TypeRef) -> Idx<TypeRef> { | ||
285 | if let Some(id) = self.map.get(&ty) { | ||
286 | return Idx::from_raw(id.into_raw()); | ||
287 | } | ||
288 | |||
289 | let ty = Arc::new(ty); | ||
290 | let idx = self.arena.alloc(ty.clone()); | ||
291 | self.map.insert(ty, idx); | ||
292 | Idx::from_raw(idx.into_raw()) | ||
293 | } | ||
294 | |||
295 | fn lookup(&self, id: Idx<TypeRef>) -> &TypeRef { | ||
296 | &self.arena[Idx::from_raw(id.into_raw())] | ||
297 | } | ||
298 | } | ||
299 | |||
300 | /// `TraitRef` interner. | ||
301 | #[derive(Default, Debug, Eq, PartialEq)] | ||
302 | struct TraitRefStorage { | ||
303 | arena: Arena<Arc<TraitRef>>, | ||
304 | map: FxHashMap<Arc<TraitRef>, Idx<Arc<TraitRef>>>, | ||
305 | } | ||
306 | |||
307 | impl TraitRefStorage { | ||
308 | // Note: We lie about the `Idx<TraitRef>` to hide the interner details. | ||
309 | |||
310 | fn intern(&mut self, ty: TraitRef) -> Idx<TraitRef> { | ||
311 | if let Some(id) = self.map.get(&ty) { | ||
312 | return Idx::from_raw(id.into_raw()); | ||
313 | } | ||
314 | |||
315 | let ty = Arc::new(ty); | ||
316 | let idx = self.arena.alloc(ty.clone()); | ||
317 | self.map.insert(ty, idx); | ||
318 | Idx::from_raw(idx.into_raw()) | ||
319 | } | ||
320 | |||
321 | fn lookup(&self, id: Idx<TraitRef>) -> &TraitRef { | ||
322 | &self.arena[Idx::from_raw(id.into_raw())] | ||
323 | } | ||
324 | } | ||
325 | |||
326 | #[derive(Default, Debug, Eq, PartialEq)] | 270 | #[derive(Default, Debug, Eq, PartialEq)] |
327 | struct ItemTreeData { | 271 | struct ItemTreeData { |
328 | imports: Arena<Import>, | 272 | imports: Arena<Import>, |
@@ -346,8 +290,6 @@ struct ItemTreeData { | |||
346 | 290 | ||
347 | vis: ItemVisibilities, | 291 | vis: ItemVisibilities, |
348 | generics: GenericParamsStorage, | 292 | generics: GenericParamsStorage, |
349 | type_refs: TypeRefStorage, | ||
350 | trait_refs: TraitRefStorage, | ||
351 | 293 | ||
352 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | 294 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, |
353 | } | 295 | } |
@@ -577,22 +519,6 @@ impl Index<GenericParamsId> for ItemTree { | |||
577 | } | 519 | } |
578 | } | 520 | } |
579 | 521 | ||
580 | impl Index<Idx<TypeRef>> for ItemTree { | ||
581 | type Output = TypeRef; | ||
582 | |||
583 | fn index(&self, id: Idx<TypeRef>) -> &Self::Output { | ||
584 | self.data().type_refs.lookup(id) | ||
585 | } | ||
586 | } | ||
587 | |||
588 | impl Index<Idx<TraitRef>> for ItemTree { | ||
589 | type Output = TraitRef; | ||
590 | |||
591 | fn index(&self, id: Idx<TraitRef>) -> &Self::Output { | ||
592 | self.data().trait_refs.lookup(id) | ||
593 | } | ||
594 | } | ||
595 | |||
596 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | 522 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { |
597 | type Output = N; | 523 | type Output = N; |
598 | fn index(&self, id: FileItemTreeId<N>) -> &N { | 524 | fn index(&self, id: FileItemTreeId<N>) -> &N { |
@@ -637,13 +563,13 @@ pub struct Function { | |||
637 | /// `extern "abi" fn`). | 563 | /// `extern "abi" fn`). |
638 | pub is_in_extern_block: bool, | 564 | pub is_in_extern_block: bool, |
639 | pub params: IdRange<Param>, | 565 | pub params: IdRange<Param>, |
640 | pub ret_type: Idx<TypeRef>, | 566 | pub ret_type: Interned<TypeRef>, |
641 | pub ast_id: FileAstId<ast::Fn>, | 567 | pub ast_id: FileAstId<ast::Fn>, |
642 | } | 568 | } |
643 | 569 | ||
644 | #[derive(Debug, Clone, Eq, PartialEq)] | 570 | #[derive(Debug, Clone, Eq, PartialEq)] |
645 | pub enum Param { | 571 | pub enum Param { |
646 | Normal(Idx<TypeRef>), | 572 | Normal(Interned<TypeRef>), |
647 | Varargs, | 573 | Varargs, |
648 | } | 574 | } |
649 | 575 | ||
@@ -699,7 +625,7 @@ pub struct Const { | |||
699 | /// const _: () = (); | 625 | /// const _: () = (); |
700 | pub name: Option<Name>, | 626 | pub name: Option<Name>, |
701 | pub visibility: RawVisibilityId, | 627 | pub visibility: RawVisibilityId, |
702 | pub type_ref: Idx<TypeRef>, | 628 | pub type_ref: Interned<TypeRef>, |
703 | pub ast_id: FileAstId<ast::Const>, | 629 | pub ast_id: FileAstId<ast::Const>, |
704 | } | 630 | } |
705 | 631 | ||
@@ -710,7 +636,7 @@ pub struct Static { | |||
710 | pub mutable: bool, | 636 | pub mutable: bool, |
711 | /// Whether the static is in an `extern` block. | 637 | /// Whether the static is in an `extern` block. |
712 | pub is_extern: bool, | 638 | pub is_extern: bool, |
713 | pub type_ref: Idx<TypeRef>, | 639 | pub type_ref: Interned<TypeRef>, |
714 | pub ast_id: FileAstId<ast::Static>, | 640 | pub ast_id: FileAstId<ast::Static>, |
715 | } | 641 | } |
716 | 642 | ||
@@ -729,8 +655,8 @@ pub struct Trait { | |||
729 | #[derive(Debug, Clone, Eq, PartialEq)] | 655 | #[derive(Debug, Clone, Eq, PartialEq)] |
730 | pub struct Impl { | 656 | pub struct Impl { |
731 | pub generic_params: GenericParamsId, | 657 | pub generic_params: GenericParamsId, |
732 | pub target_trait: Option<Idx<TraitRef>>, | 658 | pub target_trait: Option<Interned<TraitRef>>, |
733 | pub self_ty: Idx<TypeRef>, | 659 | pub self_ty: Interned<TypeRef>, |
734 | pub is_negative: bool, | 660 | pub is_negative: bool, |
735 | pub items: Box<[AssocItem]>, | 661 | pub items: Box<[AssocItem]>, |
736 | pub ast_id: FileAstId<ast::Impl>, | 662 | pub ast_id: FileAstId<ast::Impl>, |
@@ -743,7 +669,7 @@ pub struct TypeAlias { | |||
743 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. | 669 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. |
744 | pub bounds: Box<[TypeBound]>, | 670 | pub bounds: Box<[TypeBound]>, |
745 | pub generic_params: GenericParamsId, | 671 | pub generic_params: GenericParamsId, |
746 | pub type_ref: Option<Idx<TypeRef>>, | 672 | pub type_ref: Option<Interned<TypeRef>>, |
747 | pub is_extern: bool, | 673 | pub is_extern: bool, |
748 | pub ast_id: FileAstId<ast::TypeAlias>, | 674 | pub ast_id: FileAstId<ast::TypeAlias>, |
749 | } | 675 | } |
@@ -768,7 +694,7 @@ pub enum ModKind { | |||
768 | #[derive(Debug, Clone, Eq, PartialEq)] | 694 | #[derive(Debug, Clone, Eq, PartialEq)] |
769 | pub struct MacroCall { | 695 | pub struct MacroCall { |
770 | /// Path to the called macro. | 696 | /// Path to the called macro. |
771 | pub path: ModPath, | 697 | pub path: Interned<ModPath>, |
772 | pub ast_id: FileAstId<ast::MacroCall>, | 698 | pub ast_id: FileAstId<ast::MacroCall>, |
773 | } | 699 | } |
774 | 700 | ||
@@ -933,6 +859,6 @@ pub enum Fields { | |||
933 | #[derive(Debug, Clone, PartialEq, Eq)] | 859 | #[derive(Debug, Clone, PartialEq, Eq)] |
934 | pub struct Field { | 860 | pub struct Field { |
935 | pub name: Name, | 861 | pub name: Name, |
936 | pub type_ref: Idx<TypeRef>, | 862 | pub type_ref: Interned<TypeRef>, |
937 | pub visibility: RawVisibilityId, | 863 | pub visibility: RawVisibilityId, |
938 | } | 864 | } |