Skip to content

Commit 31755e2

Browse files
committed
rustc: Use CStore, not a separate crate cache
This separate crate cache is one factor which is causing libstd to be loaded twice during normal compilation. The crates loaded for syntax extensions have a separate cache than the crates loaded for linking, so all crates are loaded once per #[phase] they're tagged with. This removes the cache and instead uses the CStore structure itself as the cache for loaded crates. This should allow crates loaded during the syntax phase to be shared with the crates loaded during the link phase.
1 parent ef37cfd commit 31755e2

File tree

2 files changed

+61
-70
lines changed

2 files changed

+61
-70
lines changed

src/librustc/metadata/creader.rs

Lines changed: 49 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use driver::{driver, session};
1818
use driver::session::Session;
1919
use metadata::csearch;
2020
use metadata::cstore;
21+
use metadata::cstore::CStore;
2122
use metadata::decoder;
2223
use metadata::loader;
2324
use metadata::loader::Os;
@@ -38,6 +39,13 @@ use syntax::parse::token;
3839
use syntax::crateid::CrateId;
3940
use syntax::visit;
4041

42+
struct Env<'a> {
43+
sess: &'a Session,
44+
os: loader::Os,
45+
next_crate_num: ast::CrateNum,
46+
intr: Rc<IdentInterner>
47+
}
48+
4149
// Traverses an AST, reading all the information about use'd crates and extern
4250
// libraries necessary for later resolving, typechecking, linking, etc.
4351
pub fn read_crates(sess: &Session,
@@ -47,16 +55,13 @@ pub fn read_crates(sess: &Session,
4755
let mut e = Env {
4856
sess: sess,
4957
os: os,
50-
crate_cache: @RefCell::new(Vec::new()),
51-
next_crate_num: 1,
58+
next_crate_num: sess.cstore.next_crate_num(),
5259
intr: intr
5360
};
5461
visit_crate(&e, krate);
5562
visit::walk_crate(&mut e, krate, ());
56-
dump_crates(e.crate_cache.borrow().as_slice());
57-
warn_if_multiple_versions(&mut e,
58-
sess.diagnostic(),
59-
e.crate_cache.borrow().as_slice());
63+
dump_crates(&sess.cstore);
64+
warn_if_multiple_versions(sess.diagnostic(), &sess.cstore)
6065
}
6166

6267
impl<'a> visit::Visitor<()> for Env<'a> {
@@ -70,55 +75,36 @@ impl<'a> visit::Visitor<()> for Env<'a> {
7075
}
7176
}
7277

73-
#[deriving(Clone)]
74-
struct cache_entry {
75-
cnum: ast::CrateNum,
76-
span: Span,
77-
hash: Svh,
78-
crate_id: CrateId,
79-
}
80-
81-
fn dump_crates(crate_cache: &[cache_entry]) {
78+
fn dump_crates(cstore: &CStore) {
8279
debug!("resolved crates:");
83-
for entry in crate_cache.iter() {
84-
debug!("cnum: {:?}", entry.cnum);
85-
debug!("span: {:?}", entry.span);
86-
debug!("hash: {:?}", entry.hash);
87-
}
80+
cstore.iter_crate_data(|_, data| {
81+
debug!("crate_id: {}", data.crate_id());
82+
debug!(" cnum: {}", data.cnum);
83+
debug!(" hash: {}", data.hash());
84+
})
8885
}
8986

90-
fn warn_if_multiple_versions(e: &mut Env,
91-
diag: &SpanHandler,
92-
crate_cache: &[cache_entry]) {
93-
if crate_cache.len() != 0u {
94-
let name = crate_cache[crate_cache.len() - 1].crate_id.name.clone();
95-
96-
let (matches, non_matches) = crate_cache.partitioned(|entry|
97-
name == entry.crate_id.name);
87+
fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
88+
let mut map = HashMap::new();
9889

99-
assert!(!matches.is_empty());
90+
cstore.iter_crate_data(|cnum, data| {
91+
let crateid = data.crate_id();
92+
let key = (crateid.name.clone(), crateid.path.clone());
93+
map.find_or_insert_with(key, |_| Vec::new()).push(cnum);
94+
});
10095

101-
if matches.len() != 1u {
102-
diag.handler().warn(
103-
format!("using multiple versions of crate `{}`", name));
104-
for match_ in matches.iter() {
105-
diag.span_note(match_.span, "used here");
106-
loader::note_crateid_attr(diag, &match_.crate_id);
107-
}
96+
for ((name, _), dupes) in map.move_iter() {
97+
if dupes.len() == 1 { continue }
98+
diag.handler().warn(
99+
format!("using multiple versions of crate `{}`", name));
100+
for dupe in dupes.move_iter() {
101+
let data = cstore.get_crate_data(dupe);
102+
diag.span_note(data.span, "used here");
103+
loader::note_crateid_attr(diag, &data.crate_id());
108104
}
109-
110-
warn_if_multiple_versions(e, diag, non_matches);
111105
}
112106
}
113107

114-
struct Env<'a> {
115-
sess: &'a Session,
116-
os: loader::Os,
117-
crate_cache: @RefCell<Vec<cache_entry>>,
118-
next_crate_num: ast::CrateNum,
119-
intr: Rc<IdentInterner>
120-
}
121-
122108
fn visit_crate(e: &Env, c: &ast::Crate) {
123109
for a in c.attrs.iter().filter(|m| m.name().equiv(&("link_args"))) {
124110
match a.value_str() {
@@ -269,14 +255,18 @@ fn visit_item(e: &Env, i: &ast::Item) {
269255

270256
fn existing_match(e: &Env, crate_id: &CrateId,
271257
hash: Option<&Svh>) -> Option<ast::CrateNum> {
272-
for c in e.crate_cache.borrow().iter() {
273-
if !crate_id.matches(&c.crate_id) { continue }
274-
match hash {
275-
Some(hash) if *hash != c.hash => {}
276-
Some(..) | None => return Some(c.cnum)
258+
let mut ret = None;
259+
e.sess.cstore.iter_crate_data(|cnum, data| {
260+
let other_id = data.crate_id();
261+
if crate_id.matches(&other_id) {
262+
let other_hash = data.hash();
263+
match hash {
264+
Some(hash) if *hash != other_hash => {}
265+
Some(..) | None => { ret = Some(cnum); }
266+
}
277267
}
278-
}
279-
None
268+
});
269+
return ret;
280270
}
281271

282272
fn resolve_crate<'a>(e: &mut Env,
@@ -304,17 +294,8 @@ fn resolve_crate<'a>(e: &mut Env,
304294
dylib, rlib, metadata
305295
} = load_ctxt.load_library_crate(root);
306296

307-
let crate_id = decoder::get_crate_id(metadata.as_slice());
308-
let hash = decoder::get_crate_hash(metadata.as_slice());
309-
310297
// Claim this crate number and cache it
311298
let cnum = e.next_crate_num;
312-
e.crate_cache.borrow_mut().push(cache_entry {
313-
cnum: cnum,
314-
span: span,
315-
hash: hash,
316-
crate_id: crate_id,
317-
});
318299
e.next_crate_num += 1;
319300

320301
// Stash paths for top-most crate locally if necessary.
@@ -331,16 +312,15 @@ fn resolve_crate<'a>(e: &mut Env,
331312
let root = if root.is_some() { root } else { &crate_paths };
332313

333314
// Now resolve the crates referenced by this crate
334-
let cnum_map = resolve_crate_deps(e,
335-
root,
336-
metadata.as_slice(),
337-
span);
315+
let cnum_map = resolve_crate_deps(e, root, metadata.as_slice(),
316+
span);
338317

339318
let cmeta = @cstore::crate_metadata {
340319
name: load_ctxt.crate_id.name.to_owned(),
341320
data: metadata,
342321
cnum_map: cnum_map,
343-
cnum: cnum
322+
cnum: cnum,
323+
span: span,
344324
};
345325

346326
e.sess.cstore.set_crate_data(cnum, cmeta);
@@ -390,8 +370,7 @@ impl<'a> Loader<'a> {
390370
env: Env {
391371
sess: sess,
392372
os: os,
393-
crate_cache: @RefCell::new(Vec::new()),
394-
next_crate_num: 1,
373+
next_crate_num: sess.cstore.next_crate_num(),
395374
intr: token::get_ident_interner(),
396375
}
397376
}
@@ -406,7 +385,7 @@ impl<'a> CrateLoader for Loader<'a> {
406385
let library = self.env.sess.cstore.get_used_crate_source(cnum).unwrap();
407386
MacroCrate {
408387
lib: library.dylib,
409-
cnum: cnum
388+
cnum: cnum,
410389
}
411390
}
412391

src/librustc/metadata/cstore.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ use std::c_vec::CVec;
2222
use std::rc::Rc;
2323
use collections::HashMap;
2424
use syntax::ast;
25+
use syntax::crateid::CrateId;
26+
use syntax::codemap::Span;
2527
use syntax::parse::token::IdentInterner;
2628

2729
// A map from external crate numbers (as decoded from some crate file) to
@@ -40,6 +42,7 @@ pub struct crate_metadata {
4042
pub data: MetadataBlob,
4143
pub cnum_map: cnum_map,
4244
pub cnum: ast::CrateNum,
45+
pub span: Span,
4346
}
4447

4548
#[deriving(Eq)]
@@ -88,6 +91,10 @@ impl CStore {
8891
}
8992
}
9093

94+
pub fn next_crate_num(&self) -> ast::CrateNum {
95+
self.metas.borrow().len() as ast::CrateNum + 1
96+
}
97+
9198
pub fn get_crate_data(&self, cnum: ast::CrateNum) -> @crate_metadata {
9299
*self.metas.borrow().get(&cnum)
93100
}
@@ -121,6 +128,9 @@ impl CStore {
121128
.map(|source| source.clone())
122129
}
123130

131+
pub fn dump_phase_syntax_crates(&self) {
132+
}
133+
124134
pub fn reset(&self) {
125135
self.metas.borrow_mut().clear();
126136
self.extern_mod_crate_map.borrow_mut().clear();
@@ -202,6 +212,8 @@ impl CStore {
202212

203213
impl crate_metadata {
204214
pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
215+
pub fn crate_id(&self) -> CrateId { decoder::get_crate_id(self.data()) }
216+
pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
205217
}
206218

207219
impl MetadataBlob {

0 commit comments

Comments
 (0)