Add caches for method and impl metadata

The lookups for these items in external crates currently cause repeated
decoding of the EBML metadata, which is pretty slow. Adding caches to
avoid the repeated decoding reduces the time required for the type
checking of librustc by about 25%.
This commit is contained in:
Björn Steinbrink 2013-06-15 04:28:19 +02:00
parent 7755018074
commit a710e61903
4 changed files with 53 additions and 43 deletions

View File

@ -3094,6 +3094,7 @@ pub fn trans_crate(sess: session::Session,
const_globals: @mut HashMap::new(),
const_values: @mut HashMap::new(),
extern_const_values: @mut HashMap::new(),
impl_method_cache: @mut HashMap::new(),
module_data: @mut HashMap::new(),
lltypes: @mut HashMap::new(),
llsizingtypes: @mut HashMap::new(),

View File

@ -205,6 +205,8 @@ pub struct CrateContext {
// Cache of external const values
extern_const_values: @mut HashMap<ast::def_id, ValueRef>,
impl_method_cache: @mut HashMap<(ast::def_id, ast::ident), ast::def_id>,
module_data: @mut HashMap<~str, ValueRef>,
lltypes: @mut HashMap<ty::t, TypeRef>,
llsizingtypes: @mut HashMap<ty::t, TypeRef>,

View File

@ -381,35 +381,37 @@ pub fn method_from_methods(ms: &[@ast::method], name: ast::ident)
pub fn method_with_name_or_default(ccx: @CrateContext,
impl_id: ast::def_id,
name: ast::ident) -> ast::def_id {
if impl_id.crate == ast::local_crate {
match ccx.tcx.items.get_copy(&impl_id.node) {
ast_map::node_item(@ast::item {
node: ast::item_impl(_, _, _, ref ms), _
}, _) => {
let did = method_from_methods(*ms, name);
if did.is_some() {
return did.get();
} else {
// Look for a default method
let pmm = ccx.tcx.provided_methods;
match pmm.find(&impl_id) {
Some(pmis) => {
for pmis.each |pmi| {
if pmi.method_info.ident == name {
debug!("pmi.method_info.did = %?", pmi.method_info.did);
return pmi.method_info.did;
}
}
fail!()
}
None => fail!()
}
}
}
_ => fail!("method_with_name")
*do ccx.impl_method_cache.find_or_insert_with((impl_id, name)) |_| {
if impl_id.crate == ast::local_crate {
match ccx.tcx.items.get_copy(&impl_id.node) {
ast_map::node_item(@ast::item {
node: ast::item_impl(_, _, _, ref ms), _
}, _) => {
let did = method_from_methods(*ms, name);
if did.is_some() {
did.get()
} else {
// Look for a default method
let pmm = ccx.tcx.provided_methods;
match pmm.find(&impl_id) {
Some(pmis) => {
for pmis.each |pmi| {
if pmi.method_info.ident == name {
debug!("pmi.method_info.did = %?", pmi.method_info.did);
return pmi.method_info.did;
}
}
fail!()
}
None => fail!()
}
}
}
_ => fail!("method_with_name")
}
} else {
csearch::get_impl_method(ccx.sess.cstore, impl_id, name)
}
} else {
csearch::get_impl_method(ccx.sess.cstore, impl_id, name)
}
}

View File

@ -271,6 +271,8 @@ struct ctxt_ {
// A cache for the trait_methods() routine
trait_methods_cache: @mut HashMap<def_id, @~[@Method]>,
impl_trait_cache: @mut HashMap<ast::def_id, Option<@ty::TraitRef>>,
trait_refs: @mut HashMap<node_id, @TraitRef>,
trait_defs: @mut HashMap<def_id, @TraitDef>,
@ -967,6 +969,7 @@ pub fn mk_ctxt(s: session::Session,
methods: @mut HashMap::new(),
trait_method_def_ids: @mut HashMap::new(),
trait_methods_cache: @mut HashMap::new(),
impl_trait_cache: @mut HashMap::new(),
ty_param_defs: @mut HashMap::new(),
adjustments: @mut HashMap::new(),
normalized_cache: new_ty_hash(),
@ -3749,22 +3752,24 @@ pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
}
pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> {
if id.crate == ast::local_crate {
debug!("(impl_trait_ref) searching for trait impl %?", id);
match cx.items.find(&id.node) {
Some(&ast_map::node_item(@ast::item {
node: ast::item_impl(_, opt_trait, _, _),
_},
_)) => {
match opt_trait {
Some(t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
None => None
}
}
_ => None
*do cx.impl_trait_cache.find_or_insert_with(id) |_| {
if id.crate == ast::local_crate {
debug!("(impl_trait_ref) searching for trait impl %?", id);
match cx.items.find(&id.node) {
Some(&ast_map::node_item(@ast::item {
node: ast::item_impl(_, opt_trait, _, _),
_},
_)) => {
match opt_trait {
Some(t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
None => None
}
}
_ => None
}
} else {
csearch::get_impl_trait(cx, id)
}
} else {
csearch::get_impl_trait(cx, id)
}
}