Skip to content

Commit

Permalink
Auto merge of #115418 - Zoxc:freeze-source, r=<try>
Browse files Browse the repository at this point in the history
Use `Freeze` for `SourceFile`

This uses the `Freeze` type in `SourceFile` to let accessing `external_src` and `lines` be lock-free.

Behavior of `add_external_src` is changed to set `ExternalSourceKind::AbsentErr` on a hash mismatch which matches the documentation. `ExternalSourceKind::Unneeded` was removed as it's unused.

Based on #115401.
  • Loading branch information
bors committed Sep 7, 2023
2 parents 7f0fa48 + f96fe5b commit dc98c3e
Show file tree
Hide file tree
Showing 16 changed files with 295 additions and 231 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl DebugContext {

match tcx.sess.source_map().lookup_line(span.lo()) {
Ok(SourceFileAndLine { sf: file, line }) => {
let line_pos = file.lines(|lines| lines[line]);
let line_pos = file.lines()[line];
let col = file.relative_position(span.lo()) - line_pos;

(file, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ impl CodegenCx<'_, '_> {
pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
Ok(SourceFileAndLine { sf: file, line }) => {
let line_pos = file.lines(|lines| lines[line]);
let line_pos = file.lines()[line];

// Use 1-based indexing.
let line = (line + 1) as u32;
Expand Down
62 changes: 57 additions & 5 deletions compiler/rustc_data_structures/src/sync/freeze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::sync::{AtomicBool, ReadGuard, RwLock, WriteGuard};
use crate::sync::{DynSend, DynSync};
use std::{
cell::UnsafeCell,
intrinsics::likely,
marker::PhantomData,
ops::{Deref, DerefMut},
sync::atomic::Ordering,
Expand All @@ -27,7 +28,37 @@ unsafe impl<T: DynSync + DynSend> DynSync for FreezeLock<T> {}
impl<T> FreezeLock<T> {
#[inline]
pub fn new(value: T) -> Self {
Self { data: UnsafeCell::new(value), frozen: AtomicBool::new(false), lock: RwLock::new(()) }
Self::with(value, false)
}

#[inline]
pub fn frozen(value: T) -> Self {
Self::with(value, true)
}

#[inline]
pub fn with(value: T, frozen: bool) -> Self {
Self {
data: UnsafeCell::new(value),
frozen: AtomicBool::new(frozen),
lock: RwLock::new(()),
}
}

#[inline]
pub fn is_frozen(&self) -> bool {
self.frozen.load(Ordering::Acquire)
}

/// Get the inner value if frozen.
#[inline]
pub fn get(&self) -> Option<&T> {
if likely(self.frozen.load(Ordering::Acquire)) {
// SAFETY: This is frozen so the data cannot be modified.
unsafe { Some(&*self.data.get()) }
} else {
None
}
}

#[inline]
Expand All @@ -42,13 +73,25 @@ impl<T> FreezeLock<T> {
}
}

#[inline]
pub fn borrow(&self) -> FreezeReadGuard<'_, T> {
self.read()
}

#[inline]
#[track_caller]
pub fn write(&self) -> FreezeWriteGuard<'_, T> {
let _lock_guard = self.lock.write();
// Use relaxed ordering since we're in the write lock.
assert!(!self.frozen.load(Ordering::Relaxed), "still mutable");
FreezeWriteGuard { _lock_guard, lock: self, marker: PhantomData }
self.try_write().expect("still mutable")
}

#[inline]
pub fn try_write(&self) -> Option<FreezeWriteGuard<'_, T>> {
if self.frozen.load(Ordering::Relaxed) {
None
} else {
let _lock_guard = self.lock.write();
Some(FreezeWriteGuard { _lock_guard, lock: self, marker: PhantomData })
}
}

#[inline]
Expand Down Expand Up @@ -90,6 +133,15 @@ pub struct FreezeWriteGuard<'a, T> {
marker: PhantomData<&'a mut T>,
}

impl<'a, T> FreezeWriteGuard<'a, T> {
pub fn freeze(self) -> &'a T {
self.lock.frozen.store(true, Ordering::Release);

// SAFETY: This is frozen so the data cannot be modified and shared access is sound.
unsafe { &*self.lock.data.get() }
}
}

impl<'a, T: 'a> Deref for FreezeWriteGuard<'a, T> {
type Target = T;
#[inline]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ impl AnnotateSnippetEmitterWriter {
.map(|line| {
// Ensure the source file is present before we try
// to load a string from it.
source_map.ensure_source_file_source_present(file.clone());
source_map.ensure_source_file_source_present(&file);
(
format!("{}", source_map.filename_for_diagnostics(&file.name)),
source_string(file.clone(), &line),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_errors/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1193,7 +1193,7 @@ impl EmitterWriter {
let will_be_emitted = |span: Span| {
!span.is_dummy() && {
let file = sm.lookup_source_file(span.hi());
sm.ensure_source_file_source_present(file)
sm.ensure_source_file_source_present(&file)
}
};

Expand Down Expand Up @@ -1388,7 +1388,7 @@ impl EmitterWriter {
// Print out the annotate source lines that correspond with the error
for annotated_file in annotated_files {
// we can't annotate anything if the source is unavailable.
if !sm.ensure_source_file_source_present(annotated_file.file.clone()) {
if !sm.ensure_source_file_source_present(&annotated_file.file) {
if !self.short_message {
// We'll just print an unannotated message.
for (annotation_id, line) in annotated_file.lines.iter().enumerate() {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ impl DiagnosticSpanLine {
.span_to_lines(span)
.map(|lines| {
// We can't get any lines if the source is unavailable.
if !je.sm.ensure_source_file_source_present(lines.file.clone()) {
if !je.sm.ensure_source_file_source_present(&lines.file) {
return vec![];
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ impl CodeSuggestion {
assert!(!lines.lines.is_empty() || bounding_span.is_dummy());

// We can't splice anything if the source is unavailable.
if !sm.ensure_source_file_source_present(lines.file.clone()) {
if !sm.ensure_source_file_source_present(&lines.file) {
return None;
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
// All of this logic ensures that the final result of deserialization is a 'normal'
// Span that can be used without any additional trouble.
let metadata_index = {
// Introduce a new scope so that we drop the 'lock()' temporary
match &*source_file.external_src.lock() {
// Introduce a new scope so that we drop the 'read()' temporary
match &*source_file.external_src.read() {
ExternalSource::Foreign { metadata_index, .. } => *metadata_index,
src => panic!("Unexpected external source {src:?}"),
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/on_disk_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
let len = BytePos::decode(decoder);

let file_lo = decoder.file_index_to_file(file_lo_index);
let lo = file_lo.lines(|lines| lines[line_lo - 1] + col_lo);
let lo = file_lo.lines()[line_lo - 1] + col_lo;
let lo = file_lo.absolute_position(lo);
let hi = lo + len;

Expand Down
9 changes: 5 additions & 4 deletions compiler/rustc_query_system/src/ich/impls_syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {

src_hash.hash_stable(hcx, hasher);

// We are always in `Lines` form by the time we reach here.
assert!(self.lines.borrow().is_lines());
self.lines(|lines| {
{
// We are always in `Lines` form by the time we reach here.
assert!(self.lines.read().is_lines());
let lines = self.lines();
// We only hash the relative position within this source_file
lines.len().hash_stable(hcx, hasher);
for &line in lines.iter() {
line.hash_stable(hcx, hasher);
}
});
}

// We only hash the relative position within this source_file
multibyte_chars.len().hash_stable(hcx, hasher);
Expand Down
Loading

0 comments on commit dc98c3e

Please sign in to comment.