Skip to content

Commit 5bfe107

Browse files
authored
Auto merge of #37132 - petrochenkov:intern, r=alexcrichton
Get rid of double indirection in string interner
2 parents 8e05e7e + 348c3fb commit 5bfe107

File tree

4 files changed

+48
-39
lines changed

4 files changed

+48
-39
lines changed

src/liballoc/rc.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -230,13 +230,14 @@ use core::hash::{Hash, Hasher};
230230
use core::intrinsics::{abort, assume};
231231
use core::marker;
232232
use core::marker::Unsize;
233-
use core::mem::{self, align_of_val, forget, size_of_val, uninitialized};
233+
use core::mem::{self, align_of_val, forget, size_of, size_of_val, uninitialized};
234234
use core::ops::Deref;
235235
use core::ops::CoerceUnsized;
236236
use core::ptr::{self, Shared};
237237
use core::convert::From;
238238

239239
use heap::deallocate;
240+
use raw_vec::RawVec;
240241

241242
struct RcBox<T: ?Sized> {
242243
strong: Cell<usize>,
@@ -365,6 +366,31 @@ impl<T> Rc<T> {
365366
}
366367
}
367368

369+
impl Rc<str> {
370+
/// Constructs a new `Rc<str>` from a string slice.
371+
#[doc(hidden)]
372+
#[unstable(feature = "rustc_private",
373+
reason = "for internal use in rustc",
374+
issue = "0")]
375+
pub fn __from_str(value: &str) -> Rc<str> {
376+
unsafe {
377+
// Allocate enough space for `RcBox<str>`.
378+
let aligned_len = 2 + (value.len() + size_of::<usize>() - 1) / size_of::<usize>();
379+
let vec = RawVec::<usize>::with_capacity(aligned_len);
380+
let ptr = vec.ptr();
381+
forget(vec);
382+
// Initialize fields of `RcBox<str>`.
383+
*ptr.offset(0) = 1; // strong: Cell::new(1)
384+
*ptr.offset(1) = 1; // weak: Cell::new(1)
385+
ptr::copy_nonoverlapping(value.as_ptr(), ptr.offset(2) as *mut u8, value.len());
386+
// Combine the allocation address and the string length into a fat pointer to `RcBox`.
387+
let rcbox_ptr: *mut RcBox<str> = mem::transmute([ptr as usize, value.len()]);
388+
assert!(aligned_len * size_of::<usize>() == size_of_val(&*rcbox_ptr));
389+
Rc { ptr: Shared::new(rcbox_ptr) }
390+
}
391+
}
392+
}
393+
368394
impl<T: ?Sized> Rc<T> {
369395
/// Creates a new [`Weak`][weak] pointer to this value.
370396
///

src/librustc_trans/debuginfo/metadata.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl<'tcx> TypeMap<'tcx> {
128128

129129
// Get the string representation of a UniqueTypeId. This method will fail if
130130
// the id is unknown.
131-
fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> Rc<String> {
131+
fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> Rc<str> {
132132
let UniqueTypeId(interner_key) = unique_type_id;
133133
self.unique_id_interner.get(interner_key)
134134
}
@@ -299,7 +299,7 @@ impl<'tcx> TypeMap<'tcx> {
299299
// Trim to size before storing permanently
300300
unique_type_id.shrink_to_fit();
301301

302-
let key = self.unique_id_interner.intern(unique_type_id);
302+
let key = self.unique_id_interner.intern(&unique_type_id);
303303
self.type_to_unique_id.insert(type_, UniqueTypeId(key));
304304

305305
return UniqueTypeId(key);
@@ -367,7 +367,7 @@ impl<'tcx> TypeMap<'tcx> {
367367
let enum_variant_type_id = format!("{}::{}",
368368
&self.get_unique_type_id_as_string(enum_type_id),
369369
variant_name);
370-
let interner_key = self.unique_id_interner.intern(enum_variant_type_id);
370+
let interner_key = self.unique_id_interner.intern(&enum_variant_type_id);
371371
UniqueTypeId(interner_key)
372372
}
373373
}

src/libsyntax/parse/token.rs

+3-10
Original file line numberDiff line numberDiff line change
@@ -478,27 +478,20 @@ pub fn clear_ident_interner() {
478478
/// somehow.
479479
#[derive(Clone, PartialEq, Hash, PartialOrd, Eq, Ord)]
480480
pub struct InternedString {
481-
string: Rc<String>,
481+
string: Rc<str>,
482482
}
483483

484484
impl InternedString {
485485
#[inline]
486486
pub fn new(string: &'static str) -> InternedString {
487487
InternedString {
488-
string: Rc::new(string.to_owned()),
489-
}
490-
}
491-
492-
#[inline]
493-
fn new_from_rc_str(string: Rc<String>) -> InternedString {
494-
InternedString {
495-
string: string,
488+
string: Rc::__from_str(string),
496489
}
497490
}
498491

499492
#[inline]
500493
pub fn new_from_name(name: ast::Name) -> InternedString {
501-
with_ident_interner(|interner| InternedString::new_from_rc_str(interner.get(name)))
494+
with_ident_interner(|interner| InternedString { string: interner.get(name) })
502495
}
503496
}
504497

src/libsyntax/util/interner.rs

+15-25
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,13 @@
1414
1515
use ast::Name;
1616

17-
use std::borrow::Borrow;
1817
use std::collections::HashMap;
1918
use std::rc::Rc;
2019

21-
#[derive(PartialEq, Eq, Hash)]
22-
struct RcStr(Rc<String>);
23-
24-
impl Borrow<str> for RcStr {
25-
fn borrow(&self) -> &str {
26-
&self.0
27-
}
28-
}
29-
3020
#[derive(Default)]
3121
pub struct Interner {
32-
names: HashMap<RcStr, Name>,
33-
strings: Vec<Rc<String>>,
22+
names: HashMap<Rc<str>, Name>,
23+
strings: Vec<Rc<str>>,
3424
}
3525

3626
/// When traits can extend traits, we should extend index<Name,T> to get []
@@ -47,22 +37,22 @@ impl Interner {
4737
this
4838
}
4939

50-
pub fn intern<T: Borrow<str> + Into<String>>(&mut self, string: T) -> Name {
51-
if let Some(&name) = self.names.get(string.borrow()) {
40+
pub fn intern(&mut self, string: &str) -> Name {
41+
if let Some(&name) = self.names.get(string) {
5242
return name;
5343
}
5444

5545
let name = Name(self.strings.len() as u32);
56-
let string = Rc::new(string.into());
46+
let string = Rc::__from_str(string);
5747
self.strings.push(string.clone());
58-
self.names.insert(RcStr(string), name);
48+
self.names.insert(string, name);
5949
name
6050
}
6151

6252
pub fn gensym(&mut self, string: &str) -> Name {
6353
let gensym = Name(self.strings.len() as u32);
6454
// leave out of `names` to avoid colliding
65-
self.strings.push(Rc::new(string.to_owned()));
55+
self.strings.push(Rc::__from_str(string));
6656
gensym
6757
}
6858

@@ -75,7 +65,7 @@ impl Interner {
7565
gensym
7666
}
7767

78-
pub fn get(&self, name: Name) -> Rc<String> {
68+
pub fn get(&self, name: Name) -> Rc<str> {
7969
self.strings[name.0 as usize].clone()
8070
}
8171

@@ -109,13 +99,13 @@ mod tests {
10999
assert_eq!(i.gensym("dog"), Name(4));
110100
// gensym tests again with gensym_copy:
111101
assert_eq!(i.gensym_copy(Name(2)), Name(5));
112-
assert_eq!(*i.get(Name(5)), "zebra");
102+
assert_eq!(&*i.get(Name(5)), "zebra");
113103
assert_eq!(i.gensym_copy(Name(2)), Name(6));
114-
assert_eq!(*i.get(Name(6)), "zebra");
115-
assert_eq!(*i.get(Name(0)), "dog");
116-
assert_eq!(*i.get(Name(1)), "cat");
117-
assert_eq!(*i.get(Name(2)), "zebra");
118-
assert_eq!(*i.get(Name(3)), "zebra");
119-
assert_eq!(*i.get(Name(4)), "dog");
104+
assert_eq!(&*i.get(Name(6)), "zebra");
105+
assert_eq!(&*i.get(Name(0)), "dog");
106+
assert_eq!(&*i.get(Name(1)), "cat");
107+
assert_eq!(&*i.get(Name(2)), "zebra");
108+
assert_eq!(&*i.get(Name(3)), "zebra");
109+
assert_eq!(&*i.get(Name(4)), "dog");
120110
}
121111
}

0 commit comments

Comments
 (0)