about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-10-31 02:54:11 +0100
committerGitHub <noreply@github.com>2019-10-31 02:54:11 +0100
commit30ed544948dc12b487e6c307bf76c43785841f8a (patch)
tree8cb7e61f451d177cfbca4238d78b9b39ca334073
parent60fa6d8ac258400a3b4da72019f5edda7e513dbe (diff)
parent12273cb7f66f463683ad4d6c54b17afe0b7d8422 (diff)
downloadrust-30ed544948dc12b487e6c307bf76c43785841f8a.tar.gz
rust-30ed544948dc12b487e6c307bf76c43785841f8a.zip
Rollup merge of #65979 - spastorino:crate-metadata-mutexes, r=Mark-Simulacrum
Switch CrateMetadata's source_map_import_info from RwLock to Once
-rw-r--r--src/librustc_data_structures/sync.rs14
-rw-r--r--src/librustc_metadata/creader.rs4
-rw-r--r--src/librustc_metadata/cstore.rs4
-rw-r--r--src/librustc_metadata/decoder.rs145
4 files changed, 75 insertions, 92 deletions
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index f09474ff4d3..d111471f53d 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -497,13 +497,15 @@ impl<T> Once<T> {
     /// 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<F: FnOnce() -> T>(&self, f: F) -> bool {
-        let mut lock = self.0.lock();
-        if lock.is_some() {
-            return false;
+    pub fn init_locking<F: FnOnce() -> 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 234a5395047..540b06b3a8b 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 6b06cf575ed..8dfc921c95b 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<Vec<ImportedSourceFile>>,
+    crate source_map_import_info: Once<Vec<ImportedSourceFile>>,
     /// 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 0e6ecbbf017..c5954e1ea1d 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<cstore::ImportedSourceFile>> {
-        {
-            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