about summary refs log tree commit diff
path: root/src/liballoc/rc.rs
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <arielb1@mail.tau.ac.il>2017-04-20 15:08:41 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2017-04-22 21:00:50 +0300
commitece6c8434bc4eba1d3addfa4d5900264e55395fc (patch)
tree5fe4185c3ba908c2eb5c9660111eb18f9d4918f1 /src/liballoc/rc.rs
parentacd0e40b86d718d339b13f594242575c28e966f7 (diff)
downloadrust-ece6c8434bc4eba1d3addfa4d5900264e55395fc.tar.gz
rust-ece6c8434bc4eba1d3addfa4d5900264e55395fc.zip
cache attributes of items from foreign crates
this avoids parsing item attributes on each call to `item_attrs`, which takes
off 33% (!) of translation time and 50% (!) of trans-item collection time.
Diffstat (limited to 'src/liballoc/rc.rs')
-rw-r--r--src/liballoc/rc.rs35
1 files changed, 33 insertions, 2 deletions
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index fed718e9be4..69e5351cad5 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -239,7 +239,7 @@ use core::ops::CoerceUnsized;
 use core::ptr::{self, Shared};
 use core::convert::From;
 
-use heap::deallocate;
+use heap::{allocate, deallocate, box_free};
 use raw_vec::RawVec;
 
 struct RcBox<T: ?Sized> {
@@ -248,7 +248,6 @@ struct RcBox<T: ?Sized> {
     value: T,
 }
 
-
 /// A single-threaded reference-counting pointer.
 ///
 /// See the [module-level documentation](./index.html) for more details.
@@ -438,6 +437,38 @@ impl Rc<str> {
     }
 }
 
+impl<T> Rc<[T]> {
+    /// Constructs a new `Rc<[T]>` from a `Box<[T]>`.
+    #[doc(hidden)]
+    #[unstable(feature = "rustc_private",
+               reason = "for internal use in rustc",
+               issue = "0")]
+    pub fn __from_array(value: Box<[T]>) -> Rc<[T]> {
+        unsafe {
+            let ptr: *mut RcBox<[T]> =
+                mem::transmute([mem::align_of::<RcBox<[T; 1]>>(), value.len()]);
+            // FIXME(custom-DST): creating this invalid &[T] is dubiously defined,
+            // we should have a better way of getting the size/align
+            // of a DST from its unsized part.
+            let ptr = allocate(size_of_val(&*ptr), align_of_val(&*ptr));
+            let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]);
+
+            // Initialize the new RcBox.
+            ptr::write(&mut (*ptr).strong, Cell::new(1));
+            ptr::write(&mut (*ptr).weak, Cell::new(1));
+            ptr::copy_nonoverlapping(
+                value.as_ptr(),
+                &mut (*ptr).value as *mut [T] as *mut T,
+                value.len());
+
+            // Free the original allocation without freeing its (moved) contents.
+            box_free(Box::into_raw(value));
+
+            Rc { ptr: Shared::new(ptr as *const _) }
+        }
+    }
+}
+
 impl<T: ?Sized> Rc<T> {
     /// Creates a new [`Weak`][weak] pointer to this value.
     ///