about summary refs log tree commit diff
path: root/src
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
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')
-rw-r--r--src/liballoc/heap.rs6
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/rc.rs35
-rw-r--r--src/librustc/middle/cstore.rs4
-rw-r--r--src/librustc/ty/instance.rs5
-rw-r--r--src/librustc/ty/mod.rs24
-rw-r--r--src/librustc_driver/driver.rs2
-rw-r--r--src/librustc_metadata/creader.rs1
-rw-r--r--src/librustc_metadata/cstore.rs3
-rw-r--r--src/librustc_metadata/cstore_impl.rs6
-rw-r--r--src/librustc_metadata/decoder.rs21
11 files changed, 85 insertions, 23 deletions
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index 08a0b2a6d00..056af13016c 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -16,7 +16,6 @@
             issue = "27700")]
 
 use core::{isize, usize};
-#[cfg(not(test))]
 use core::intrinsics::{min_align_of_val, size_of_val};
 
 #[allow(improper_ctypes)]
@@ -158,10 +157,9 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
     }
 }
 
-#[cfg(not(test))]
-#[lang = "box_free"]
+#[cfg_attr(not(test), lang = "box_free")]
 #[inline]
-unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
+pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
     let size = size_of_val(&*ptr);
     let align = min_align_of_val(&*ptr);
     // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 0c01eabd593..c70d82392f9 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -87,6 +87,7 @@
 #![feature(needs_allocator)]
 #![feature(optin_builtin_traits)]
 #![feature(placement_in_syntax)]
+#![cfg_attr(stage0, feature(pub_restricted))]
 #![feature(shared)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
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.
     ///
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index cbbfeacadb4..16b31bdb074 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -188,7 +188,7 @@ pub trait CrateStore {
     fn visibility(&self, def: DefId) -> ty::Visibility;
     fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
     fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
-    fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
+    fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]>;
     fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
 
     // trait info
@@ -323,7 +323,7 @@ impl CrateStore for DummyCrateStore {
     }
     fn item_generics_cloned(&self, def: DefId) -> ty::Generics
         { bug!("item_generics_cloned") }
-    fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
+    fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]> { bug!("item_attrs") }
     fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
 
     // trait info
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 67287f1b4ff..cfff3d0e573 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -13,10 +13,7 @@ use hir::def_id::DefId;
 use ty::{self, Ty, TypeFoldable, Substs};
 use util::ppaux;
 
-use std::borrow::Cow;
 use std::fmt;
-use syntax::ast;
-
 
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct Instance<'tcx> {
@@ -59,7 +56,7 @@ impl<'tcx> InstanceDef<'tcx> {
     }
 
     #[inline]
-    pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Cow<'tcx, [ast::Attribute]> {
+    pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
         tcx.get_attrs(self.def_id())
     }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index e355b69d6e6..7aa12429e5d 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -34,7 +34,6 @@ use ty::walk::TypeWalker;
 use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
 
 use serialize::{self, Encodable, Encoder};
-use std::borrow::Cow;
 use std::cell::{Cell, RefCell, Ref};
 use std::collections::BTreeMap;
 use std::cmp;
@@ -2036,6 +2035,23 @@ impl BorrowKind {
     }
 }
 
+#[derive(Debug, Clone)]
+pub enum Attributes<'gcx> {
+    Owned(Rc<[ast::Attribute]>),
+    Borrowed(&'gcx [ast::Attribute])
+}
+
+impl<'gcx> ::std::ops::Deref for Attributes<'gcx> {
+    type Target = [ast::Attribute];
+
+    fn deref(&self) -> &[ast::Attribute] {
+        match self {
+            &Attributes::Owned(ref data) => &data,
+            &Attributes::Borrowed(data) => data
+        }
+    }
+}
+
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
         self.item_tables(self.hir.body_owner_def_id(body))
@@ -2389,11 +2405,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     /// Get the attributes of a definition.
-    pub fn get_attrs(self, did: DefId) -> Cow<'gcx, [ast::Attribute]> {
+    pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
         if let Some(id) = self.hir.as_local_node_id(did) {
-            Cow::Borrowed(self.hir.attrs(id))
+            Attributes::Borrowed(self.hir.attrs(id))
         } else {
-            Cow::Owned(self.sess.cstore.item_attrs(did))
+            Attributes::Owned(self.sess.cstore.item_attrs(did))
         }
     }
 
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index ac4e2bd5c10..438f482fa55 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -225,6 +225,8 @@ pub fn compile_input(sess: &Session,
         sess.code_stats.borrow().print_type_sizes();
     }
 
