Skip to content

Commit 6b12d36

Browse files
committed
Auto merge of #49882 - Zoxc:sync-misc2, r=michaelwoerister
More thread-safety changes r? @michaelwoerister
2 parents 186db76 + fe63637 commit 6b12d36

File tree

13 files changed

+159
-53
lines changed

13 files changed

+159
-53
lines changed

src/Cargo.lock

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/libarena/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@ version = "0.0.0"
77
name = "arena"
88
path = "lib.rs"
99
crate-type = ["dylib"]
10+
11+
[dependencies]
12+
rustc_data_structures = { path = "../librustc_data_structures" }

src/libarena/lib.rs

+71
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
#![allow(deprecated)]
3333

3434
extern crate alloc;
35+
extern crate rustc_data_structures;
36+
37+
use rustc_data_structures::sync::MTLock;
3538

3639
use std::cell::{Cell, RefCell};
3740
use std::cmp;
@@ -290,6 +293,8 @@ pub struct DroplessArena {
290293
chunks: RefCell<Vec<TypedArenaChunk<u8>>>,
291294
}
292295

296+
unsafe impl Send for DroplessArena {}
297+
293298
impl DroplessArena {
294299
pub fn new() -> DroplessArena {
295300
DroplessArena {
@@ -410,6 +415,72 @@ impl DroplessArena {
410415
}
411416
}
412417

418+
pub struct SyncTypedArena<T> {
419+
lock: MTLock<TypedArena<T>>,
420+
}
421+
422+
impl<T> SyncTypedArena<T> {
423+
#[inline(always)]
424+
pub fn new() -> SyncTypedArena<T> {
425+
SyncTypedArena {
426+
lock: MTLock::new(TypedArena::new())
427+
}
428+
}
429+
430+
#[inline(always)]
431+
pub fn alloc(&self, object: T) -> &mut T {
432+
// Extend the lifetime of the result since it's limited to the lock guard
433+
unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
434+
}
435+
436+
#[inline(always)]
437+
pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
438+
where
439+
T: Copy,
440+
{
441+
// Extend the lifetime of the result since it's limited to the lock guard
442+
unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
443+
}
444+
445+
#[inline(always)]
446+
pub fn clear(&mut self) {
447+
self.lock.get_mut().clear();
448+
}
449+
}
450+
451+
pub struct SyncDroplessArena {
452+
lock: MTLock<DroplessArena>,
453+
}
454+
455+
impl SyncDroplessArena {
456+
#[inline(always)]
457+
pub fn new() -> SyncDroplessArena {
458+
SyncDroplessArena {
459+
lock: MTLock::new(DroplessArena::new())
460+
}
461+
}
462+
463+
#[inline(always)]
464+
pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
465+
self.lock.lock().in_arena(ptr)
466+
}
467+
468+
#[inline(always)]
469+
pub fn alloc<T>(&self, object: T) -> &mut T {
470+
// Extend the lifetime of the result since it's limited to the lock guard
471+
unsafe { &mut *(self.lock.lock().alloc(object) as *mut T) }
472+
}
473+
474+
#[inline(always)]
475+
pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
476+
where
477+
T: Copy,
478+
{
479+
// Extend the lifetime of the result since it's limited to the lock guard
480+
unsafe { &mut *(self.lock.lock().alloc_slice(slice) as *mut [T]) }
481+
}
482+
}
483+
413484
#[cfg(test)]
414485
mod tests {
415486
extern crate test;

src/librustc/hir/map/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use hir::print::Nested;
3232
use hir::svh::Svh;
3333
use util::nodemap::{DefIdMap, FxHashMap};
3434

35-
use arena::TypedArena;
35+
use arena::SyncTypedArena;
3636
use std::io;
3737
use ty::TyCtxt;
3838

@@ -219,15 +219,15 @@ impl<'hir> MapEntry<'hir> {
219219
pub struct Forest {
220220
krate: Crate,
221221
pub dep_graph: DepGraph,
222-
inlined_bodies: TypedArena<Body>
222+
inlined_bodies: SyncTypedArena<Body>
223223
}
224224

225225
impl Forest {
226226
pub fn new(krate: Crate, dep_graph: &DepGraph) -> Forest {
227227
Forest {
228228
krate,
229229
dep_graph: dep_graph.clone(),
230-
inlined_bodies: TypedArena::new()
230+
inlined_bodies: SyncTypedArena::new()
231231
}
232232
}
233233

src/librustc/infer/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use errors::DiagnosticBuilder;
3737
use syntax_pos::{self, Span};
3838
use syntax_pos::symbol::InternedString;
3939
use util::nodemap::FxHashMap;
40-
use arena::DroplessArena;
40+
use arena::SyncDroplessArena;
4141

4242
use self::combine::CombineFields;
4343
use self::higher_ranked::HrMatchResult;
@@ -407,15 +407,15 @@ impl fmt::Display for FixupError {
407407
/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
408408
pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
409409
global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
410-
arena: DroplessArena,
410+
arena: SyncDroplessArena,
411411
fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
412412
}
413413

414414
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
415415
pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
416416
InferCtxtBuilder {
417417
global_tcx: self,
418-
arena: DroplessArena::new(),
418+
arena: SyncDroplessArena::new(),
419419
fresh_tables: None,
420420

421421
}

src/librustc/lint/context.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use self::TargetLint::*;
2828

2929
use std::slice;
30+
use rustc_data_structures::sync::{RwLock, ReadGuard};
3031
use lint::{EarlyLintPassObject, LateLintPassObject};
3132
use lint::{Level, Lint, LintId, LintPass, LintBuffer};
3233
use lint::builtin::BuiltinLintDiagnostics;
@@ -39,7 +40,6 @@ use ty::layout::{LayoutError, LayoutOf, TyLayout};
3940
use util::nodemap::FxHashMap;
4041

4142
use std::default::Default as StdDefault;
42-
use std::cell::{Ref, RefCell};
4343
use syntax::ast;
4444
use syntax::edition;
4545
use syntax_pos::{MultiSpan, Span};
@@ -78,7 +78,7 @@ pub struct LintStore {
7878

7979
pub struct LintSession<'a, PassObject> {
8080
/// Reference to the store of registered lints.
81-
lints: Ref<'a, LintStore>,
81+
lints: ReadGuard<'a, LintStore>,
8282

8383
/// Trait objects for each lint pass.
8484
passes: Option<Vec<PassObject>>,
@@ -336,7 +336,7 @@ impl<'a, PassObject: LintPassObject> LintSession<'a, PassObject> {
336336
/// Creates a new `LintSession`, by moving out the `LintStore`'s initial
337337
/// lint levels and pass objects. These can be restored using the `restore`
338338
/// method.
339-
fn new(store: &'a RefCell<LintStore>) -> LintSession<'a, PassObject> {
339+
fn new(store: &'a RwLock<LintStore>) -> LintSession<'a, PassObject> {
340340
let mut s = store.borrow_mut();
341341
let passes = PassObject::take_passes(&mut *s);
342342
drop(s);
@@ -347,7 +347,7 @@ impl<'a, PassObject: LintPassObject> LintSession<'a, PassObject> {
347347
}
348348

349349
/// Restores the levels back to the original lint store.
350-
fn restore(self, store: &RefCell<LintStore>) {
350+
fn restore(self, store: &RwLock<LintStore>) {
351351
drop(self.lints);
352352
let mut s = store.borrow_mut();
353353
PassObject::restore_passes(&mut *s, self.passes);

src/librustc/session/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use util::nodemap::{FxHashSet};
2626
use util::common::{duration_to_secs_str, ErrorReported};
2727
use util::common::ProfileQueriesMsg;
2828

29-
use rustc_data_structures::sync::{Lrc, Lock, LockCell, OneThread, Once};
29+
use rustc_data_structures::sync::{Lrc, Lock, LockCell, OneThread, Once, RwLock};
3030

3131
use syntax::ast::NodeId;
3232
use errors::{self, DiagnosticBuilder, DiagnosticId};
@@ -83,8 +83,8 @@ pub struct Session {
8383

8484
// FIXME: lint_store and buffered_lints are not thread-safe,
8585
// but are only used in a single thread
86-
pub lint_store: OneThread<RefCell<lint::LintStore>>,
87-
pub buffered_lints: OneThread<RefCell<Option<lint::LintBuffer>>>,
86+
pub lint_store: RwLock<lint::LintStore>,
87+
pub buffered_lints: Lock<Option<lint::LintBuffer>>,
8888

8989
/// Set of (DiagnosticId, Option<Span>, message) tuples tracking
9090
/// (sub)diagnostics that have been set once, but should not be set again,
@@ -1089,8 +1089,8 @@ pub fn build_session_(
10891089
default_sysroot,
10901090
local_crate_source_file,
10911091
working_dir,
1092-
lint_store: OneThread::new(RefCell::new(lint::LintStore::new())),
1093-
buffered_lints: OneThread::new(RefCell::new(Some(lint::LintBuffer::new()))),
1092+
lint_store: RwLock::new(lint::LintStore::new()),
1093+
buffered_lints: Lock::new(Some(lint::LintBuffer::new())),
10941094
one_time_diagnostics: RefCell::new(FxHashSet()),
10951095
plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
10961096
plugin_attributes: OneThread::new(RefCell::new(Vec::new())),

src/librustc/ty/context.rs

+18-18
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,11 @@ use rustc_data_structures::accumulate_vec::AccumulateVec;
5757
use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
5858
StableHasher, StableHasherResult,
5959
StableVec};
60-
use arena::{TypedArena, DroplessArena};
60+
use arena::{TypedArena, SyncDroplessArena};
6161
use rustc_data_structures::indexed_vec::IndexVec;
6262
use rustc_data_structures::sync::{Lrc, Lock};
6363
use std::any::Any;
6464
use std::borrow::Borrow;
65-
use std::cell::Cell;
6665
use std::cmp::Ordering;
6766
use std::collections::hash_map::{self, Entry};
6867
use std::hash::{Hash, Hasher};
@@ -83,14 +82,14 @@ use hir;
8382

8483
pub struct AllArenas<'tcx> {
8584
pub global: GlobalArenas<'tcx>,
86-
pub interner: DroplessArena,
85+
pub interner: SyncDroplessArena,
8786
}
8887

8988
impl<'tcx> AllArenas<'tcx> {
9089
pub fn new() -> Self {
9190
AllArenas {
9291
global: GlobalArenas::new(),
93-
interner: DroplessArena::new(),
92+
interner: SyncDroplessArena::new(),
9493
}
9594
}
9695
}
@@ -130,7 +129,7 @@ type InternedSet<'tcx, T> = Lock<FxHashSet<Interned<'tcx, T>>>;
130129

131130
pub struct CtxtInterners<'tcx> {
132131
/// The arena that types, regions, etc are allocated from
133-
arena: &'tcx DroplessArena,
132+
arena: &'tcx SyncDroplessArena,
134133

135134
/// Specifically use a speedy hash algorithm for these hash sets,
136135
/// they're accessed quite often.
@@ -147,7 +146,7 @@ pub struct CtxtInterners<'tcx> {
147146
}
148147

149148
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
150-
fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
149+
fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> {
151150
CtxtInterners {
152151
arena,
153152
type_: Default::default(),
@@ -174,10 +173,10 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
174173
return ty;
175174
}
176175
let global_interner = global_interners.map(|interners| {
177-
interners.type_.borrow_mut()
176+
(interners.type_.borrow_mut(), &interners.arena)
178177
});
179-
if let Some(ref interner) = global_interner {
180-
if let Some(&Interned(ty)) = interner.get(&st) {
178+
if let Some((ref type_, _)) = global_interner {
179+
if let Some(&Interned(ty)) = type_.get(&st) {
181180
return ty;
182181
}
183182
}
@@ -193,18 +192,18 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
193192
// determine that all contents are in the global tcx.
194193
// See comments on Lift for why we can't use that.
195194
if !flags.flags.intersects(ty::TypeFlags::KEEP_IN_LOCAL_TCX) {
196-
if let Some(interner) = global_interners {
195+
if let Some((mut type_, arena)) = global_interner {
197196
let ty_struct: TyS<'gcx> = unsafe {
198197
mem::transmute(ty_struct)
199198
};
200-
let ty: Ty<'gcx> = interner.arena.alloc(ty_struct);
201-
global_interner.unwrap().insert(Interned(ty));
199+
let ty: Ty<'gcx> = arena.alloc(ty_struct);
200+
type_.insert(Interned(ty));
202201
return ty;
203202
}
204203
} else {
205204
// Make sure we don't end up with inference
206205
// types/regions in the global tcx.
207-
if global_interners.is_none() {
206+
if global_interner.is_none() {
208207
drop(interner);
209208
bug!("Attempted to intern `{:?}` which contains \
210209
inference types/regions in the global type context",
@@ -915,9 +914,6 @@ pub struct GlobalCtxt<'tcx> {
915914
/// Data layout specification for the current target.
916915
pub data_layout: TargetDataLayout,
917916

918-
/// Used to prevent layout from recursing too deeply.
919-
pub layout_depth: Cell<usize>,
920-
921917
stability_interner: Lock<FxHashSet<&'tcx attr::Stability>>,
922918

923919
pub interpret_interner: InterpretInterner<'tcx>,
@@ -1292,7 +1288,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
12921288
crate_name: Symbol::intern(crate_name),
12931289
data_layout,
12941290
layout_interner: Lock::new(FxHashSet()),
1295-
layout_depth: Cell::new(0),
12961291
stability_interner: Lock::new(FxHashSet()),
12971292
interpret_interner: Default::default(),
12981293
tx_to_llvm_workers: Lock::new(tx),
@@ -1559,7 +1554,7 @@ impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
15591554
/// Call the closure with a local `TyCtxt` using the given arena.
15601555
pub fn enter_local<F, R>(
15611556
&self,
1562-
arena: &'tcx DroplessArena,
1557+
arena: &'tcx SyncDroplessArena,
15631558
f: F
15641559
) -> R
15651560
where
@@ -1574,6 +1569,7 @@ impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
15741569
let new_icx = ty::tls::ImplicitCtxt {
15751570
tcx,
15761571
query: icx.query.clone(),
1572+
layout_depth: icx.layout_depth,
15771573
};
15781574
ty::tls::enter_context(&new_icx, |new_icx| {
15791575
f(new_icx.tcx)
@@ -1768,6 +1764,9 @@ pub mod tls {
17681764
/// The current query job, if any. This is updated by start_job in
17691765
/// ty::maps::plumbing when executing a query
17701766
pub query: Option<Lrc<maps::QueryJob<'gcx>>>,
1767+
1768+
/// Used to prevent layout from recursing too deeply.
1769+
pub layout_depth: usize,
17711770
}
17721771

17731772
// A thread local value which stores a pointer to the current ImplicitCtxt
@@ -1853,6 +1852,7 @@ pub mod tls {
18531852
let icx = ImplicitCtxt {
18541853
tcx,
18551854
query: None,
1855+
layout_depth: 0,
18561856
};
18571857
enter_context(&icx, |_| {
18581858
f(tcx)

0 commit comments

Comments
 (0)