Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a Rayon thread pool #50235

Merged
merged 5 commits into from
May 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions src/librustc/hir/itemlikevisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,33 @@ impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V>
self.visitor.visit_impl_item(impl_item);
}
}

/// A parallel variant of ItemLikeVisitor
pub trait ParItemLikeVisitor<'hir> {
fn visit_item(&self, item: &'hir Item);
fn visit_trait_item(&self, trait_item: &'hir TraitItem);
fn visit_impl_item(&self, impl_item: &'hir ImplItem);
}

pub trait IntoVisitor<'hir> {
type Visitor: Visitor<'hir>;
fn into_visitor(&self) -> Self::Visitor;
}

pub struct ParDeepVisitor<V>(pub V);

impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor<V>
where V: IntoVisitor<'hir>
{
fn visit_item(&self, item: &'hir Item) {
self.0.into_visitor().visit_item(item);
}

fn visit_trait_item(&self, trait_item: &'hir TraitItem) {
self.0.into_visitor().visit_trait_item(trait_item);
}

fn visit_impl_item(&self, impl_item: &'hir ImplItem) {
self.0.into_visitor().visit_impl_item(impl_item);
}
}
26 changes: 26 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ use ty::AdtKind;
use ty::maps::Providers;

use rustc_data_structures::indexed_vec;
use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope};

use serialize::{self, Encoder, Encodable, Decoder, Decodable};
use std::collections::BTreeMap;
Expand Down Expand Up @@ -720,6 +721,31 @@ impl Crate {
}
}

/// A parallel version of visit_all_item_likes
pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send
{
scope(|s| {
s.spawn(|_| {
par_iter(&self.items).for_each(|(_, item)| {
visitor.visit_item(item);
});
});

s.spawn(|_| {
par_iter(&self.trait_items).for_each(|(_, trait_item)| {
visitor.visit_trait_item(trait_item);
});
});

s.spawn(|_| {
par_iter(&self.impl_items).for_each(|(_, impl_item)| {
visitor.visit_impl_item(impl_item);
});
});
});
}

pub fn body(&self, id: BodyId) -> &Body {
&self.bodies[&id]
}
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
use syntax_pos::Span;
use rustc_target::spec::Target;
use rustc_data_structures::sync::{MetadataRef, Lrc};
use rustc_data_structures::sync::{self, MetadataRef, Lrc};

pub use self::NativeLibraryKind::*;

Expand Down Expand Up @@ -255,6 +255,8 @@ pub trait CrateStore {
fn metadata_encoding_version(&self) -> &[u8];
}

pub type CrateStoreDyn = CrateStore + sync::Sync;

// FIXME: find a better place for this?
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
let mut err_count = 0;
Expand Down
8 changes: 7 additions & 1 deletion src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -869,10 +869,16 @@ impl Session {
ret
}

/// Returns the number of query threads that should be used for this
/// compilation
pub fn query_threads_from_opts(opts: &config::Options) -> usize {
opts.debugging_opts.query_threads.unwrap_or(1)
}

/// Returns the number of query threads that should be used for this
/// compilation
pub fn query_threads(&self) -> usize {
self.opts.debugging_opts.query_threads.unwrap_or(1)
Self::query_threads_from_opts(&self.opts)
}

/// Returns the number of codegen units that should be used for this
Expand Down
14 changes: 8 additions & 6 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use lint::{self, Lint};
use ich::{StableHashingContext, NodeIdHashingMode};
use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
use infer::outlives::free_region_map::FreeRegionMap;
use middle::cstore::{CrateStore, LinkMeta};
use middle::cstore::{CrateStoreDyn, LinkMeta};
use middle::cstore::EncodedMetadata;
use middle::lang_items;
use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
Expand Down Expand Up @@ -852,7 +852,7 @@ pub struct GlobalCtxt<'tcx> {
global_arenas: &'tcx GlobalArenas<'tcx>,
global_interners: CtxtInterners<'tcx>,

cstore: &'tcx dyn CrateStore,
cstore: &'tcx CrateStoreDyn,

pub sess: &'tcx Session,

