Skip to content

Commit 6645a93

Browse files
committed
Auto merge of #115711 - Zoxc:freeze-cstore, r=oli-obk
Use `FreezeLock` for `CStore` This uses `FreezeLock` to protect the `CStore`. `FreezeReadGuard` and `FreezeWriteGuard` are changed to support a `map` operation. r? `@oli-obk`
2 parents 01ce2d0 + 1d8fdc0 commit 6645a93

File tree

8 files changed

+63
-38
lines changed

8 files changed

+63
-38
lines changed

compiler/rustc_data_structures/src/sync/freeze.rs

+45-16
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{
66
intrinsics::likely,
77
marker::PhantomData,
88
ops::{Deref, DerefMut},
9+
ptr::NonNull,
910
sync::atomic::Ordering,
1011
};
1112

@@ -79,7 +80,7 @@ impl<T> FreezeLock<T> {
7980
} else {
8081
Some(self.lock.read())
8182
},
82-
lock: self,
83+
data: unsafe { NonNull::new_unchecked(self.data.get()) },
8384
}
8485
}
8586

@@ -101,7 +102,12 @@ impl<T> FreezeLock<T> {
101102
if self.frozen.load(Ordering::Relaxed) {
102103
None
103104
} else {
104-
Some(FreezeWriteGuard { _lock_guard, lock: self, marker: PhantomData })
105+
Some(FreezeWriteGuard {
106+
_lock_guard,
107+
data: unsafe { NonNull::new_unchecked(self.data.get()) },
108+
frozen: &self.frozen,
109+
marker: PhantomData,
110+
})
105111
}
106112
}
107113

@@ -120,52 +126,75 @@ impl<T> FreezeLock<T> {
120126

121127
/// A guard holding shared access to a `FreezeLock` which is in a locked state or frozen.
122128
#[must_use = "if unused the FreezeLock may immediately unlock"]
123-
pub struct FreezeReadGuard<'a, T> {
129+
pub struct FreezeReadGuard<'a, T: ?Sized> {
124130
_lock_guard: Option<ReadGuard<'a, ()>>,
125-
lock: &'a FreezeLock<T>,
131+
data: NonNull<T>,
126132
}
127133

128-
impl<'a, T: 'a> Deref for FreezeReadGuard<'a, T> {
134+
impl<'a, T: ?Sized + 'a> Deref for FreezeReadGuard<'a, T> {
129135
type Target = T;
130136
#[inline]
131137
fn deref(&self) -> &T {
132-
// SAFETY: If `lock` is not frozen, `_lock_guard` holds the lock to the `UnsafeCell` so
133-
// this has shared access until the `FreezeReadGuard` is dropped. If `lock` is frozen,
138+
// SAFETY: If the lock is not frozen, `_lock_guard` holds the lock to the `UnsafeCell` so
139+
// this has shared access until the `FreezeReadGuard` is dropped. If the lock is frozen,
134140
// the data cannot be modified and shared access is sound.
135-
unsafe { &*self.lock.data.get() }
141+
unsafe { &*self.data.as_ptr() }
142+
}
143+
}
144+
145+
impl<'a, T: ?Sized> FreezeReadGuard<'a, T> {
146+
#[inline]
147+
pub fn map<U: ?Sized>(this: Self, f: impl FnOnce(&T) -> &U) -> FreezeReadGuard<'a, U> {
148+
FreezeReadGuard { data: NonNull::from(f(&*this)), _lock_guard: this._lock_guard }
136149
}
137150
}
138151

139152
/// A guard holding mutable access to a `FreezeLock` which is in a locked state or frozen.
140153
#[must_use = "if unused the FreezeLock may immediately unlock"]
141-
pub struct FreezeWriteGuard<'a, T> {
154+
pub struct FreezeWriteGuard<'a, T: ?Sized> {
142155
_lock_guard: WriteGuard<'a, ()>,
143-
lock: &'a FreezeLock<T>,
156+
frozen: &'a AtomicBool,
157+
data: NonNull<T>,
144158
marker: PhantomData<&'a mut T>,
145159
}
146160

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

151165
// SAFETY: This is frozen so the data cannot be modified and shared access is sound.
152-
unsafe { &*self.lock.data.get() }
166+
unsafe { &*self.data.as_ptr() }
167+
}
168+
}
169+
170+
impl<'a, T: ?Sized> FreezeWriteGuard<'a, T> {
171+
#[inline]
172+
pub fn map<U: ?Sized>(
173+
mut this: Self,
174+
f: impl FnOnce(&mut T) -> &mut U,
175+
) -> FreezeWriteGuard<'a, U> {
176+
FreezeWriteGuard {
177+
data: NonNull::from(f(&mut *this)),
178+
_lock_guard: this._lock_guard,
179+
frozen: this.frozen,
180+
marker: PhantomData,
181+
}
153182
}
154183
}
155184

