Skip to content

Commit a16a3d3

Browse files
Shrink ItemTreeSourceMaps
This saves 16mb on `analysis-stats .`.
1 parent fc5bce9 commit a16a3d3

File tree

3 files changed

+155
-73
lines changed

3 files changed

+155
-73
lines changed

src/tools/rust-analyzer/crates/hir-def/src/generics.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -385,15 +385,15 @@ impl GenericParams {
385385
(enabled_params, None)
386386
} else {
387387
let source_maps = loc.id.item_tree_with_source_map(db).1;
388-
let item_source_maps = &source_maps[loc.id.value];
388+
let item_source_maps = source_maps.function(loc.id.value);
389389
let mut generic_params = GenericParamsCollector {
390390
type_or_consts: enabled_params.type_or_consts.clone(),
391391
lifetimes: enabled_params.lifetimes.clone(),
392392
where_predicates: enabled_params.where_predicates.clone().into(),
393393
};
394394

395395
let (mut types_map, mut types_source_maps) =
396-
(enabled_params.types_map.clone(), item_source_maps.generics.clone());
396+
(enabled_params.types_map.clone(), item_source_maps.generics().clone());
397397
// Don't create an `Expander` if not needed since this
398398
// could cause a reparse after the `ItemTree` has been created due to the spanmap.
399399
let mut expander = None;
@@ -408,7 +408,7 @@ impl GenericParams {
408408
},
409409
param,
410410
&item.types_map,
411-
&item_source_maps.item,
411+
item_source_maps.item(),
412412
);
413413
}
414414
let generics = generic_params.finish(types_map, &mut types_source_maps);

src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs

