Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bcc6e63

Browse files
committedDec 10, 2018
Auto merge of #56614 - Zoxc:query-perf2, r=<try>
Replace LockCell with atomic types Split from #56509 r? @michaelwoerister
2 parents 3a75e80 + ed78d93 commit bcc6e63

File tree

6 files changed

+123
-175
lines changed

6 files changed

+123
-175
lines changed
 

‎src/librustc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#![feature(trusted_len)]
6565
#![feature(vec_remove_item)]
6666
#![feature(step_trait)]
67+
#![feature(stmt_expr_attributes)]
6768
#![feature(integer_atomics)]
6869
#![feature(test)]
6970
#![feature(in_band_lifetimes)]

‎src/librustc/session/mod.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ use util::common::{duration_to_secs_str, ErrorReported};
2626
use util::common::ProfileQueriesMsg;
2727

2828
use rustc_data_structures::base_n;
29-
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
29+
use rustc_data_structures::sync::{
30+
self, Lrc, Lock, OneThread, Once, RwLock, AtomicU64, AtomicUsize, AtomicBool, Ordering,
31+
Ordering::SeqCst,
32+
};
3033

3134
use errors::{self, DiagnosticBuilder, DiagnosticId, Applicability};
3235
use errors::emitter::{Emitter, EmitterWriter};
@@ -51,7 +54,6 @@ use std::io::Write;
5154
use std::path::{Path, PathBuf};
5255
use std::time::Duration;
5356
use std::sync::mpsc;
54-
use std::sync::atomic::{AtomicUsize, Ordering};
5557

5658
mod code_stats;
5759
pub mod config;
@@ -142,15 +144,15 @@ pub struct Session {
142144
/// If -zfuel=crate=n is specified, Some(crate).
143145
optimization_fuel_crate: Option<String>,
144146
/// If -zfuel=crate=n is specified, initially set to n. Otherwise 0.
145-
optimization_fuel_limit: LockCell<u64>,
147+
optimization_fuel_limit: AtomicU64,
146148
/// We're rejecting all further optimizations.
147-
out_of_fuel: LockCell<bool>,
149+
out_of_fuel: AtomicBool,
148150

149151
// The next two are public because the driver needs to read them.
150152
/// If -zprint-fuel=crate, Some(crate).
151153
pub print_fuel_crate: Option<String>,
152154
/// Always set to zero and incremented so that we can print fuel expended by a crate.
153-
pub print_fuel: LockCell<u64>,
155+
pub print_fuel: AtomicU64,
154156

155157
/// Loaded up early on in the initialization of this `Session` to avoid
156158
/// false positives about a job server in our environment.
@@ -859,32 +861,43 @@ impl Session {
859861
self.perf_stats.normalize_projection_ty.load(Ordering::Relaxed));
860862
}
861863

862-
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
863-
/// This expends fuel if applicable, and records fuel if applicable.
864-
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
864+
#[inline(never)]
865+
#[cold]
866+
pub fn consider_optimizing_cold<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
865867
let mut ret = true;
866868
if let Some(ref c) = self.optimization_fuel_crate {
867869
if c == crate_name {
868870
assert_eq!(self.query_threads(), 1);
869-
let fuel = self.optimization_fuel_limit.get();
871+
let fuel = self.optimization_fuel_limit.load(SeqCst);
870872
ret = fuel != 0;
871-
if fuel == 0 && !self.out_of_fuel.get() {
873+
if fuel == 0 && !self.out_of_fuel.load(SeqCst) {
872874
eprintln!("optimization-fuel-exhausted: {}", msg());
873-
self.out_of_fuel.set(true);
875+
self.out_of_fuel.store(true, SeqCst);
874876
} else if fuel > 0 {
875-
self.optimization_fuel_limit.set(fuel - 1);
877+
self.optimization_fuel_limit.store(fuel - 1, SeqCst);
876878
}
877879
}
878880
}
879881
if let Some(ref c) = self.print_fuel_crate {
880882
if c == crate_name {
881883
assert_eq!(self.query_threads(), 1);
882-
self.print_fuel.set(self.print_fuel.get() + 1);
884+
self.print_fuel.store(self.print_fuel.load(SeqCst) + 1, SeqCst);
883885
}
884886
}
885887
ret
886888
}
887889

