Skip to content

Commit adf2135

Browse files
committed
Auto merge of #48936 - Zoxc:cstore, r=michaelwoerister
Make CrateMetadata and CStore thread-safe r? @michaelwoerister
2 parents 61b6bf5 + 5b8f9c5 commit adf2135

File tree

7 files changed

+68
-43
lines changed

7 files changed

+68
-43
lines changed

src/librustc_metadata/creader.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use cstore::{self, CStore, CrateSource, MetadataBlob};
1414
use locator::{self, CratePaths};
1515
use native_libs::relevant_lib;
1616
use schema::CrateRoot;
17-
use rustc_data_structures::sync::Lrc;
17+
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
1818

1919
use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
2020
use rustc::hir::svh::Svh;
@@ -30,7 +30,6 @@ use rustc::util::common::record_time;
3030
use rustc::util::nodemap::FxHashSet;
3131
use rustc::hir::map::Definitions;
3232

33-
use std::cell::{RefCell, Cell};
3433
use std::ops::Deref;
3534
use std::path::PathBuf;
3635
use std::{cmp, fs};
@@ -63,7 +62,7 @@ fn dump_crates(cstore: &CStore) {
6362
info!(" name: {}", data.name());
6463
info!(" cnum: {}", data.cnum);
6564
info!(" hash: {}", data.hash());
66-
info!(" reqd: {:?}", data.dep_kind.get());
65+
info!(" reqd: {:?}", *data.dep_kind.lock());
6766
let CrateSource { dylib, rlib, rmeta } = data.source.clone();
6867
dylib.map(|dl| info!(" dylib: {}", dl.0.display()));
6968
rlib.map(|rl| info!(" rlib: {}", rl.0.display()));
@@ -233,19 +232,19 @@ impl<'a> CrateLoader<'a> {
233232

234233
let mut cmeta = cstore::CrateMetadata {
235234
name,
236-
extern_crate: Cell::new(None),
235+
extern_crate: Lock::new(None),
237236
def_path_table: Lrc::new(def_path_table),
238237
trait_impls,
239238
proc_macros: crate_root.macro_derive_registrar.map(|_| {
240239
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
241240
}),
242241
root: crate_root,
243242
blob: metadata,
244-
cnum_map: RefCell::new(cnum_map),
243+
cnum_map: Lock::new(cnum_map),
245244
cnum,
246-
codemap_import_info: RefCell::new(vec![]),
247-
attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
248-
dep_kind: Cell::new(dep_kind),
245+
codemap_import_info: RwLock::new(vec![]),
246+
attribute_cache: Lock::new([Vec::new(), Vec::new()]),
247+
dep_kind: Lock::new(dep_kind),
249248
source: cstore::CrateSource {
250249
dylib,
251250
rlib,
@@ -335,7 +334,9 @@ impl<'a> CrateLoader<'a> {
335334
if data.root.macro_derive_registrar.is_some() {
336335
dep_kind = DepKind::UnexportedMacrosOnly;
337336
}
338-
data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind));
337+
data.dep_kind.with_lock(|data_dep_kind| {
338+
*data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
339+
});
339340
(cnum, data)
340341
}
341342
LoadResult::Loaded(library) => {
@@ -379,14 +380,14 @@ impl<'a> CrateLoader<'a> {
379380
if !visited.insert((cnum, extern_crate.direct)) { return }
380381

381382
let cmeta = self.cstore.get_crate_data(cnum);
382-
let old_extern_crate = cmeta.extern_crate.get();
383+
let mut old_extern_crate = cmeta.extern_crate.borrow_mut();
383384

384385
// Prefer:
385386
// - something over nothing (tuple.0);
386387
// - direct extern crate to indirect (tuple.1);
387388
// - shorter paths to longer (tuple.2).
388389
let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
389-
let old_rank = match old_extern_crate {
390+
let old_rank = match *old_extern_crate {
390391
None => (false, false, !0),
391392
Some(ref c) => (true, c.direct, !c.path_len),
392393
};
@@ -395,7 +396,9 @@ impl<'a> CrateLoader<'a> {
395396
return; // no change needed
396397
}
397398

398-
cmeta.extern_crate.set(Some(extern_crate));
399+
*old_extern_crate = Some(extern_crate);
400+
drop(old_extern_crate);
401+
399402
// Propagate the extern crate info to dependencies.
400403
extern_crate.direct = false;
401404
for &dep_cnum in cmeta.cnum_map.borrow().iter() {
@@ -646,7 +649,7 @@ impl<'a> CrateLoader<'a> {
646649
// #![panic_runtime] crate.
647650
self.inject_dependency_if(cnum, "a panic runtime",
648651
&|data| data.needs_panic_runtime(sess));
649-
runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
652+
runtime_found = runtime_found || *data.dep_kind.lock() == DepKind::Explicit;
650653
}
651654
});
652655

src/librustc_metadata/cstore.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ use rustc_back::PanicStrategy;
2222
use rustc_data_structures::indexed_vec::IndexVec;
2323
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};
2424

25-
use std::cell::{RefCell, Cell};
26-
use rustc_data_structures::sync::Lrc;
25+
use rustc_data_structures::sync::{Lrc, RwLock, Lock};
2726
use syntax::{ast, attr};
2827
use syntax::ext::base::SyntaxExtension;
2928
use syntax::symbol::Symbol;
@@ -62,13 +61,13 @@ pub struct CrateMetadata {
6261
/// Information about the extern crate that caused this crate to
6362
/// be loaded. If this is `None`, then the crate was injected
6463
/// (e.g., by the allocator)
65-
pub extern_crate: Cell<Option<ExternCrate>>,
64+
pub extern_crate: Lock<Option<ExternCrate>>,
6665

6766
pub blob: MetadataBlob,
68-
pub cnum_map: RefCell<CrateNumMap>,
67+
pub cnum_map: Lock<CrateNumMap>,
6968
pub cnum: CrateNum,
70-
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
71-
pub attribute_cache: RefCell<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,
69+
pub codemap_import_info: RwLock<Vec<ImportedFileMap>>,
70+
pub attribute_cache: Lock<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,
7271

7372
pub root: schema::CrateRoot,
7473

@@ -81,7 +80,7 @@ pub struct CrateMetadata {
8180

8281
pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,
8382

84-
pub dep_kind: Cell<DepKind>,
83+
pub dep_kind: Lock<DepKind>,
8584
pub source: CrateSource,
8685

8786
pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
@@ -90,21 +89,23 @@ pub struct CrateMetadata {
9089
}
9190

9291
pub struct CStore {
93-
metas: RefCell<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
92+
metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
9493
/// Map from NodeId's of local extern crate statements to crate numbers
95-
extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
96-
pub metadata_loader: Box<MetadataLoader>,
94+
extern_mod_crate_map: Lock<NodeMap<CrateNum>>,
95+
pub metadata_loader: Box<MetadataLoader + Sync>,
9796
}
9897

9998
impl CStore {
100-
pub fn new(metadata_loader: Box<MetadataLoader>) -> CStore {
99+
pub fn new(metadata_loader: Box<MetadataLoader + Sync>) -> CStore {
101100
CStore {
102-
metas: RefCell::new(IndexVec::new()),
103-
extern_mod_crate_map: RefCell::new(FxHashMap()),
101+
metas: RwLock::new(IndexVec::new()),
102+
extern_mod_crate_map: Lock::new(FxHashMap()),
104103
metadata_loader,
105104
}
106105
}
107106

107+
/// You cannot use this function to allocate a CrateNum in a thread-safe manner.
108+
/// It is currently only used in CrateLoader which is single-threaded code.
108109
pub fn next_crate_num(&self) -> CrateNum {
109110
CrateNum::new(self.metas.borrow().len() + 1)
110111
}

src/librustc_metadata/cstore_impl.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,10 @@ provide! { <'tcx> tcx, def_id, other, cdata,
175175
is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) }
176176
is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) }
177177
panic_strategy => { cdata.panic_strategy() }
178-
extern_crate => { Lrc::new(cdata.extern_crate.get()) }
178+
extern_crate => {
179+
let r = Lrc::new(*cdata.extern_crate.lock());
180+
r
181+
}
179182
is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
180183
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
181184
reachable_non_generics => {
@@ -225,7 +228,10 @@ provide! { <'tcx> tcx, def_id, other, cdata,
225228
cdata.is_dllimport_foreign_item(def_id.index)
226229
}
227230
visibility => { cdata.get_visibility(def_id.index) }
228-
dep_kind => { cdata.dep_kind.get() }
231+
dep_kind => {
232+
let r = *cdata.dep_kind.lock();
233+
r
234+
}
229235
crate_name => { cdata.name }
230236
item_children => {
231237
let mut result = vec![];
@@ -241,10 +247,11 @@ provide! { <'tcx> tcx, def_id, other, cdata,
241247
}
242248

243249
missing_extern_crate_item => {
244-
match cdata.extern_crate.get() {
250+
let r = match *cdata.extern_crate.borrow() {
245251
Some(extern_crate) if !extern_crate.direct => true,
246252
_ => false,
247-
}
253+
};
254+
r
248255
}
249256

250257
used_crate_source => { Lrc::new(cdata.source.clone()) }
@@ -419,13 +426,16 @@ impl CrateStore for cstore::CStore {
419426

420427
fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind
421428
{
422-
self.get_crate_data(cnum).dep_kind.get()
429+
let data = self.get_crate_data(cnum);
430+
let r = *data.dep_kind.lock();
431+
r
423432
}
424433

425434
fn export_macros_untracked(&self, cnum: CrateNum) {
426435
let data = self.get_crate_data(cnum);
427-
if data.dep_kind.get() == DepKind::UnexportedMacrosOnly {
428-
data.dep_kind.set(DepKind::MacrosOnly)
436+
let mut dep_kind = data.dep_kind.lock();
437+
if *dep_kind == DepKind::UnexportedMacrosOnly {
438+
*dep_kind = DepKind::MacrosOnly;
429439
}
430440
}
431441

src/librustc_metadata/decoder.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
1414
use schema::*;
1515

16-
use rustc_data_structures::sync::Lrc;
16+
use rustc_data_structures::sync::{Lrc, ReadGuard};
1717
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
1818
use rustc::hir;
1919
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
@@ -31,7 +31,6 @@ use rustc::ty::codec::TyDecoder;
3131
use rustc::mir::Mir;
3232
use rustc::util::nodemap::FxHashMap;
3333

34-
use std::cell::Ref;
3534
use std::collections::BTreeMap;
3635
use std::io;
3736
use std::mem;
@@ -714,7 +713,7 @@ impl<'a, 'tcx> CrateMetadata {
714713
};
715714

716715
// Iterate over all children.
717-
let macros_only = self.dep_kind.get().macros_only();
716+
let macros_only = self.dep_kind.lock().macros_only();
718717
for child_index in item.children.decode((self, sess)) {
719718
if macros_only {
720719
continue
@@ -950,6 +949,8 @@ impl<'a, 'tcx> CrateMetadata {
950949
if vec_.len() < node_index + 1 {
951950
vec_.resize(node_index + 1, None);
952951
}
952+
// This can overwrite the result produced by another thread, but the value
953+
// written should be the same
953954
vec_[node_index] = Some(result.clone());
954955
result
955956
}
@@ -1156,14 +1157,22 @@ impl<'a, 'tcx> CrateMetadata {
11561157
/// for items inlined from other crates.
11571158
pub fn imported_filemaps(&'a self,
11581159
local_codemap: &codemap::CodeMap)
1159-
-> Ref<'a, Vec<cstore::ImportedFileMap>> {
1160+
-> ReadGuard<'a, Vec<cstore::ImportedFileMap>> {
11601161
{
11611162
let filemaps = self.codemap_import_info.borrow();
11621163
if !filemaps.is_empty() {
11631164
return filemaps;
11641165
}
11651166
}
11661167

1168+
// Lock the codemap_import_info to ensure this only happens once
1169+
let mut codemap_import_info = self.codemap_import_info.borrow_mut();
1170+
1171+
if !codemap_import_info.is_empty() {
1172+
drop(codemap_import_info);
1173+
return self.codemap_import_info.borrow();
1174+
}
1175+
11671176
let external_codemap = self.root.codemap.decode(self);
11681177

11691178
let imported_filemaps = external_codemap.map(|filemap_to_import| {
@@ -1222,8 +1231,10 @@ impl<'a, 'tcx> CrateMetadata {
12221231
}
12231232
}).collect();
12241233

1234+
*codemap_import_info = imported_filemaps;
1235+
drop(codemap_import_info);
1236+
12251237
// This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
1226-
*self.codemap_import_info.borrow_mut() = imported_filemaps;
12271238
self.codemap_import_info.borrow()
12281239
}
12291240
}

src/librustc_trans/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl TransCrate for LlvmTransCrate {
201201
target_features(sess)
202202
}
203203

204-
fn metadata_loader(&self) -> Box<MetadataLoader> {
204+
fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
205205
box metadata::LlvmMetadataLoader
206206
}
207207

src/librustc_trans_utils/trans_crate.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub trait TransCrate {
5858
fn print_version(&self) {}
5959
fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] }
6060

61-
fn metadata_loader(&self) -> Box<MetadataLoader>;
61+
fn metadata_loader(&self) -> Box<MetadataLoader + Sync>;
6262
fn provide(&self, _providers: &mut Providers);
6363
fn provide_extern(&self, _providers: &mut Providers);
6464
fn trans_crate<'a, 'tcx>(
@@ -84,7 +84,7 @@ pub trait TransCrate {
8484
pub struct DummyTransCrate;
8585

8686
impl TransCrate for DummyTransCrate {
87-
fn metadata_loader(&self) -> Box<MetadataLoader> {
87+
fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
8888
box DummyMetadataLoader(())
8989
}
9090

@@ -195,7 +195,7 @@ impl TransCrate for MetadataOnlyTransCrate {
195195
}
196196
}
197197

198-
fn metadata_loader(&self) -> Box<MetadataLoader> {
198+
fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
199199
box NoLlvmMetadataLoader
200200
}
201201

src/test/run-make/hotplug_codegen_backend/the_backend.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_trans_utils::trans_crate::{TransCrate, MetadataOnlyTransCrate};
2828
struct TheBackend(Box<TransCrate>);
2929

3030
impl TransCrate for TheBackend {
31-
fn metadata_loader(&self) -> Box<MetadataLoader> {
31+
fn metadata_loader(&self) -> Box<MetadataLoader + Sync> {
3232
self.0.metadata_loader()
3333
}
3434

0 commit comments

Comments
 (0)