156-
impl<'a, T: 'a> Deref for FreezeWriteGuard<'a, T> {
185+
impl<'a, T: ?Sized + 'a> Deref for FreezeWriteGuard<'a, T> {
157186
type Target = T;
158187
#[inline]
159188
fn deref(&self) -> &T {
160189
// SAFETY: `self._lock_guard` holds the lock to the `UnsafeCell` so this has shared access.
161-
unsafe { &*self.lock.data.get() }
190+
unsafe { &*self.data.as_ptr() }
162191
}
163192
}
164193

165-
impl<'a, T: 'a> DerefMut for FreezeWriteGuard<'a, T> {
194+
impl<'a, T: ?Sized + 'a> DerefMut for FreezeWriteGuard<'a, T> {
166195
#[inline]
167196
fn deref_mut(&mut self) -> &mut T {
168197
// SAFETY: `self._lock_guard` holds the lock to the `UnsafeCell` so this has mutable access.
169-
unsafe { &mut *self.lock.data.get() }
198+
unsafe { &mut *self.data.as_ptr() }
170199
}
171200
}

compiler/rustc_interface/src/passes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ fn resolver_for_lowering<'tcx>(
584584
let krate = configure_and_expand(krate, &pre_configured_attrs, &mut resolver);
585585

586586
// Make sure we don't mutate the cstore from here on.
587-
tcx.untracked().cstore.leak();
587+
tcx.untracked().cstore.freeze();
588588