890+
/// We want to know if we're allowed to do an optimization for crate foo from -z fuel=foo=n.
891+
/// This expends fuel if applicable, and records fuel if applicable.
892+
#[inline(always)]
893+
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
894+
if likely!(self.optimization_fuel_crate.is_none() && self.print_fuel_crate.is_none()) {
895+
true
896+
} else {
897+
self.consider_optimizing_cold(crate_name, msg)
898+
}
899+
}
900+
888901
/// Returns the number of query threads that should be used for this
889902
/// compilation
890903
pub fn query_threads_from_opts(opts: &config::Options) -> usize {
@@ -1121,9 +1134,9 @@ pub fn build_session_(
11211134

11221135
let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
11231136
let optimization_fuel_limit =
1124-
LockCell::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
1137+
AtomicU64::new(sopts.debugging_opts.fuel.as_ref().map(|i| i.1).unwrap_or(0));
11251138
let print_fuel_crate = sopts.debugging_opts.print_fuel.clone();
1126-
let print_fuel = LockCell::new(0);
1139+
let print_fuel = AtomicU64::new(0);
11271140

11281141
let working_dir = env::current_dir().unwrap_or_else(|e|
11291142
p_s.span_diagnostic
@@ -1182,7 +1195,7 @@ pub fn build_session_(
11821195
optimization_fuel_limit,
11831196
print_fuel_crate,
11841197
print_fuel,
1185-
out_of_fuel: LockCell::new(false),
1198+
out_of_fuel: AtomicBool::new(false),
11861199
// Note that this is unsafe because it may misinterpret file descriptors
11871200
// on Unix as jobserver file descriptors. We hopefully execute this near
11881201
// the beginning of the process though to ensure we don't get false

‎src/librustc_data_structures/lib.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@
3030
#![feature(allow_internal_unstable)]
3131
#![feature(vec_resize_with)]
3232
#![feature(hash_raw_entry)]
33+
#![feature(stmt_expr_attributes)]
34+
#![feature(core_intrinsics)]
35+
#![feature(integer_atomics)]
3336

3437
#![cfg_attr(unix, feature(libc))]
3538
#![cfg_attr(test, feature(test))]
@@ -58,6 +61,26 @@ extern crate rustc_cratesio_shim;
5861

5962
pub use rustc_serialize::hex::ToHex;
6063

64+
#[macro_export]
65+
macro_rules! likely {
66+
($e:expr) => {
67+
#[allow(unused_unsafe)]
68+
{
69+
unsafe { std::intrinsics::likely($e) }
70+
}
71+
}
72+
}
73+
74+
#[macro_export]
75+
macro_rules! unlikely {
76+
($e:expr) => {
77+
#[allow(unused_unsafe)]
78+
{
79+
unsafe { std::intrinsics::unlikely($e) }
80+
}
81+
}
82+
}
83+
6184
pub mod macros;
6285
pub mod svh;
6386
pub mod base_n;

‎src/librustc_data_structures/sync.rs

Lines changed: 61 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@
2020
//! It internally uses `parking_lot::RwLock` if cfg!(parallel_queries) is true,
2121
//! `RefCell` otherwise.
2222
//!
23-
//! `LockCell` is a thread safe version of `Cell`, with `set` and `get` operations.
24-
//! It can never deadlock. It uses `Cell` when
25-
//! cfg!(parallel_queries) is false, otherwise it is a `Lock`.
26-
//!
2723
//! `MTLock` is a mutex which disappears if cfg!(parallel_queries) is false.
2824
//!
2925
//! `MTRef` is a immutable reference if cfg!(parallel_queries), and an mutable reference otherwise.
@@ -33,11 +29,7 @@
3329
3430
use std::collections::HashMap;
3531
use std::hash::{Hash, BuildHasher};
36-
use std::cmp::Ordering;
3732
use std::marker::PhantomData;
38-
use std::fmt::Debug;
39-
use std::fmt::Formatter;
40-
use std::fmt;
4133
use std::ops::{Deref, DerefMut};
4234
use owning_ref::{Erased, OwningRef};
4335

@@ -64,6 +56,9 @@ pub fn serial_scope<F, R>(f: F) -> R
6456
f(&SerialScope)
6557
}
6658

59+
pub use std::sync::atomic::Ordering::SeqCst;
60+
pub use std::sync::atomic::Ordering;
61+
6762
cfg_if! {
6863
if #[cfg(not(parallel_queries))] {
6964
pub auto trait Send {}
@@ -79,6 +74,62 @@ cfg_if! {
7974
}
8075
}
8176

77+
use std::ops::Add;
78+
79+
#[derive(Debug)]
80+
pub struct Atomic<T: Copy>(Cell<T>);
81+
82+
impl<T: Copy> Atomic<T> {
83+
pub fn new(v: T) -> Self {
84+
Atomic(Cell::new(v))
85+
}
86+
}
87+
88+
impl<T: Copy + PartialEq> Atomic<T> {
89+
pub fn into_inner(self) -> T {
90+
self.0.into_inner()
91+
}
92+
93+
pub fn load(&self, _: Ordering) -> T {
94+
self.0.get()
95+
}
96+
97+
pub fn store(&self, val: T, _: Ordering) {
98+
self.0.set(val)
99+
}
100+
101+
pub fn swap(&self, val: T, _: Ordering) -> T {
102+
self.0.replace(val)
103+
}
104+
105+
pub fn compare_exchange(&self,
106+
current: T,
107+
new: T,
108+
_: Ordering,
109+
_: Ordering)
110+
-> Result<T, T> {
111+
let read = self.0.get();
112+
if read == current {
113+
self.0.set(new);
114+
Ok(read)
115+
} else {
116+
Err(read)
117+
}
118+
}
119+
}
120+
121+
impl<T: Add<Output=T> + Copy> Atomic<T> {
122+
pub fn fetch_add(&self, val: T, _: Ordering) -> T {
123+
let old = self.0.get();
124+
self.0.set(old + val);
125+
old
126+
}
127+
}
128+
129+
pub type AtomicUsize = Atomic<usize>;
130+
pub type AtomicBool = Atomic<bool>;
131+
pub type AtomicU64 = Atomic<u64>;
132+
82133
pub use self::serial_join as join;
83134
pub use self::serial_scope as scope;
84135

@@ -170,47 +221,6 @@ cfg_if! {
170221
MTLock(self.0.clone())
171222
}
172223
}
173-
174-
pub struct LockCell<T>(Cell<T>);
175-
176-
impl<T> LockCell<T> {
177-
#[inline(always)]
178-
pub fn new(inner: T) -> Self {
179-
LockCell(Cell::new(inner))
180-
}
181-
182-
#[inline(always)]
183-
pub fn into_inner(self) -> T {
184-
self.0.into_inner()
185-
}
186-
187-
#[inline(always)]
188-
pub fn set(&self, new_inner: T) {
189-
self.0.set(new_inner);
190-
}
191-
192-
#[inline(always)]
193-
pub fn get(&self) -> T where T: Copy {
194-
self.0.get()
195-
}
196-
197-
#[inline(always)]
198-
pub fn set_mut(&mut self, new_inner: T) {
199-
self.0.set(new_inner);
200-
}
201-
202-
#[inline(always)]
203-
pub fn get_mut(&mut self) -> T where T: Copy {
204-
self.0.get()
205-
}
206-
}
207-
208-
impl<T> LockCell<Option<T>> {
209-
#[inline(always)]
210-
pub fn take(&self) -> Option<T> {
211-
unsafe { (*self.0.as_ptr()).take() }
212-
}
213-
}
214224
} else {
215225
pub use std::marker::Send as Send;
216226
pub use std::marker::Sync as Sync;
@@ -223,6 +233,8 @@ cfg_if! {
223233
pub use parking_lot::MutexGuard as LockGuard;
224234
pub use parking_lot::MappedMutexGuard as MappedLockGuard;
225235

236+
pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU64};
237+
226238
pub use std::sync::Arc as Lrc;
227239
pub use std::sync::Weak as Weak;
228240

@@ -288,47 +300,6 @@ cfg_if! {
288300
v.erase_send_sync_owner()
289301
}}
290302
}
291-
292-
pub struct LockCell<T>(Lock<T>);
293-
294-
impl<T> LockCell<T> {
295-
#[inline(always)]
296-
pub fn new(inner: T) -> Self {
297-
LockCell(Lock::new(inner))
298-
}
299-
300-
#[inline(always)]
301-
pub fn into_inner(self) -> T {
302-
self.0.into_inner()
303-
}
304-
305-
#[inline(always)]
306-
pub fn set(&self, new_inner: T) {
307-
*self.0.lock() = new_inner;
308-
}
309-
310-
#[inline(always)]
311-
pub fn get(&self) -> T where T: Copy {
312-
*self.0.lock()
313-
}
314-
315-
#[inline(always)]
316-
pub fn set_mut(&mut self, new_inner: T) {
317-
*self.0.get_mut() = new_inner;
318-
}
319-
320-
#[inline(always)]
321-
pub fn get_mut(&mut self) -> T where T: Copy {
322-
*self.0.get_mut()
323-
}
324-
}
325-
326-
impl<T> LockCell<Option<T>> {
327-
#[inline(always)]
328-
pub fn take(&self) -> Option<T> {
329-
self.0.lock().take()
330-
}
331-
}
332303
}
333304
}
334305

