Skip to content

Commit 334c5d7

Browse files
debuginfo: Use inlinable_string crate to avoid allocations for small strings.
1 parent 7320fdf commit 334c5d7

File tree

8 files changed

+63
-29
lines changed

8 files changed

+63
-29
lines changed

Cargo.lock

+8
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,12 @@ dependencies = [
17681768
"unindent",
17691769
]
17701770

1771+
[[package]]
1772+
name = "inlinable_string"
1773+
version = "0.1.15"
1774+
source = "registry+https://github.com/rust-lang/crates.io-index"
1775+
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
1776+
17711777
[[package]]
17721778
name = "installer"
17731779
version = "0.0.0"
@@ -3537,6 +3543,7 @@ version = "0.0.0"
35373543
dependencies = [
35383544
"bitflags",
35393545
"cstr",
3546+
"inlinable_string",
35403547
"libc",
35413548
"libloading",
35423549
"measureme 10.0.0",
@@ -3633,6 +3640,7 @@ dependencies = [
36333640
"cfg-if 0.1.10",
36343641
"ena",
36353642
"indexmap",
3643+
"inlinable_string",
36363644
"jobserver",
36373645
"libc",
36383646
"measureme 10.0.0",

compiler/rustc_codegen_llvm/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ doctest = false
1010
[dependencies]
1111
bitflags = "1.0"
1212
cstr = "0.2"
13+
inlinable_string = { version = "0.1", features = ["nightly"] }
1314
libc = "0.2"
1415
libloading = "0.7.1"
1516
measureme = "10.0.0"

compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs

+45-24
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ use crate::llvm::debuginfo::{
2020
use crate::value::Value;
2121

2222
use cstr::cstr;
23+
use inlinable_string::InlinableString;
2324
use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo;
2425
use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind;
2526
use rustc_codegen_ssa::traits::*;
27+
use rustc_data_structures::base_n;
2628
use rustc_data_structures::fx::FxHashMap;
2729
use rustc_fs_util::path_to_c_string;
2830
use rustc_hir::def::CtorKind;
@@ -93,8 +95,23 @@ pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
9395

9496
pub const NO_SCOPE_METADATA: Option<&DIScope> = None;
9597

98+
/// Same as format!() but produces an InlinableString to avoid
99+
/// unnecessary memory allocations.
100+
macro_rules! format_inline {
101+
($($tokens:expr),*) => {
102+
{
103+
use inlinable_string::StringExt;
104+
let mut string = inlinable_string::InlinableString::new();
105+
write!(&mut string, $($tokens),*).unwrap();
106+
string
107+
}
108+
};
109+
}
110+
96111
mod unique_type_id {
112+
use inlinable_string::InlinableString;
97113
use rustc_data_structures::{
114+
base_n,
98115
fingerprint::Fingerprint,
99116
stable_hasher::{HashStable, NodeIdHashingMode, StableHasher},
100117
};
@@ -163,15 +180,16 @@ mod unique_type_id {
163180
UniqueTypeId::VTableTy(self_type, implemented_trait, HiddenZst { _inaccessible: () })
164181
}
165182

166-
pub fn to_string(&self, tcx: TyCtxt<'tcx>) -> String {
183+
pub fn to_string(&self, tcx: TyCtxt<'tcx>) -> InlinableString {
167184
let mut hasher = StableHasher::new();
168185
let mut hcx = tcx.create_stable_hashing_context();
169186
hcx.while_hashing_spans(false, |hcx| {
170187
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
171188
self.hash_stable(hcx, &mut hasher);
172189
});
173190
});
174-
hasher.finish::<Fingerprint>().to_hex()
191+
let (low, high) = hasher.finish::<Fingerprint>().as_value();
192+
base_n::encode((low as u128) | ((high as u128) << 64), base_n::MAX_BASE)
175193
}
176194
}
177195
}
@@ -884,7 +902,7 @@ fn foreign_type_metadata<'ll, 'tcx>(
884902

885903
fn param_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
886904
debug!("param_type_metadata: {:?}", t);
887-
let name = format!("{:?}", t);
905+
let name = format_inline!("{:?}", t);
888906
unsafe {
889907
llvm::LLVMRustDIBuilderCreateBasicType(
890908
DIB(cx),
@@ -1077,7 +1095,7 @@ struct SourceInfo<'ll> {
10771095
/// structs or tuples) or an enum variant.
10781096
#[derive(Debug)]
10791097
struct MemberDescription<'ll> {
1080-
name: String,
1098+
name: InlinableString,
10811099
type_metadata: &'ll DIType,
10821100
offset: Size,
10831101
size: Size,
@@ -1162,9 +1180,9 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
11621180
.enumerate()
11631181
.map(|(i, f)| {
11641182
let name = if self.variant.ctor_kind == CtorKind::Fn {
1165-
format!("__{}", i)
1183+
format_inline!("__{}", i)
11661184
} else {
1167-
f.name.to_string()
1185+
f.name.as_str().into()
11681186
};
11691187
let field = layout.field(cx, i);
11701188
MemberDescription {
@@ -1227,7 +1245,10 @@ fn prepare_struct_metadata<'ll, 'tcx>(
12271245
/// Here are some examples:
12281246
/// - `name__field1__field2` when the upvar is captured by value.
12291247
/// - `_ref__name__field` when the upvar is captured by reference.
1230-
fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<String> {
1248+
fn closure_saved_names_of_captured_variables(
1249+
tcx: TyCtxt<'_>,
1250+
def_id: DefId,
1251+
) -> Vec<InlinableString> {
12311252
let body = tcx.optimized_mir(def_id);
12321253

12331254
body.var_debug_info
@@ -1242,7 +1263,7 @@ fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) ->
12421263
_ => return None,
12431264
};
12441265
let prefix = if is_ref { "_ref__" } else { "" };
1245-
Some(prefix.to_owned() + var.name.as_str())
1266+
Some(format_inline!("{}{}", prefix, var.name))
12461267
})
12471268
.collect::<Vec<_>>()
12481269
}
@@ -1273,7 +1294,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
12731294
let name = if let Some(names) = capture_names.as_mut() {
12741295
names.next().unwrap()
12751296
} else {
1276-
format!("__{}", i)
1297+
format_inline!("__{}", i)
12771298
};
12781299
MemberDescription {
12791300
name,
@@ -1345,7 +1366,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> {
13451366
.map(|(i, f)| {
13461367
let field = self.layout.field(cx, i);
13471368
MemberDescription {
1348-
name: f.name.to_string(),
1369+
name: f.name.as_str().into(),
13491370
type_metadata: type_metadata(cx, field.ty),
13501371
offset: Size::ZERO,
13511372
size: field.size,
@@ -1563,7 +1584,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
15631584

15641585
MemberDescription {
15651586
name: if fallback {
1566-
format!("variant{}", i.as_u32())
1587+
format_inline!("variant{}", i.as_u32())
15671588
} else {
15681589
variant_info.variant_name()
15691590
},
@@ -1697,7 +1718,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
16971718
vec![
16981719
MemberDescription {
16991720
// Name the dataful variant so that we can identify it for natvis
1700-
name: "dataful_variant".to_string(),
1721+
name: "dataful_variant".into(),
17011722
type_metadata: variant_type_metadata,
17021723
offset: Size::ZERO,
17031724
size: self.layout.size,
@@ -1762,7 +1783,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
17621783
struct VariantMemberDescriptionFactory<'tcx> {
17631784
/// Cloned from the `layout::Struct` describing the variant.
17641785
offsets: Vec<Size>,
1765-
args: Vec<(String, Ty<'tcx>)>,
1786+
args: Vec<(InlinableString, Ty<'tcx>)>,
17661787
}
17671788

17681789
impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
@@ -1776,7 +1797,7 @@ impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
17761797
.map(|(i, &(ref name, ty))| {
17771798
let (size, align) = cx.size_and_align_of(ty);
17781799
MemberDescription {
1779-
name: name.to_string(),
1800+
name: name.clone(),
17801801
type_metadata: type_metadata(cx, ty),
17811802
offset: self.offsets[i],
17821803
size,
@@ -1819,20 +1840,20 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
18191840
}
18201841
}
18211842

1822-
fn variant_name(&self) -> String {
1843+
fn variant_name(&self) -> InlinableString {
18231844
match self {
1824-
VariantInfo::Adt(variant, _) => variant.name.to_string(),
1845+
VariantInfo::Adt(variant, _) => variant.name.as_str().into(),
18251846
VariantInfo::Generator { variant_index, .. } => {
18261847
// Since GDB currently prints out the raw discriminant along
18271848
// with every variant, make each variant name be just the value
18281849
// of the discriminant. The struct name for the variant includes
18291850
// the actual variant description.
1830-
format!("{}", variant_index.as_usize())
1851+
base_n::encode(variant_index.as_usize() as u128, 10)
18311852
}
18321853
}
18331854
}
18341855

1835-
fn field_name(&self, i: usize) -> String {
1856+
fn field_name(&self, i: usize) -> InlinableString {
18361857
let field_name = match *self {
18371858
VariantInfo::Adt(variant, _) if variant.ctor_kind != CtorKind::Fn => {
18381859
Some(variant.fields[i].name)
@@ -1848,7 +1869,7 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
18481869
}
18491870
_ => None,
18501871
};
1851-
field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i))
1872+
field_name.map(|name| name.as_str().into()).unwrap_or_else(|| format_inline!("__{}", i))
18521873
}
18531874

18541875
fn source_info<'ll>(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option<SourceInfo<'ll>> {
@@ -2532,19 +2553,19 @@ fn vtable_type_metadata<'ll, 'tcx>(
25322553
.filter_map(|(index, vtable_entry)| {
25332554
let (field_name, field_type) = match vtable_entry {
25342555
ty::VtblEntry::MetadataDropInPlace => {
2535-
("drop_in_place".to_string(), void_pointer_type_debuginfo)
2556+
("drop_in_place".into(), void_pointer_type_debuginfo)
25362557
}
25372558
ty::VtblEntry::Method(_) => {
25382559
// Note: This code does not try to give a proper name to each method
25392560
// because their might be multiple methods with the same name
25402561
// (coming from different traits).
2541-
(format!("__method{}", index), void_pointer_type_debuginfo)
2562+
(format_inline!("__method{}", index), void_pointer_type_debuginfo)
25422563
}
25432564
ty::VtblEntry::TraitVPtr(_) => {
2544-
(format!("__super_trait_ptr{}", index), void_pointer_type_debuginfo)
2565+
(format_inline!("__super_trait_ptr{}", index), void_pointer_type_debuginfo)
25452566
}
2546-
ty::VtblEntry::MetadataAlign => ("align".to_string(), usize_debuginfo),
2547-
ty::VtblEntry::MetadataSize => ("size".to_string(), usize_debuginfo),
2567+
ty::VtblEntry::MetadataAlign => ("align".into(), usize_debuginfo),
2568+
ty::VtblEntry::MetadataSize => ("size".into(), usize_debuginfo),
25482569
ty::VtblEntry::Vacant => return None,
25492570
};
25502571

compiler/rustc_data_structures/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ measureme = "10.0.0"
2727
libc = "0.2"
2828
stacker = "0.1.14"
2929
tempfile = "3.2"
30+
inlinable_string = { version = "0.1", features = ["nightly"] }
3031

3132
[dependencies.parking_lot]
3233
version = "0.11"

compiler/rustc_data_structures/src/base_n.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
/// Bases up to and including 36 can be used for case-insensitive things.
33
use std::str;
44

5+
use inlinable_string::{InlinableString, StringExt};
6+
57
#[cfg(test)]
68
mod tests;
79

@@ -13,7 +15,7 @@ const BASE_64: &[u8; MAX_BASE as usize] =
1315
b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@$";
1416

1517
#[inline]
16-
pub fn push_str(mut n: u128, base: usize, output: &mut String) {
18+
pub fn push_str<'a>(mut n: u128, base: usize, output: &mut impl StringExt<'a>) {
1719
debug_assert!(base >= 2 && base <= MAX_BASE);
1820
let mut s = [0u8; 128];
1921
let mut index = 0;
@@ -35,8 +37,8 @@ pub fn push_str(mut n: u128, base: usize, output: &mut String) {
3537
}
3638

3739
#[inline]
38-
pub fn encode(n: u128, base: usize) -> String {
39-
let mut s = String::new();
40+
pub fn encode(n: u128, base: usize) -> InlinableString {
41+
let mut s = InlinableString::new();
4042
push_str(n, base, &mut s);
4143
s
4244
}

compiler/rustc_incremental/src/persist/fs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime
640640
fn timestamp_to_string(timestamp: SystemTime) -> String {
641641
let duration = timestamp.duration_since(UNIX_EPOCH).unwrap();
642642
let micros = duration.as_secs() * 1_000_000 + (duration.subsec_nanos() as u64) / 1000;
643-
base_n::encode(micros as u128, INT_ENCODE_BASE)
643+
base_n::encode(micros as u128, INT_ENCODE_BASE).to_string()
644644
}
645645

646646
fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {

compiler/rustc_middle/src/mir/mono.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ impl<'tcx> CodegenUnit<'tcx> {
325325
human_readable_name.hash(&mut hasher);
326326
let hash: u128 = hasher.finish();
327327
let hash = hash & ((1u128 << 80) - 1);
328-
base_n::encode(hash, base_n::CASE_INSENSITIVE)
328+
base_n::encode(hash, base_n::CASE_INSENSITIVE).to_string()
329329
}
330330

331331
pub fn estimate_size(&mut self, tcx: TyCtxt<'tcx>) {

src/tools/tidy/src/deps.rs

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
123123
"humantime",
124124
"if_chain",
125125
"indexmap",
126+
"inlinable_string",
126127
"instant",
127128
"itertools",
128129
"itoa",

0 commit comments

Comments
 (0)