Lines changed: 122 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl ItemTree {
113113
let ctx = lower::Ctx::new(db, file_id);
114114
let syntax = db.parse_or_expand(file_id);
115115
let mut top_attrs = None;
116-
let (mut item_tree, mut source_maps) = match_ast! {
116+
let (mut item_tree, source_maps) = match_ast! {
117117
match syntax {
118118
ast::SourceFile(file) => {
119119
top_attrs = Some(RawAttrs::new(db.upcast(), &file, ctx.span_map()));
@@ -155,7 +155,6 @@ impl ItemTree {
155155
.clone()
156156
} else {
157157
item_tree.shrink_to_fit();
158-
source_maps.shrink_to_fit();
159158
(Arc::new(item_tree), Arc::new(source_maps))
160159
}
161160
}
@@ -175,7 +174,7 @@ impl ItemTree {
175174
let block = loc.ast_id.to_node(db.upcast());
176175

177176
let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
178-
let (mut item_tree, mut source_maps) = ctx.lower_block(&block);
177+
let (mut item_tree, source_maps) = ctx.lower_block(&block);
179178
if item_tree.data.is_none() && item_tree.top_level.is_empty() && item_tree.attrs.is_empty()
180179
{
181180
EMPTY
@@ -192,7 +191,6 @@ impl ItemTree {
192191
.clone()
193192
} else {
194193
item_tree.shrink_to_fit();
195-
source_maps.shrink_to_fit();
196194
(Arc::new(item_tree), Arc::new(source_maps))
197195
}
198196
}
@@ -331,29 +329,59 @@ struct ItemTreeData {
331329
}
332330

333331
#[derive(Default, Debug, Eq, PartialEq)]
334-
pub struct GenericItemSourceMap {
332+
pub struct ItemTreeSourceMaps {
333+
all_concatenated: Box<[TypesSourceMap]>,
334+
structs_offset: u32,
335+
unions_offset: u32,
336+
enum_generics_offset: u32,
337+
variants_offset: u32,
338+
consts_offset: u32,
339+
statics_offset: u32,
340+
trait_generics_offset: u32,
341+
trait_alias_generics_offset: u32,
342+
impls_offset: u32,
343+
type_aliases_offset: u32,
344+
}
345+
346+
#[derive(Clone, Copy)]
347+
pub struct GenericItemSourceMap<'a>(&'a [TypesSourceMap; 2]);
348+
349+
impl<'a> GenericItemSourceMap<'a> {
350+
#[inline]
351+
pub fn item(self) -> &'a TypesSourceMap {
352+
&self.0[0]
353+
}
354+
355+
#[inline]
356+
pub fn generics(self) -> &'a TypesSourceMap {
357+
&self.0[1]
358+
}
359+
}
360+
361+
#[derive(Default, Debug, Eq, PartialEq)]
362+
pub struct GenericItemSourceMapBuilder {
335363
pub item: TypesSourceMap,
336364
pub generics: TypesSourceMap,
337365
}
338366

339367
#[derive(Default, Debug, Eq, PartialEq)]
340-
pub struct ItemTreeSourceMaps {
341-
functions: Vec<GenericItemSourceMap>,
342-
structs: Vec<GenericItemSourceMap>,
343-
unions: Vec<GenericItemSourceMap>,
368+
struct ItemTreeSourceMapsBuilder {
369+
functions: Vec<GenericItemSourceMapBuilder>,
370+
structs: Vec<GenericItemSourceMapBuilder>,
371+
unions: Vec<GenericItemSourceMapBuilder>,
344372
enum_generics: Vec<TypesSourceMap>,
345373
variants: Vec<TypesSourceMap>,
346374
consts: Vec<TypesSourceMap>,
347375
statics: Vec<TypesSourceMap>,
348376
trait_generics: Vec<TypesSourceMap>,
349377
trait_alias_generics: Vec<TypesSourceMap>,
350-
impls: Vec<GenericItemSourceMap>,
351-
type_aliases: Vec<GenericItemSourceMap>,
378+
impls: Vec<GenericItemSourceMapBuilder>,
379+
type_aliases: Vec<GenericItemSourceMapBuilder>,
352380
}
353381

354-
impl ItemTreeSourceMaps {
355-
fn shrink_to_fit(&mut self) {
356-
let ItemTreeSourceMaps {
382+
impl ItemTreeSourceMapsBuilder {
383+
fn build(self) -> ItemTreeSourceMaps {
384+
let ItemTreeSourceMapsBuilder {
357385
functions,
358386
structs,
359387
unions,
@@ -366,44 +394,92 @@ impl ItemTreeSourceMaps {
366394
impls,
367395
type_aliases,
368396
} = self;
369-
functions.shrink_to_fit();
370-
structs.shrink_to_fit();
371-
unions.shrink_to_fit();
372-
enum_generics.shrink_to_fit();
373-
variants.shrink_to_fit();
374-
consts.shrink_to_fit();
375-
statics.shrink_to_fit();
376-
trait_generics.shrink_to_fit();
377-
trait_alias_generics.shrink_to_fit();
378-
impls.shrink_to_fit();
379-
type_aliases.shrink_to_fit();
397+
let structs_offset = functions.len() as u32 * 2;
398+
let unions_offset = structs_offset + (structs.len() as u32 * 2);
399+
let enum_generics_offset = unions_offset + (unions.len() as u32 * 2);
400+
let variants_offset = enum_generics_offset + (enum_generics.len() as u32);
401+
let consts_offset = variants_offset + (variants.len() as u32);
402+
let statics_offset = consts_offset + (consts.len() as u32);
403+
let trait_generics_offset = statics_offset + (statics.len() as u32);
404+
let trait_alias_generics_offset = trait_generics_offset + (trait_generics.len() as u32);
405+
let impls_offset = trait_alias_generics_offset + (trait_alias_generics.len() as u32);
406+
let type_aliases_offset = impls_offset + (impls.len() as u32 * 2);
407+
let all_concatenated = generics_concat(functions)
408+
.chain(generics_concat(structs))
409+
.chain(generics_concat(unions))
410+
.chain(enum_generics)
411+
.chain(variants)
412+
.chain(consts)
413+
.chain(statics)
414+
.chain(trait_generics)
415+
.chain(trait_alias_generics)
416+
.chain(generics_concat(impls))
417+
.chain(generics_concat(type_aliases))
418+
.collect();
419+
return ItemTreeSourceMaps {
420+
all_concatenated,
421+
structs_offset,
422+
unions_offset,
423+
enum_generics_offset,
424+
variants_offset,
425+
consts_offset,
426+
statics_offset,
427+
trait_generics_offset,
428+
trait_alias_generics_offset,
429+
impls_offset,
430+
type_aliases_offset,
431+
};
432+
433+
fn generics_concat(
434+
source_maps: Vec<GenericItemSourceMapBuilder>,
435+
) -> impl Iterator<Item = TypesSourceMap> {
436+
source_maps.into_iter().flat_map(|it| [it.item, it.generics])
437+
}
380438
}
381439
}
382440

383-
macro_rules! index_source_maps {
384-
( $( $field:ident[$tree_id:ident] = $result:ident, )* ) => {
385-
$(
386-
impl Index<FileItemTreeId<$tree_id>> for ItemTreeSourceMaps {
387-
type Output = $result;
388-
fn index(&self, index: FileItemTreeId<$tree_id>) -> &Self::Output {
389-
&self.$field[index.0.into_raw().into_u32() as usize]
441+
impl ItemTreeSourceMaps {
442+
#[inline]
443+
fn generic_item(&self, offset: u32, index: u32) -> GenericItemSourceMap<'_> {
444+
GenericItemSourceMap(
445+
self.all_concatenated[(offset + (index * 2)) as usize..][..2].try_into().unwrap(),
446+
)
447+
}
448+
449+
#[inline]
450+
fn non_generic_item(&self, offset: u32, index: u32) -> &TypesSourceMap {
451+
&self.all_concatenated[(offset + index) as usize]
452+
}
453+
454+
#[inline]
455+
pub fn function(&self, index: FileItemTreeId<Function>) -> GenericItemSourceMap<'_> {
456+
self.generic_item(0, index.0.into_raw().into_u32())
457+
}
458+
}
459+
460+
macro_rules! index_item_source_maps {
461+
( $( $name:ident; $field:ident[$tree_id:ident]; $fn:ident; $ret:ty, )* ) => {
462+
impl ItemTreeSourceMaps {
463+
$(
464+
#[inline]
465+
pub fn $name(&self, index: FileItemTreeId<$tree_id>) -> $ret {
466+
self.$fn(self.$field, index.0.into_raw().into_u32())
390467
}
391-
}
392-
)*
468+
)*
469+
}
393470
};
394471
}
395-
index_source_maps! {
396-
functions[Function] = GenericItemSourceMap,
397-
structs[Struct] = GenericItemSourceMap,
398-
unions[Union] = GenericItemSourceMap,
399-
enum_generics[Enum] = TypesSourceMap,
400-
variants[Variant] = TypesSourceMap,
401-
consts[Const] = TypesSourceMap,
402-
statics[Static] = TypesSourceMap,
403-
trait_generics[Trait] = TypesSourceMap,
404-
trait_alias_generics[TraitAlias] = TypesSourceMap,
405-
impls[Impl] = GenericItemSourceMap,
406-
type_aliases[TypeAlias] = GenericItemSourceMap,
472+
index_item_source_maps! {
473+
strukt; structs_offset[Struct]; generic_item; GenericItemSourceMap<'_>,
474+
union; unions_offset[Union]; generic_item; GenericItemSourceMap<'_>,
475+
enum_generic; enum_generics_offset[Enum]; non_generic_item; &TypesSourceMap,
476+
variant; variants_offset[Variant]; non_generic_item; &TypesSourceMap,
477+
konst; consts_offset[Const]; non_generic_item; &TypesSourceMap,
478+
statik; statics_offset[Static]; non_generic_item; &TypesSourceMap,
479+
trait_generic; trait_generics_offset[Trait]; non_generic_item; &TypesSourceMap,
480+
trait_alias_generic; trait_alias_generics_offset[TraitAlias]; non_generic_item; &TypesSourceMap,
481+
impl_; impls_offset[Impl]; generic_item; GenericItemSourceMap<'_>,
482+
type_alias; type_aliases_offset[TypeAlias]; generic_item; GenericItemSourceMap<'_>,
407483
}
408484

409485
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]

src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ use crate::{
2323
generics::{GenericParams, GenericParamsCollector, TypeParamData, TypeParamProvenance},
2424
item_tree::{
2525
AssocItem, AttrOwner, Const, Either, Enum, ExternBlock, ExternCrate, Field, FieldParent,
26-
FieldsShape, FileItemTreeId, FnFlags, Function, GenericArgs, GenericItemSourceMap,
26+
FieldsShape, FileItemTreeId, FnFlags, Function, GenericArgs, GenericItemSourceMapBuilder,
2727
GenericModItem, Idx, Impl, ImportAlias, Interned, ItemTree, ItemTreeData,
28-
ItemTreeSourceMaps, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, ModPath,
29-
Mutability, Name, Param, Path, Range, RawAttrs, RawIdx, RawVisibilityId, Static, Struct,
30-
StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind, Variant,
28+
ItemTreeSourceMaps, ItemTreeSourceMapsBuilder, Macro2, MacroCall, MacroRules, Mod, ModItem,
29+
ModKind, ModPath, Mutability, Name, Param, Path, Range, RawAttrs, RawIdx, RawVisibilityId,
30+
Static, Struct, StructKind, Trait, TraitAlias, TypeAlias, Union, Use, UseTree, UseTreeKind,
31+
Variant,
3132
},
3233
lower::LowerCtx,
3334
path::AssociatedTypeBinding,
@@ -51,7 +52,7 @@ pub(super) struct Ctx<'a> {
5152
FxHashMap<Either<LocalTypeOrConstParamId, LocalLifetimeParamId>, RawAttrs>,
5253
span_map: OnceCell<SpanMap>,
5354
file: HirFileId,
54-
source_maps: ItemTreeSourceMaps,
55+
source_maps: ItemTreeSourceMapsBuilder,
5556
}
5657

5758
impl<'a> Ctx<'a> {
@@ -63,7 +64,7 @@ impl<'a> Ctx<'a> {
6364
source_ast_id_map: db.ast_id_map(file),
6465
file,
6566
span_map: OnceCell::new(),
66-
source_maps: ItemTreeSourceMaps::default(),
67+
source_maps: ItemTreeSourceMapsBuilder::default(),
6768
}
6869
}
6970

@@ -97,7 +98,7 @@ impl<'a> Ctx<'a> {
9798
self.tree.top_level =
9899
item_owner.items().flat_map(|item| self.lower_mod_item(&item)).collect();
99100
assert!(self.generic_param_attr_buffer.is_empty());
100-
(self.tree, self.source_maps)
101+
(self.tree, self.source_maps.build())
101102
}
102103

103104
pub(super) fn lower_macro_stmts(
@@ -134,7 +135,7 @@ impl<'a> Ctx<'a> {
134135
}
135136

136137
assert!(self.generic_param_attr_buffer.is_empty());
137-
(self.tree, self.source_maps)
138+
(self.tree, self.source_maps.build())
138139
}
139140

140141
pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> (ItemTree, ItemTreeSourceMaps) {
@@ -163,7 +164,7 @@ impl<'a> Ctx<'a> {
163164
}
164165

165166
assert!(self.generic_param_attr_buffer.is_empty());
166-
(self.tree, self.source_maps)
167+
(self.tree, self.source_maps.build())
167168
}
168169

169170
fn data(&mut self) -> &mut ItemTreeData {
@@ -249,9 +250,10 @@ impl<'a> Ctx<'a> {
249250
types_map: Arc::new(types_map),
250251
};
251252
let id = id(self.data().structs.alloc(res));
252-
self.source_maps
253-
.structs
254-
.push(GenericItemSourceMap { item: types_source_map, generics: generics_source_map });
253+
self.source_maps.structs.push(GenericItemSourceMapBuilder {
254+
item: types_source_map,
255+
generics: generics_source_map,
256+
});
255257
for (idx, attr) in attrs {
256258
self.add_attrs(
257259
AttrOwner::Field(
@@ -352,9 +354,10 @@ impl<'a> Ctx<'a> {
352354
types_map: Arc::new(types_map),
353355
};
354356
let id = id(self.data().unions.alloc(res));
355-
self.source_maps
356-
.unions
357-
.push(GenericItemSourceMap { item: types_source_map, generics: generics_source_map });
357+
self.source_maps.unions.push(GenericItemSourceMapBuilder {
358+
item: types_source_map,
359+
generics: generics_source_map,
360+
});
358361
for (idx, attr) in attrs {
359362
self.add_attrs(
360363
AttrOwner::Field(
@@ -558,9 +561,10 @@ impl<'a> Ctx<'a> {
558561
};
559562

560563
let id = id(self.data().functions.alloc(res));
561-
self.source_maps
562-
.functions
563-
.push(GenericItemSourceMap { item: types_source_map, generics: generics_source_map });
564+
self.source_maps.functions.push(GenericItemSourceMapBuilder {
565+
item: types_source_map,
566+
generics: generics_source_map,
567+
});
564568
for (idx, attr) in attrs {
565569
self.add_attrs(AttrOwner::Param(id, Idx::from_raw(RawIdx::from_u32(idx as u32))), attr);
566570
}
@@ -594,9 +598,10 @@ impl<'a> Ctx<'a> {
594598
types_map: Arc::new(types_map),
595599
};
596600
let id = id(self.data().type_aliases.alloc(res));
597-
self.source_maps
598-
.type_aliases
599-
.push(GenericItemSourceMap { item: types_source_map, generics: generics_source_map });
601+
self.source_maps.type_aliases.push(GenericItemSourceMapBuilder {
602+
item: types_source_map,
603+
generics: generics_source_map,
604+
});
600605
self.write_generic_params_attributes(id.into());
601606
Some(id)
602607
}
@@ -751,9 +756,10 @@ impl<'a> Ctx<'a> {
751756
types_map: Arc::new(types_map),
752757
};
753758
let id = id(self.data().impls.alloc(res));
754-
self.source_maps
755-
.impls
756-
.push(GenericItemSourceMap { item: types_source_map, generics: generics_source_map });
759+
self.source_maps.impls.push(GenericItemSourceMapBuilder {
760+
item: types_source_map,
761+
generics: generics_source_map,
762+
});
757763
self.write_generic_params_attributes(id.into());
758764
id
759765
}

0 commit comments

Comments
 (0)