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.
This commit is contained in:
parent
acd0e40b86
commit
ece6c8434b
|
@ -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.
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
})
|
||||
|
|
|
@ -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> {
|
||||
|
|
Loading…
Reference in New Issue