589589
let ty::ResolverOutputs {
590590
global_ctxt: untracked_resolutions,

compiler/rustc_interface/src/queries.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ use rustc_codegen_ssa::traits::CodegenBackend;
77
use rustc_codegen_ssa::CodegenResults;
88
use rustc_data_structures::steal::Steal;
99
use rustc_data_structures::svh::Svh;
10-
use rustc_data_structures::sync::{
11-
AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, RwLock, WorkerLocal,
12-
};
10+
use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, Lrc, OnceLock, WorkerLocal};
1311
use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE};
1412
use rustc_hir::definitions::Definitions;
1513
use rustc_incremental::DepGraphFuture;
@@ -195,7 +193,7 @@ impl<'tcx> Queries<'tcx> {
195193
self.compiler.register_lints.as_deref(),
196194
&pre_configured_attrs,
197195
));
198-
let cstore = RwLock::new(Box::new(CStore::new(
196+
let cstore = FreezeLock::new(Box::new(CStore::new(
199197
self.codegen_backend().metadata_loader(),
200198
stable_crate_id,
201199
)) as _);

compiler/rustc_metadata/src/creader.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_ast::expand::allocator::{alloc_error_handler_name, global_fn_name, All
88
use rustc_ast::{self as ast, *};
99
use rustc_data_structures::fx::FxHashSet;
1010
use rustc_data_structures::svh::Svh;
11-
use rustc_data_structures::sync::{MappedReadGuard, MappedWriteGuard, ReadGuard, WriteGuard};
11+
use rustc_data_structures::sync::{FreezeReadGuard, FreezeWriteGuard};
1212
use rustc_expand::base::SyntaxExtension;
1313
use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, StableCrateIdMap, LOCAL_CRATE};
1414
use rustc_hir::definitions::Definitions;
@@ -134,14 +134,14 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
134134
}
135135

136136
impl CStore {
137-
pub fn from_tcx(tcx: TyCtxt<'_>) -> MappedReadGuard<'_, CStore> {
138-
ReadGuard::map(tcx.untracked().cstore.read(), |cstore| {
137+
pub fn from_tcx(tcx: TyCtxt<'_>) -> FreezeReadGuard<'_, CStore> {
138+
FreezeReadGuard::map(tcx.untracked().cstore.read(), |cstore| {
139139
cstore.as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`")
140140
})
141141
}
142142

143-
pub fn from_tcx_mut(tcx: TyCtxt<'_>) -> MappedWriteGuard<'_, CStore> {
144-
WriteGuard::map(tcx.untracked().cstore.write(), |cstore| {
143+
pub fn from_tcx_mut(tcx: TyCtxt<'_>) -> FreezeWriteGuard<'_, CStore> {
144+
FreezeWriteGuard::map(tcx.untracked().cstore.write(), |cstore| {
145145
cstore.untracked_as_any().downcast_mut().expect("`tcx.cstore` is not a `CStore`")
146146
})
147147
}

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ macro_rules! provide_one {
131131
$tcx.ensure().crate_hash($def_id.krate);
132132
}
133133

134-
let cdata = rustc_data_structures::sync::MappedReadGuard::map(CStore::from_tcx($tcx), |c| {
134+
let cdata = rustc_data_structures::sync::FreezeReadGuard::map(CStore::from_tcx($tcx), |c| {
135135
c.get_crate_data($def_id.krate).cdata
136136
});
137137
let $cdata = crate::creader::CrateMetadataRef {
@@ -510,7 +510,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
510510
crates: |tcx, ()| {
511511
// The list of loaded crates is now frozen in query cache,
512512
// so make sure cstore is not mutably accessed from here on.
513-
tcx.untracked().cstore.leak();
513+
tcx.untracked().cstore.freeze();
514514
tcx.arena.alloc_from_iter(CStore::from_tcx(tcx).iter_crate_data().map(|(cnum, _)| cnum))
515515
},
516516
..*providers

compiler/rustc_middle/src/ty/context.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
3939
use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
4040
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
4141
use rustc_data_structures::steal::Steal;
42-
use rustc_data_structures::sync::{
43-
self, FreezeReadGuard, Lock, Lrc, MappedReadGuard, ReadGuard, WorkerLocal,
44-
};
42+
use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal};
4543
use rustc_data_structures::unord::UnordSet;
4644
use rustc_errors::{
4745
DecorateLint, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, MultiSpan,
@@ -995,8 +993,8 @@ impl<'tcx> TyCtxt<'tcx> {
995993
/// Note that this is *untracked* and should only be used within the query
996994
/// system if the result is otherwise tracked through queries
997995
#[inline]
998-
pub fn cstore_untracked(self) -> MappedReadGuard<'tcx, CrateStoreDyn> {
999-
ReadGuard::map(self.untracked.cstore.read(), |c| &**c)
996+
pub fn cstore_untracked(self) -> FreezeReadGuard<'tcx, CrateStoreDyn> {
997+
FreezeReadGuard::map(self.untracked.cstore.read(), |c| &**c)
1000998
}
1001999

10021000
/// Give out access to the untracked data without any sanity checks.

compiler/rustc_resolve/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArg
3434
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
3535
use rustc_data_structures::intern::Interned;
3636
use rustc_data_structures::steal::Steal;
37-
use rustc_data_structures::sync::{Lrc, MappedReadGuard};
37+
use rustc_data_structures::sync::{FreezeReadGuard, Lrc};
3838
use rustc_errors::{
3939
Applicability, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, SubdiagnosticMessage,
4040
};
@@ -1544,7 +1544,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15441544
))
15451545
}
15461546

1547-
fn cstore(&self) -> MappedReadGuard<'_, CStore> {
1547+
fn cstore(&self) -> FreezeReadGuard<'_, CStore> {
15481548
CStore::from_tcx(self.tcx)
15491549
}
15501550

@@ -1599,7 +1599,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
15991599
});
16001600

16011601
// Make sure we don't mutate the cstore from here on.
1602-
self.tcx.untracked().cstore.leak();
1602+
self.tcx.untracked().cstore.freeze();
16031603
}
16041604

16051605
fn traits_in_scope(

compiler/rustc_session/src/cstore.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::utils::NativeLibKind;
77
use crate::Session;
88
use rustc_ast as ast;
99
use rustc_data_structures::owned_slice::OwnedSlice;
10-
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock, RwLock};
10+
use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock};
1111
use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
1212
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
1313
use rustc_span::hygiene::{ExpnHash, ExpnId};
@@ -258,7 +258,7 @@ pub trait CrateStore: std::fmt::Debug {
258258
pub type CrateStoreDyn = dyn CrateStore + sync::DynSync + sync::DynSend;
259259

260260
pub struct Untracked {
261-
pub cstore: RwLock<Box<CrateStoreDyn>>,
261+
pub cstore: FreezeLock<Box<CrateStoreDyn>>,
262262
/// Reference span for definitions.
263263
pub source_span: AppendOnlyIndexVec<LocalDefId, Span>,
264264
pub definitions: FreezeLock<Definitions>,

0 commit comments

Comments
 (0)