Skip to content

Commit 844bc65

Browse files
committed
Auto merge of #50235 - Zoxc:rayon, r=michaelwoerister
Add a Rayon thread pool r? @michaelwoerister
2 parents 6fb34bd + 4afdae6 commit 844bc65

File tree

22 files changed

+573
-357
lines changed

22 files changed

+573
-357
lines changed

src/Cargo.lock

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

src/librustc/hir/itemlikevisit.rs

+30
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,33 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V>
8888
self.visitor.visit_impl_item(impl_item);
8989
}
9090
}
91+
92+
/// A parallel variant of ItemLikeVisitor
93+
pub trait ParItemLikeVisitor<'hir> {
94+
fn visit_item(&self, item: &'hir Item);
95+
fn visit_trait_item(&self, trait_item: &'hir TraitItem);
96+
fn visit_impl_item(&self, impl_item: &'hir ImplItem);
97+
}
98+
99+
pub trait IntoVisitor<'hir> {
100+
type Visitor: Visitor<'hir>;
101+
fn into_visitor(&self) -> Self::Visitor;
102+
}
103+
104+
pub struct ParDeepVisitor<V>(pub V);
105+
106+
impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor<V>
107+
where V: IntoVisitor<'hir>
108+
{
109+
fn visit_item(&self, item: &'hir Item) {
110+
self.0.into_visitor().visit_item(item);
111+
}
112+
113+
fn visit_trait_item(&self, trait_item: &'hir TraitItem) {
114+
self.0.into_visitor().visit_trait_item(trait_item);
115+
}
116+
117+
fn visit_impl_item(&self, impl_item: &'hir ImplItem) {
118+
self.0.into_visitor().visit_impl_item(impl_item);
119+
}
120+
}

src/librustc/hir/mod.rs

+26
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use ty::AdtKind;
4848
use ty::maps::Providers;
4949

5050
use rustc_data_structures::indexed_vec;
51+
use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope};
5152

5253
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
5354
use std::collections::BTreeMap;
@@ -720,6 +721,31 @@ impl Crate {
720721
}
721722
}
722723

724+
/// A parallel version of visit_all_item_likes
725+
pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
726+
where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send
727+
{
728+
scope(|s| {
729+
s.spawn(|_| {
730+
par_iter(&self.items).for_each(|(_, item)| {
731+
visitor.visit_item(item);
732+
});
733+
});
734+
735+
s.spawn(|_| {
736+
par_iter(&self.trait_items).for_each(|(_, trait_item)| {
737+
visitor.visit_trait_item(trait_item);
738+
});
739+
});
740+
741+
s.spawn(|_| {
742+
par_iter(&self.impl_items).for_each(|(_, impl_item)| {
743+
visitor.visit_impl_item(impl_item);
744+
});
745+
});
746+
});
747+
}
748+
723749
pub fn body(&self, id: BodyId) -> &Body {
724750
&self.bodies[&id]
725751
}

src/librustc/middle/cstore.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use syntax::ext::base::SyntaxExtension;
3838
use syntax::symbol::Symbol;
3939
use syntax_pos::Span;
4040
use rustc_target::spec::Target;
41-
use rustc_data_structures::sync::{MetadataRef, Lrc};
41+
use rustc_data_structures::sync::{self, MetadataRef, Lrc};
4242

4343
pub use self::NativeLibraryKind::*;
4444

@@ -255,6 +255,8 @@ pub trait CrateStore {
255255
fn metadata_encoding_version(&self) -> &[u8];
256256
}
257257

258+
pub type CrateStoreDyn = CrateStore + sync::Sync;
259+
258260
// FIXME: find a better place for this?
259261
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
260262
let mut err_count = 0;

src/librustc/session/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -869,10 +869,16 @@ impl Session {
869869
ret
870870
}
871871

872+
/// Returns the number of query threads that should be used for this
873+
/// compilation
874+
pub fn query_threads_from_opts(opts: &config::Options) -> usize {
875+
opts.debugging_opts.query_threads.unwrap_or(1)
876+
}
877+
872878
/// Returns the number of query threads that should be used for this
873879
/// compilation
874880
pub fn query_threads(&self) -> usize {
875-
self.opts.debugging_opts.query_threads.unwrap_or(1)
881+
Self::query_threads_from_opts(&self.opts)
876882
}
877883

878884
/// Returns the number of codegen units that should be used for this

