about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-05-19 12:06:11 +0000
committerbors <bors@rust-lang.org>2023-05-19 12:06:11 +0000
commitbb78059be4d090571bd70de57831f84eee5be678 (patch)
treeb32093ae1c01581b74aa6fccdb6973ba56e8e1c3
parentce936177f93e96a6df9215c1c7dbcf97bf9c18c9 (diff)
parent23ce228d545aef4ad7933e69ff9d68961f407605 (diff)
downloadrust-bb78059be4d090571bd70de57831f84eee5be678.tar.gz
rust-bb78059be4d090571bd70de57831f84eee5be678.zip
Auto merge of #14847 - HKalbasi:layout, r=HKalbasi
Reduce MIR memory usage
-rw-r--r--crates/hir-ty/src/mir.rs40
-rw-r--r--crates/hir-ty/src/mir/borrowck.rs4
-rw-r--r--crates/hir-ty/src/mir/eval.rs2
-rw-r--r--crates/hir-ty/src/mir/lower.rs40
-rw-r--r--crates/hir-ty/src/mir/lower/as_place.rs19
-rw-r--r--crates/hir-ty/src/mir/lower/pattern_matching.rs33
6 files changed, 83 insertions, 55 deletions
diff --git a/crates/hir-ty/src/mir.rs b/crates/hir-ty/src/mir.rs
index 11c35dfb8a8..f8451f28d73 100644
--- a/crates/hir-ty/src/mir.rs
+++ b/crates/hir-ty/src/mir.rs
@@ -205,7 +205,7 @@ type PlaceElem = ProjectionElem<LocalId, Ty>;
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Place {
     pub local: LocalId,
-    pub projection: Vec<PlaceElem>,
+    pub projection: Box<[PlaceElem]>,
 }
 
 impl Place {
@@ -216,13 +216,20 @@ impl Place {
     fn iterate_over_parents(&self) -> impl Iterator<Item = Place> + '_ {
         (0..self.projection.len())
             .map(|x| &self.projection[0..x])
-            .map(|x| Place { local: self.local, projection: x.to_vec() })
+            .map(|x| Place { local: self.local, projection: x.to_vec().into() })
+    }
+
+    fn project(&self, projection: PlaceElem) -> Place {
+        Place {
+            local: self.local,
+            projection: self.projection.iter().cloned().chain([projection]).collect(),
+        }
     }
 }
 
 impl From<LocalId> for Place {
     fn from(local: LocalId) -> Self {
-        Self { local, projection: vec![] }
+        Self { local, projection: vec![].into() }
     }
 }
 
@@ -437,7 +444,7 @@ pub enum TerminatorKind {
         /// These are owned by the callee, which is free to modify them.
         /// This allows the memory occupied by "by-value" arguments to be
         /// reused across function calls without duplicating the contents.
-        args: Vec<Operand>,
+        args: Box<[Operand]>,
         /// Where the returned value will be written
         destination: Place,
         /// Where to go after this call returns. If none, the call necessarily diverges.
@@ -894,7 +901,7 @@ pub enum Rvalue {
     ///
     /// Disallowed after deaggregation for all aggregate kinds except `Array` and `Generator`. After
     /// generator lowering, `Generator` aggregate kinds are disallowed too.
-    Aggregate(AggregateKind, Vec<Operand>),
+    Aggregate(AggregateKind, Box<[Operand]>),
 
     /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
     ///
@@ -1011,7 +1018,7 @@ impl MirBody {
                                 for_operand(o2, &mut f);
                             }
                             Rvalue::Aggregate(_, ops) => {
-                                for op in ops {
+                                for op in ops.iter_mut() {
                                     for_operand(op, &mut f);
                                 }
                             }
@@ -1058,6 +1065,27 @@ impl MirBody {
             }
         }
     }
+
+    fn shrink_to_fit(&mut self) {
+        let MirBody {
+            basic_blocks,
+            locals,
+            start_block: _,
+            owner: _,
+            binding_locals,
+            param_locals,
+            closures,
+        } = self;
+        basic_blocks.shrink_to_fit();
+        locals.shrink_to_fit();
+        binding_locals.shrink_to_fit();
+        param_locals.shrink_to_fit();
+        closures.shrink_to_fit();
+        for (_, b) in basic_blocks.iter_mut() {
+            let BasicBlock { statements, terminator: _, is_cleanup: _ } = b;
+            statements.shrink_to_fit();
+        }
+    }
 }
 
 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
