about summary refs log tree commit diff
path: root/compiler/rustc_span/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_span/src')
-rw-r--r--compiler/rustc_span/src/hygiene.rs126
-rw-r--r--compiler/rustc_span/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs9
3 files changed, 98 insertions, 39 deletions
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 9f2ff437842..88081700c3b 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -34,11 +34,13 @@ use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::HashingControls;
 use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
-use rustc_data_structures::sync::{Lock, Lrc};
+use rustc_data_structures::sync::{Lock, Lrc, WorkerLocal};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_index::IndexVec;
 use rustc_macros::HashStable_Generic;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use std::cell::RefCell;
+use std::collections::hash_map::Entry;
 use std::fmt;
 use std::hash::Hash;
 
@@ -1241,13 +1243,25 @@ impl HygieneEncodeContext {
 
 #[derive(Default)]
 /// Additional information used to assist in decoding hygiene data
-pub struct HygieneDecodeContext {
+struct HygieneDecodeContextInner {
     // Maps serialized `SyntaxContext` ids to a `SyntaxContext` in the current
     // global `HygieneData`. When we deserialize a `SyntaxContext`, we need to create
     // a new id in the global `HygieneData`. This map tracks the ID we end up picking,
     // so that multiple occurrences of the same serialized id are decoded to the same
-    // `SyntaxContext`
-    remapped_ctxts: Lock<Vec<Option<SyntaxContext>>>,
+    // `SyntaxContext`. This only stores `SyntaxContext`s which are completly decoded.
+    remapped_ctxts: Vec<Option<SyntaxContext>>,
+
+    /// Maps serialized `SyntaxContext` ids that are currently being decoded to a `SyntaxContext`.
+    decoding: FxHashMap<u32, SyntaxContext>,
+}
+
+#[derive(Default)]
+/// Additional information used to assist in decoding hygiene data
+pub struct HygieneDecodeContext {
+    inner: Lock<HygieneDecodeContextInner>,
+
+    /// A set of serialized `SyntaxContext` ids that are currently being decoded on each thread.
+    local_in_progress: WorkerLocal<RefCell<FxHashMap<u32, ()>>>,
 }
 
 /// Register an expansion which has been decoded from the on-disk-cache for the local crate.
@@ -1277,11 +1291,11 @@ pub fn register_expn_id(
     let expn_id = ExpnId { krate, local_id };
     HygieneData::with(|hygiene_data| {
         let _old_data = hygiene_data.foreign_expn_data.insert(expn_id, data);
-        debug_assert!(_old_data.is_none());
+        debug_assert!(_old_data.is_none() || cfg!(parallel_compiler));
         let _old_hash = hygiene_data.foreign_expn_hashes.insert(expn_id, hash);
-        debug_assert!(_old_hash.is_none());
+        debug_assert!(_old_hash.is_none() || _old_hash == Some(hash));
         let _old_id = hygiene_data.expn_hash_to_expn_id.insert(hash, expn_id);
-        debug_assert!(_old_id.is_none());
+        debug_assert!(_old_id.is_none() || _old_id == Some(expn_id));
     });
     expn_id
 }
@@ -1331,38 +1345,56 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
         return SyntaxContext::root();
     }
 
-    let outer_ctxts = &context.remapped_ctxts;
+    let ctxt = {
+        let mut inner = context.inner.lock();
 
-    // Ensure that the lock() temporary is dropped early
-    {
-        if let Some(ctxt) = outer_ctxts.lock().get(raw_id as usize).copied().flatten() {
+        if let Some(ctxt) = inner.remapped_ctxts.get(raw_id as usize).copied().flatten() {
+            // This has already beeen decoded.
             return ctxt;
         }
-    }
 
-    // Allocate and store SyntaxContext id *before* calling the decoder function,
-    // as the SyntaxContextData may reference itself.
-    let new_ctxt = HygieneData::with(|hygiene_data| {
-        let new_ctxt = SyntaxContext(hygiene_data.syntax_context_data.len() as u32);
-        // Push a dummy SyntaxContextData to ensure that nobody else can get the
-        // same ID as us. This will be overwritten after call `decode_Data`
-        hygiene_data.syntax_context_data.push(SyntaxContextData {
-            outer_expn: ExpnId::root(),
-            outer_transparency: Transparency::Transparent,
-            parent: SyntaxContext::root(),
-            opaque: SyntaxContext::root(),
-            opaque_and_semitransparent: SyntaxContext::root(),
-            dollar_crate_name: kw::Empty,
-        });
-        let mut ctxts = outer_ctxts.lock();
-        let new_len = raw_id as usize + 1;
-        if ctxts.len() < new_len {
-            ctxts.resize(new_len, None);
+        match inner.decoding.entry(raw_id) {
+            Entry::Occupied(ctxt_entry) => {
+                match context.local_in_progress.borrow_mut().entry(raw_id) {
+                    Entry::Occupied(..) => {
+                        // We're decoding this already on the current thread. Return here
+                        // and let the function higher up the stack finish decoding to handle
+                        // recursive cases.
+                        return *ctxt_entry.get();
+                    }
+                    Entry::Vacant(entry) => {
+                        entry.insert(());
+
+                        // Some other thread is current decoding this. Race with it.
+                        *ctxt_entry.get()
+                    }
+                }
+            }
+            Entry::Vacant(entry) => {
+                // We are the first thread to start decoding. Mark the current thread as being progress.
+                context.local_in_progress.borrow_mut().insert(raw_id, ());
+
+                // Allocate and store SyntaxContext id *before* calling the decoder function,
+                // as the SyntaxContextData may reference itself.
+                let new_ctxt = HygieneData::with(|hygiene_data| {
+                    let new_ctxt = SyntaxContext(hygiene_data.syntax_context_data.len() as u32);
+                    // Push a dummy SyntaxContextData to ensure that nobody else can get the
+                    // same ID as us. This will be overwritten after call `decode_Data`
+                    hygiene_data.syntax_context_data.push(SyntaxContextData {
+                        outer_expn: ExpnId::root(),
+                        outer_transparency: Transparency::Transparent,
+                        parent: SyntaxContext::root(),
+                        opaque: SyntaxContext::root(),
+                        opaque_and_semitransparent: SyntaxContext::root(),
+                        dollar_crate_name: kw::Empty,
+                    });
+                    new_ctxt
+                });
+                entry.insert(new_ctxt);
+                new_ctxt
+            }
         }
-        ctxts[raw_id as usize] = Some(new_ctxt);
-        drop(ctxts);
-        new_ctxt
-    });
+    };
 
     // Don't try to decode data while holding the lock, since we need to
     // be able to recursively decode a SyntaxContext
@@ -1375,14 +1407,32 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
     // Overwrite the dummy data with our decoded SyntaxContextData
     HygieneData::with(|hygiene_data| {
         let dummy = std::mem::replace(
-            &mut hygiene_data.syntax_context_data[new_ctxt.as_u32() as usize],
+            &mut hygiene_data.syntax_context_data[ctxt.as_u32() as usize],
             ctxt_data,
         );
-        // Make sure nothing weird happening while `decode_data` was running
-        assert_eq!(dummy.dollar_crate_name, kw::Empty);
+        if cfg!(not(parallel_compiler)) {
+            // Make sure nothing weird happened while `decode_data` was running.
+            // We used `kw::Empty` for the dummy value and we expect nothing to be
+            // modifying the dummy entry.
+            // This does not hold for the parallel compiler as another thread may
+            // have inserted the fully decoded data.
+            assert_eq!(dummy.dollar_crate_name, kw::Empty);
+        }
     });
 
-    new_ctxt
+    // Mark the context as completed
+
+    context.local_in_progress.borrow_mut().remove(&raw_id);
+
+    let mut inner = context.inner.lock();
+    let new_len = raw_id as usize + 1;
+    if inner.remapped_ctxts.len() < new_len {
+        inner.remapped_ctxts.resize(new_len, None);
+    }
+    inner.remapped_ctxts[raw_id as usize] = Some(ctxt);
+    inner.decoding.remove(&raw_id);
+
+    ctxt
 }
 
 fn for_all_ctxts_in<F: FnMut(u32, SyntaxContext, &SyntaxContextData)>(
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index c24b8d9ec17..efaed0f68ce 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -23,7 +23,7 @@
 #![feature(round_char_boundary)]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
-#![cfg_attr(not(bootstrap), allow(internal_features))]
+#![allow(internal_features)]
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 90dc6766cf2..07bae08d558 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -232,11 +232,13 @@ symbols! {
         NonZeroI32,
         NonZeroI64,
         NonZeroI8,
+        NonZeroIsize,
         NonZeroU128,
         NonZeroU16,
         NonZeroU32,
         NonZeroU64,
         NonZeroU8,
+        NonZeroUsize,
         None,
         Ok,
         Option,
@@ -278,6 +280,7 @@ symbols! {
         RwLock,
         RwLockReadGuard,
         RwLockWriteGuard,
+        Saturating,
         Send,
         SeqCst,
         SliceIndex,
@@ -305,6 +308,7 @@ symbols! {
         Vec,
         VecDeque,
         Wrapper,
+        Wrapping,
         Yield,
         _DECLS,
         _Self,
@@ -1374,6 +1378,7 @@ symbols! {
         sanitizer_cfi_normalize_integers,
         sanitizer_runtime,
         saturating_add,
+        saturating_div,
         saturating_sub,
         self_in_typedefs,
         self_struct_ctor,
@@ -1619,6 +1624,7 @@ symbols! {
         unix_sigpipe,
         unlikely,
         unmarked_api,
+        unnamed_fields,
         unpin,
         unreachable,
         unreachable_2015,
@@ -1691,7 +1697,10 @@ symbols! {
         windows_subsystem,
         with_negative_coherence,
         wrapping_add,
+        wrapping_div,
         wrapping_mul,
+        wrapping_rem,
+        wrapping_rem_euclid,
         wrapping_sub,
         wreg,
         write_bytes,