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:
Ariel Ben-Yehuda 2017-04-20 15:08:41 +03:00 committed by Ariel Ben-Yehuda
parent acd0e40b86
commit ece6c8434b
11 changed files with 85 additions and 23 deletions

View File

@ -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.

View File

@ -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)]

View File

@ -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.
///

View File

@ -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

View File

@ -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())
}

View File

@ -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))
}
}

View File

@ -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,

View File

@ -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,

View File

@ -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;
}

View File

@ -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,
})

View File

@ -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> {