@@ -476,65 +447,6 @@ impl<T> Once<T> {
476447
}
477448
}
478449

479-
impl<T: Copy + Debug> Debug for LockCell<T> {
480-
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
481-
f.debug_struct("LockCell")
482-
.field("value", &self.get())
483-
.finish()
484-
}
485-
}
486-
487-
impl<T:Default> Default for LockCell<T> {
488-
/// Creates a `LockCell<T>`, with the `Default` value for T.
489-
#[inline]
490-
fn default() -> LockCell<T> {
491-
LockCell::new(Default::default())
492-
}
493-
}
494-
495-
impl<T:PartialEq + Copy> PartialEq for LockCell<T> {
496-
#[inline]
497-
fn eq(&self, other: &LockCell<T>) -> bool {
498-
self.get() == other.get()
499-
}
500-
}
501-
502-
impl<T:Eq + Copy> Eq for LockCell<T> {}
503-
504-
impl<T:PartialOrd + Copy> PartialOrd for LockCell<T> {
505-
#[inline]
506-
fn partial_cmp(&self, other: &LockCell<T>) -> Option<Ordering> {
507-
self.get().partial_cmp(&other.get())
508-
}
509-
510-
#[inline]
511-
fn lt(&self, other: &LockCell<T>) -> bool {
512-
self.get() < other.get()
513-
}
514-
515-
#[inline]
516-
fn le(&self, other: &LockCell<T>) -> bool {
517-
self.get() <= other.get()
518-
}
519-
520-
#[inline]
521-
fn gt(&self, other: &LockCell<T>) -> bool {
522-
self.get() > other.get()
523-
}
524-
525-
#[inline]
526-
fn ge(&self, other: &LockCell<T>) -> bool {
527-
self.get() >= other.get()
528-
}
529-
}
530-
531-
impl<T:Ord + Copy> Ord for LockCell<T> {
532-
#[inline]
533-
fn cmp(&self, other: &LockCell<T>) -> Ordering {
534-
self.get().cmp(&other.get())
535-
}
536-
}
537-
538450
#[derive(Debug)]
539451
pub struct Lock<T>(InnerLock<T>);
540452