src/librustc/ty/context.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use lint::{self, Lint};
2626
use ich::{StableHashingContext, NodeIdHashingMode};
2727
use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
2828
use infer::outlives::free_region_map::FreeRegionMap;
29-
use middle::cstore::{CrateStore, LinkMeta};
29+
use middle::cstore::{CrateStoreDyn, LinkMeta};
3030
use middle::cstore::EncodedMetadata;
3131
use middle::lang_items;
3232
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
@@ -852,7 +852,7 @@ pub struct GlobalCtxt<'tcx> {
852852
global_arenas: &'tcx GlobalArenas<'tcx>,
853853
global_interners: CtxtInterners<'tcx>,
854854

855-
cstore: &'tcx dyn CrateStore,
855+
cstore: &'tcx CrateStoreDyn,
856856

857857
pub sess: &'tcx Session,
858858

@@ -1188,7 +1188,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
11881188
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
11891189
/// reference to the context, to allow formatting values that need it.
11901190
pub fn create_and_enter<F, R>(s: &'tcx Session,
1191-
cstore: &'tcx dyn CrateStore,
1191+
cstore: &'tcx CrateStoreDyn,
11921192
local_providers: ty::maps::Providers<'tcx>,
11931193
extern_providers: ty::maps::Providers<'tcx>,
11941194
arenas: &'tcx AllArenas<'tcx>,
@@ -1800,9 +1800,11 @@ pub mod tls {
18001800
/// in librustc otherwise. It is used to when diagnostic messages are
18011801
/// emitted and stores them in the current query, if there is one.
18021802
fn track_diagnostic(diagnostic: &Diagnostic) {
1803-
with_context(|context| {
1804-
if let Some(ref query) = context.query {
1805-
query.diagnostics.lock().push(diagnostic.clone());
1803+
with_context_opt(|icx| {
1804+
if let Some(icx) = icx {
1805+
if let Some(ref query) = icx.query {
1806+
query.diagnostics.lock().push(diagnostic.clone());
1807+
}
18061808
}
18071809
})
18081810
}

src/librustc_data_structures/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ serialize = { path = "../libserialize" }
1616
cfg-if = "0.1.2"
1717
stable_deref_trait = "1.0.0"
1818
parking_lot_core = "0.2.8"
19+
rustc-rayon = "0.1.0"
1920

2021
[dependencies.parking_lot]
2122
version = "0.5"

src/librustc_data_structures/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ extern crate parking_lot;
4444
#[macro_use]
4545
extern crate cfg_if;
4646
extern crate stable_deref_trait;
47+
extern crate rustc_rayon as rayon;
4748

4849
// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
4950
#[allow(unused_extern_crates)]

src/librustc_data_structures/sync.rs

+43-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! This mdoule defines types which are thread safe if cfg!(parallel_queries) is true.
11+
//! This module defines types which are thread safe if cfg!(parallel_queries) is true.
1212
//!
1313
//! `Lrc` is an alias of either Rc or Arc.
1414
//!
@@ -40,6 +40,29 @@ use std;
4040
use std::ops::{Deref, DerefMut};
4141
use owning_ref::{Erased, OwningRef};
4242

43+
pub fn serial_join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
44+
where A: FnOnce() -> RA,
45+
B: FnOnce() -> RB
46+
{
47+
(oper_a(), oper_b())
48+
}
49+
50+
pub struct SerialScope;
51+
52+
impl SerialScope {
53+
pub fn spawn<F>(&self, f: F)
54+
where F: FnOnce(&SerialScope)
55+
{
56+
f(self)
57+
}
58+
}
59+
60+
pub fn serial_scope<F, R>(f: F) -> R
61+
where F: FnOnce(&SerialScope) -> R
62+
{
63+
f(&SerialScope)
64+
}
65+
4366
cfg_if! {
4467
if #[cfg(not(parallel_queries))] {
4568
pub auto trait Send {}
@@ -55,9 +78,19 @@ cfg_if! {
5578
}
5679
}
5780

81+
pub use self::serial_join as join;
82+
pub use self::serial_scope as scope;
83+
84+
pub use std::iter::Iterator as ParallelIterator;
85+
86+
pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
87+
t.into_iter()
88+
}
89+
5890
pub type MetadataRef = OwningRef<Box<Erased>, [u8]>;
5991

6092
pub use std::rc::Rc as Lrc;
93+
pub use std::rc::Weak as Weak;
6194
pub use std::cell::Ref as ReadGuard;
6295
pub use std::cell::RefMut as WriteGuard;
6396
pub use std::cell::RefMut as LockGuard;
@@ -160,13 +193,22 @@ cfg_if! {
160193
pub use parking_lot::MutexGuard as LockGuard;
161194

162195
pub use std::sync::Arc as Lrc;
196+
pub use std::sync::Weak as Weak;
163197

164198
pub use self::Lock as MTLock;
165199

166200
use parking_lot::Mutex as InnerLock;
167201
use parking_lot::RwLock as InnerRwLock;
168202

169203
use std::thread;
204+
pub use rayon::{join, scope};
205+
206+
pub use rayon::iter::ParallelIterator;
207+
use rayon::iter::IntoParallelIterator;
208+
209+
pub fn par_iter<T: IntoParallelIterator>(t: T) -> T::Iter {
210+
t.into_par_iter()
211+
}
170212

171213
pub type MetadataRef = OwningRef<Box<Erased + Send + Sync>, [u8]>;
172214

src/librustc_driver/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ arena = { path = "../libarena" }
1313
graphviz = { path = "../libgraphviz" }
1414
log = "0.4"
1515
env_logger = { version = "0.5", default-features = false }
16+
rustc-rayon = "0.1.0"
17+
scoped-tls = { version = "0.1.1", features = ["nightly"] }
1618
rustc = { path = "../librustc" }
1719
rustc_allocator = { path = "../librustc_allocator" }
1820
rustc_target = { path = "../librustc_target" }

src/librustc_driver/driver.rs

+48-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc::session::config::{self, Input, OutputFilenames, OutputType};
2020
use rustc::session::search_paths::PathKind;
2121
use rustc::lint;
2222
use rustc::middle::{self, reachable, resolve_lifetime, stability};
23-
use rustc::middle::cstore::CrateStore;
23+
use rustc::middle::cstore::CrateStoreDyn;
2424
use rustc::middle::privacy::AccessLevels;
2525
use rustc::ty::{self, AllArenas, Resolutions, TyCtxt};
2626
use rustc::traits;
@@ -49,7 +49,7 @@ use std::fs;
4949
use std::io::{self, Write};
5050
use std::iter;
5151
use std::path::{Path, PathBuf};
52-
use rustc_data_structures::sync::Lrc;
52+
use rustc_data_structures::sync::{self, Lrc};
5353
use std::sync::mpsc;
5454
use syntax::{self, ast, attr, diagnostics, visit};
5555
use syntax::ext::base::ExtCtxt;
@@ -64,6 +64,51 @@ use pretty::ReplaceBodyWithLoop;
6464

6565
use profile;
6666

67+
#[cfg(not(parallel_queries))]
68+
pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::Send>(
69+
opts: config::Options,
70+
f: F
71+
) -> R {
72+
f(opts)
73+
}
74+
75+
#[cfg(parallel_queries)]
76+
pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::Send>(
77+
opts: config::Options,
78+
f: F
79+
) -> R {
80+
use syntax;
81+
use syntax_pos;
82+
use rayon::{ThreadPoolBuilder, ThreadPool};
83+
84+
let config = ThreadPoolBuilder::new().num_threads(Session::query_threads_from_opts(&opts))
85+
.stack_size(16 * 1024 * 1024);
86+
87+
let with_pool = move |pool: &ThreadPool| {
88+
pool.install(move || f(opts))
89+
};
90+
91+
syntax::GLOBALS.with(|syntax_globals| {
92+
syntax_pos::GLOBALS.with(|syntax_pos_globals| {
93+
// The main handler run for each Rayon worker thread and sets up
94+
// the thread local rustc uses. syntax_globals and syntax_pos_globals are
95+
// captured and set on the new threads. ty::tls::with_thread_locals sets up
96+
// thread local callbacks from libsyntax
97+
let main_handler = move |worker: &mut FnMut()| {
98+
syntax::GLOBALS.set(syntax_globals, || {
99+
syntax_pos::GLOBALS.set(syntax_pos_globals, || {
100+
ty::tls::with_thread_locals(|| {
101+
worker()
102+
})
103+
})
104+
})
105+
};
106+
107+
ThreadPool::scoped_pool(config, main_handler, with_pool).unwrap()
108+
})
109+
})
110+
}
111+
67112
pub fn compile_input(
68113
trans: Box<TransCrate>,
69114
sess: &Session,
@@ -1047,7 +1092,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(
10471092
trans: &TransCrate,
10481093
control: &CompileController,
10491094
sess: &'tcx Session,
1050-
cstore: &'tcx CrateStore,
1095+
cstore: &'tcx CrateStoreDyn,
10511096
hir_map: hir_map::Map<'tcx>,
10521097
mut analysis: ty::CrateAnalysis,
10531098
resolutions: Resolutions,

0 commit comments

Comments
 (0)