Skip to content

Commit b6ed349

Browse files
committed
Try AtomicPtrs
1 parent 91ecdb4 commit b6ed349

2 files changed

Lines changed: 31 additions & 28 deletions

File tree

compiler/rustc_middle/src/dep_graph/graph.rs

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::assert_matches;
22
use std::fmt::Debug;
33
use std::hash::Hash;
44
use std::sync::Arc;
5-
use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
5+
use std::sync::atomic::{AtomicPtr, AtomicU32, Ordering};
66

77
use rustc_data_structures::fingerprint::{Fingerprint, PackedFingerprint};
88
use rustc_data_structures::fx::FxHashSet;
@@ -54,8 +54,7 @@ pub enum QuerySideEffect {
5454

5555
#[derive(Clone)]
5656
pub struct DepGraph {
57-
is_in_sandbox: Arc<AtomicBool>,
58-
data: [Option<Arc<DepGraphData>>; 2],
57+
data: Arc<AtomicPtr<Option<DepGraphData>>>,
5958

6059
/// This field is used for assigning DepNodeIndices when running in
6160
/// non-incremental mode. Even in non-incremental mode we make sure that
@@ -170,31 +169,26 @@ impl DepGraph {
170169
}
171170

172171
DepGraph {
173-
data: [
174-
Some(Arc::new(DepGraphData {
175-
previous_work_products: prev_work_products,
176-
current,
177-
previous: prev_graph,
178-
colors,
179-
debug_loaded_from_disk: Default::default(),
180-
})),
181-
None,
182-
],
172+
data: Arc::new(AtomicPtr::new(Box::into_raw(Box::new(Some(DepGraphData {
173+
previous_work_products: prev_work_products,
174+
current,
175+
previous: prev_graph,
176+
colors,
177+
debug_loaded_from_disk: Default::default(),
178+
}))))),
183179
virtual_dep_node_index: Arc::new(AtomicU32::new(0)),
184-
is_in_sandbox: Default::default(),
185180
}
186181
}
187182

188183
pub fn new_disabled() -> DepGraph {
189184
DepGraph {
190-
data: [None, None],
185+
data: Arc::new(AtomicPtr::new(Box::into_raw(Box::new(None)))),
191186
virtual_dep_node_index: Arc::new(AtomicU32::new(0)),
192-
is_in_sandbox: Default::default(),
193187
}
194188
}
195189

196190
pub fn data(&self) -> Option<&DepGraphData> {
197-
self.data[self.is_in_sandbox.load(Ordering::Relaxed) as usize].as_deref()
191+
unsafe { self.data.load(Ordering::Relaxed).as_ref_unchecked().as_ref() }
198192
}
199193

200194
/// Returns `true` if we are actually building the full dep-graph, and `false` otherwise.
@@ -291,11 +285,12 @@ impl DepGraph {
291285

292286
pub fn with_sandbox(&self, op: impl FnOnce()) {
293287
self.with_query_deserialization(|| {
294-
self.is_in_sandbox.store(true, Ordering::Relaxed);
288+
let real_graph = self.data.swap(Box::into_raw(Box::new(None)), Ordering::Relaxed);
295289

296290
op();
297291

298-
self.is_in_sandbox.store(false, Ordering::Relaxed);
292+
let fake_graph = self.data.swap(real_graph, Ordering::Relaxed);
293+
unsafe { drop(Box::from_raw(fake_graph)) };
299294
});
300295
}
301296

compiler/rustc_middle/src/query/caches.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use std::sync::OnceLock;
2+
use std::sync::atomic::{AtomicPtr, Ordering};
3+
14
use rustc_data_structures::sharded::ShardedHashMap;
2-
use rustc_data_structures::sync::Lock;
35
pub use rustc_data_structures::vec_cache::VecCache;
46
use rustc_hir::def_id::LOCAL_CRATE;
57
use rustc_index::Idx;
@@ -98,12 +100,12 @@ where
98100
/// In-memory cache for queries whose key type only has one value (e.g. `()`).
99101
/// The cache therefore only needs to store one query return value.
100102
pub struct SingleCache<V> {
101-
cache: Lock<Option<(V, DepNodeIndex)>>,
103+
cache: AtomicPtr<OnceLock<(V, DepNodeIndex)>>,
102104
}
103105

104106
impl<V> Default for SingleCache<V> {
105107
fn default() -> Self {
106-
SingleCache { cache: Default::default() }
108+
SingleCache { cache: AtomicPtr::new(Box::into_raw(Box::new(Default::default()))) }
107109
}
108110
}
109111

@@ -116,27 +118,33 @@ where
116118

117119
#[inline(always)]
118120
fn lookup(&self, _key: &()) -> Option<(V, DepNodeIndex)> {
119-
self.cache.lock().clone()
121+
unsafe { self.cache.load(Ordering::Relaxed).as_ref_unchecked().get().copied() }
120122
}
121123

122124
#[inline]
123125
fn complete(&self, _key: (), value: V, index: DepNodeIndex) {
124-
*self.cache.lock() = Some((value, index))
126+
unsafe {
127+
self.cache.load(Ordering::Relaxed).as_ref_unchecked().set((value, index)).ok();
128+
}
125129
}
126130

127131
fn for_each(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
128-
if let Some(value) = self.cache.lock().clone() {
129-
f(&(), &value.0, value.1)
132+
unsafe {
133+
if let Some(value) = self.cache.load(Ordering::Relaxed).as_ref_unchecked().get() {
134+
f(&(), &value.0, value.1)
135+
}
130136
}
131137
}
132138

133139
fn len(&self) -> usize {
134-
self.cache.lock().is_some().into()
140+
unsafe { self.cache.load(Ordering::Relaxed).as_ref_unchecked().get().is_some().into() }
135141
}
136142

137143
fn invalidate(&self, selector: impl Fn(Self::Key) -> bool) {
138144
if selector(()) {
139-
*self.cache.lock() = None;
145+
let prev =
146+
self.cache.swap(Box::into_raw(Box::new(Default::default())), Ordering::Relaxed);
147+
unsafe { drop(Box::from_raw(prev)) }
140148
}
141149
}
142150
}

0 commit comments

Comments
 (0)