Skip to content

Commit dc98c3e

Browse files
committed
Auto merge of rust-lang#115418 - Zoxc:freeze-source, r=<try>
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 rust-lang#115401.
2 parents 7f0fa48 + f96fe5b commit dc98c3e

File tree

16 files changed

+295
-231
lines changed

16 files changed

+295
-231
lines changed

compiler/rustc_codegen_cranelift/src/debuginfo/line_info.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl DebugContext {
8181

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

8787
(file, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)

compiler/rustc_codegen_llvm/src/debuginfo/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ impl CodegenCx<'_, '_> {
263263
pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
264264
let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
265265
Ok(SourceFileAndLine { sf: file, line }) => {
266-
let line_pos = file.lines(|lines| lines[line]);
266+
let line_pos = file.lines()[line];
267267

268268
// Use 1-based indexing.
269269
let line = (line + 1) as u32;

compiler/rustc_data_structures/src/sync/freeze.rs

+57-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::sync::{AtomicBool, ReadGuard, RwLock, WriteGuard};
33
use crate::sync::{DynSend, DynSync};
44
use std::{
55
cell::UnsafeCell,
6+
intrinsics::likely,
67
marker::PhantomData,
78
ops::{Deref, DerefMut},
89
sync::atomic::Ordering,
@@ -27,7 +28,37 @@ unsafe impl<T: DynSync + DynSend> DynSync for FreezeLock<T> {}
2728
impl<T> FreezeLock<T> {
2829
#[inline]
2930
pub fn new(value: T) -> Self {
30-
Self { data: UnsafeCell::new(value), frozen: AtomicBool::new(false), lock: RwLock::new(()) }
31+
Self::with(value, false)
32+
}
33+
34+
#[inline]
35+
pub fn frozen(value: T) -> Self {
36+
Self::with(value, true)
37+
}
38+
39+
#[inline]
40+
pub fn with(value: T, frozen: bool) -> Self {
41+
Self {
42+
data: UnsafeCell::new(value),
43+
frozen: AtomicBool::new(frozen),
44+
lock: RwLock::new(()),
45+
}
46+
}
47+
48+
#[inline]
49+
pub fn is_frozen(&self) -> bool {
50+
self.frozen.load(Ordering::Acquire)
51+
}
52+
53+
/// Get the inner value if frozen.
54+
#[inline]
55+
pub fn get(&self) -> Option<&T> {
56+
if likely(self.frozen.load(Ordering::Acquire)) {
57+
// SAFETY: This is frozen so the data cannot be modified.
58+
unsafe { Some(&*self.data.get()) }
59+
} else {
60+
None
61+
}
3162
}
3263

3364
#[inline]
@@ -42,13 +73,25 @@ impl<T> FreezeLock<T> {
4273
}
4374
}
4475

76+
#[inline]
77+
pub fn borrow(&self) -> FreezeReadGuard<'_, T> {
78+
self.read()
79+
}
80+
4581
#[inline]
4682
#[track_caller]
4783
pub fn write(&self) -> FreezeWriteGuard<'_, T> {
48-
let _lock_guard = self.lock.write();
49-
// Use relaxed ordering since we're in the write lock.
50-
assert!(!self.frozen.load(Ordering::Relaxed), "still mutable");
51-
FreezeWriteGuard { _lock_guard, lock: self, marker: PhantomData }
84+
self.try_write().expect("still mutable")
85+
}
86+
87+
#[inline]
88+
pub fn try_write(&self) -> Option<FreezeWriteGuard<'_, T>> {
89+
if self.frozen.load(Ordering::Relaxed) {
90+
None
91+
} else {
92+
let _lock_guard = self.lock.write();
93+
Some(FreezeWriteGuard { _lock_guard, lock: self, marker: PhantomData })
94+
}
5295
}
5396

5497
#[inline]
@@ -90,6 +133,15 @@ pub struct FreezeWriteGuard<'a, T> {
90133
marker: PhantomData<&'a mut T>,
91134
}
92135

