Skip to content

Commit

Permalink
Auto merge of #46004 - michaelwoerister:cached-mir-wip-3, r=nikomatsakis
Browse files Browse the repository at this point in the history
incr.comp.: Implement query result cache and use it to cache type checking tables.

This is a spike implementation of caching more than LLVM IR and object files when doing incremental compilation. At the moment, only the `typeck_tables_of` query is cached but MIR and borrow-check will follow shortly. The feature is activated by running with `-Zincremental-queries` in addition to `-Zincremental`, it is not yet active by default.

r? @nikomatsakis
  • Loading branch information
bors committed Nov 17, 2017
2 parents b32267f + 0a1f6dd commit 02eed2e
Show file tree
Hide file tree
Showing 29 changed files with 1,161 additions and 370 deletions.
2 changes: 1 addition & 1 deletion src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ define_dep_nodes!( <'tcx>

[input] Freevars(DefId),
[input] MaybeUnusedTraitImport(DefId),
[] MaybeUnusedExternCrates,
[input] MaybeUnusedExternCrates,
[] StabilityIndex,
[input] AllCrateNums,
[] ExportedSymbols(CrateNum),
Expand Down
6 changes: 6 additions & 0 deletions src/librustc/dep_graph/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ impl DepGraph {
}
}

#[inline]
pub fn fingerprint_of(&self, dep_node: &DepNode) -> Fingerprint {
match self.fingerprints.borrow().get(dep_node) {
Some(&fingerprint) => fingerprint,
Expand All @@ -340,6 +341,11 @@ impl DepGraph {
self.data.as_ref().unwrap().previous.fingerprint_of(dep_node)
}

#[inline]
pub fn prev_dep_node_index_of(&self, dep_node: &DepNode) -> SerializedDepNodeIndex {
self.data.as_ref().unwrap().previous.node_to_index(dep_node)
}

/// Indicates that a previous work product exists for `v`. This is
/// invoked during initial start-up based on what nodes are clean
/// (and what files exist in the incr. directory).
Expand Down
5 changes: 5 additions & 0 deletions src/librustc/dep_graph/prev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ impl PreviousDepGraph {
self.data.nodes[dep_node_index].0
}

#[inline]
pub fn node_to_index(&self, dep_node: &DepNode) -> SerializedDepNodeIndex {
self.index[dep_node]
}

#[inline]
pub fn fingerprint_of(&self, dep_node: &DepNode) -> Option<Fingerprint> {
self.index
Expand Down
74 changes: 58 additions & 16 deletions src/librustc/hir/def_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
use ty;

use rustc_data_structures::indexed_vec::Idx;
use serialize::{self, Encoder, Decoder};

use serialize;
use std::fmt;
use std::u32;

Expand All @@ -32,6 +31,10 @@ newtype_index!(CrateNum

/// A CrateNum value that indicates that something is wrong.
const INVALID_CRATE = u32::MAX - 1,

/// A special CrateNum that we use for the tcx.rcache when decoding from
/// the incr. comp. cache.
const RESERVED_FOR_INCR_COMP_CACHE = u32::MAX - 2,
});

impl CrateNum {
Expand Down Expand Up @@ -61,17 +64,8 @@ impl fmt::Display for CrateNum {
}
}

impl serialize::UseSpecializedEncodable for CrateNum {
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_u32(self.0)
}
}

impl serialize::UseSpecializedDecodable for CrateNum {
fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
d.read_u32().map(CrateNum)
}
}
impl serialize::UseSpecializedEncodable for CrateNum {}
impl serialize::UseSpecializedDecodable for CrateNum {}

/// A DefIndex is an index into the hir-map for a crate, identifying a
/// particular definition. It should really be considered an interned
Expand All @@ -88,6 +82,7 @@ impl serialize::UseSpecializedDecodable for CrateNum {
/// don't have to care about these ranges.
newtype_index!(DefIndex
{
ENCODABLE = custom
DEBUG_FORMAT = custom,

/// The start of the "high" range of DefIndexes.
Expand Down Expand Up @@ -146,6 +141,9 @@ impl DefIndex {
}
}

impl serialize::UseSpecializedEncodable for DefIndex {}
impl serialize::UseSpecializedDecodable for DefIndex {}

#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub enum DefIndexAddressSpace {
Low = 0,
Expand All @@ -166,7 +164,7 @@ impl DefIndexAddressSpace {

/// A DefId identifies a particular *definition*, by combining a crate
/// index and a def index.
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, RustcDecodable, Hash, Copy)]
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, Hash, Copy)]
pub struct DefId {
pub krate: CrateNum,
pub index: DefIndex,
Expand All @@ -188,14 +186,58 @@ impl fmt::Debug for DefId {
}
}


