diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index ce30b3fae47ae..1f9c5a8eecad0 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1730,10 +1730,10 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(BasicBlockData<'_>, 160); + static_assert_size!(BasicBlockData<'_>, 144); static_assert_size!(LocalDecl<'_>, 40); static_assert_size!(SourceScopeData<'_>, 64); - static_assert_size!(Statement<'_>, 56); + static_assert_size!(Statement<'_>, 40); static_assert_size!(Terminator<'_>, 104); static_assert_size!(VarDebugInfo<'_>, 88); // tidy-alphabetical-end diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index f25eaf3c6d32e..a7aeadaaff318 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -1,7 +1,6 @@ //! Functionality for statements, operands, places, and things that appear in them. use std::ops; - use tracing::{debug, instrument}; use super::interpret::GlobalAlloc; @@ -1034,27 +1033,42 @@ impl RawPtrKind { } } +// FIXME(panstromek) +// I'd like to use real ThinVec here, but it fails to borrow check, +// probably because ThinVec doesn't have #[may_dangle] on Drop impl? +type ThinVec = Option>>; + #[derive(Default, Debug, Clone, TyEncodable, TyDecodable, StableHash, TypeFoldable, TypeVisitable)] -pub struct StmtDebugInfos<'tcx>(Vec>); +pub struct StmtDebugInfos<'tcx>(ThinVec>); impl<'tcx> StmtDebugInfos<'tcx> { pub fn push(&mut self, debuginfo: StmtDebugInfo<'tcx>) { - self.0.push(debuginfo); + self.0.get_or_insert_default().push(debuginfo); } pub fn drop_debuginfo(&mut self) { - self.0.clear(); + self.0.as_mut().map(|v| v.clear()); } + #[inline] pub fn is_empty(&self) -> bool { - self.0.is_empty() + match &self.0 { + None => true, + Some(v) => Self::is_empty_inner(v) + } + } + + #[cold] + #[inline(never)] + fn is_empty_inner(v: &Box>>) -> bool { + v.is_empty() } pub fn prepend(&mut self, debuginfos: &mut Self) { if debuginfos.is_empty() { return; }; - debuginfos.0.append(self); + debuginfos.append(self); std::mem::swap(debuginfos, self); } @@ -1062,38 +1076,59 @@ impl<'tcx> StmtDebugInfos<'tcx> { if debuginfos.is_empty() { return; }; - self.0.append(debuginfos); + self.0.get_or_insert_default().append(debuginfos.0.as_mut().unwrap().as_mut()); } pub fn extend(&mut self, debuginfos: &Self) { if debuginfos.is_empty() { return; }; - self.0.extend_from_slice(debuginfos); + self.0.get_or_insert_default().extend_from_slice(debuginfos.as_slice()); + } + + #[inline] + pub fn as_slice(&self) -> &[StmtDebugInfo<'tcx>] { + match &self.0 { + None => &[], + Some(items) => items.as_slice(), + } + } + + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [StmtDebugInfo<'tcx>] { + match &mut self.0 { + None => &mut [], + Some(items) => items.as_mut_slice() + } } pub fn retain_locals(&mut self, locals: &DenseBitSet) { - self.retain(|debuginfo| match debuginfo { - StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => { - locals.contains(*local) + match &mut self.0 { + None => (), + Some(items) => { + items.retain(|debuginfo| match debuginfo { + StmtDebugInfo::AssignRef(local, _) | StmtDebugInfo::InvalidAssign(local) => { + locals.contains(*local) + } + }) } - }); + } } } impl<'tcx> ops::Deref for StmtDebugInfos<'tcx> { - type Target = Vec>; + type Target = [StmtDebugInfo<'tcx>]; #[inline] - fn deref(&self) -> &Vec> { - &self.0 + fn deref(&self) -> &Self::Target { + self.as_slice() } } impl<'tcx> ops::DerefMut for StmtDebugInfos<'tcx> { #[inline] - fn deref_mut(&mut self) -> &mut Vec> { - &mut self.0 + fn deref_mut(&mut self) -> &mut Self::Target { + self.as_mut_slice() } }