Skip to content

Commit 74a819c

Browse files
author
Ariel Ben-Yehuda
committed
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.
1 parent f3682e5 commit 74a819c

File tree

10 files changed

+83
-22
lines changed

10 files changed

+83
-22
lines changed

src/liballoc/heap.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,9 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
158158
}
159159
}
160160

161-
#[cfg(not(test))]
162-
#[lang = "box_free"]
161+
#[cfg_attr(not(test), lang = "box_free")]
163162
#[inline]
164-
unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
163+
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
165164
let size = size_of_val(&*ptr);
166165
let align = min_align_of_val(&*ptr);
167166
// We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.

src/liballoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
#![feature(needs_allocator)]
8888
#![feature(optin_builtin_traits)]
8989
#![feature(placement_in_syntax)]
90+
#![cfg_attr(stage0, feature(pub_restricted))]
9091
#![feature(shared)]
9192
#![feature(staged_api)]
9293
#![feature(unboxed_closures)]

src/liballoc/rc.rs

+33-2
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ use core::ops::CoerceUnsized;
239239
use core::ptr::{self, Shared};
240240
use core::convert::From;
241241

242-
use heap::deallocate;
242+
use heap::{allocate, deallocate, box_free};
243243
use raw_vec::RawVec;
244244

245245
struct RcBox<T: ?Sized> {
@@ -248,7 +248,6 @@ struct RcBox<T: ?Sized> {
248248
value: T,
249249
}
250250

251-
252251
/// A single-threaded reference-counting pointer.
253252
///
254253
/// See the [module-level documentation](./index.html) for more details.
@@ -438,6 +437,38 @@ impl Rc<str> {
438437
}
439438
}
440439

440+
impl<T> Rc<[T]> {
441+
/// Constructs a new `Rc<[T]>` from a `Box<[T]>`.
442+
#[doc(hidden)]
443+
#[unstable(feature = "rustc_private",
444+
reason = "for internal use in rustc",
445+
issue = "0")]
446+
pub fn __from_array(value: Box<[T]>) -> Rc<[T]> {
447+
unsafe {
448+
let ptr: *mut RcBox<[T]> =
449+
mem::transmute([mem::align_of::<RcBox<[T; 1]>>(), value.len()]);
450+
// FIXME(custom-DST): creating this invalid &[T] is dubiously defined,
451+
// we should have a better way of getting the size/align
452+
// of a DST from its unsized part.
453+
let ptr = allocate(size_of_val(&*ptr), align_of_val(&*ptr));
454+
let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]);
455+
456+
// Initialize the new RcBox.
457+
ptr::write(&mut (*ptr).strong, Cell::new(1));
458+
ptr::write(&mut (*ptr).weak, Cell::new(1));
459+
ptr::copy_nonoverlapping(
460+
value.as_ptr(),
461+
&mut (*ptr).value as *mut [T] as *mut T,
462+
value.len());
463+
464+
// Free the original allocation without freeing its (moved) contents.
465+
box_free(Box::into_raw(value));
466+
467+
Rc { ptr: Shared::new(ptr as *const _) }
468+
}
469+
}
470+
}
471+
441472
impl<T: ?Sized> Rc<T> {
442473
/// Creates a new [`Weak`][weak] pointer to this value.
443474
///

src/librustc/middle/cstore.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ pub trait CrateStore {
188188
fn visibility(&self, def: DefId) -> ty::Visibility;
189189
fn visible_parent_map<'a>(&'a self) -> ::std::cell::Ref<'a, DefIdMap<DefId>>;
190190
fn item_generics_cloned(&self, def: DefId) -> ty::Generics;
191-
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
191+
fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]>;
192192
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name>;
193193

194194
// trait info
@@ -323,7 +323,7 @@ impl CrateStore for DummyCrateStore {
323323
}
324324
fn item_generics_cloned(&self, def: DefId) -> ty::Generics
325325
{ bug!("item_generics_cloned") }
326-
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
326+
fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]> { bug!("item_attrs") }
327327
fn fn_arg_names(&self, did: DefId) -> Vec<ast::Name> { bug!("fn_arg_names") }
328328

329329
// trait info

src/librustc/ty/instance.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ use hir::def_id::DefId;
1313
use ty::{self, Ty, TypeFoldable, Substs};
1414
use util::ppaux;
1515

16-
use std::borrow::Cow;
1716
use std::fmt;
18-
use syntax::ast;
19-
2017

2118
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
2219
pub struct Instance<'tcx> {
@@ -59,7 +56,7 @@ impl<'tcx> InstanceDef<'tcx> {
5956
}
6057

6158
#[inline]
62-
pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> Cow<'tcx, [ast::Attribute]> {
59+
pub fn attrs<'a>(&self, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> ty::Attributes<'tcx> {
6360
tcx.get_attrs(self.def_id())
6461
}
6562

src/librustc/ty/mod.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ use ty::walk::TypeWalker;
3434
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
3535

3636
use serialize::{self, Encodable, Encoder};
37-
use std::borrow::Cow;
3837
use std::cell::{Cell, RefCell, Ref};
3938
use std::collections::BTreeMap;
4039
use std::hash::{Hash, Hasher};
@@ -2023,6 +2022,23 @@ impl BorrowKind {
20232022
}
20242023
}
20252024