diff --git a/crates/hir-ty/src/mir/borrowck.rs b/crates/hir-ty/src/mir/borrowck.rs
index 412390d3fa1..66af6658e81 100644
--- a/crates/hir-ty/src/mir/borrowck.rs
+++ b/crates/hir-ty/src/mir/borrowck.rs
@@ -93,7 +93,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
         Operand::Copy(p) | Operand::Move(p) => {
             let mut ty: Ty = body.locals[p.local].ty.clone();
             let mut is_dereference_of_ref = false;
-            for proj in &p.projection {
+            for proj in &*p.projection {
                 if *proj == ProjectionElem::Deref && ty.as_reference().is_some() {
                     is_dereference_of_ref = true;
                 }
@@ -143,7 +143,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
                         for_operand(o2, statement.span);
                     }
                     Rvalue::Aggregate(_, ops) => {
-                        for op in ops {
+                        for op in ops.iter() {
                             for_operand(op, statement.span);
                         }
                     }
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 327161b99eb..e4acd10aa9b 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -562,7 +562,7 @@ impl Evaluator<'_> {
         let mut ty: Ty =
             self.ty_filler(&locals.body.locals[p.local].ty, locals.subst, locals.body.owner)?;
         let mut metadata: Option<IntervalOrOwned> = None; // locals are always sized
-        for proj in &p.projection {
+        for proj in &*p.projection {
             let prev_ty = ty.clone();
             ty = proj.projected_ty(
                 ty,
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 292a771baf9..f73b25d83f4 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -387,7 +387,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                                 current,
                                 place,
                                 ty,
-                                vec![],
+                                Box::new([]),
                                 expr_id.into(),
                             )?;
                         }
@@ -561,7 +561,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                 };
                 self.push_assignment(current, ref_mut_iterator_place.clone(), Rvalue::Ref(BorrowKind::Mut { allow_two_phase_borrow: false }, iterator_place), expr_id.into());
                 self.lower_loop(current, place, label, expr_id.into(), |this, begin| {
-                    let Some(current) = this.lower_call(iter_next_fn_op, vec![Operand::Copy(ref_mut_iterator_place)], option_item_place.clone(), begin, false, expr_id.into())?
+                    let Some(current) = this.lower_call(iter_next_fn_op, Box::new([Operand::Copy(ref_mut_iterator_place)]), option_item_place.clone(), begin, false, expr_id.into())?
                     else {
                         return Ok(());
                     };
@@ -758,8 +758,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                                         match x {
                                             Some(x) => x,
                                             None => {
-                                                let mut p = sp.clone();
-                                                p.projection.push(ProjectionElem::Field(FieldId {
+                                                let p = sp.project(ProjectionElem::Field(FieldId {
                                                     parent: variant_id,
                                                     local_id: LocalFieldId::from_raw(RawIdx::from(i as u32)),
                                                 }));
@@ -782,10 +781,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                         };
                         let local_id =
                             variant_data.field(name).ok_or(MirLowerError::UnresolvedField)?;
-                        let mut place = place;
-                        place
-                            .projection
-                            .push(PlaceElem::Field(FieldId { parent: union_id.into(), local_id }));
+                        let place = place.project(PlaceElem::Field(FieldId { parent: union_id.into(), local_id }));
                         self.lower_expr_to_place(*expr, place, current)
                     }
                 }
@@ -826,8 +822,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                 let Some((operand, current)) = self.lower_expr_to_some_operand(*expr, current)? else {
                     return Ok(None);
                 };
-                let mut p = place;
-                p.projection.push(ProjectionElem::Deref);
+                let p = place.project(ProjectionElem::Deref);
                 self.push_assignment(current, p, operand.into(), expr_id.into());
                 Ok(Some(current))
             },
@@ -1031,7 +1026,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
                 self.push_assignment(
                     current,
                     place,
-                    Rvalue::Aggregate(AggregateKind::Closure(ty), operands),
+                    Rvalue::Aggregate(AggregateKind::Closure(ty), operands.into()),
                     expr_id.into(),
                 );
                 Ok(Some(current))
@@ -1128,11 +1123,11 @@ impl<'ctx> MirLowerCtx<'ctx> {
                 let index = name
                     .as_tuple_index()
                     .ok_or(MirLowerError::TypeError("named field on tuple"))?;
-                place.projection.push(ProjectionElem::TupleOrClosureField(index))
+                *place = place.project(ProjectionElem::TupleOrClosureField(index))
             } else {
                 let field =
                     self.infer.field_resolution(expr_id).ok_or(MirLowerError::UnresolvedField)?;
-                place.projection.push(ProjectionElem::Field(field));
+                *place = place.project(ProjectionElem::Field(field));
             }
         } else {
             not_supported!("")
@@ -1242,7 +1237,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
         prev_block: BasicBlockId,
         place: Place,
         ty: Ty,
-        fields: Vec<Operand>,
+        fields: Box<[Operand]>,
         span: MirSpan,
     ) -> Result<BasicBlockId> {
         let subst = match ty.kind(Interner) {
@@ -1280,13 +1275,13 @@ impl<'ctx> MirLowerCtx<'ctx> {
         else {
             return Ok(None);
         };
-        self.lower_call(func, args, place, current, is_uninhabited, span)
+        self.lower_call(func, args.into(), place, current, is_uninhabited, span)
     }
 
     fn lower_call(
         &mut self,
         func: Operand,
-        args: Vec<Operand>,
+        args: Box<[Operand]>,
         place: Place,
         current: BasicBlockId,
         is_uninhabited: bool,
@@ -1744,12 +1739,13 @@ pub fn mir_body_for_closure_query(
             match r {
                 Some(x) => {
                     p.local = closure_local;
-                    let prev_projs =
-                        mem::replace(&mut p.projection, vec![PlaceElem::TupleOrClosureField(x.1)]);
+                    let mut next_projs = vec![PlaceElem::TupleOrClosureField(x.1)];
+                    let prev_projs = mem::take(&mut p.projection);
                     if x.0.kind != CaptureKind::ByValue {
-                        p.projection.push(ProjectionElem::Deref);
+                        next_projs.push(ProjectionElem::Deref);
                     }
-                    p.projection.extend(prev_projs.into_iter().skip(x.0.place.projections.len()));
+                    next_projs.extend(prev_projs.iter().cloned().skip(x.0.place.projections.len()));
+                    p.projection = next_projs.into();
                 }
                 None => err = Some(p.clone()),
             }
@@ -1764,6 +1760,7 @@ pub fn mir_body_for_closure_query(
     if let Some(err) = err {
         return Err(MirLowerError::UnresolvedUpvar(err));
     }
+    ctx.result.shrink_to_fit();
     Ok(Arc::new(ctx.result))
 }
 
@@ -1780,7 +1777,8 @@ pub fn mir_body_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Result<Arc<Mi
     });
     let body = db.body(def);
     let infer = db.infer(def);
-    let result = lower_to_mir(db, def, &body, &infer, body.body_expr)?;
+    let mut result = lower_to_mir(db, def, &body, &infer, body.body_expr)?;
+    result.shrink_to_fit();
     Ok(Arc::new(result))
 }
 
diff --git a/crates/hir-ty/src/mir/lower/as_place.rs b/crates/hir-ty/src/mir/lower/as_place.rs
index 9515c18bb64..d2c8d9a089e 100644
--- a/crates/hir-ty/src/mir/lower/as_place.rs
+++ b/crates/hir-ty/src/mir/lower/as_place.rs
@@ -65,7 +65,7 @@ impl MirLowerCtx<'_> {
                     )? else {
                         return Ok(None);
                     };
-                    x.0.projection.push(ProjectionElem::Deref);
+                    x.0 = x.0.project(ProjectionElem::Deref);
                     Ok(Some(x))
                 }
                 Adjust::Deref(Some(od)) => {
@@ -139,15 +139,14 @@ impl MirLowerCtx<'_> {
                         let ty = self.expr_ty_without_adjust(expr_id);
                         let ref_ty =
                             TyKind::Ref(Mutability::Not, static_lifetime(), ty).intern(Interner);
-                        let mut temp: Place = self.temp(ref_ty, current, expr_id.into())?.into();
+                        let temp: Place = self.temp(ref_ty, current, expr_id.into())?.into();
                         self.push_assignment(
                             current,
                             temp.clone(),
                             Operand::Static(s).into(),
                             expr_id.into(),
                         );
-                        temp.projection.push(ProjectionElem::Deref);
-                        Ok(Some((temp, current)))
+                        Ok(Some((temp.project(ProjectionElem::Deref), current)))
                     }
                     _ => try_rvalue(self),
                 }
@@ -196,7 +195,7 @@ impl MirLowerCtx<'_> {
                     let Some((mut r, current)) = self.lower_expr_as_place(current, *expr, true)? else {
                         return Ok(None);
                     };
-                    r.projection.push(ProjectionElem::Deref);
+                    r = r.project(ProjectionElem::Deref);
                     Ok(Some((r, current)))
                 }
                 _ => try_rvalue(self),
@@ -253,7 +252,7 @@ impl MirLowerCtx<'_> {
                 let Some(current) = self.lower_expr_to_place(*index, l_index.into(), current)? else {
                     return Ok(None);
                 };
-                p_base.projection.push(ProjectionElem::Index(l_index));
+                p_base = p_base.project(ProjectionElem::Index(l_index));
                 Ok(Some((p_base, current)))
             }
             _ => try_rvalue(self),
@@ -283,10 +282,10 @@ impl MirLowerCtx<'_> {
             )
             .intern(Interner),
         );
