Skip to content

Commit 2b3a114

Browse files
authored
Rollup merge of rust-lang#71942 - nnethercote:shrink-LocalDecl, r=matthewjasper
Shrink `LocalDecl` `LocalDecl` contributes 4-8% of peak heap memory usage on a range of benchmarks. This PR reduces its size from 128 bytes to 56 bytes on 64-bit, and does some clean-ups as well. r? @matthewjasper
2 parents d16d02b + 001496c commit 2b3a114

File tree

25 files changed

+206
-267
lines changed

25 files changed

+206
-267
lines changed

src/librustc_middle/mir/mod.rs

+57-59
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,13 @@ pub struct SourceInfo {
474474
pub scope: SourceScope,
475475
}
476476

477+
impl SourceInfo {
478+
#[inline]
479+
pub fn outermost(span: Span) -> Self {
480+
SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }
481+
}
482+
}
483+
477484
///////////////////////////////////////////////////////////////////////////
478485
// Borrow kinds
479486

@@ -689,7 +696,7 @@ pub struct LocalDecl<'tcx> {
689696
pub mutability: Mutability,
690697

691698
// FIXME(matthewjasper) Don't store in this in `Body`
692-
pub local_info: LocalInfo<'tcx>,
699+
pub local_info: Option<Box<LocalInfo<'tcx>>>,
693700

694701
/// `true` if this is an internal local.
695702
///
@@ -725,7 +732,7 @@ pub struct LocalDecl<'tcx> {
725732
/// borrow checker needs this information since it can affect
726733
/// region inference.
727734
// FIXME(matthewjasper) Don't store in this in `Body`
728-
pub user_ty: UserTypeProjections,
735+
pub user_ty: Option<Box<UserTypeProjections>>,
729736

730737
/// The *syntactic* (i.e., not visibility) source scope the local is defined
731738
/// in. If the local was defined in a let-statement, this
@@ -809,7 +816,13 @@ pub struct LocalDecl<'tcx> {
809816
pub source_info: SourceInfo,
810817
}
811818

812-
/// Extra information about a local that's used for diagnostics.
819+
// `LocalDecl` is used a lot. Make sure it doesn't unintentionally get bigger.
820+
#[cfg(target_arch = "x86_64")]
821+
static_assert_size!(LocalDecl<'_>, 56);
822+
823+
/// Extra information about a some locals that's used for diagnostics. (Not
824+
/// used for non-StaticRef temporaries, the return place, or anonymous function
825+
/// parameters.)
813826
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
814827
pub enum LocalInfo<'tcx> {
815828
/// A user-defined local variable or function parameter
@@ -820,8 +833,6 @@ pub enum LocalInfo<'tcx> {
820833
User(ClearCrossCrate<BindingForm<'tcx>>),
821834
/// A temporary created that references the static with the given `DefId`.
822835
StaticRef { def_id: DefId, is_thread_local: bool },
823-
/// Any other temporary, the return place, or an anonymous function parameter.
824-
Other,
825836
}
826837

827838
impl<'tcx> LocalDecl<'tcx> {
@@ -833,16 +844,16 @@ impl<'tcx> LocalDecl<'tcx> {
833844
/// - or `match ... { C(x) => ... }`
834845
pub fn can_be_made_mutable(&self) -> bool {
835846
match self.local_info {
836-
LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
847+
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
837848
binding_mode: ty::BindingMode::BindByValue(_),
838849
opt_ty_info: _,
839850
opt_match_place: _,
840851
pat_span: _,
841-
}))) => true,
852+
})))) => true,
842853

843-
LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
854+
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(
844855
ImplicitSelfKind::Imm,
845-
))) => true,
856+
)))) => true,
846857

847858
_ => false,
848859
}
@@ -853,14 +864,14 @@ impl<'tcx> LocalDecl<'tcx> {
853864
/// mutable bindings, but the inverse does not necessarily hold).
854865
pub fn is_nonref_binding(&self) -> bool {
855866
match self.local_info {
856-
LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
867+
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
857868
binding_mode: ty::BindingMode::BindByValue(_),
858869
opt_ty_info: _,
859870
opt_match_place: _,
860871
pat_span: _,
861-
}))) => true,
872+
})))) => true,
862873

863-
LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_))) => true,
874+
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(_)))) => true,
864875