‎src/librustc_driver/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#![feature(set_stdio)]
2828
#![feature(rustc_stack_internals)]
2929
#![feature(no_debug)]
30+
#![feature(integer_atomics)]
3031

3132
#![recursion_limit="256"]
3233

@@ -78,7 +79,7 @@ use pretty::{PpMode, UserIdentifiedItem};
7879
use rustc_resolve as resolve;
7980
use rustc_save_analysis as save;
8081
use rustc_save_analysis::DumpHandler;
81-
use rustc_data_structures::sync::{self, Lrc};
82+
use rustc_data_structures::sync::{self, Lrc, Ordering::SeqCst};
8283
use rustc_data_structures::OnDrop;
8384
use rustc::session::{self, config, Session, build_session, CompileResult};
8485
use rustc::session::CompileIncomplete;
@@ -954,7 +955,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
954955
let sess = state.session;
955956
eprintln!("Fuel used by {}: {}",
956957
sess.print_fuel_crate.as_ref().unwrap(),
957-
sess.print_fuel.get());
958+
sess.print_fuel.load(SeqCst));
958959
}
959960
}
960961
control

‎src/librustc_errors/lib.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,13 @@ use self::Level::*;
3636

3737
use emitter::{Emitter, EmitterWriter};
3838

39-
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell};
39+
use rustc_data_structures::sync::{self, Lrc, Lock, AtomicUsize, AtomicBool, SeqCst};
4040
use rustc_data_structures::fx::FxHashSet;
4141
use rustc_data_structures::stable_hasher::StableHasher;
4242

