Skip to content

rustc::metadata::decoder: cleanup and slightly speed up each_path #6946

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 70 additions & 82 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -476,103 +476,91 @@ pub fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) -> bool {
}

/// Iterates over all the paths in the given crate.
pub fn _each_path(intr: @ident_interner,
cdata: cmd,
get_crate_data: GetCrateDataCb,
f: &fn(&str, def_like, ast::visibility) -> bool)
-> bool {
pub fn each_path(intr: @ident_interner,
cdata: cmd,
get_crate_data: GetCrateDataCb,
f: &fn(&str, def_like, ast::visibility) -> bool)
-> bool {
// FIXME #4572: This function needs to be nuked, as it's impossible to make fast.
// It's the source of most of the performance problems when compiling small crates.

let root = reader::Doc(cdata.data);
let items = reader::get_doc(root, tag_items);
let items_data = reader::get_doc(items, tag_items_data);

let mut broken = false;

// First, go through all the explicit items.
for reader::tagged_docs(items_data, tag_items_data_item) |item_doc| {
if !broken {
let path = ast_map::path_to_str_with_sep(
item_path(item_doc), "::", intr);
let path_is_empty = path.is_empty();
if !path_is_empty {
// Extract the def ID.
let def_id = item_def_id(item_doc, cdata);

// Construct the def for this item.
debug!("(each_path) yielding explicit item: %s", path);
let def_like = item_to_def_like(item_doc, def_id, cdata.cnum);

let vis = item_visibility(item_doc);

// Hand the information off to the iteratee.
if !f(path, def_like, vis) {
broken = true; // FIXME #4572: This is awful.
}
let path = ast_map::path_to_str(item_path(item_doc), intr);
let path_is_empty = path.is_empty();
if !path_is_empty {
// Extract the def ID.
let def_id = item_def_id(item_doc, cdata);

// Construct the def for this item.
debug!("(each_path) yielding explicit item: %s", path);
let def_like = item_to_def_like(item_doc, def_id, cdata.cnum);

let vis = item_visibility(item_doc);

// Hand the information off to the iteratee.
if !f(path, def_like, vis) {
return false;
}
}

// If this is a module, find the reexports.
for each_reexport(item_doc) |reexport_doc| {
if !broken {
let def_id_doc =
reader::get_doc(reexport_doc,
tag_items_data_item_reexport_def_id);
let def_id =
reader::with_doc_data(def_id_doc,
|d| parse_def_id(d));
let def_id = translate_def_id(cdata, def_id);

let reexport_name_doc =
reader::get_doc(reexport_doc,
tag_items_data_item_reexport_name);
let reexport_name = reader::doc_as_str(reexport_name_doc);

let reexport_path;
if path_is_empty {
reexport_path = reexport_name;
} else {
reexport_path = path + "::" + reexport_name;
}
// If this is a module, find the reexports.
for each_reexport(item_doc) |reexport_doc| {
let def_id_doc =
reader::get_doc(reexport_doc,
tag_items_data_item_reexport_def_id);
let def_id =
reader::with_doc_data(def_id_doc,
|d| parse_def_id(d));
let def_id = translate_def_id(cdata, def_id);

let reexport_name_doc =
reader::get_doc(reexport_doc,
tag_items_data_item_reexport_name);
let reexport_name = reader::doc_as_str(reexport_name_doc);

let reexport_path;
if path_is_empty {
reexport_path = reexport_name;
} else {
reexport_path = path + "::" + reexport_name;
}

// This reexport may be in yet another crate
let other_crates_items = if def_id.crate == cdata.cnum {
items
} else {
let crate_data = get_crate_data(def_id.crate);
let root = reader::Doc(crate_data.data);
reader::get_doc(root, tag_items)
};

// Get the item.
match maybe_find_item(def_id.node, other_crates_items) {
None => {}
Some(item_doc) => {
// Construct the def for this item.
let def_like = item_to_def_like(item_doc,
def_id,
cdata.cnum);

// Hand the information off to the iteratee.
debug!("(each_path) yielding reexported \
item: %s", reexport_path);

if (!f(reexport_path, def_like, ast::public)) {
broken = true; // FIXME #4572: This is awful.
}
}
// This reexport may be in yet another crate
let other_crates_items = if def_id.crate == cdata.cnum {
items
} else {
let crate_data = get_crate_data(def_id.crate);
let root = reader::Doc(crate_data.data);
reader::get_doc(root, tag_items)
};

// Get the item.
match maybe_find_item(def_id.node, other_crates_items) {
None => {}
Some(item_doc) => {
// Construct the def for this item.
let def_like = item_to_def_like(item_doc,
def_id,
cdata.cnum);

// Hand the information off to the iteratee.
debug!("(each_path) yielding reexported \
item: %s", reexport_path);

if (!f(reexport_path, def_like, ast::public)) {
return false;
}
}
}
}
}

return broken;
}

pub fn each_path(intr: @ident_interner,
cdata: cmd,
get_crate_data: GetCrateDataCb,
f: &fn(&str, def_like, ast::visibility) -> bool)
-> bool {
_each_path(intr, cdata, get_crate_data, f)
return true;
}

pub fn get_item_path(cdata: cmd, id: ast::node_id)
Expand Down