rustc: Never register syntax crates in CStore
When linking, all crates in the local CStore are used to link the final product. With #[phase(syntax)], crates want to be omitted from this linkage phase, and this was achieved by dumping the entire CStore after loading crates. This causes crates like the standard library to get loaded twice. This loading process is a fairly expensive operation when dealing with decompressing metadata. This commit alters the loading process to never register syntax crates in CStore. Instead, only phase(link) crates ever make their way into the map of crates. The CrateLoader trait was altered to return everything in one method instead of having separate methods for finding information.
This commit is contained in:
@@ -241,8 +241,6 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
|||||||
cfg,
|
cfg,
|
||||||
krate)
|
krate)
|
||||||
});
|
});
|
||||||
// dump the syntax-time crates
|
|
||||||
sess.cstore.reset();
|
|
||||||
|
|
||||||
// strip again, in case expansion added anything with a #[cfg].
|
// strip again, in case expansion added anything with a #[cfg].
|
||||||
krate = time(time_passes, "configuration 2", krate, |krate|
|
krate = time(time_passes, "configuration 2", krate, |krate|
|
||||||
|
|||||||
@@ -114,21 +114,24 @@ fn visit_crate(e: &Env, c: &ast::Crate) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
|
fn should_link(i: &ast::ViewItem) -> bool {
|
||||||
let should_load = i.attrs.iter().all(|attr| {
|
i.attrs.iter().all(|attr| {
|
||||||
attr.name().get() != "phase" ||
|
attr.name().get() != "phase" ||
|
||||||
attr.meta_item_list().map_or(false, |phases| {
|
attr.meta_item_list().map_or(false, |phases| {
|
||||||
attr::contains_name(phases.as_slice(), "link")
|
attr::contains_name(phases.as_slice(), "link")
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if !should_load {
|
fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
|
||||||
|
if !should_link(i) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match extract_crate_info(e, i) {
|
match extract_crate_info(e, i) {
|
||||||
Some(info) => {
|
Some(info) => {
|
||||||
let cnum = resolve_crate(e, &None, info.ident, &info.crate_id, None,
|
let (cnum, _, _) = resolve_crate(e, &None, info.ident,
|
||||||
|
&info.crate_id, None, true,
|
||||||
i.span);
|
i.span);
|
||||||
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
|
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
|
||||||
}
|
}
|
||||||
@@ -140,6 +143,7 @@ struct CrateInfo {
|
|||||||
ident: ~str,
|
ident: ~str,
|
||||||
crate_id: CrateId,
|
crate_id: CrateId,
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
|
should_link: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option<CrateInfo> {
|
fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option<CrateInfo> {
|
||||||
@@ -165,6 +169,7 @@ fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option<CrateInfo> {
|
|||||||
ident: ident.get().to_str(),
|
ident: ident.get().to_str(),
|
||||||
crate_id: crate_id,
|
crate_id: crate_id,
|
||||||
id: id,
|
id: id,
|
||||||
|
should_link: should_link(i),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => None
|
_ => None
|
||||||
@@ -274,8 +279,10 @@ fn resolve_crate<'a>(e: &mut Env,
|
|||||||
ident: &str,
|
ident: &str,
|
||||||
crate_id: &CrateId,
|
crate_id: &CrateId,
|
||||||
hash: Option<&Svh>,
|
hash: Option<&Svh>,
|
||||||
|
should_link: bool,
|
||||||
span: Span)
|
span: Span)
|
||||||
-> ast::CrateNum {
|
-> (ast::CrateNum, @cstore::crate_metadata,
|
||||||
|
cstore::CrateSource) {
|
||||||
match existing_match(e, crate_id, hash) {
|
match existing_match(e, crate_id, hash) {
|
||||||
None => {
|
None => {
|
||||||
let id_hash = link::crate_id_hash(crate_id);
|
let id_hash = link::crate_id_hash(crate_id);
|
||||||
@@ -312,8 +319,11 @@ fn resolve_crate<'a>(e: &mut Env,
|
|||||||
let root = if root.is_some() { root } else { &crate_paths };
|
let root = if root.is_some() { root } else { &crate_paths };
|
||||||
|
|
||||||
// Now resolve the crates referenced by this crate
|
// Now resolve the crates referenced by this crate
|
||||||
let cnum_map = resolve_crate_deps(e, root, metadata.as_slice(),
|
let cnum_map = if should_link {
|
||||||
span);
|
resolve_crate_deps(e, root, metadata.as_slice(), span)
|
||||||
|
} else {
|
||||||
|
@RefCell::new(HashMap::new())
|
||||||
|
};
|
||||||
|
|
||||||
let cmeta = @cstore::crate_metadata {
|
let cmeta = @cstore::crate_metadata {
|
||||||
name: load_ctxt.crate_id.name.to_owned(),
|
name: load_ctxt.crate_id.name.to_owned(),
|
||||||
@@ -323,15 +333,21 @@ fn resolve_crate<'a>(e: &mut Env,
|
|||||||
span: span,
|
span: span,
|
||||||
};
|
};
|
||||||
|
|
||||||
e.sess.cstore.set_crate_data(cnum, cmeta);
|
let source = cstore::CrateSource {
|
||||||
e.sess.cstore.add_used_crate_source(cstore::CrateSource {
|
|
||||||
dylib: dylib,
|
dylib: dylib,
|
||||||
rlib: rlib,
|
rlib: rlib,
|
||||||
cnum: cnum,
|
cnum: cnum,
|
||||||
});
|
};
|
||||||
cnum
|
|
||||||
|
if should_link {
|
||||||
|
e.sess.cstore.set_crate_data(cnum, cmeta);
|
||||||
|
e.sess.cstore.add_used_crate_source(source.clone());
|
||||||
}
|
}
|
||||||
Some(cnum) => cnum
|
(cnum, cmeta, source)
|
||||||
|
}
|
||||||
|
Some(cnum) => (cnum,
|
||||||
|
e.sess.cstore.get_crate_data(cnum),
|
||||||
|
e.sess.cstore.get_used_crate_source(cnum).unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,10 +364,11 @@ fn resolve_crate_deps(e: &mut Env,
|
|||||||
for dep in r.iter() {
|
for dep in r.iter() {
|
||||||
let extrn_cnum = dep.cnum;
|
let extrn_cnum = dep.cnum;
|
||||||
debug!("resolving dep crate {} hash: `{}`", dep.crate_id, dep.hash);
|
debug!("resolving dep crate {} hash: `{}`", dep.crate_id, dep.hash);
|
||||||
let local_cnum = resolve_crate(e, root,
|
let (local_cnum, _, _) = resolve_crate(e, root,
|
||||||
dep.crate_id.name.as_slice(),
|
dep.crate_id.name.as_slice(),
|
||||||
&dep.crate_id,
|
&dep.crate_id,
|
||||||
Some(&dep.hash),
|
Some(&dep.hash),
|
||||||
|
true,
|
||||||
span);
|
span);
|
||||||
cnum_map.insert(extrn_cnum, local_cnum);
|
cnum_map.insert(extrn_cnum, local_cnum);
|
||||||
}
|
}
|
||||||
@@ -380,23 +397,17 @@ impl<'a> Loader<'a> {
|
|||||||
impl<'a> CrateLoader for Loader<'a> {
|
impl<'a> CrateLoader for Loader<'a> {
|
||||||
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
|
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
|
||||||
let info = extract_crate_info(&self.env, krate).unwrap();
|
let info = extract_crate_info(&self.env, krate).unwrap();
|
||||||
let cnum = resolve_crate(&mut self.env, &None, info.ident,
|
let (cnum, data, library) = resolve_crate(&mut self.env, &None,
|
||||||
&info.crate_id, None, krate.span);
|
info.ident, &info.crate_id,
|
||||||
let library = self.env.sess.cstore.get_used_crate_source(cnum).unwrap();
|
None, true, krate.span);
|
||||||
|
let macros = decoder::get_exported_macros(data);
|
||||||
|
let cstore = &self.env.sess.cstore;
|
||||||
|
let registrar = csearch::get_macro_registrar_fn(cstore, cnum)
|
||||||
|
.map(|did| csearch::get_symbol(cstore, did));
|
||||||
MacroCrate {
|
MacroCrate {
|
||||||
lib: library.dylib,
|
lib: library.dylib,
|
||||||
cnum: cnum,
|
macros: macros.move_iter().collect(),
|
||||||
|
registrar_symbol: registrar,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_exported_macros(&mut self, cnum: ast::CrateNum) -> Vec<~str> {
|
|
||||||
csearch::get_exported_macros(&self.env.sess.cstore, cnum).move_iter()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_registrar_symbol(&mut self, cnum: ast::CrateNum) -> Option<~str> {
|
|
||||||
let cstore = &self.env.sess.cstore;
|
|
||||||
csearch::get_macro_registrar_fn(cstore, cnum)
|
|
||||||
.map(|did| csearch::get_symbol(cstore, did))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -293,13 +293,12 @@ pub fn syntax_expander_table() -> SyntaxEnv {
|
|||||||
|
|
||||||
pub struct MacroCrate {
|
pub struct MacroCrate {
|
||||||
pub lib: Option<Path>,
|
pub lib: Option<Path>,
|
||||||
pub cnum: ast::CrateNum,
|
pub macros: Vec<~str>,
|
||||||
|
pub registrar_symbol: Option<~str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CrateLoader {
|
pub trait CrateLoader {
|
||||||
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate;
|
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate;
|
||||||
fn get_exported_macros(&mut self, crate_num: ast::CrateNum) -> Vec<~str> ;
|
|
||||||
fn get_registrar_symbol(&mut self, crate_num: ast::CrateNum) -> Option<~str>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// One of these is made during expansion and incrementally updated as we go;
|
// One of these is made during expansion and incrementally updated as we go;
|
||||||
|
|||||||
@@ -487,7 +487,8 @@ pub fn expand_view_item(vi: &ast::ViewItem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
|
fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
|
||||||
let MacroCrate { lib, cnum } = fld.cx.ecfg.loader.load_crate(krate);
|
let MacroCrate { lib, macros, registrar_symbol } =
|
||||||
|
fld.cx.ecfg.loader.load_crate(krate);
|
||||||
|
|
||||||
let crate_name = match krate.node {
|
let crate_name = match krate.node {
|
||||||
ast::ViewItemExternCrate(name, _, _) => name,
|
ast::ViewItemExternCrate(name, _, _) => name,
|
||||||
@@ -495,8 +496,7 @@ fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
|
|||||||
};
|
};
|
||||||
let name = format!("<{} macros>", token::get_ident(crate_name));
|
let name = format!("<{} macros>", token::get_ident(crate_name));
|
||||||
|
|
||||||
let exported_macros = fld.cx.ecfg.loader.get_exported_macros(cnum);
|
for source in macros.iter() {
|
||||||
for source in exported_macros.iter() {
|
|
||||||
let item = parse::parse_item_from_source_str(name.clone(),
|
let item = parse::parse_item_from_source_str(name.clone(),
|
||||||
(*source).clone(),
|
(*source).clone(),
|
||||||
fld.cx.cfg(),
|
fld.cx.cfg(),
|
||||||
@@ -512,7 +512,7 @@ fn load_extern_macros(krate: &ast::ViewItem, fld: &mut MacroExpander) {
|
|||||||
// Make sure the path contains a / or the linker will search for it.
|
// Make sure the path contains a / or the linker will search for it.
|
||||||
let path = os::make_absolute(&path);
|
let path = os::make_absolute(&path);
|
||||||
|
|
||||||
let registrar = match fld.cx.ecfg.loader.get_registrar_symbol(cnum) {
|
let registrar = match registrar_symbol {
|
||||||
Some(registrar) => registrar,
|
Some(registrar) => registrar,
|
||||||
None => return
|
None => return
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user