4343
use std::borrow::Cow;
4444
use std::cell::Cell;
4545
use std::{error, fmt};
46-
use std::sync::atomic::AtomicUsize;
47-
use std::sync::atomic::Ordering::SeqCst;
4846
use std::panic;
4947

5048
use termcolor::{ColorSpec, Color};
@@ -281,7 +279,7 @@ pub struct Handler {
281279

282280
err_count: AtomicUsize,
283281
emitter: Lock<Box<dyn Emitter + sync::Send>>,
284-
continue_after_error: LockCell<bool>,
282+
continue_after_error: AtomicBool,
285283
delayed_span_bugs: Lock<Vec<Diagnostic>>,
286284

287285
// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
@@ -380,7 +378,7 @@ impl Handler {
380378
flags,
381379
err_count: AtomicUsize::new(0),
382380
emitter: Lock::new(e),
383-
continue_after_error: LockCell::new(true),
381+
continue_after_error: AtomicBool::new(true),
384382
delayed_span_bugs: Lock::new(Vec::new()),
385383
taught_diagnostics: Default::default(),
386384
emitted_diagnostic_codes: Default::default(),
@@ -389,7 +387,7 @@ impl Handler {
389387
}
390388

391389
pub fn set_continue_after_error(&self, continue_after_error: bool) {
392-
self.continue_after_error.set(continue_after_error);
390+
self.continue_after_error.store(continue_after_error, SeqCst);
393391
}
394392

395393
/// Resets the diagnostic error count as well as the cached emitted diagnostics.
@@ -668,7 +666,7 @@ impl Handler {
668666
let mut db = DiagnosticBuilder::new(self, lvl, msg);
669667
db.set_span(msp.clone());
670668
db.emit();
671-
if !self.continue_after_error.get() {
669+
if !self.continue_after_error.load(SeqCst) {
672670
self.abort_if_errors();
673671
}
674672
}
@@ -679,7 +677,7 @@ impl Handler {
679677
let mut db = DiagnosticBuilder::new_with_code(self, lvl, Some(code), msg);
680678
db.set_span(msp.clone());
681679
db.emit();
682-
if !self.continue_after_error.get() {
680+
if !self.continue_after_error.load(SeqCst) {
683681
self.abort_if_errors();
684682
}
685683
}

0 commit comments

Comments
 (0)
Please sign in to comment.