2025+
#[derive(Debug, Clone)]
2026+
pub enum Attributes<'gcx> {
2027+
Owned(Rc<[ast::Attribute]>),
2028+
Borrowed(&'gcx [ast::Attribute])
2029+
}
2030+
2031+
impl<'gcx> ::std::ops::Deref for Attributes<'gcx> {
2032+
type Target = [ast::Attribute];
2033+
2034+
fn deref(&self) -> &[ast::Attribute] {
2035+
match self {
2036+
&Attributes::Owned(ref data) => &data,
2037+
&Attributes::Borrowed(data) => data
2038+
}
2039+
}
2040+
}
2041+
20262042
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
20272043
pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
20282044
self.item_tables(self.hir.body_owner_def_id(body))
@@ -2410,11 +2426,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
24102426
}
24112427

24122428
/// Get the attributes of a definition.
2413-
pub fn get_attrs(self, did: DefId) -> Cow<'gcx, [ast::Attribute]> {
2429+
pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
24142430
if let Some(id) = self.hir.as_local_node_id(did) {
2415-
Cow::Borrowed(self.hir.attrs(id))
2431+
Attributes::Borrowed(self.hir.attrs(id))
24162432
} else {
2417-
Cow::Owned(self.sess.cstore.item_attrs(did))
2433+
Attributes::Owned(self.sess.cstore.item_attrs(did))
24182434
}
24192435
}
24202436

src/librustc_metadata/creader.rs

+1
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ impl<'a> CrateLoader<'a> {
326326
cnum_map: RefCell::new(cnum_map),
327327
cnum: cnum,
328328
codemap_import_info: RefCell::new(vec![]),
329+
attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
329330
dep_kind: Cell::new(dep_kind),
330331
source: cstore::CrateSource {
331332
dylib: dylib,

src/librustc_metadata/cstore.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub struct CrateMetadata {
7272
pub cnum_map: RefCell<CrateNumMap>,
7373
pub cnum: CrateNum,
7474
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
75+
pub attribute_cache: RefCell<[Vec<Option<Rc<[ast::Attribute]>>>; 2]>,
7576

7677
pub root: schema::CrateRoot,
7778

@@ -269,7 +270,7 @@ impl CrateMetadata {
269270
}
270271

271272
pub fn is_staged_api(&self) -> bool {
272-
for attr in self.get_item_attrs(CRATE_DEF_INDEX) {
273+
for attr in self.get_item_attrs(CRATE_DEF_INDEX).iter() {
273274
if attr.path == "stable" || attr.path == "unstable" {
274275
return true;
275276
}

src/librustc_metadata/cstore_impl.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ impl CrateStore for cstore::CStore {
148148
self.get_crate_data(def.krate).get_generics(def.index)
149149
}
150150

151-
fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>
151+
fn item_attrs(&self, def_id: DefId) -> Rc<[ast::Attribute]>
152152
{
153153
self.dep_graph.read(DepNode::MetaData(def_id));
154154
self.get_crate_data(def_id.krate).get_item_attrs(def_id.index)
@@ -405,7 +405,7 @@ impl CrateStore for cstore::CStore {
405405

406406
// Mark the attrs as used
407407
let attrs = data.get_item_attrs(id.index);
408-
for attr in &attrs {
408+
for attr in attrs.iter() {
409409
attr::mark_used(attr);
410410
}
411411

@@ -418,7 +418,7 @@ impl CrateStore for cstore::CStore {
418418
ident: ast::Ident::with_empty_ctxt(name),
419419
id: ast::DUMMY_NODE_ID,
420420
span: local_span,
421-
attrs: attrs,
421+
attrs: attrs.iter().cloned().collect(),
422422
node: ast::ItemKind::MacroDef(body.into()),
423423
vis: ast::Visibility::Inherited,
424424
})

src/librustc_metadata/decoder.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use std::cell::Ref;
3131
use std::collections::BTreeMap;
3232
use std::io;
3333
use std::mem;
34+
use std::rc::Rc;
3435
use std::str;
3536
use std::u32;
3637

@@ -859,10 +860,18 @@ impl<'a, 'tcx> CrateMetadata {
859860
}
860861
}
861862

862-
pub fn get_item_attrs(&self, node_id: DefIndex) -> Vec<ast::Attribute> {
863+
pub fn get_item_attrs(&self, node_id: DefIndex) -> Rc<[ast::Attribute]> {
864+
let (node_as, node_index) =
865+
(node_id.address_space().index(), node_id.as_array_index());
863866
if self.is_proc_macro(node_id) {
864-
return Vec::new();
867+
return Rc::new([]);
865868
}
869+
870+
if let Some(&Some(ref val)) =
871+
self.attribute_cache.borrow()[node_as].get(node_index) {
872+
return val.clone();
873+
}
874+
866875
// The attributes for a tuple struct are attached to the definition, not the ctor;
867876
// we assume that someone passing in a tuple struct ctor is actually wanting to
868877
// look at the definition
@@ -871,7 +880,13 @@ impl<'a, 'tcx> CrateMetadata {
871880
if def_key.disambiguated_data.data == DefPathData::StructCtor {
872881
item = self.entry(def_key.parent.unwrap());
873882
}
874-
self.get_attributes(&item)
883+
let result = Rc::__from_array(self.get_attributes(&item).into_boxed_slice());
884+
let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
885+
if vec_.len() < node_index + 1 {
886+
vec_.resize(node_index + 1, None);
887+
}
888+
vec_[node_index] = Some(result.clone());
889+
result
875890
}
876891

877892
pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {

0 commit comments

Comments
 (0)