diff options
| author | bors <bors@rust-lang.org> | 2016-10-15 09:32:06 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-10-15 09:32:06 -0700 |
| commit | 5bfe10740168eb8213101c827302b4c45b1b5b74 (patch) | |
| tree | 87a212efaa05f0461b26e463fdeabb8718b0c8c3 /src/liballoc | |
| parent | 8e05e7ee3c19a5594b79d67c8390cef78970be7c (diff) | |
| parent | 348c3fb0851c155f06768e54c44990d39b6eb142 (diff) | |
Auto merge of #37132 - petrochenkov:intern, r=alexcrichton
Get rid of double indirection in string interner
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/rc.rs | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 699f777138d..740d13c4762 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -230,13 +230,14 @@ use core::hash::{Hash, Hasher}; use core::intrinsics::{abort, assume}; use core::marker; use core::marker::Unsize; -use core::mem::{self, align_of_val, forget, size_of_val, uninitialized}; +use core::mem::{self, align_of_val, forget, size_of, size_of_val, uninitialized}; use core::ops::Deref; use core::ops::CoerceUnsized; use core::ptr::{self, Shared}; use core::convert::From; use heap::deallocate; +use raw_vec::RawVec; struct RcBox<T: ?Sized> { strong: Cell<usize>, @@ -365,6 +366,31 @@ impl<T> Rc<T> { } } +impl Rc<str> { + /// Constructs a new `Rc<str>` from a string slice. + #[doc(hidden)] + #[unstable(feature = "rustc_private", + reason = "for internal use in rustc", + issue = "0")] + pub fn __from_str(value: &str) -> Rc<str> { + unsafe { + // Allocate enough space for `RcBox<str>`. + let aligned_len = 2 + (value.len() + size_of::<usize>() - 1) / size_of::<usize>(); + let vec = RawVec::<usize>::with_capacity(aligned_len); + let ptr = vec.ptr(); + forget(vec); + // Initialize fields of `RcBox<str>`. + *ptr.offset(0) = 1; // strong: Cell::new(1) + *ptr.offset(1) = 1; // weak: Cell::new(1) + ptr::copy_nonoverlapping(value.as_ptr(), ptr.offset(2) as *mut u8, value.len()); + // Combine the allocation address and the string length into a fat pointer to `RcBox`. + let rcbox_ptr: *mut RcBox<str> = mem::transmute([ptr as usize, value.len()]); + assert!(aligned_len * size_of::<usize>() == size_of_val(&*rcbox_ptr)); + Rc { ptr: Shared::new(rcbox_ptr) } + } + } +} + impl<T: ?Sized> Rc<T> { /// Creates a new [`Weak`][weak] pointer to this value. /// |