136+
impl<'a, T> FreezeWriteGuard<'a, T> {
137+
pub fn freeze(self) -> &'a T {
138+
self.lock.frozen.store(true, Ordering::Release);
139+
140+
// SAFETY: This is frozen so the data cannot be modified and shared access is sound.
141+
unsafe { &*self.lock.data.get() }
142+
}
143+
}
144+
93145
impl<'a, T: 'a> Deref for FreezeWriteGuard<'a, T> {
94146
type Target = T;
95147
#[inline]

compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ impl AnnotateSnippetEmitterWriter {
169169
.map(|line| {
170170
// Ensure the source file is present before we try
171171
// to load a string from it.
172-
source_map.ensure_source_file_source_present(file.clone());
172+
source_map.ensure_source_file_source_present(&file);
173173
(
174174
format!("{}", source_map.filename_for_diagnostics(&file.name)),
175175
source_string(file.clone(), &line),

compiler/rustc_errors/src/emitter.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,7 @@ impl EmitterWriter {
11931193
let will_be_emitted = |span: Span| {
11941194
!span.is_dummy() && {
11951195
let file = sm.lookup_source_file(span.hi());
1196-
sm.ensure_source_file_source_present(file)
1196+
sm.ensure_source_file_source_present(&file)
11971197
}
11981198
};
11991199

@@ -1388,7 +1388,7 @@ impl EmitterWriter {
13881388
// Print out the annotate source lines that correspond with the error
13891389
for annotated_file in annotated_files {
13901390
// we can't annotate anything if the source is unavailable.
1391-
if !sm.ensure_source_file_source_present(annotated_file.file.clone()) {
1391+
if !sm.ensure_source_file_source_present(&annotated_file.file) {
13921392
if !self.short_message {
13931393
// We'll just print an unannotated message.
13941394
for (annotation_id, line) in annotated_file.lines.iter().enumerate() {

compiler/rustc_errors/src/json.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ impl DiagnosticSpanLine {
558558
.span_to_lines(span)
559559
.map(|lines| {
560560
// We can't get any lines if the source is unavailable.
561-
if !je.sm.ensure_source_file_source_present(lines.file.clone()) {
561+
if !je.sm.ensure_source_file_source_present(&lines.file) {
562562
return vec![];
563563
}
564564

compiler/rustc_errors/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ impl CodeSuggestion {
273273
assert!(!lines.lines.is_empty() || bounding_span.is_dummy());
274274

275275
// We can't splice anything if the source is unavailable.
276-
if !sm.ensure_source_file_source_present(lines.file.clone()) {
276+
if !sm.ensure_source_file_source_present(&lines.file) {
277277
return None;
278278
}
279279

compiler/rustc_metadata/src/rmeta/encoder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,8 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SpanData {
280280
// All of this logic ensures that the final result of deserialization is a 'normal'
281281
// Span that can be used without any additional trouble.
282282
let metadata_index = {
283-
// Introduce a new scope so that we drop the 'lock()' temporary
284-
match &*source_file.external_src.lock() {
283+
// Introduce a new scope so that we drop the 'read()' temporary
284+
match &*source_file.external_src.read() {
285285
ExternalSource::Foreign { metadata_index, .. } => *metadata_index,
286286
src => panic!("Unexpected external source {src:?}"),
287287
}

compiler/rustc_middle/src/query/on_disk_cache.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
692692
let len = BytePos::decode(decoder);
693693

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

compiler/rustc_query_system/src/ich/impls_syntax.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,16 @@ impl<'a> HashStable<StableHashingContext<'a>> for SourceFile {
7979

8080
src_hash.hash_stable(hcx, hasher);
8181

82-
// We are always in `Lines` form by the time we reach here.
83-
assert!(self.lines.borrow().is_lines());
84-
self.lines(|lines| {
82+
{
83+
// We are always in `Lines` form by the time we reach here.
84+
assert!(self.lines.read().is_lines());
85+
let lines = self.lines();
8586
// We only hash the relative position within this source_file
8687
lines.len().hash_stable(hcx, hasher);
8788
for &line in lines.iter() {
8889
line.hash_stable(hcx, hasher);
8990
}
90-
});
91+
}
9192

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

0 commit comments

Comments
 (0)