Skip to content

Commit ece6c84

Browse files
Ariel Ben-Yehudaarielb1
Ariel Ben-Yehuda
authored andcommitted
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 acd0e40 commit ece6c84

File tree

11 files changed

+85
-23
lines changed

11 files changed

+85
-23
lines changed

src/liballoc/heap.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
issue = "27700")]
1717

1818
use core::{isize, usize};
19-
#[cfg(not(test))]
2019
use core::intrinsics::{min_align_of_val, size_of_val};
2120

2221
#[allow(improper_ctypes)]
@@ -158,10 +157,9 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
158157
}
159158
}
160159

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

src/liballoc/lib.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 33 additions & 2 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 1 addition & 4 deletions
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

Lines changed: 20 additions & 4 deletions
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::cmp;
@@ -2036,6 +2035,23 @@ impl BorrowKind {
20362035
}
20372036
}
20382037

2038+
#[derive(Debug, Clone)]
2039+
pub enum Attributes<'gcx> {
2040+
Owned(Rc<[ast::Attribute]>),
2041+
Borrowed(&'gcx [ast::Attribute])
2042+
}
2043+
2044+
impl<'gcx> ::std::ops::Deref for Attributes<'gcx> {
2045+
type Target = [ast::Attribute];
2046+
2047+
fn deref(&self) -> &[ast::Attribute] {
2048+
match self {
2049+
&Attributes::Owned(ref data) => &data,
2050+
&Attributes::Borrowed(data) => data
2051+
}
2052+
}
2053+
}
2054+
20392055
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
20402056
pub fn body_tables(self, body: hir::BodyId) -> &'gcx TypeckTables<'gcx> {
20412057
self.item_tables(self.hir.body_owner_def_id(body))
@@ -2389,11 +2405,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
23892405
}
23902406

23912407
/// Get the attributes of a definition.
2392-
pub fn get_attrs(self, did: DefId) -> Cow<'gcx, [ast::Attribute]> {
2408+
pub fn get_attrs(self, did: DefId) -> Attributes<'gcx> {
23932409
if let Some(id) = self.hir.as_local_node_id(did) {
2394-
Cow::Borrowed(self.hir.attrs(id))
2410+
Attributes::Borrowed(self.hir.attrs(id))
23952411
} else {
2396-
Cow::Owned(self.sess.cstore.item_attrs(did))
2412+
Attributes::Owned(self.sess.cstore.item_attrs(did))
23972413
}
23982414
}
23992415

src/librustc_driver/driver.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ pub fn compile_input(sess: &Session,
225225
sess.code_stats.borrow().print_type_sizes();
226226
}
227227

228+
if ::std::env::var("SKIP_LLVM").is_ok() { ::std::process::exit(0); }
229+
228230
let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs);
229231

230232
controller_entry_point!(after_llvm,

src/librustc_metadata/creader.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 2 additions & 1 deletion
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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ impl CrateStore for cstore::CStore {
149149
self.get_crate_data(def.krate).get_generics(def.index)
150150
}
151151

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

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

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

src/librustc_metadata/decoder.rs

Lines changed: 18 additions & 3 deletions
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)