865876
_ => false,
866877
}
@@ -871,7 +882,7 @@ impl<'tcx> LocalDecl<'tcx> {
871882
#[inline]
872883
pub fn is_user_variable(&self) -> bool {
873884
match self.local_info {
874-
LocalInfo::User(_) => true,
885+
Some(box LocalInfo::User(_)) => true,
875886
_ => false,
876887
}
877888
}
@@ -881,7 +892,7 @@ impl<'tcx> LocalDecl<'tcx> {
881892
/// match arm.
882893
pub fn is_ref_for_guard(&self) -> bool {
883894
match self.local_info {
884-
LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard)) => true,
895+
Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::RefForGuard))) => true,
885896
_ => false,
886897
}
887898
}
@@ -890,7 +901,7 @@ impl<'tcx> LocalDecl<'tcx> {
890901
/// access that static
891902
pub fn is_ref_to_static(&self) -> bool {
892903
match self.local_info {
893-
LocalInfo::StaticRef { .. } => true,
904+
Some(box LocalInfo::StaticRef { .. }) => true,
894905
_ => false,
895906
}
896907
}
@@ -899,7 +910,7 @@ impl<'tcx> LocalDecl<'tcx> {
899910
/// access that static
900911
pub fn is_ref_to_thread_local(&self) -> bool {
901912
match self.local_info {
902-
LocalInfo::StaticRef { is_thread_local, .. } => is_thread_local,
913+
Some(box LocalInfo::StaticRef { is_thread_local, .. }) => is_thread_local,
903914
_ => false,
904915
}
905916
}
@@ -911,10 +922,31 @@ impl<'tcx> LocalDecl<'tcx> {
911922
self.source_info.span.desugaring_kind().is_some()
912923
}
913924

914-
/// Creates a new `LocalDecl` for a temporary.
925+
/// Creates a new `LocalDecl` for a temporary: mutable, non-internal.
915926
#[inline]
916-
pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
917-
Self::new_local(ty, Mutability::Mut, false, span)
927+
pub fn new(ty: Ty<'tcx>, span: Span) -> Self {
928+
Self::with_source_info(ty, SourceInfo::outermost(span))
929+
}
930+
931+
/// Like `LocalDecl::new`, but takes a `SourceInfo` instead of a `Span`.
932+
#[inline]
933+
pub fn with_source_info(ty: Ty<'tcx>, source_info: SourceInfo) -> Self {
934+
LocalDecl {
935+
mutability: Mutability::Mut,
936+
local_info: None,
937+
internal: false,
938+
is_block_tail: None,
939+
ty,
940+
user_ty: None,
941+
source_info,
942+
}
943+
}
944+
945+
/// Converts `self` into same `LocalDecl` except tagged as internal.
946+
#[inline]
947+
pub fn internal(mut self) -> Self {
948+
self.internal = true;
949+
self
918950
}
919951

920952
/// Converts `self` into same `LocalDecl` except tagged as immutable.
@@ -931,41 +963,6 @@ impl<'tcx> LocalDecl<'tcx> {
931963
self.is_block_tail = Some(info);
932964
self
933965
}
934-
935-
/// Creates a new `LocalDecl` for a internal temporary.
936-
#[inline]
937-
pub fn new_internal(ty: Ty<'tcx>, span: Span) -> Self {
938-
Self::new_local(ty, Mutability::Mut, true, span)
939-
}
940-
941-
#[inline]
942-
fn new_local(ty: Ty<'tcx>, mutability: Mutability, internal: bool, span: Span) -> Self {
943-
LocalDecl {
944-
mutability,
945-
ty,
946-
user_ty: UserTypeProjections::none(),
947-
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
948-
internal,
949-
local_info: LocalInfo::Other,
950-
is_block_tail: None,
951-
}
952-
}
953-
954-
/// Builds a `LocalDecl` for the return place.
955-
///
956-
/// This must be inserted into the `local_decls` list as the first local.
957-
#[inline]
958-
pub fn new_return_place(return_ty: Ty<'_>, span: Span) -> LocalDecl<'_> {
959-
LocalDecl {
960-
mutability: Mutability::Mut,
961-
ty: return_ty,
962-
user_ty: UserTypeProjections::none(),
963-
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
964-
internal: false,
965-
is_block_tail: None,
966-
local_info: LocalInfo::Other,
967-
}
968-
}
969966
}
970967

971968
/// Debug information pertaining to a user variable.
@@ -1406,10 +1403,7 @@ impl<'tcx> BasicBlockData<'tcx> {
14061403
let mut gap = self.statements.len()..self.statements.len() + extra_stmts;
14071404
self.statements.resize(
14081405
gap.end,
1409-
Statement {
1410-
source_info: SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE },
1411-
kind: StatementKind::Nop,
1412-
},
1406+
Statement { source_info: SourceInfo::outermost(DUMMY_SP), kind: StatementKind::Nop },
14131407
);
14141408
for (splice_start, new_stmts) in splices.into_iter().rev() {
14151409
let splice_end = splice_start + new_stmts.size_hint().0;
@@ -2457,14 +2451,18 @@ impl Constant<'tcx> {
24572451
/// &'static str`.
24582452
#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)]
24592453
pub struct UserTypeProjections {
2460-
pub(crate) contents: Vec<(UserTypeProjection, Span)>,
2454+
pub contents: Vec<(UserTypeProjection, Span)>,
24612455
}
24622456

24632457
impl<'tcx> UserTypeProjections {
24642458
pub fn none() -> Self {
24652459
UserTypeProjections { contents: vec![] }
24662460
}
24672461

2462+
pub fn is_empty(&self) -> bool {
2463+
self.contents.is_empty()
2464+
}
2465+
24682466
pub fn from_projections(projs: impl Iterator<Item = (UserTypeProjection, Span)>) -> Self {
24692467
UserTypeProjections { contents: projs.collect() }
24702468
}

src/librustc_middle/mir/visit.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,10 @@ macro_rules! make_mir_visitor {
242242
) {
243243
let span = body.span;
244244
if let Some(yield_ty) = &$($mutability)? body.yield_ty {
245-
self.visit_ty(yield_ty, TyContext::YieldTy(SourceInfo {
246-
span,
247-
scope: OUTERMOST_SOURCE_SCOPE,
248-
}));
245+
self.visit_ty(
246+
yield_ty,
247+
TyContext::YieldTy(SourceInfo::outermost(span))
248+
);
249249
}
250250

251251
// for best performance, we want to use an iterator rather
@@ -263,10 +263,10 @@ macro_rules! make_mir_visitor {
263263
self.visit_source_scope_data(scope);
264264
}
265265

266-
self.visit_ty(&$($mutability)? body.return_ty(), TyContext::ReturnTy(SourceInfo {
267-
span: body.span,
268-
scope: OUTERMOST_SOURCE_SCOPE,
269-
}));
266+
self.visit_ty(
267+
&$($mutability)? body.return_ty(),
268+
TyContext::ReturnTy(SourceInfo::outermost(body.span))
269+
);
270270

271271
for local in body.local_decls.indices() {
272272
self.visit_local_decl(local, & $($mutability)? body.local_decls[local]);
@@ -715,8 +715,10 @@ macro_rules! make_mir_visitor {
715715
local,
716716
source_info: *source_info,
717717
});
718-
for (user_ty, _) in & $($mutability)? user_ty.contents {
719-
self.visit_user_type_projection(user_ty);
718+
if let Some(user_ty) = user_ty {
719+
for (user_ty, _) in & $($mutability)? user_ty.contents {
720+
self.visit_user_type_projection(user_ty);
721+
}
720722
}
721723
self.visit_source_info(source_info);
722724
}

src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1447,15 +1447,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
14471447
let (place_description, assigned_span) = match local_decl {
14481448
Some(LocalDecl {
14491449
local_info:
1450-
LocalInfo::User(
1450+
Some(box LocalInfo::User(
14511451
ClearCrossCrate::Clear
14521452
| ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
14531453
opt_match_place: None,
14541454
..
14551455
})),
1456-
)
1457-
| LocalInfo::StaticRef { .. }
1458-
| LocalInfo::Other,
1456+
))
1457+
| Some(box LocalInfo::StaticRef { .. })
1458+
| None,
14591459
..
14601460
})
14611461
| None => (self.describe_any_place(place.as_ref()), assigned_span),

src/librustc_mir/borrow_check/diagnostics/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
202202
if self.body.local_decls[local].is_ref_to_static() =>
203203
{
204204
let local_info = &self.body.local_decls[local].local_info;
205-
if let LocalInfo::StaticRef { def_id, .. } = *local_info {
205+
if let Some(box LocalInfo::StaticRef { def_id, .. }) = *local_info {
206206
buf.push_str(&self.infcx.tcx.item_name(def_id).as_str());
207207
} else {
208208
unreachable!();

src/librustc_mir/borrow_check/diagnostics/move_errors.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -103,14 +103,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
103103
//
104104
// opt_match_place is None for let [mut] x = ... statements,
105105
// whether or not the right-hand side is a place expression
106-
if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
106+
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
107107
VarBindingForm {
108108
opt_match_place: Some((opt_match_place, match_span)),
109109
binding_mode: _,
110110
opt_ty_info: _,
111111
pat_span: _,
112112
},
113-
))) = local_decl.local_info
113+
)))) = local_decl.local_info
114114
{
115115
let stmt_source_info = self.body.source_info(location);
116116
self.append_binding_error(
@@ -482,10 +482,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
482482
let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
483483
for local in binds_to {
484484
let bind_to = &self.body.local_decls[*local];
485-
if let LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
486-
pat_span,
487-
..
488-
}))) = bind_to.local_info
485+
if let Some(box LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var(
486+
VarBindingForm { pat_span, .. },
487+
)))) = bind_to.local_info
489488
{
490489
if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span)
491490
{

0 commit comments

Comments
 (0)