Expand Down Expand Up @@ -1188,7 +1188,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
/// reference to the context, to allow formatting values that need it.
pub fn create_and_enter<F, R>(s: &'tcx Session,
cstore: &'tcx dyn CrateStore,
cstore: &'tcx CrateStoreDyn,
local_providers: ty::maps::Providers<'tcx>,
extern_providers: ty::maps::Providers<'tcx>,
arenas: &'tcx AllArenas<'tcx>,
Expand Down Expand Up @@ -1800,9 +1800,11 @@ pub mod tls {
/// in librustc otherwise. It is used to when diagnostic messages are
/// emitted and stores them in the current query, if there is one.
fn track_diagnostic(diagnostic: &Diagnostic) {
with_context(|context| {
if let Some(ref query) = context.query {
query.diagnostics.lock().push(diagnostic.clone());
with_context_opt(|icx| {
if let Some(icx) = icx {
if let Some(ref query) = icx.query {
query.diagnostics.lock().push(diagnostic.clone());
}
}
})
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_data_structures/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ serialize = { path = "../libserialize" }
cfg-if = "0.1.2"
stable_deref_trait = "1.0.0"
parking_lot_core = "0.2.8"
rustc-rayon = "0.1.0"

[dependencies.parking_lot]
version = "0.5"
Expand Down
1 change: 1 addition & 0 deletions src/librustc_data_structures/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extern crate parking_lot;
#[macro_use]
extern crate cfg_if;
extern crate stable_deref_trait;
extern crate rustc_rayon as rayon;

// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
#[allow(unused_extern_crates)]
Expand Down
44 changes: 43 additions & 1 deletion src/librustc_data_structures/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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

pub fn serial_join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
where A: FnOnce() -> RA,
B: FnOnce() -> RB
{
(oper_a(), oper_b())
}

pub struct SerialScope;

impl SerialScope {
pub fn spawn<F>(&self, f: F)
where F: FnOnce(&SerialScope)
{
f(self)
}
}

pub fn serial_scope<F, R>(f: F) -> R
where F: FnOnce(&SerialScope) -> R
{
f(&SerialScope)
}

cfg_if! {
if #[cfg(not(parallel_queries))] {
pub auto trait Send {}
Expand All @@ -55,9 +78,19 @@ cfg_if! {
}
}

pub use self::serial_join as join;
pub use self::serial_scope as scope;

pub use std::iter::Iterator as ParallelIterator;

pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
t.into_iter()
}

pub type MetadataRef = OwningRef<Box<Erased>, [u8]>;

pub use std::rc::Rc as Lrc;
pub use std::rc::Weak as Weak;
pub use std::cell::Ref as ReadGuard;
pub use std::cell::RefMut as WriteGuard;
pub use std::cell::RefMut as LockGuard;
Expand Down Expand Up @@ -160,13 +193,22 @@ cfg_if! {
pub use parking_lot::MutexGuard as LockGuard;

pub use std::sync::Arc as Lrc;
pub use std::sync::Weak as Weak;

pub use self::Lock as MTLock;

use parking_lot::Mutex as InnerLock;
use parking_lot::RwLock as InnerRwLock;

use std::thread;
pub use rayon::{join, scope};

pub use rayon::iter::ParallelIterator;
use rayon::iter::IntoParallelIterator;

pub fn par_iter<T: IntoParallelIterator>(t: T) -> T::Iter {
t.into_par_iter()
}

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

Expand Down
2 changes: 2 additions & 0 deletions src/librustc_driver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ arena = { path = "../libarena" }
graphviz = { path = "../libgraphviz" }
log = "0.4"
env_logger = { version = "0.5", default-features = false }
rustc-rayon = "0.1.0"
scoped-tls = { version = "0.1.1", features = ["nightly"] }
rustc = { path = "../librustc" }
rustc_allocator = { path = "../librustc_allocator" }
rustc_target = { path = "../librustc_target" }
Expand Down
51 changes: 48 additions & 3 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rustc::session::config::{self, Input, OutputFilenames, OutputType};
use rustc::session::search_paths::PathKind;
use rustc::lint;
use rustc::middle::{self, reachable, resolve_lifetime, stability};
use rustc::middle::cstore::CrateStore;
use rustc::middle::cstore::CrateStoreDyn;
use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, AllArenas, Resolutions, TyCtxt};
use rustc::traits;
Expand Down Expand Up @@ -49,7 +49,7 @@ use std::fs;
use std::io::{self, Write};
use std::iter;
use std::path::{Path, PathBuf};
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::sync::{self, Lrc};
use std::sync::mpsc;
use syntax::{self, ast, attr, diagnostics, visit};
use syntax::ext::base::ExtCtxt;
Expand All @@ -64,6 +64,51 @@ use pretty::ReplaceBodyWithLoop;

use profile;

#[cfg(not(parallel_queries))]
pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::Send>(
opts: config::Options,
f: F
) -> R {
f(opts)
}

#[cfg(parallel_queries)]
pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::Send>(
opts: config::Options,
f: F
) -> R {
use syntax;
use syntax_pos;
use rayon::{ThreadPoolBuilder, ThreadPool};

let config = ThreadPoolBuilder::new().num_threads(Session::query_threads_from_opts(&opts))
.stack_size(16 * 1024 * 1024);

let with_pool = move |pool: &ThreadPool| {
pool.install(move || f(opts))
};

syntax::GLOBALS.with(|syntax_globals| {
syntax_pos::GLOBALS.with(|syntax_pos_globals| {
// The main handler run for each Rayon worker thread and sets up
// the thread local rustc uses. syntax_globals and syntax_pos_globals are
// captured and set on the new threads. ty::tls::with_thread_locals sets up
// thread local callbacks from libsyntax
let main_handler = move |worker: &mut FnMut()| {
syntax::GLOBALS.set(syntax_globals, || {
syntax_pos::GLOBALS.set(syntax_pos_globals, || {
ty::tls::with_thread_locals(|| {
worker()
})
})
})
};

ThreadPool::scoped_pool(config, main_handler, with_pool).unwrap()
})
})
}

pub fn compile_input(
trans: Box<TransCrate>,
sess: &Session,
Expand Down Expand Up @@ -1047,7 +1092,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(
trans: &TransCrate,
control: &CompileController,
sess: &'tcx Session,
cstore: &'tcx CrateStore,
cstore: &'tcx CrateStoreDyn,
hir_map: hir_map::Map<'tcx>,
mut analysis: ty::CrateAnalysis,
resolutions: Resolutions,
Expand Down
Loading