Skip to content

Commit 05f4449

Browse files
committed
Use WokerLocal to avoid lock when checking features
1 parent 74da246 commit 05f4449

5 files changed

Lines changed: 50 additions & 17 deletions

File tree

compiler/rustc_driver_impl/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ use std::io::{self, IsTerminal, Read, Write};
2121
use std::panic::{self, PanicHookInfo};
2222
use std::path::{Path, PathBuf};
2323
use std::process::{Command, ExitCode, Stdio, Termination};
24+
use std::sync::OnceLock;
2425
use std::sync::atomic::{AtomicBool, Ordering};
25-
use std::sync::{Arc, OnceLock};
2626
use std::time::Instant;
2727
use std::{env, str};
2828

@@ -714,7 +714,7 @@ fn print_crate_info(
714714
let lint_store = crate::unerased_lint_store(sess);
715715
let registered_tools = rustc_resolve::registered_tools_ast(sess.dcx(), attrs);
716716
let features = rustc_feature::TrackedFeatures::new(
717-
Arc::clone(&sess.used_features),
717+
sess.used_features_weak(),
718718
rustc_expand::config::features(sess, attrs, crate_name),
719719
);
720720
let lint_levels = rustc_lint::LintLevelsBuilder::crate_root(

compiler/rustc_feature/src/unstable.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//! List of the unstable feature gates.
22
3+
use std::cell::RefCell;
34
use std::path::PathBuf;
4-
use std::sync::{Arc, Mutex};
5+
use std::sync::Weak;
56
use std::time::{SystemTime, UNIX_EPOCH};
67

78
use rustc_data_structures::fx::FxHashSet;
9+
use rustc_data_structures::sync::WorkerLocal;
810
use rustc_span::{Span, Symbol, sym};
911

1012
use super::{Feature, to_nonzero};
@@ -45,17 +47,19 @@ macro_rules! status_to_enum {
4547
/// "unused features" diagnostics.
4648
#[derive(Clone, Debug)]
4749
pub struct TrackedFeatures {
48-
used_features: Arc<Mutex<FxHashSet<Symbol>>>,
50+
used_features: Weak<WorkerLocal<RefCell<FxHashSet<Symbol>>>>,
4951
features: Features,
5052
}
5153

5254
impl TrackedFeatures {
53-
pub fn new(used_features: Arc<Mutex<FxHashSet<Symbol>>>, features: Features) -> Self {
55+
pub fn new(
56+
used_features: Weak<WorkerLocal<RefCell<FxHashSet<Symbol>>>>,
57+
features: Features,
58+
) -> Self {
5459
Self { used_features, features }
5560
}
5661

57-
pub fn unused_features(&self) -> Vec<(Symbol, Span)> {
58-
let used_features = self.used_features.lock().unwrap();
62+
pub fn unused_features(&self, used_features: &FxHashSet<Symbol>) -> Vec<(Symbol, Span)> {
5963
self.enabled_features_iter_stable_order()
6064
.filter(|(f, _)| {
6165
!used_features.contains(f)
@@ -72,7 +76,9 @@ impl TrackedFeatures {
7276

7377
/// Is the given feature enabled (via `#[feature(...)]`)?
7478
pub fn enabled(&self, feature: Symbol) -> bool {
75-
self.used_features.lock().unwrap().insert(feature);
79+
if let Some(used_features) = self.used_features.upgrade() {
80+
used_features.borrow_mut().insert(feature);
81+
}
7682
self.features.enabled(feature)
7783
}
7884

compiler/rustc_interface/src/passes.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -877,10 +877,8 @@ pub fn write_interface<'tcx>(tcx: TyCtxt<'tcx>) {
877877

878878
pub fn tracked_features_query<'tcx>(tcx: TyCtxt<'tcx>) -> &'tcx rustc_feature::TrackedFeatures {
879879
let features = tcx.features_query(());
880-
tcx.arena.alloc(rustc_feature::TrackedFeatures::new(
881-
Arc::clone(&tcx.sess.used_features),
882-
features.clone(),
883-
))
880+
tcx.arena
881+
.alloc(rustc_feature::TrackedFeatures::new(tcx.sess.used_features_weak(), features.clone()))
884882
}
885883

886884
pub static DEFAULT_QUERY_PROVIDERS: LazyLock<Providers> = LazyLock::new(|| {

compiler/rustc_middle/src/ty/context.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1678,7 +1678,8 @@ impl<'tcx> TyCtxt<'tcx> {
16781678
}
16791679

16801680
pub fn finish(self) {
1681-
for (feature, span) in self.features().unused_features() {
1681+
let used_features = self.sess.take_used_features();
1682+
for (feature, span) in self.features().unused_features(&used_features) {
16821683
self.node_span_lint(
16831684
rustc_session::lint::builtin::UNUSED_FEATURES,
16841685
CRATE_HIR_ID,

compiler/rustc_session/src/session.rs

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
use std::any::Any;
2+
use std::cell::RefCell;
23
use std::path::PathBuf;
34
use std::str::FromStr;
45
use std::sync::atomic::AtomicBool;
5-
use std::sync::{Arc, Mutex};
6+
use std::sync::{Arc, Weak};
67
use std::{env, io};
78

89
use rand::{RngCore, rng};
910
use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
1011
use rustc_data_structures::flock;
1112
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
1213
use rustc_data_structures::profiling::{SelfProfiler, SelfProfilerRef};
13-
use rustc_data_structures::sync::{DynSend, DynSync, Lock, MappedReadGuard, ReadGuard, RwLock};
14+
use rustc_data_structures::sync::{
15+
DynSend, DynSync, Lock, MappedReadGuard, ReadGuard, RwLock, WorkerLocal,
16+
};
1417
use rustc_errors::annotate_snippet_emitter_writer::AnnotateSnippetEmitter;
1518
use rustc_errors::codes::*;
1619
use rustc_errors::emitter::{DynEmitter, HumanReadableErrorType, OutputTheme, stderr_destination};
@@ -159,7 +162,8 @@ pub struct Session {
159162
/// with its own implementations.
160163
pub replaced_intrinsics: FxHashSet<Symbol>,
161164

162-
pub used_features: Arc<Mutex<FxHashSet<Symbol>>>,
165+
pub used_features: Lock<Option<Arc<WorkerLocal<RefCell<FxHashSet<Symbol>>>>>>,
166+
used_features_weak: Weak<WorkerLocal<RefCell<FxHashSet<Symbol>>>>,
163167
}
164168

165169
#[derive(Clone, Copy)]
@@ -194,6 +198,27 @@ impl Session {
194198
self.miri_unleashed_features.lock().push((span, feature_gate));
195199
}
196200

201+
pub fn used_features_weak(&self) -> Weak<WorkerLocal<RefCell<FxHashSet<Symbol>>>> {
202+
self.used_features_weak.clone()
203+
}
204+
205+
// Collect used features into a single set from all threads.
206+
#[allow(rustc::potential_query_instability)]
207+
pub fn take_used_features(&self) -> FxHashSet<Symbol> {
208+
let used_features = self.used_features.lock().take().expect("used_features must be set");
209+
210+
let mut result = FxHashSet::default();
211+
for set in Arc::try_unwrap(used_features)
212+
.ok()
213+
.expect("used_features has outstanding strong references")
214+
.into_inner()
215+
{
216+
result.extend(set.take());
217+
}
218+
219+
result
220+
}
221+
197222
pub fn local_crate_source_file(&self) -> Option<RealFileName> {
198223
Some(
199224
self.source_map()
@@ -1066,6 +1091,8 @@ pub fn build_session(
10661091

10671092
let timings = TimingSectionHandler::new(sopts.json_timings);
10681093

1094+
let used_features = Arc::new(WorkerLocal::new(|_| RefCell::new(FxHashSet::default())));
1095+
let used_features_weak = Arc::downgrade(&used_features);
10691096
let sess = Session {
10701097
target,
10711098
host,
@@ -1090,7 +1117,8 @@ pub fn build_session(
10901117
host_filesearch,
10911118
invocation_temp,
10921119
replaced_intrinsics: FxHashSet::default(), // filled by `run_compiler`
1093-
used_features: Arc::new(Mutex::new(FxHashSet::default())),
1120+
used_features: Lock::new(Some(used_features)),
1121+
used_features_weak,
10941122
};
10951123

10961124
validate_commandline_args_with_session_available(&sess);

0 commit comments

Comments
 (0)