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(ptr: *mut T) { +pub(crate) unsafe fn box_free(ptr: *mut T) { let size = size_of_val(&*ptr); let align = min_align_of_val(&*ptr); // We do not allocate for Box 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 { @@ -248,7 +248,6 @@ struct RcBox { value: T, } - /// A single-threaded reference-counting pointer. /// /// See the [module-level documentation](./index.html) for more details. @@ -438,6 +437,38 @@ impl Rc { } } +impl 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::>(), 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 Rc { /// 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>; fn item_generics_cloned(&self, def: DefId) -> ty::Generics; - fn item_attrs(&self, def_id: DefId) -> Vec; + fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]>; fn fn_arg_names(&self, did: DefId) -> Vec; // 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 { bug!("item_attrs") } + fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]> { bug!("item_attrs") } fn fn_arg_names(&self, did: DefId) -> Vec { 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, pub cnum: CrateNum, pub codemap_import_info: RefCell>, + pub attribute_cache: RefCell<[Vec>>; 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 + 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 { + 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 {