impl DefId {
/// Make a local `DefId` with the given index.
#[inline]
pub fn local(index: DefIndex) -> DefId {
DefId { krate: LOCAL_CRATE, index: index }
}

pub fn is_local(&self) -> bool {
#[inline]
pub fn is_local(self) -> bool {
self.krate == LOCAL_CRATE
}

#[inline]
pub fn to_local(self) -> LocalDefId {
LocalDefId::from_def_id(self)
}
}

impl serialize::UseSpecializedEncodable for DefId {}
impl serialize::UseSpecializedDecodable for DefId {}

/// A LocalDefId is equivalent to a DefId with `krate == LOCAL_CRATE`. Since
/// we encode this information in the type, we can ensure at compile time that
/// no DefIds from upstream crates get thrown into the mix. There are quite a
/// few cases where we know that only DefIds from the local crate are expected
/// and a DefId from a different crate would signify a bug somewhere. This
/// is when LocalDefId comes in handy.
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct LocalDefId(DefIndex);

impl LocalDefId {

#[inline]
pub fn from_def_id(def_id: DefId) -> LocalDefId {
assert!(def_id.is_local());
LocalDefId(def_id.index)
}

#[inline]
pub fn to_def_id(self) -> DefId {
DefId {
krate: LOCAL_CRATE,
index: self.0
}
}
}

impl fmt::Debug for LocalDefId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.to_def_id().fmt(f)
}
}

impl serialize::UseSpecializedEncodable for LocalDefId {}
impl serialize::UseSpecializedDecodable for LocalDefId {}
12 changes: 11 additions & 1 deletion src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,

use dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex};

use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndexAddressSpace};
use hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace};

use syntax::abi::Abi;
use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
Expand Down Expand Up @@ -359,6 +359,16 @@ impl<'hir> Map<'hir> {
self.definitions.as_local_node_id(DefId::local(def_index)).unwrap()
}

#[inline]
pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId {
self.definitions.def_index_to_hir_id(def_id.to_def_id().index)
}

#[inline]
pub fn local_def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId {
self.definitions.as_local_node_id(def_id.to_def_id()).unwrap()
}

fn entry_count(&self) -> usize {
self.map.len()
}
Expand Down
29 changes: 27 additions & 2 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use ty::AdtKind;

use rustc_data_structures::indexed_vec;

use serialize::{self, Encoder, Encodable, Decoder, Decodable};
use std::collections::BTreeMap;
use std::fmt;

Expand Down Expand Up @@ -85,13 +86,37 @@ pub mod svh;
/// the local_id part of the HirId changing, which is a very useful property in
/// incremental compilation where we have to persist things through changes to
/// the code base.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
RustcEncodable, RustcDecodable)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct HirId {
pub owner: DefIndex,
pub local_id: ItemLocalId,
}

impl serialize::UseSpecializedEncodable for HirId {
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
let HirId {
owner,
local_id,
} = *self;

owner.encode(s)?;
local_id.encode(s)
}
}

impl serialize::UseSpecializedDecodable for HirId {
fn default_decode<D: Decoder>(d: &mut D) -> Result<HirId, D::Error> {
let owner = DefIndex::decode(d)?;
let local_id = ItemLocalId::decode(d)?;

Ok(HirId {
owner,
local_id
})
}
}


