Skip to content
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

Make CrateNum allocation more thread-safe. #50538

Merged
merged 3 commits into from
May 11, 2018
Merged
Show file tree
Hide file tree
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
5 changes: 1 addition & 4 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ pub struct Library {
pub struct CrateLoader<'a> {
pub sess: &'a Session,
cstore: &'a CStore,
next_crate_num: CrateNum,
local_crate_name: Symbol,
}

Expand Down Expand Up @@ -102,7 +101,6 @@ impl<'a> CrateLoader<'a> {
CrateLoader {
sess,
cstore,
next_crate_num: cstore.next_crate_num(),
local_crate_name: Symbol::intern(local_crate_name),
}
}
Expand Down Expand Up @@ -198,8 +196,7 @@ impl<'a> CrateLoader<'a> {
self.verify_no_symbol_conflicts(span, &crate_root);

// Claim this crate number and cache it
let cnum = self.next_crate_num;
self.next_crate_num = CrateNum::from_u32(cnum.as_u32() + 1);
let cnum = self.cstore.alloc_new_crate_num();

// Stash paths for top-most crate locally if necessary.
let crate_paths = if root.is_none() {
Expand Down
42 changes: 23 additions & 19 deletions src/librustc_metadata/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,32 +96,34 @@ pub struct CStore {
impl CStore {
pub fn new(metadata_loader: Box<MetadataLoader + Sync>) -> CStore {
CStore {
metas: RwLock::new(IndexVec::new()),
// We add an empty entry for LOCAL_CRATE (which maps to zero) in
// order to make array indices in `metas` match with the
// corresponding `CrateNum`. This first entry will always remain
// `None`.
metas: RwLock::new(IndexVec::from_elem_n(None, 1)),
extern_mod_crate_map: Lock::new(FxHashMap()),
metadata_loader,
}
}

/// You cannot use this function to allocate a CrateNum in a thread-safe manner.
/// It is currently only used in CrateLoader which is single-threaded code.
pub fn next_crate_num(&self) -> CrateNum {
CrateNum::new(self.metas.borrow().len() + 1)
pub(super) fn alloc_new_crate_num(&self) -> CrateNum {
let mut metas = self.metas.borrow_mut();
let cnum = CrateNum::new(metas.len());
metas.push(None);
cnum
}

pub fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
pub(super) fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
self.metas.borrow()[cnum].clone().unwrap()
}

pub fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
use rustc_data_structures::indexed_vec::Idx;
let mut met = self.metas.borrow_mut();
while met.len() <= cnum.index() {
met.push(None);
}
met[cnum] = Some(data);
pub(super) fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
let mut metas = self.metas.borrow_mut();
assert!(metas[cnum].is_none(), "Overwriting crate metadata entry");
metas[cnum] = Some(data);
}

pub fn iter_crate_data<I>(&self, mut i: I)
pub(super) fn iter_crate_data<I>(&self, mut i: I)
where I: FnMut(CrateNum, &Lrc<CrateMetadata>)
{
for (k, v) in self.metas.borrow().iter_enumerated() {
Expand All @@ -131,14 +133,16 @@ impl CStore {
}
}

pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
pub(super) fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
let mut ordering = Vec::new();
self.push_dependencies_in_postorder(&mut ordering, krate);
ordering.reverse();
ordering
}

pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
pub(super) fn push_dependencies_in_postorder(&self,
ordering: &mut Vec<CrateNum>,
krate: CrateNum) {
if ordering.contains(&krate) {
return;
}
Expand All @@ -153,7 +157,7 @@ impl CStore {
ordering.push(krate);
}

pub fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
pub(super) fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
let mut ordering = Vec::new();
for (num, v) in self.metas.borrow().iter_enumerated() {
if let &Some(_) = v {
Expand All @@ -163,11 +167,11 @@ impl CStore {
return ordering
}

pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
pub(super) fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
}

pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
pub(super) fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
}
}
Expand Down