Skip to content

Commit

Permalink
Make CrateMetadata thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
Zoxc committed Mar 12, 2018
1 parent 37e897f commit 4edb539
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 32 deletions.
29 changes: 16 additions & 13 deletions src/librustc_metadata/creader.rs
Expand Up @@ -14,7 +14,7 @@ use cstore::{self, CStore, CrateSource, MetadataBlob};
use locator::{self, CratePaths};
use native_libs::relevant_lib;
use schema::CrateRoot;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::sync::{Lrc, RwLock, Lock};

use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
use rustc::hir::svh::Svh;
Expand All @@ -30,7 +30,6 @@ use rustc::util::common::record_time;
use rustc::util::nodemap::FxHashSet;
use rustc::hir::map::Definitions;

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

let mut cmeta = cstore::CrateMetadata {
name,
extern_crate: Cell::new(None),
extern_crate: Lock::new(None),
def_path_table: Lrc::new(def_path_table),
trait_impls,
proc_macros: crate_root.macro_derive_registrar.map(|_| {
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
}),
root: crate_root,
blob: metadata,
cnum_map: RefCell::new(cnum_map),
cnum_map: Lock::new(cnum_map),
cnum,
codemap_import_info: RefCell::new(vec![]),
attribute_cache: RefCell::new([Vec::new(), Vec::new()]),
dep_kind: Cell::new(dep_kind),
codemap_import_info: RwLock::new(vec![]),
attribute_cache: Lock::new([Vec::new(), Vec::new()]),
dep_kind: Lock::new(dep_kind),
source: cstore::CrateSource {
dylib,
rlib,
Expand Down Expand Up @@ -335,7 +334,9 @@ impl<'a> CrateLoader<'a> {
if data.root.macro_derive_registrar.is_some() {
dep_kind = DepKind::UnexportedMacrosOnly;
}
data.dep_kind.set(cmp::max(data.dep_kind.get(), dep_kind));
data.dep_kind.with_lock(|data_dep_kind| {
*data_dep_kind = cmp::max(*data_dep_kind, dep_kind);
});
(cnum, data)
}
LoadResult::Loaded(library) => {
Expand Down Expand Up @@ -379,14 +380,14 @@ impl<'a> CrateLoader<'a> {
if !visited.insert((cnum, extern_crate.direct)) { return }

let cmeta = self.cstore.get_crate_data(cnum);
let old_extern_crate = cmeta.extern_crate.get();
let mut old_extern_crate = cmeta.extern_crate.borrow_mut();

// Prefer:
// - something over nothing (tuple.0);
// - direct extern crate to indirect (tuple.1);
// - shorter paths to longer (tuple.2).
let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
let old_rank = match old_extern_crate {
let old_rank = match *old_extern_crate {
None => (false, false, !0),
Some(ref c) => (true, c.direct, !c.path_len),
};
Expand All @@ -395,7 +396,9 @@ impl<'a> CrateLoader<'a> {
return; // no change needed
}

cmeta.extern_crate.set(Some(extern_crate));
*old_extern_crate = Some(extern_crate);
drop(old_extern_crate);

// Propagate the extern crate info to dependencies.
extern_crate.direct = false;
for &dep_cnum in cmeta.cnum_map.borrow().iter() {
Expand Down Expand Up @@ -646,7 +649,7 @@ impl<'a> CrateLoader<'a> {
// #![panic_runtime] crate.
self.inject_dependency_if(cnum, "a panic runtime",
&|data| data.needs_panic_runtime(sess));
runtime_found = runtime_found || data.dep_kind.get() == DepKind::Explicit;
runtime_found = runtime_found || *data.dep_kind.lock() == DepKind::Explicit;
}
});

Expand Down
13 changes: 6 additions & 7 deletions src/librustc_metadata/cstore.rs
Expand Up @@ -22,8 +22,7 @@ use rustc_back::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};

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

pub blob: MetadataBlob,
pub cnum_map: RefCell<CrateNumMap>,
pub cnum_map: Lock<CrateNumMap>,
pub cnum: CrateNum,
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
pub attribute_cache: RefCell<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,
pub codemap_import_info: RwLock<Vec<ImportedFileMap>>,
pub attribute_cache: Lock<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,

pub root: schema::CrateRoot,

Expand All @@ -81,7 +80,7 @@ pub struct CrateMetadata {

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

pub dep_kind: Cell<DepKind>,
pub dep_kind: Lock<DepKind>,
pub source: CrateSource,

pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
Expand Down
24 changes: 17 additions & 7 deletions src/librustc_metadata/cstore_impl.rs
Expand Up @@ -175,7 +175,10 @@ provide! { <'tcx> tcx, def_id, other, cdata,
is_sanitizer_runtime => { cdata.is_sanitizer_runtime(tcx.sess) }
is_profiler_runtime => { cdata.is_profiler_runtime(tcx.sess) }
panic_strategy => { cdata.panic_strategy() }
extern_crate => { Lrc::new(cdata.extern_crate.get()) }
extern_crate => {
let r = Lrc::new(*cdata.extern_crate.lock());
r
}
is_no_builtins => { cdata.is_no_builtins(tcx.sess) }
impl_defaultness => { cdata.get_impl_defaultness(def_id.index) }
reachable_non_generics => {
Expand Down Expand Up @@ -225,7 +228,10 @@ provide! { <'tcx> tcx, def_id, other, cdata,
cdata.is_dllimport_foreign_item(def_id.index)
}
visibility => { cdata.get_visibility(def_id.index) }
dep_kind => { cdata.dep_kind.get() }
dep_kind => {
let r = *cdata.dep_kind.lock();
r
}
crate_name => { cdata.name }
item_children => {
let mut result = vec![];
Expand All @@ -241,10 +247,11 @@ provide! { <'tcx> tcx, def_id, other, cdata,
}

missing_extern_crate_item => {
match cdata.extern_crate.get() {
let r = match *cdata.extern_crate.borrow() {
Some(extern_crate) if !extern_crate.direct => true,
_ => false,
}
};
r
}

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

fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind
{
self.get_crate_data(cnum).dep_kind.get()
let data = self.get_crate_data(cnum);
let r = *data.dep_kind.lock();
r
}

fn export_macros_untracked(&self, cnum: CrateNum) {
let data = self.get_crate_data(cnum);
if data.dep_kind.get() == DepKind::UnexportedMacrosOnly {
data.dep_kind.set(DepKind::MacrosOnly)
let mut dep_kind = data.dep_kind.lock();
if *dep_kind == DepKind::UnexportedMacrosOnly {
*dep_kind = DepKind::MacrosOnly;
}
}

Expand Down
21 changes: 16 additions & 5 deletions src/librustc_metadata/decoder.rs
Expand Up @@ -13,7 +13,7 @@
use cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary};
use schema::*;

use rustc_data_structures::sync::Lrc;
use rustc_data_structures::sync::{Lrc, ReadGuard};
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc::hir;
use rustc::middle::cstore::{LinkagePreference, ExternConstBody,
Expand All @@ -31,7 +31,6 @@ use rustc::ty::codec::TyDecoder;
use rustc::mir::Mir;
use rustc::util::nodemap::FxHashMap;

use std::cell::Ref;
use std::collections::BTreeMap;
use std::io;
use std::mem;
Expand Down Expand Up @@ -714,7 +713,7 @@ impl<'a, 'tcx> CrateMetadata {
};

// Iterate over all children.
let macros_only = self.dep_kind.get().macros_only();
let macros_only = self.dep_kind.lock().macros_only();
for child_index in item.children.decode((self, sess)) {
if macros_only {
continue
Expand Down Expand Up @@ -950,6 +949,8 @@ impl<'a, 'tcx> CrateMetadata {
if vec_.len() < node_index + 1 {
vec_.resize(node_index + 1, None);
}
// This can overwrite the result produced by another thread, but the value
// written should be the same
vec_[node_index] = Some(result.clone());
result
}
Expand Down Expand Up @@ -1156,14 +1157,22 @@ impl<'a, 'tcx> CrateMetadata {
/// for items inlined from other crates.
pub fn imported_filemaps(&'a self,
local_codemap: &codemap::CodeMap)
-> Ref<'a, Vec<cstore::ImportedFileMap>> {
-> ReadGuard<'a, Vec<cstore::ImportedFileMap>> {
{
let filemaps = self.codemap_import_info.borrow();
if !filemaps.is_empty() {
return filemaps;
}
}

// Lock the codemap_import_info to ensure this only happens once
let mut codemap_import_info = self.codemap_import_info.borrow_mut();

if !codemap_import_info.is_empty() {
drop(codemap_import_info);
return self.codemap_import_info.borrow();
}

let external_codemap = self.root.codemap.decode(self);

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

*codemap_import_info = imported_filemaps;
drop(codemap_import_info);

// This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
*self.codemap_import_info.borrow_mut() = imported_filemaps;
self.codemap_import_info.borrow()
}
}

0 comments on commit 4edb539

Please sign in to comment.