/// An `ItemLocalId` uniquely identifies something within a given "item-like",
/// that is within a hir::Item, hir::TraitItem, or hir::ImplItem. There is no
/// guarantee that the numerical value of a given `ItemLocalId` corresponds to
Expand Down
20 changes: 19 additions & 1 deletion src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
use hir;
use hir::map::DefPathHash;
use hir::def_id::{DefId, CrateNum, CRATE_DEF_INDEX};
use hir::def_id::{DefId, LocalDefId, CrateNum, CRATE_DEF_INDEX};
use ich::{StableHashingContext, NodeIdHashingMode};
use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey,
StableHasher, StableHasherResult};
Expand All @@ -38,6 +38,24 @@ impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for DefId {
}
}

impl<'gcx> HashStable<StableHashingContext<'gcx>> for LocalDefId {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
hcx.def_path_hash(self.to_def_id()).hash_stable(hcx, hasher);
}
}

impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for LocalDefId {
type KeyType = DefPathHash;

#[inline]
fn to_stable_hash_key(&self, hcx: &StableHashingContext<'gcx>) -> DefPathHash {
hcx.def_path_hash(self.to_def_id())
}
}

impl<'gcx> HashStable<StableHashingContext<'gcx>> for CrateNum {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
use hir;
use hir::def;
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use hir::map as hir_map;
use hir::map::definitions::{Definitions, DefKey, DefPathTable};
use hir::svh::Svh;
Expand Down Expand Up @@ -180,7 +180,7 @@ impl EncodedMetadata {
/// upstream crate.
#[derive(Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
pub struct EncodedMetadataHash {
pub def_index: DefIndex,
pub def_index: u32,
pub hash: ich::Fingerprint,
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use self::TrackMatchMode::*;
use self::OverloadedCallType::*;

use hir::def::Def;
use hir::def_id::{DefId};
use hir::def_id::DefId;
use infer::InferCtxt;
use middle::mem_categorization as mc;
use middle::region;
Expand Down Expand Up @@ -915,7 +915,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
let closure_def_id = self.tcx().hir.local_def_id(closure_expr.id);
let upvar_id = ty::UpvarId {
var_id: var_hir_id,
closure_expr_id: closure_def_id.index
closure_expr_id: closure_def_id.to_local(),
};
let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub use self::Note::*;
use self::Aliasability::*;

use middle::region;
use hir::def_id::{DefId, DefIndex};
use hir::def_id::{DefId, LocalDefId};
use hir::map as hir_map;
use infer::InferCtxt;
use hir::def::{Def, CtorKind};
Expand Down Expand Up @@ -191,7 +191,7 @@ pub type cmt<'tcx> = Rc<cmt_<'tcx>>;

pub enum ImmutabilityBlame<'tcx> {
ImmLocal(ast::NodeId),
ClosureEnv(DefIndex),
ClosureEnv(LocalDefId),
LocalDeref(ast::NodeId),
AdtFieldDeref(&'tcx ty::AdtDef, &'tcx ty::FieldDef)
}
Expand Down Expand Up @@ -759,11 +759,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
ref t => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", t),
};

let closure_expr_def_index = self.tcx.hir.local_def_id(fn_node_id).index;
let closure_expr_def_id = self.tcx.hir.local_def_id(fn_node_id);
let var_hir_id = self.tcx.hir.node_to_hir_id(var_id);
let upvar_id = ty::UpvarId {
var_id: var_hir_id,
closure_expr_id: closure_expr_def_index
closure_expr_id: closure_expr_def_id.to_local(),
};

let var_ty = self.node_ty(var_hir_id)?;
Expand Down Expand Up @@ -838,7 +838,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
// The environment of a closure is guaranteed to
// outlive any bindings introduced in the body of the
// closure itself.
scope: DefId::local(upvar_id.closure_expr_id),
scope: upvar_id.closure_expr_id.to_def_id(),
bound_region: ty::BrEnv
}));

Expand Down
2 changes: 2 additions & 0 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"enable incremental compilation (experimental)"),
incremental_cc: bool = (false, parse_bool, [UNTRACKED],
"enable cross-crate incremental compilation (even more experimental)"),
incremental_queries: bool = (true, parse_bool, [UNTRACKED],
"enable incremental compilation support for queries (experimental)"),
incremental_info: bool = (false, parse_bool, [UNTRACKED],
"print high-level information about incremental reuse (or the lack thereof)"),
incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED],
Expand Down
Loading

0 comments on commit 02eed2e

Please sign in to comment.