diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index f09474ff4d344..d111471f53d7d 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -497,13 +497,15 @@ impl Once { /// If the value was already initialized the closure is not called and `false` is returned, /// otherwise if the value from the closure initializes the inner value, `true` is returned #[inline] - pub fn init_locking T>(&self, f: F) -> bool { - let mut lock = self.0.lock(); - if lock.is_some() { - return false; + pub fn init_locking T>(&self, f: F) -> &T { + { + let mut lock = self.0.lock(); + if lock.is_none() { + *lock = Some(f()); + } } - *lock = Some(f()); - true + + self.borrow() } /// Tries to initialize the inner value by calling the closure without ensuring that no-one diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 234a5395047c6..540b06b3a8be9 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -3,7 +3,7 @@ use crate::cstore::{self, CStore, MetadataBlob}; use crate::locator::{self, CratePaths}; use crate::schema::{CrateRoot, CrateDep}; -use rustc_data_structures::sync::{RwLock, Lock, AtomicCell}; +use rustc_data_structures::sync::{Lock, Once, AtomicCell}; use rustc::hir::def_id::CrateNum; use rustc_data_structures::svh::Svh; @@ -249,7 +249,7 @@ impl<'a> CrateLoader<'a> { cnum_map, cnum, dependencies: Lock::new(dependencies), - source_map_import_info: RwLock::new(vec![]), + source_map_import_info: Once::new(), alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index), dep_kind: Lock::new(dep_kind), source, diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 6b06cf575edcf..8dfc921c95b3d 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -9,7 +9,7 @@ use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate}; use rustc::mir::interpret::AllocDecodingState; use rustc_index::vec::IndexVec; use rustc::util::nodemap::FxHashMap; -use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell}; +use rustc_data_structures::sync::{Lrc, Lock, MetadataRef, Once, AtomicCell}; use syntax::ast; use syntax::edition::Edition; use syntax_expand::base::SyntaxExtension; @@ -62,7 +62,7 @@ crate struct CrateMetadata { /// Proc macro descriptions for this crate, if it's a proc macro crate. crate raw_proc_macros: Option<&'static [ProcMacro]>, /// Source maps for code from the crate. - crate source_map_import_info: RwLock>, + crate source_map_import_info: Once>, /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. crate alloc_decoding_state: AllocDecodingState, /// The `DepNodeIndex` of the `DepNode` representing this upstream crate. diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0e6ecbbf0176a..c5954e1ea1d98 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -5,7 +5,7 @@ use crate::schema::*; use crate::table::{FixedSizeEncoding, PerDefTable}; use rustc_index::vec::IndexVec; -use rustc_data_structures::sync::{Lrc, ReadGuard}; +use rustc_data_structures::sync::Lrc; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, ForeignModule}; @@ -664,7 +664,7 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { self.root.per_def.predicates.get(self, item_id).unwrap().decode((self, tcx)) -} + } crate fn get_predicates_defined_on( &self, @@ -1290,87 +1290,68 @@ impl<'a, 'tcx> CrateMetadata { fn imported_source_files( &'a self, local_source_map: &source_map::SourceMap, - ) -> ReadGuard<'a, Vec> { - { - let source_files = self.source_map_import_info.borrow(); - if !source_files.is_empty() { - return source_files; - } - } - - // Lock the source_map_import_info to ensure this only happens once - let mut source_map_import_info = self.source_map_import_info.borrow_mut(); - - if !source_map_import_info.is_empty() { - drop(source_map_import_info); - return self.source_map_import_info.borrow(); - } - - let external_source_map = self.root.source_map.decode(self); - - let imported_source_files = external_source_map.map(|source_file_to_import| { - // We can't reuse an existing SourceFile, so allocate a new one - // containing the information we need. - let syntax_pos::SourceFile { name, - name_was_remapped, - src_hash, - start_pos, - end_pos, - mut lines, - mut multibyte_chars, - mut non_narrow_chars, - mut normalized_pos, - name_hash, - .. } = source_file_to_import; - - let source_length = (end_pos - start_pos).to_usize(); - - // Translate line-start positions and multibyte character - // position into frame of reference local to file. - // `SourceMap::new_imported_source_file()` will then translate those - // coordinates to their new global frame of reference when the - // offset of the SourceFile is known. - for pos in &mut lines { - *pos = *pos - start_pos; - } - for mbc in &mut multibyte_chars { - mbc.pos = mbc.pos - start_pos; - } - for swc in &mut non_narrow_chars { - *swc = *swc - start_pos; - } - for np in &mut normalized_pos { - np.pos = np.pos - start_pos; - } - - let local_version = local_source_map.new_imported_source_file(name, - name_was_remapped, - self.cnum.as_u32(), - src_hash, - name_hash, - source_length, - lines, - multibyte_chars, - non_narrow_chars, - normalized_pos); - debug!("CrateMetaData::imported_source_files alloc \ - source_file {:?} original (start_pos {:?} end_pos {:?}) \ - translated (start_pos {:?} end_pos {:?})", - local_version.name, start_pos, end_pos, - local_version.start_pos, local_version.end_pos); - - cstore::ImportedSourceFile { - original_start_pos: start_pos, - original_end_pos: end_pos, - translated_source_file: local_version, - } - }).collect(); - - *source_map_import_info = imported_source_files; - drop(source_map_import_info); + ) -> &[cstore::ImportedSourceFile] { + self.source_map_import_info.init_locking(|| { + let external_source_map = self.root.source_map.decode(self); + + external_source_map.map(|source_file_to_import| { + // We can't reuse an existing SourceFile, so allocate a new one + // containing the information we need. + let syntax_pos::SourceFile { name, + name_was_remapped, + src_hash, + start_pos, + end_pos, + mut lines, + mut multibyte_chars, + mut non_narrow_chars, + mut normalized_pos, + name_hash, + .. } = source_file_to_import; + + let source_length = (end_pos - start_pos).to_usize(); + + // Translate line-start positions and multibyte character + // position into frame of reference local to file. + // `SourceMap::new_imported_source_file()` will then translate those + // coordinates to their new global frame of reference when the + // offset of the SourceFile is known. + for pos in &mut lines { + *pos = *pos - start_pos; + } + for mbc in &mut multibyte_chars { + mbc.pos = mbc.pos - start_pos; + } + for swc in &mut non_narrow_chars { + *swc = *swc - start_pos; + } + for np in &mut normalized_pos { + np.pos = np.pos - start_pos; + } - // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. - self.source_map_import_info.borrow() + let local_version = local_source_map.new_imported_source_file(name, + name_was_remapped, + self.cnum.as_u32(), + src_hash, + name_hash, + source_length, + lines, + multibyte_chars, + non_narrow_chars, + normalized_pos); + debug!("CrateMetaData::imported_source_files alloc \ + source_file {:?} original (start_pos {:?} end_pos {:?}) \ + translated (start_pos {:?} end_pos {:?})", + local_version.name, start_pos, end_pos, + local_version.start_pos, local_version.end_pos); + + cstore::ImportedSourceFile { + original_start_pos: start_pos, + original_end_pos: end_pos, + translated_source_file: local_version, + } + }).collect() + }) } /// Get the `DepNodeIndex` corresponding this crate. The result of this