]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Use CStore, not a separate crate cache
authorAlex Crichton <alex@alexcrichton.com>
Mon, 7 Apr 2014 19:14:33 +0000 (12:14 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 8 Apr 2014 07:03:11 +0000 (00:03 -0700)
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.

src/librustc/metadata/creader.rs
src/librustc/metadata/cstore.rs

index 8ce4a2f8eed860b87535e4b9c5eafb39f33d6e77..9c0c73288eb0d007059d1ceaf6d4e69c9922cb33 100644 (file)
@@ -18,6 +18,7 @@
 use driver::session::Session;
 use metadata::csearch;
 use metadata::cstore;
+use metadata::cstore::CStore;
 use metadata::decoder;
 use metadata::loader;
 use metadata::loader::Os;
 use syntax::crateid::CrateId;
 use syntax::visit;
 
+struct Env<'a> {
+    sess: &'a Session,
+    os: loader::Os,
+    next_crate_num: ast::CrateNum,
+    intr: Rc<IdentInterner>
+}
+
 // Traverses an AST, reading all the information about use'd crates and extern
 // libraries necessary for later resolving, typechecking, linking, etc.
 pub fn read_crates(sess: &Session,
@@ -47,16 +55,13 @@ pub fn read_crates(sess: &Session,
     let mut e = Env {
         sess: sess,
         os: os,
-        crate_cache: @RefCell::new(Vec::new()),
-        next_crate_num: 1,
+        next_crate_num: sess.cstore.next_crate_num(),
         intr: intr
     };
     visit_crate(&e, krate);
     visit::walk_crate(&mut e, krate, ());
-    dump_crates(e.crate_cache.borrow().as_slice());
-    warn_if_multiple_versions(&mut e,
-                              sess.diagnostic(),
-                              e.crate_cache.borrow().as_slice());
+    dump_crates(&sess.cstore);
+    warn_if_multiple_versions(sess.diagnostic(), &sess.cstore)
 }
 
 impl<'a> visit::Visitor<()> for Env<'a> {
@@ -70,55 +75,36 @@ fn visit_item(&mut self, a: &ast::Item, _: ()) {
     }
 }
 
-#[deriving(Clone)]
-struct cache_entry {
-    cnum: ast::CrateNum,
-    span: Span,
-    hash: Svh,
-    crate_id: CrateId,
-}
-
-fn dump_crates(crate_cache: &[cache_entry]) {
+fn dump_crates(cstore: &CStore) {
     debug!("resolved crates:");
-    for entry in crate_cache.iter() {
-        debug!("cnum: {:?}", entry.cnum);
-        debug!("span: {:?}", entry.span);
-        debug!("hash: {:?}", entry.hash);
-    }
+    cstore.iter_crate_data(|_, data| {
+        debug!("crate_id: {}", data.crate_id());
+        debug!("  cnum: {}", data.cnum);
+        debug!("  hash: {}", data.hash());
+    })
 }
 
-fn warn_if_multiple_versions(e: &mut Env,
-                             diag: &SpanHandler,
-                             crate_cache: &[cache_entry]) {
-    if crate_cache.len() != 0u {
-        let name = crate_cache[crate_cache.len() - 1].crate_id.name.clone();
-
-        let (matches, non_matches) = crate_cache.partitioned(|entry|
-            name == entry.crate_id.name);
+fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
+    let mut map = HashMap::new();
 
-        assert!(!matches.is_empty());
+    cstore.iter_crate_data(|cnum, data| {
+        let crateid = data.crate_id();
+        let key = (crateid.name.clone(), crateid.path.clone());
+        map.find_or_insert_with(key, |_| Vec::new()).push(cnum);
+    });
 
-        if matches.len() != 1u {
-            diag.handler().warn(
-                format!("using multiple versions of crate `{}`", name));
-            for match_ in matches.iter() {
-                diag.span_note(match_.span, "used here");
-                loader::note_crateid_attr(diag, &match_.crate_id);
-            }
+    for ((name, _), dupes) in map.move_iter() {
+        if dupes.len() == 1 { continue }
+        diag.handler().warn(
+            format!("using multiple versions of crate `{}`", name));
+        for dupe in dupes.move_iter() {
+            let data = cstore.get_crate_data(dupe);
+            diag.span_note(data.span, "used here");
+            loader::note_crateid_attr(diag, &data.crate_id());
         }
-
-        warn_if_multiple_versions(e, diag, non_matches);
     }
 }
 
-struct Env<'a> {
-    sess: &'a Session,
-    os: loader::Os,
-    crate_cache: @RefCell<Vec<cache_entry>>,
-    next_crate_num: ast::CrateNum,
-    intr: Rc<IdentInterner>
-}
-
 fn visit_crate(e: &Env, c: &ast::Crate) {
     for a in c.attrs.iter().filter(|m| m.name().equiv(&("link_args"))) {
         match a.value_str() {
@@ -269,14 +255,18 @@ fn visit_item(e: &Env, i: &ast::Item) {
 
 fn existing_match(e: &Env, crate_id: &CrateId,
                   hash: Option<&Svh>) -> Option<ast::CrateNum> {
-    for c in e.crate_cache.borrow().iter() {
-        if !crate_id.matches(&c.crate_id) { continue }
-        match hash {
-            Some(hash) if *hash != c.hash => {}
-            Some(..) | None => return Some(c.cnum)
+    let mut ret = None;
+    e.sess.cstore.iter_crate_data(|cnum, data| {
+        let other_id = data.crate_id();
+        if crate_id.matches(&other_id) {
+            let other_hash = data.hash();
+            match hash {
+                Some(hash) if *hash != other_hash => {}
+                Some(..) | None => { ret = Some(cnum); }
+            }
         }
-    }
-    None
+    });
+    return ret;
 }
 
 fn resolve_crate<'a>(e: &mut Env,
@@ -304,17 +294,8 @@ fn resolve_crate<'a>(e: &mut Env,
                 dylib, rlib, metadata
             } = load_ctxt.load_library_crate(root);
 
-            let crate_id = decoder::get_crate_id(metadata.as_slice());
-            let hash = decoder::get_crate_hash(metadata.as_slice());
-
             // Claim this crate number and cache it
             let cnum = e.next_crate_num;
-            e.crate_cache.borrow_mut().push(cache_entry {
-                cnum: cnum,
-                span: span,
-                hash: hash,
-                crate_id: crate_id,
-            });
             e.next_crate_num += 1;
 
             // Stash paths for top-most crate locally if necessary.
@@ -331,16 +312,15 @@ fn resolve_crate<'a>(e: &mut Env,
             let root = if root.is_some() { root } else { &crate_paths };
 
             // Now resolve the crates referenced by this crate
-            let cnum_map = resolve_crate_deps(e,
-            root,
-            metadata.as_slice(),
-            span);
+            let cnum_map = resolve_crate_deps(e, root, metadata.as_slice(),
+                                              span);
 
             let cmeta = @cstore::crate_metadata {
                 name: load_ctxt.crate_id.name.to_owned(),
                 data: metadata,
                 cnum_map: cnum_map,
-                cnum: cnum
+                cnum: cnum,
+                span: span,
             };
 
             e.sess.cstore.set_crate_data(cnum, cmeta);
@@ -390,8 +370,7 @@ pub fn new(sess: &'a Session) -> Loader<'a> {
             env: Env {
                 sess: sess,
                 os: os,
-                crate_cache: @RefCell::new(Vec::new()),
-                next_crate_num: 1,
+                next_crate_num: sess.cstore.next_crate_num(),
                 intr: token::get_ident_interner(),
             }
         }
@@ -406,7 +385,7 @@ fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
         let library = self.env.sess.cstore.get_used_crate_source(cnum).unwrap();
         MacroCrate {
             lib: library.dylib,
-            cnum: cnum
+            cnum: cnum,
         }
     }
 
index e3a3239bdb5b852d11accd3aa22dd4c9db4610fa..2d46f92e88fa47939859c746c4aba9214effef25 100644 (file)
@@ -22,6 +22,8 @@
 use std::rc::Rc;
 use collections::HashMap;
 use syntax::ast;
+use syntax::crateid::CrateId;
+use syntax::codemap::Span;
 use syntax::parse::token::IdentInterner;
 
 // A map from external crate numbers (as decoded from some crate file) to
@@ -40,6 +42,7 @@ pub struct crate_metadata {
     pub data: MetadataBlob,
     pub cnum_map: cnum_map,
     pub cnum: ast::CrateNum,
+    pub span: Span,
 }
 
 #[deriving(Eq)]
@@ -88,6 +91,10 @@ pub fn new(intr: Rc<IdentInterner>) -> CStore {
         }
     }
 
+    pub fn next_crate_num(&self) -> ast::CrateNum {
+        self.metas.borrow().len() as ast::CrateNum + 1
+    }
+
     pub fn get_crate_data(&self, cnum: ast::CrateNum) -> @crate_metadata {
         *self.metas.borrow().get(&cnum)
     }
@@ -121,6 +128,9 @@ pub fn get_used_crate_source(&self, cnum: ast::CrateNum)
             .map(|source| source.clone())
     }
 
+    pub fn dump_phase_syntax_crates(&self) {
+    }
+
     pub fn reset(&self) {
         self.metas.borrow_mut().clear();
         self.extern_mod_crate_map.borrow_mut().clear();
@@ -202,6 +212,8 @@ pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
 
 impl crate_metadata {
     pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
+    pub fn crate_id(&self) -> CrateId { decoder::get_crate_id(self.data()) }
+    pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
 }
 
 impl MetadataBlob {