-        let Some(current) = self.lower_call(index_fn_op, vec![Operand::Copy(place), index_operand], result.clone(), current, false, span)? else {
+        let Some(current) = self.lower_call(index_fn_op, Box::new([Operand::Copy(place), index_operand]), result.clone(), current, false, span)? else {
             return Ok(None);
         };
-        result.projection.push(ProjectionElem::Deref);
+        result = result.project(ProjectionElem::Deref);
         Ok(Some((result, current)))
     }
 
@@ -330,10 +329,10 @@ impl MirLowerCtx<'_> {
             .intern(Interner),
         );
         let mut result: Place = self.temp(target_ty_ref, current, span)?.into();
-        let Some(current) = self.lower_call(deref_fn_op, vec![Operand::Copy(ref_place)], result.clone(), current, false, span)? else {
+        let Some(current) = self.lower_call(deref_fn_op, Box::new([Operand::Copy(ref_place)]), result.clone(), current, false, span)? else {
             return Ok(None);
         };
-        result.projection.push(ProjectionElem::Deref);
+        result = result.project(ProjectionElem::Deref);
         Ok(Some((result, current)))
     }
 }
diff --git a/crates/hir-ty/src/mir/lower/pattern_matching.rs b/crates/hir-ty/src/mir/lower/pattern_matching.rs
index 45c245e281b..00864907ac8 100644
--- a/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/crates/hir-ty/src/mir/lower/pattern_matching.rs
@@ -110,10 +110,10 @@ impl MirLowerCtx<'_> {
             Pat::Slice { prefix, slice, suffix } => {
                 pattern_matching_dereference(&mut cond_ty, &mut binding_mode, &mut cond_place);
                 for (i, &pat) in prefix.iter().enumerate() {
-                    let mut next_place = cond_place.clone();
-                    next_place
-                        .projection
-                        .push(ProjectionElem::ConstantIndex { offset: i as u64, from_end: false });
+                    let next_place = cond_place.project(ProjectionElem::ConstantIndex {
+                        offset: i as u64,
+                        from_end: false,
+                    });
                     let cond_ty = self.infer[pat].clone();
                     (current, current_else) = self.pattern_match(
                         current,
@@ -126,8 +126,7 @@ impl MirLowerCtx<'_> {
                 }
                 if let Some(slice) = slice {
                     if let Pat::Bind { id, subpat: _ } = self.body[*slice] {
-                        let mut next_place = cond_place.clone();
-                        next_place.projection.push(ProjectionElem::Subslice {
+                        let next_place = cond_place.project(ProjectionElem::Subslice {
                             from: prefix.len() as u64,
                             to: suffix.len() as u64,
                         });
@@ -142,10 +141,10 @@ impl MirLowerCtx<'_> {
                     }
                 }
                 for (i, &pat) in suffix.iter().enumerate() {
-                    let mut next_place = cond_place.clone();
-                    next_place
-                        .projection
-                        .push(ProjectionElem::ConstantIndex { offset: i as u64, from_end: true });
+                    let next_place = cond_place.project(ProjectionElem::ConstantIndex {
+                        offset: i as u64,
+                        from_end: true,
+                    });
                     let cond_ty = self.infer[pat].clone();
                     (current, current_else) = self.pattern_match(
                         current,
@@ -269,11 +268,10 @@ impl MirLowerCtx<'_> {
             Pat::Ref { pat, mutability: _ } => {
                 if let Some((ty, _, _)) = cond_ty.as_reference() {
                     cond_ty = ty.clone();
-                    cond_place.projection.push(ProjectionElem::Deref);
                     self.pattern_match(
                         current,
                         current_else,
-                        cond_place,
+                        cond_place.project(ProjectionElem::Deref),
                         cond_ty,
                         *pat,
                         binding_mode,
@@ -479,8 +477,7 @@ impl MirLowerCtx<'_> {
         binding_mode: BindingAnnotation,
     ) -> Result<(BasicBlockId, Option<BasicBlockId>)> {
         for (proj, arg, ty) in args {
-            let mut cond_place = cond_place.clone();
-            cond_place.projection.push(proj);
+            let cond_place = cond_place.project(proj);
             (current, current_else) =
                 self.pattern_match(current, current_else, cond_place, ty, arg, binding_mode)?;
         }
@@ -513,5 +510,11 @@ fn pattern_matching_dereference(
     cond_place: &mut Place,
 ) {
     let cnt = pattern_matching_dereference_count(cond_ty, binding_mode);
-    cond_place.projection.extend((0..cnt).map(|_| ProjectionElem::Deref));
+    cond_place.projection = cond_place
+        .projection
+        .iter()
+        .cloned()
+        .chain((0..cnt).map(|_| ProjectionElem::Deref))
+        .collect::<Vec<_>>()
+        .into();
 }