aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-04-06 14:43:37 +0100
committerGitHub <[email protected]>2021-04-06 14:43:37 +0100
commit7d39b13996e312a8a738ed0dfccab45978fc42f8 (patch)
tree91761b9bf78d9015fbb6083b9245eb9f6133e234
parent12e86433ab57ee8b1c96b8da0480fd311752487b (diff)
parent4e2a6ac7eae3ff193962421cc3c86e5d8f9a7e31 (diff)
Merge #8364
8364: Memory usage improvements r=jonas-schievink a=alexmaco These are mostly focused on splitting up enum variants with large size differences between variants by `Box`-ing things up. In my testing this reduces the memory usage somewhere in the low percentages, even though the measurements are quite noisy. Co-authored-by: Alexandru Macovei <[email protected]>
-rw-r--r--Cargo.lock1
-rw-r--r--crates/hir_def/src/body/lower.rs22
-rw-r--r--crates/hir_def/src/expr.rs14
-rw-r--r--crates/hir_def/src/path.rs6
-rw-r--r--crates/hir_ty/src/infer/expr.rs10
-rw-r--r--crates/hir_ty/src/infer/pat.rs4
-rw-r--r--crates/vfs/Cargo.toml1
-rw-r--r--crates/vfs/src/path_interner.rs29
8 files changed, 54 insertions, 33 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e40c12a92..ca0311595 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1867,6 +1867,7 @@ name = "vfs"
1867version = "0.0.0" 1867version = "0.0.0"
1868dependencies = [ 1868dependencies = [
1869 "fst", 1869 "fst",
1870 "indexmap",
1870 "paths", 1871 "paths",
1871 "rustc-hash", 1872 "rustc-hash",
1872] 1873]
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 63e89a1f4..1e743e5d5 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -322,8 +322,10 @@ impl ExprCollector<'_> {
322 Vec::new() 322 Vec::new()
323 }; 323 };
324 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 324 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
325 let generic_args = 325 let generic_args = e
326 e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); 326 .generic_arg_list()
327 .and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
328 .map(Box::new);
327 self.alloc_expr( 329 self.alloc_expr(
328 Expr::MethodCall { receiver, method_name, args, generic_args }, 330 Expr::MethodCall { receiver, method_name, args, generic_args },
329 syntax_ptr, 331 syntax_ptr,
@@ -385,7 +387,7 @@ impl ExprCollector<'_> {
385 self.alloc_expr(Expr::Yield { expr }, syntax_ptr) 387 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
386 } 388 }
387 ast::Expr::RecordExpr(e) => { 389 ast::Expr::RecordExpr(e) => {
388 let path = e.path().and_then(|path| self.expander.parse_path(path)); 390 let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
389 let record_lit = if let Some(nfl) = e.record_expr_field_list() { 391 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
390 let fields = nfl 392 let fields = nfl
391 .fields() 393 .fields()
@@ -430,7 +432,7 @@ impl ExprCollector<'_> {
430 } 432 }
431 ast::Expr::CastExpr(e) => { 433 ast::Expr::CastExpr(e) => {
432 let expr = self.collect_expr_opt(e.expr()); 434 let expr = self.collect_expr_opt(e.expr());
433 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); 435 let type_ref = Box::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
434 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 436 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
435 } 437 }
436 ast::Expr::RefExpr(e) => { 438 ast::Expr::RefExpr(e) => {
@@ -469,8 +471,10 @@ impl ExprCollector<'_> {
469 arg_types.push(type_ref); 471 arg_types.push(type_ref);
470 } 472 }
471 } 473 }
472 let ret_type = 474 let ret_type = e
473 e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); 475 .ret_type()
476 .and_then(|r| r.ty())
477 .map(|it| Box::new(TypeRef::from_ast(&self.ctx(), it)));
474 let body = self.collect_expr_opt(e.body()); 478 let body = self.collect_expr_opt(e.body());
475 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 479 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
476 } 480 }
@@ -755,7 +759,7 @@ impl ExprCollector<'_> {
755 } 759 }
756 } 760 }
757 ast::Pat::TupleStructPat(p) => { 761 ast::Pat::TupleStructPat(p) => {
758 let path = p.path().and_then(|path| self.expander.parse_path(path)); 762 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
759 let (args, ellipsis) = self.collect_tuple_pat(p.fields()); 763 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
760 Pat::TupleStruct { path, args, ellipsis } 764 Pat::TupleStruct { path, args, ellipsis }
761 } 765 }
@@ -765,7 +769,7 @@ impl ExprCollector<'_> {
765 Pat::Ref { pat, mutability } 769 Pat::Ref { pat, mutability }
766 } 770 }
767 ast::Pat::PathPat(p) => { 771 ast::Pat::PathPat(p) => {
768 let path = p.path().and_then(|path| self.expander.parse_path(path)); 772 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
769 path.map(Pat::Path).unwrap_or(Pat::Missing) 773 path.map(Pat::Path).unwrap_or(Pat::Missing)
770 } 774 }
771 ast::Pat::OrPat(p) => { 775 ast::Pat::OrPat(p) => {
@@ -779,7 +783,7 @@ impl ExprCollector<'_> {
779 } 783 }
780 ast::Pat::WildcardPat(_) => Pat::Wild, 784 ast::Pat::WildcardPat(_) => Pat::Wild,
781 ast::Pat::RecordPat(p) => { 785 ast::Pat::RecordPat(p) => {
782 let path = p.path().and_then(|path| self.expander.parse_path(path)); 786 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
783 let args: Vec<_> = p 787 let args: Vec<_> = p
784 .record_pat_field_list() 788 .record_pat_field_list()
785 .expect("every struct should have a field list") 789 .expect("every struct should have a field list")
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index 6c7376fad..62a28bdba 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -86,7 +86,7 @@ pub enum Expr {
86 receiver: ExprId, 86 receiver: ExprId,
87 method_name: Name, 87 method_name: Name,
88 args: Vec<ExprId>, 88 args: Vec<ExprId>,
89 generic_args: Option<GenericArgs>, 89 generic_args: Option<Box<GenericArgs>>,
90 }, 90 },
91 Match { 91 Match {
92 expr: ExprId, 92 expr: ExprId,
@@ -106,7 +106,7 @@ pub enum Expr {
106 expr: Option<ExprId>, 106 expr: Option<ExprId>,
107 }, 107 },
108 RecordLit { 108 RecordLit {
109 path: Option<Path>, 109 path: Option<Box<Path>>,
110 fields: Vec<RecordLitField>, 110 fields: Vec<RecordLitField>,
111 spread: Option<ExprId>, 111 spread: Option<ExprId>,
112 }, 112 },
@@ -131,7 +131,7 @@ pub enum Expr {
131 }, 131 },
132 Cast { 132 Cast {
133 expr: ExprId, 133 expr: ExprId,
134 type_ref: TypeRef, 134 type_ref: Box<TypeRef>,
135 }, 135 },
136 Ref { 136 Ref {
137 expr: ExprId, 137 expr: ExprId,
@@ -162,7 +162,7 @@ pub enum Expr {
162 Lambda { 162 Lambda {
163 args: Vec<PatId>, 163 args: Vec<PatId>,
164 arg_types: Vec<Option<TypeRef>>, 164 arg_types: Vec<Option<TypeRef>>,
165 ret_type: Option<TypeRef>, 165 ret_type: Option<Box<TypeRef>>,
166 body: ExprId, 166 body: ExprId,
167 }, 167 },
168 Tuple { 168 Tuple {
@@ -412,13 +412,13 @@ pub enum Pat {
412 Wild, 412 Wild,
413 Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, 413 Tuple { args: Vec<PatId>, ellipsis: Option<usize> },
414 Or(Vec<PatId>), 414 Or(Vec<PatId>),
415 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, 415 Record { path: Option<Box<Path>>, args: Vec<RecordFieldPat>, ellipsis: bool },
416 Range { start: ExprId, end: ExprId }, 416 Range { start: ExprId, end: ExprId },
417 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, 417 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> },
418 Path(Path), 418 Path(Box<Path>),
419 Lit(ExprId), 419 Lit(ExprId),
420 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, 420 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
421 TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, 421 TupleStruct { path: Option<Box<Path>>, args: Vec<PatId>, ellipsis: Option<usize> },
422 Ref { pat: PatId, mutability: Mutability }, 422 Ref { pat: PatId, mutability: Mutability },
423 Box { inner: PatId }, 423 Box { inner: PatId },
424 ConstBlock(ExprId), 424 ConstBlock(ExprId),
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index f9c8328f0..b528ff8ba 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -289,6 +289,12 @@ impl From<Name> for Path {
289 } 289 }
290} 290}
291 291
292impl From<Name> for Box<Path> {
293 fn from(name: Name) -> Box<Path> {
294 Box::new(Path::from(name))
295 }
296}
297
292impl From<Name> for ModPath { 298impl From<Name> for ModPath {
293 fn from(name: Name) -> ModPath { 299 fn from(name: Name) -> ModPath {
294 ModPath::from_segments(PathKind::Plain, iter::once(name)) 300 ModPath::from_segments(PathKind::Plain, iter::once(name))
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index dab137ae1..5b3cdab4e 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -318,7 +318,13 @@ impl<'a> InferenceContext<'a> {
318 self.normalize_associated_types_in(ret_ty) 318 self.normalize_associated_types_in(ret_ty)
319 } 319 }
320 Expr::MethodCall { receiver, args, method_name, generic_args } => self 320 Expr::MethodCall { receiver, args, method_name, generic_args } => self
321 .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), 321 .infer_method_call(
322 tgt_expr,
323 *receiver,
324 &args,
325 &method_name,
326 generic_args.as_deref(),
327 ),
322 Expr::Match { expr, arms } => { 328 Expr::Match { expr, arms } => {
323 let input_ty = self.infer_expr(*expr, &Expectation::none()); 329 let input_ty = self.infer_expr(*expr, &Expectation::none());
324 330
@@ -399,7 +405,7 @@ impl<'a> InferenceContext<'a> {
399 TyKind::Never.intern(&Interner) 405 TyKind::Never.intern(&Interner)
400 } 406 }
401 Expr::RecordLit { path, fields, spread } => { 407 Expr::RecordLit { path, fields, spread } => {
402 let (ty, def_id) = self.resolve_variant(path.as_ref()); 408 let (ty, def_id) = self.resolve_variant(path.as_deref());
403 if let Some(variant) = def_id { 409 if let Some(variant) = def_id {
404 self.write_variant_resolution(tgt_expr.into(), variant); 410 self.write_variant_resolution(tgt_expr.into(), variant);
405 } 411 }
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index fc2bc3ef8..12431ae07 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -174,7 +174,7 @@ impl<'a> InferenceContext<'a> {
174 TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner) 174 TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner)
175 } 175 }
176 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 176 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
177 p.as_ref(), 177 p.as_deref(),
178 subpats, 178 subpats,
179 expected, 179 expected,
180 default_bm, 180 default_bm,
@@ -182,7 +182,7 @@ impl<'a> InferenceContext<'a> {
182 *ellipsis, 182 *ellipsis,
183 ), 183 ),
184 Pat::Record { path: p, args: fields, ellipsis: _ } => { 184 Pat::Record { path: p, args: fields, ellipsis: _ } => {
185 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 185 self.infer_record_pat(p.as_deref(), fields, expected, default_bm, pat)
186 } 186 }
187 Pat::Path(path) => { 187 Pat::Path(path) => {
188 // FIXME use correct resolver for the surrounding expression 188 // FIXME use correct resolver for the surrounding expression
diff --git a/crates/vfs/Cargo.toml b/crates/vfs/Cargo.toml
index c318a68f7..894944b18 100644
--- a/crates/vfs/Cargo.toml
+++ b/crates/vfs/Cargo.toml
@@ -14,3 +14,4 @@ rustc-hash = "1.0"
14fst = "0.4" 14fst = "0.4"
15 15
16paths = { path = "../paths", version = "0.0.0" } 16paths = { path = "../paths", version = "0.0.0" }
17indexmap = "1.6.2"
diff --git a/crates/vfs/src/path_interner.rs b/crates/vfs/src/path_interner.rs
index 2189e5e25..6e049f0d4 100644
--- a/crates/vfs/src/path_interner.rs
+++ b/crates/vfs/src/path_interner.rs
@@ -1,15 +1,22 @@
1//! Maps paths to compact integer ids. We don't care about clearings paths which 1//! Maps paths to compact integer ids. We don't care about clearings paths which
2//! no longer exist -- the assumption is total size of paths we ever look at is 2//! no longer exist -- the assumption is total size of paths we ever look at is
3//! not too big. 3//! not too big.
4use rustc_hash::FxHashMap; 4use std::hash::BuildHasherDefault;
5
6use indexmap::IndexSet;
7use rustc_hash::FxHasher;
5 8
6use crate::{FileId, VfsPath}; 9use crate::{FileId, VfsPath};
7 10
8/// Structure to map between [`VfsPath`] and [`FileId`]. 11/// Structure to map between [`VfsPath`] and [`FileId`].
9#[derive(Default)]
10pub(crate) struct PathInterner { 12pub(crate) struct PathInterner {
11 map: FxHashMap<VfsPath, FileId>, 13 map: IndexSet<VfsPath, BuildHasherDefault<FxHasher>>,
12 vec: Vec<VfsPath>, 14}
15
16impl Default for PathInterner {
17 fn default() -> Self {
18 Self { map: IndexSet::default() }
19 }
13} 20}
14 21
15impl PathInterner { 22impl PathInterner {
@@ -17,7 +24,7 @@ impl PathInterner {
17 /// 24 ///
18 /// If `path` does not exists in `self`, returns [`None`]. 25 /// If `path` does not exists in `self`, returns [`None`].
19 pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> { 26 pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> {
20 self.map.get(path).copied() 27 self.map.get_index_of(path).map(|i| FileId(i as u32))
21 } 28 }
22 29
23 /// Insert `path` in `self`. 30 /// Insert `path` in `self`.
@@ -25,13 +32,9 @@ impl PathInterner {
25 /// - If `path` already exists in `self`, returns its associated id; 32 /// - If `path` already exists in `self`, returns its associated id;
26 /// - Else, returns a newly allocated id. 33 /// - Else, returns a newly allocated id.
27 pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { 34 pub(crate) fn intern(&mut self, path: VfsPath) -> FileId {
28 if let Some(id) = self.get(&path) { 35 let (id, _added) = self.map.insert_full(path);
29 return id; 36 assert!(id < u32::MAX as usize);
30 } 37 FileId(id as u32)
31 let id = FileId(self.vec.len() as u32);
32 self.map.insert(path.clone(), id);
33 self.vec.push(path);
34 id
35 } 38 }
36 39
37 /// Returns the path corresponding to `id`. 40 /// Returns the path corresponding to `id`.
@@ -40,6 +43,6 @@ impl PathInterner {
40 /// 43 ///
41 /// Panics if `id` does not exists in `self`. 44 /// Panics if `id` does not exists in `self`.
42 pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { 45 pub(crate) fn lookup(&self, id: FileId) -> &VfsPath {
43 &self.vec[id.0 as usize] 46 self.map.get_index(id.0 as usize).unwrap()
44 } 47 }
45} 48}