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")]
|
issue = "27700")]
|
||||||
|
|
||||||
use core::{isize, usize};
|
use core::{isize, usize};
|
||||||
#[cfg(not(test))]
|
|
||||||
use core::intrinsics::{min_align_of_val, size_of_val};
|
use core::intrinsics::{min_align_of_val, size_of_val};
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
|
@ -158,10 +157,9 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg_attr(not(test), lang = "box_free")]
|
||||||
#[lang = "box_free"]
|
|
||||||
#[inline]
|
#[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 size = size_of_val(&*ptr);
|
||||||
let align = min_align_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.
|
// 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(needs_allocator)]
|
||||||
#![feature(optin_builtin_traits)]
|
#![feature(optin_builtin_traits)]
|
||||||
#![feature(placement_in_syntax)]
|
#![feature(placement_in_syntax)]
|
||||||
|
#![cfg_attr(stage0, feature(pub_restricted))]
|
||||||
#![feature(shared)]
|
#![feature(shared)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
|
|
|
@ -239,7 +239,7 @@ use core::ops::CoerceUnsized;
|
||||||
use core::ptr::{self, Shared};
|
use core::ptr::{self, Shared};
|
||||||
use core::convert::From;
|
use core::convert::From;
|
||||||
|
|
||||||
use heap::deallocate;
|
use heap::{allocate, deallocate, box_free};
|
||||||
use raw_vec::RawVec;
|
use raw_vec::RawVec;
|
||||||
|
|
||||||
struct RcBox<T: ?Sized> {
|
struct RcBox<T: ?Sized> {
|
||||||
|
@ -248,7 +248,6 @@ struct RcBox<T: ?Sized> {
|
||||||
value: T,
|
value: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A single-threaded reference-counting pointer.
|
/// A single-threaded reference-counting pointer.
|
||||||
///
|
///
|
||||||
/// See the [module-level documentation](./index.html) for more details.
|
/// 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> {
|
impl<T: ?Sized> Rc<T> {
|
||||||
/// Creates a new [`Weak`][weak] pointer to this value.
|
/// Creates a new [`Weak`][weak] pointer to this value.
|
||||||
///
|
///
|
||||||
|
|
|
@ -188,7 +188,7 @@ pub trait CrateStore {
|
||||||
fn visibility(&self, def: DefId) -> ty::Visibility;
|
fn visibility(&self, def: DefId) -> ty::Visibility;
|
||||||
fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
|
fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
|
||||||
fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
|
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>;
|
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
|
||||||
|
|
||||||
// trait info
|
// trait info
|
||||||
|
@ -323,7 +323,7 @@ impl CrateStore for DummyCrateStore {
|
||||||
}
|
}
|
||||||
fn item_generics_cloned(&self, def: DefId) -> ty::Generics
|
fn item_generics_cloned(&self, def: DefId) -> ty::Generics
|
||||||
{ bug!("item_generics_cloned") }
|
{ 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") }
|
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
|
||||||
|
|
||||||
// trait info
|
// trait info
|
||||||
|
|
|
@ -13,10 +13,7 @@ use hir::def_id::DefId;
|
||||||
use ty::{self, Ty, TypeFoldable, Substs};
|
use ty::{self, Ty, TypeFoldable, Substs};
|
||||||
use util::ppaux;
|
use util::ppaux;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use syntax::ast;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct Instance<'tcx> {
|
pub struct Instance<'tcx> {
|
||||||
|
@ -59,7 +56,7 @@ impl<'tcx> InstanceDef<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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())
|
tcx.get_attrs(self.def_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ use ty::walk::TypeWalker;
|
||||||
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
|
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
|
||||||
|
|
||||||
use serialize::{self, Encodable, Encoder};
|
use serialize::{self, Encodable, Encoder};
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::cell::{Cell, RefCell, Ref};
|
use std::cell::{Cell, RefCell, Ref};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::cmp;
|
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> {
|
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
|
pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
|
||||||
self.item_tables(self.hir.body_owner_def_id(body))
|
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.
|
/// 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) {
|
if let Some(id) = self.hir.as_local_node_id(did) {
|
||||||
Cow::Borrowed(self.hir.attrs(id))
|
Attributes::Borrowed(self.hir.attrs(id))
|
||||||
} else {
|
} 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();
|
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);
|
let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
|
||||||
|
|
||||||
controller_entry_point!(after_llvm,
|
controller_entry_point!(after_llvm,
|
||||||
|
|
|
@ -326,6 +326,7 @@ impl<'a> CrateLoader<'a> {
|
||||||
cnum_map: RefCell::new(cnum_map),
|
cnum_map: RefCell::new(cnum_map),
|
||||||
cnum: cnum,
|
cnum: cnum,
|
||||||
codemap_import_info: RefCell::new(vec![]),
|
codemap_import_info: RefCell::new(vec![]),
|
||||||
|
attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
|
||||||
dep_kind: Cell::new(dep_kind),
|
dep_kind: Cell::new(dep_kind),
|
||||||
source: cstore::CrateSource {
|
source: cstore::CrateSource {
|
||||||
dylib: dylib,
|
dylib: dylib,
|
||||||
|
|
|
@ -72,6 +72,7 @@ pub struct CrateMetadata {
|
||||||
pub cnum_map: RefCell<CrateNumMap>,
|
pub cnum_map: RefCell<CrateNumMap>,
|
||||||
pub cnum: CrateNum,
|
pub cnum: CrateNum,
|
||||||
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
|
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
|
||||||
|
pub attribute_cache: RefCell<[Vec<Option<Rc<[ast::Attribute]>>>; 2]>,
|
||||||
|
|
||||||
pub root: schema::CrateRoot,
|
pub root: schema::CrateRoot,
|
||||||
|
|
||||||
|
@ -269,7 +270,7 @@ impl CrateMetadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_staged_api(&self) -> bool {
|
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" {
|
if attr.path == "stable" || attr.path == "unstable" {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ impl CrateStore for cstore::CStore {
|
||||||
self.get_crate_data(def.krate).get_generics(def.index)
|
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.dep_graph.read(DepNode::MetaData(def_id));
|
||||||
self.get_crate_data(def_id.krate).get_item_attrs(def_id.index)
|
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
|
// Mark the attrs as used
|
||||||
let attrs = data.get_item_attrs(id.index);
|
let attrs = data.get_item_attrs(id.index);
|
||||||
for attr in &attrs {
|
for attr in attrs.iter() {
|
||||||
attr::mark_used(attr);
|
attr::mark_used(attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ impl CrateStore for cstore::CStore {
|
||||||
ident: ast::Ident::with_empty_ctxt(name),
|
ident: ast::Ident::with_empty_ctxt(name),
|
||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
span: local_span,
|
span: local_span,
|
||||||
attrs: attrs,
|
attrs: attrs.iter().cloned().collect(),
|
||||||
node: ast::ItemKind::MacroDef(body.into()),
|
node: ast::ItemKind::MacroDef(body.into()),
|
||||||
vis: ast::Visibility::Inherited,
|
vis: ast::Visibility::Inherited,
|
||||||
})
|
})
|
||||||
|
|
|
@ -31,6 +31,7 @@ use std::cell::Ref;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::u32;
|
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) {
|
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;
|
// 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
|
// we assume that someone passing in a tuple struct ctor is actually wanting to
|
||||||
// look at the definition
|
// look at the definition
|
||||||
|
@ -871,7 +880,13 @@ impl<'a, 'tcx> CrateMetadata {
|
||||||
if def_key.disambiguated_data.data == DefPathData::StructCtor {
|
if def_key.disambiguated_data.data == DefPathData::StructCtor {
|
||||||
item = self.entry(def_key.parent.unwrap());
|
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> {
|
pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
|
||||||
|
|
Loading…
Reference in New Issue