+    if ::std::env::var("SKIP_LLVM").is_ok() { ::std::process::exit(0); }
+
     let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
 
     controller_entry_point!(after_llvm,
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index a8ee999505e..7bc0e8a512b 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -326,6 +326,7 @@ impl<'a> CrateLoader<'a> {
             cnum_map: RefCell::new(cnum_map),
             cnum: cnum,
             codemap_import_info: RefCell::new(vec![]),
+            attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
             dep_kind: Cell::new(dep_kind),
             source: cstore::CrateSource {
                 dylib: dylib,
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 17a6a706e0a..72ad1d75a56 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -72,6 +72,7 @@ pub struct CrateMetadata {
     pub cnum_map: RefCell<CrateNumMap>,
     pub cnum: CrateNum,
     pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
+    pub attribute_cache: RefCell<[Vec<Option<Rc<[ast::Attribute]>>>; 2]>,
 
     pub root: schema::CrateRoot,
 
@@ -269,7 +270,7 @@ impl CrateMetadata {
     }
 
     pub fn is_staged_api(&self) -> bool {
-        for attr in self.get_item_attrs(CRATE_DEF_INDEX) {
+        for attr in self.get_item_attrs(CRATE_DEF_INDEX).iter() {
             if attr.path == "stable" || attr.path == "unstable" {
                 return true;
             }
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 3cff063a8f5..e02c61f3646 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -149,7 +149,7 @@ impl CrateStore for cstore::CStore {
         self.get_crate_data(def.krate).get_generics(def.index)
     }
 
-    fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>
+    fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]>
     {
         self.dep_graph.read(DepNode::MetaData(def_id));
         self.get_crate_data(def_id.krate).get_item_attrs(def_id.index)
@@ -406,7 +406,7 @@ impl CrateStore for cstore::CStore {
 
         // Mark the attrs as used
         let attrs = data.get_item_attrs(id.index);
-        for attr in &attrs {
+        for attr in attrs.iter() {
             attr::mark_used(attr);
         }
 
@@ -419,7 +419,7 @@ impl CrateStore for cstore::CStore {
             ident: ast::Ident::with_empty_ctxt(name),
             id: ast::DUMMY_NODE_ID,
             span: local_span,
-            attrs: attrs,
+            attrs: attrs.iter().cloned().collect(),
             node: ast::ItemKind::MacroDef(body.into()),
             vis: ast::Visibility::Inherited,
         })
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index fac6079529e..2d562aceb65 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -31,6 +31,7 @@ use std::cell::Ref;
 use std::collections::BTreeMap;
 use std::io;
 use std::mem;
+use std::rc::Rc;
 use std::str;
 use std::u32;
 
@@ -859,10 +860,18 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
-    pub fn get_item_attrs(&self, node_id: DefIndex) -> Vec<ast::Attribute> {
+    pub fn get_item_attrs(&self, node_id: DefIndex) -> Rc<[ast::Attribute]> {
+        let (node_as, node_index) =
+            (node_id.address_space().index(), node_id.as_array_index());
         if self.is_proc_macro(node_id) {
-            return Vec::new();
+            return Rc::new([]);
         }
+
+        if let Some(&Some(ref val)) =
+            self.attribute_cache.borrow()[node_as].get(node_index) {
+            return val.clone();
+        }
+
         // The attributes for a tuple struct are attached to the definition, not the ctor;
         // we assume that someone passing in a tuple struct ctor is actually wanting to
         // look at the definition
@@ -871,7 +880,13 @@ impl<'a, 'tcx> CrateMetadata {
         if def_key.disambiguated_data.data == DefPathData::StructCtor {
             item = self.entry(def_key.parent.unwrap());
         }
-        self.get_attributes(&item)
+        let result = Rc::__from_array(self.get_attributes(&item).into_boxed_slice());
+        let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
+        if vec_.len() < node_index + 1 {
+            vec_.resize(node_index + 1, None);
+        }
+        vec_[node_index] = Some(result.clone());
+        result
     }
 
     pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {