Skip to content

Commit 4199a6c

Browse files
authored
Rollup merge of rust-lang#50538 - michaelwoerister:atomic-cnums, r=Zoxc
Make CrateNum allocation more thread-safe. This PR makes sure that we can't have race conditions when assigning CrateNums. It's a slight improvement but a larger refactoring of the CrateStore/CrateLoader infrastructure would be good, I think. r? @Zoxc
2 parents 296f952 + 4537025 commit 4199a6c

File tree

2 files changed

+24
-23
lines changed

2 files changed

+24
-23
lines changed

src/librustc_metadata/creader.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ pub struct Library {
5151
pub struct CrateLoader<'a> {
5252
pub sess: &'a Session,
5353
cstore: &'a CStore,
54-
next_crate_num: CrateNum,
5554
local_crate_name: Symbol,
5655
}
5756

@@ -102,7 +101,6 @@ impl<'a> CrateLoader<'a> {
102101
CrateLoader {
103102
sess,
104103
cstore,
105-
next_crate_num: cstore.next_crate_num(),
106104
local_crate_name: Symbol::intern(local_crate_name),
107105
}
108106
}
@@ -198,8 +196,7 @@ impl<'a> CrateLoader<'a> {
198196
self.verify_no_symbol_conflicts(span, &crate_root);
199197

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

204201
// Stash paths for top-most crate locally if necessary.
205202
let crate_paths = if root.is_none() {

src/librustc_metadata/cstore.rs

+23-19
Original file line numberDiff line numberDiff line change
@@ -97,32 +97,34 @@ pub struct CStore {
9797
impl CStore {
9898
pub fn new(metadata_loader: Box<MetadataLoader + Sync>) -> CStore {
9999
CStore {
100-
metas: RwLock::new(IndexVec::new()),
100+
// We add an empty entry for LOCAL_CRATE (which maps to zero) in
101+
// order to make array indices in `metas` match with the
102+
// corresponding `CrateNum`. This first entry will always remain
103+
// `None`.
104+
metas: RwLock::new(IndexVec::from_elem_n(None, 1)),
101105
extern_mod_crate_map: Lock::new(FxHashMap()),
102106
metadata_loader,
103107
}
104108
}
105109

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

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

116-
pub fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
117-
use rustc_data_structures::indexed_vec::Idx;
118-
let mut met = self.metas.borrow_mut();
119-
while met.len() <= cnum.index() {
120-
met.push(None);
121-
}
122-
met[cnum] = Some(data);
121+
pub(super) fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
122+
let mut metas = self.metas.borrow_mut();
123+
assert!(metas[cnum].is_none(), "Overwriting crate metadata entry");
124+
metas[cnum] = Some(data);
123125
}
124126

125-
pub fn iter_crate_data<I>(&self, mut i: I)
127+
pub(super) fn iter_crate_data<I>(&self, mut i: I)
126128
where I: FnMut(CrateNum, &Lrc<CrateMetadata>)
127129
{
128130
for (k, v) in self.metas.borrow().iter_enumerated() {
@@ -132,14 +134,16 @@ impl CStore {
132134
}
133135
}
134136

135-
pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
137+
pub(super) fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
136138
let mut ordering = Vec::new();
137139
self.push_dependencies_in_postorder(&mut ordering, krate);
138140
ordering.reverse();
139141
ordering
140142
}
141143

142-
pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
144+
pub(super) fn push_dependencies_in_postorder(&self,
145+
ordering: &mut Vec<CrateNum>,
146+
krate: CrateNum) {
143147
if ordering.contains(&krate) {
144148
return;
145149
}
@@ -154,7 +158,7 @@ impl CStore {
154158
ordering.push(krate);
155159
}
156160

157-
pub fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
161+
pub(super) fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
158162
let mut ordering = Vec::new();
159163
for (num, v) in self.metas.borrow().iter_enumerated() {
160164
if let &Some(_) = v {
@@ -164,11 +168,11 @@ impl CStore {
164168
return ordering
165169
}
166170

167-
pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
171+
pub(super) fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
168172
self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
169173
}
170174

171-
pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
175+
pub(super) fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
172176
self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
173177
}
174178
}

0 commit comments

Comments
 (0)