diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 800f794121a..2254d553337 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -294,15 +294,36 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { let key = ty::CReaderCacheKey { cnum: self.cdata().cnum, pos: shorthand }; - if let Some(&ty) = tcx.rcache.borrow().get(&key) { + if let Some(&ty) = tcx.ty_rcache.borrow().get(&key) { return Ok(ty); } let ty = or_insert_with(self)?; - tcx.rcache.borrow_mut().insert(key, ty); + tcx.ty_rcache.borrow_mut().insert(key, ty); Ok(ty) } + fn cached_predicate_for_shorthand( + &mut self, + shorthand: usize, + or_insert_with: F, + ) -> Result, Self::Error> + where + F: FnOnce(&mut Self) -> Result, Self::Error>, + { + let tcx = self.tcx(); + + let key = ty::CReaderCacheKey { cnum: self.cdata().cnum, pos: shorthand }; + + if let Some(&pred) = tcx.pred_rcache.borrow().get(&key) { + return Ok(pred); + } + + let pred = or_insert_with(self)?; + tcx.pred_rcache.borrow_mut().insert(key, pred); + Ok(pred) + } + fn with_position(&mut self, pos: usize, f: F) -> R where F: FnOnce(&mut Self) -> R, diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 31821ea459f..d01c767e2bc 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -239,6 +239,17 @@ where } } +impl<'b, 'tcx> SpecializedEncoder> for EncodeContext<'tcx> { + fn specialized_encode(&mut self, predicate: &ty::Predicate<'b>) -> Result<(), Self::Error> { + debug_assert!(self.tcx.lift(predicate).is_some()); + let predicate = + unsafe { std::mem::transmute::<&ty::Predicate<'b>, &ty::Predicate<'tcx>>(predicate) }; + ty_codec::encode_with_shorthand(self, predicate, |encoder| { + &mut encoder.predicate_shorthands + }) + } +} + impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> { use std::collections::hash_map::Entry; @@ -256,22 +267,6 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { } } -impl<'a, 'b, 'tcx> SpecializedEncoder<&'a [(ty::Predicate<'b>, Span)]> for EncodeContext<'tcx> { - fn specialized_encode( - &mut self, - predicates: &&'a [(ty::Predicate<'b>, Span)], - ) -> Result<(), Self::Error> { - debug_assert!(self.tcx.lift(*predicates).is_some()); - let predicates = unsafe { - std::mem::transmute::< - &&'a [(ty::Predicate<'b>, Span)], - &&'tcx [(ty::Predicate<'tcx>, Span)], - >(predicates) - }; - ty_codec::encode_spanned_predicates(self, &predicates, |ecx| &mut ecx.predicate_shorthands) - } -} - impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> { f.encode_opaque(&mut self.opaque) diff --git a/src/librustc_middle/ty/codec.rs b/src/librustc_middle/ty/codec.rs index 1a8e5c45dd2..67ceaca103e 100644 --- a/src/librustc_middle/ty/codec.rs +++ b/src/librustc_middle/ty/codec.rs @@ -10,7 +10,7 @@ use crate::arena::ArenaAllocatable; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use crate::mir::{self, interpret::Allocation}; use crate::ty::subst::SubstsRef; -use crate::ty::{self, List, ToPredicate, Ty, TyCtxt}; +use crate::ty::{self, List, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; @@ -95,23 +95,6 @@ where Ok(()) } -pub fn encode_spanned_predicates<'tcx, E, C>( - encoder: &mut E, - predicates: &[(ty::Predicate<'tcx>, Span)], - cache: C, -) -> Result<(), E::Error> -where - E: TyEncoder, - C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap, usize>, -{ - predicates.len().encode(encoder)?; - for (predicate, span) in predicates { - encode_with_shorthand(encoder, predicate, &cache)?; - span.encode(encoder)?; - } - Ok(()) -} - pub trait TyDecoder<'tcx>: Decoder { fn tcx(&self) -> TyCtxt<'tcx>; @@ -127,6 +110,14 @@ pub trait TyDecoder<'tcx>: Decoder { where F: FnOnce(&mut Self) -> Result, Self::Error>; + fn cached_predicate_for_shorthand( + &mut self, + shorthand: usize, + or_insert_with: F, + ) -> Result, Self::Error> + where + F: FnOnce(&mut Self) -> Result, Self::Error>; + fn with_position(&mut self, pos: usize, f: F) -> R where F: FnOnce(&mut Self) -> R; @@ -188,6 +179,26 @@ where } } +#[inline] +pub fn decode_predicate(decoder: &mut D) -> Result, D::Error> +where + D: TyDecoder<'tcx>, +{ + // Handle shorthands first, if we have an usize > 0x80. + if decoder.positioned_at_shorthand() { + let pos = decoder.read_usize()?; + assert!(pos >= SHORTHAND_OFFSET); + let shorthand = pos - SHORTHAND_OFFSET; + + decoder.cached_predicate_for_shorthand(shorthand, |decoder| { + decoder.with_position(shorthand, ty::Predicate::decode) + }) + } else { + let tcx = decoder.tcx(); + Ok(tcx.mk_predicate(ty::PredicateKind::decode(decoder)?)) + } +} + #[inline] pub fn decode_spanned_predicates( decoder: &mut D, @@ -198,20 +209,7 @@ where let tcx = decoder.tcx(); Ok(tcx.arena.alloc_from_iter( (0..decoder.read_usize()?) - .map(|_| { - // Handle shorthands first, if we have an usize > 0x80. - let predicate_kind = if decoder.positioned_at_shorthand() { - let pos = decoder.read_usize()?; - assert!(pos >= SHORTHAND_OFFSET); - let shorthand = pos - SHORTHAND_OFFSET; - - decoder.with_position(shorthand, ty::PredicateKind::decode) - } else { - ty::PredicateKind::decode(decoder) - }?; - let predicate = predicate_kind.to_predicate(tcx); - Ok((predicate, Decodable::decode(decoder)?)) - }) + .map(|_| Decodable::decode(decoder)) .collect::, _>>()?, )) } @@ -421,7 +419,6 @@ macro_rules! implement_ty_decoder { // FIXME(#36588): These impls are horribly unsound as they allow // the caller to pick any lifetime for `'tcx`, including `'static`. - rustc_hir::arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx); arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx); impl<$($typaram),*> SpecializedDecoder @@ -436,7 +433,24 @@ macro_rules! implement_ty_decoder { where &'_x ty::TyS<'_y>: UseSpecializedDecodable { fn specialized_decode(&mut self) -> Result<&'_x ty::TyS<'_y>, Self::Error> { - unsafe { transmute::, Self::Error>, Result<&'_x ty::TyS<'_y>, Self::Error>>(decode_ty(self)) } + unsafe { + transmute::< + Result, Self::Error>, + Result<&'_x ty::TyS<'_y>, Self::Error>, + >(decode_ty(self)) + } + } + } + + impl<'_x, $($typaram),*> SpecializedDecoder> + for $DecoderName<$($typaram),*> { + fn specialized_decode(&mut self) -> Result, Self::Error> { + unsafe { + transmute::< + Result, Self::Error>, + Result, Self::Error>, + >(decode_predicate(self)) + } } } diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 5b44ffe8caf..1b909b42fdf 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -938,8 +938,9 @@ pub struct GlobalCtxt<'tcx> { /// via `extern crate` item and not `--extern` option or compiler built-in. pub extern_prelude: FxHashMap, - // Internal cache for metadata decoding. No need to track deps on this. - pub rcache: Lock>>, + // Internal caches for metadata decoding. No need to track deps on this. + pub ty_rcache: Lock>>, + pub pred_rcache: Lock>>, /// Caches the results of trait selection. This cache is used /// for things that do not have to do with the parameters in scope. @@ -1128,7 +1129,8 @@ impl<'tcx> TyCtxt<'tcx> { definitions, def_path_hash_to_def_id, queries: query::Queries::new(providers, extern_providers, on_disk_query_result_cache), - rcache: Default::default(), + ty_rcache: Default::default(), + pred_rcache: Default::default(), selection_cache: Default::default(), evaluation_cache: Default::default(), crate_name: Symbol::intern(crate_name), diff --git a/src/librustc_middle/ty/query/on_disk_cache.rs b/src/librustc_middle/ty/query/on_disk_cache.rs index 5374dff4224..c84a7c38d0a 100644 --- a/src/librustc_middle/ty/query/on_disk_cache.rs +++ b/src/librustc_middle/ty/query/on_disk_cache.rs @@ -524,16 +524,39 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> { let cache_key = ty::CReaderCacheKey { cnum: CrateNum::ReservedForIncrCompCache, pos: shorthand }; - if let Some(&ty) = tcx.rcache.borrow().get(&cache_key) { + if let Some(&ty) = tcx.ty_rcache.borrow().get(&cache_key) { return Ok(ty); } let ty = or_insert_with(self)?; // This may overwrite the entry, but it should overwrite with the same value. - tcx.rcache.borrow_mut().insert_same(cache_key, ty); + tcx.ty_rcache.borrow_mut().insert_same(cache_key, ty); Ok(ty) } + fn cached_predicate_for_shorthand( + &mut self, + shorthand: usize, + or_insert_with: F, + ) -> Result, Self::Error> + where + F: FnOnce(&mut Self) -> Result, Self::Error>, + { + let tcx = self.tcx(); + + let cache_key = + ty::CReaderCacheKey { cnum: CrateNum::ReservedForIncrCompCache, pos: shorthand }; + + if let Some(&pred) = tcx.pred_rcache.borrow().get(&cache_key) { + return Ok(pred); + } + + let pred = or_insert_with(self)?; + // This may overwrite the entry, but it should overwrite with the same value. + tcx.pred_rcache.borrow_mut().insert_same(cache_key, pred); + Ok(pred) + } + fn with_position(&mut self, pos: usize, f: F) -> R where F: FnOnce(&mut Self) -> R, @@ -820,24 +843,16 @@ where } } -impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b [(ty::Predicate<'c>, Span)]> - for CacheEncoder<'a, 'tcx, E> +impl<'a, 'b, 'tcx, E> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> where E: 'a + TyEncoder, { #[inline] - fn specialized_encode( - &mut self, - predicates: &&'b [(ty::Predicate<'c>, Span)], - ) -> Result<(), Self::Error> { - debug_assert!(self.tcx.lift(*predicates).is_some()); - let predicates = unsafe { - std::mem::transmute::< - &&'b [(ty::Predicate<'c>, Span)], - &&'tcx [(ty::Predicate<'tcx>, Span)], - >(predicates) - }; - ty_codec::encode_spanned_predicates(self, predicates, |encoder| { + fn specialized_encode(&mut self, predicate: &ty::Predicate<'b>) -> Result<(), Self::Error> { + debug_assert!(self.tcx.lift(predicate).is_some()); + let predicate = + unsafe { std::mem::transmute::<&ty::Predicate<'b>, &ty::Predicate<'tcx>>(predicate) }; + ty_codec::encode_with_shorthand(self, predicate, |encoder| { &mut encoder.predicate_shorthands }) }