1
Fork 0

Cache decoded predicate shorthands

This commit is contained in:
Matthew Jasper 2020-06-10 09:26:54 +01:00
parent 228a0ed7b0
commit 8ea55f1a99
5 changed files with 118 additions and 71 deletions

View file

@ -294,15 +294,36 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
let key = ty::CReaderCacheKey { cnum: self.cdata().cnum, pos: shorthand }; 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); return Ok(ty);
} }
let ty = or_insert_with(self)?; let ty = or_insert_with(self)?;
tcx.rcache.borrow_mut().insert(key, ty); tcx.ty_rcache.borrow_mut().insert(key, ty);
Ok(ty) Ok(ty)
} }
fn cached_predicate_for_shorthand<F>(
&mut self,
shorthand: usize,
or_insert_with: F,
) -> Result<ty::Predicate<'tcx>, Self::Error>
where
F: FnOnce(&mut Self) -> Result<ty::Predicate<'tcx>, 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<F, R>(&mut self, pos: usize, f: F) -> R fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
where where
F: FnOnce(&mut Self) -> R, F: FnOnce(&mut Self) -> R,

View file

@ -239,6 +239,17 @@ where
} }
} }
impl<'b, 'tcx> SpecializedEncoder<ty::Predicate<'b>> 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<interpret::AllocId> for EncodeContext<'tcx> { impl<'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> { fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
@ -256,22 +267,6 @@ impl<'tcx> SpecializedEncoder<interpret::AllocId> 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<Fingerprint> for EncodeContext<'tcx> { impl<'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'tcx> {
fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> { fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
f.encode_opaque(&mut self.opaque) f.encode_opaque(&mut self.opaque)

View file

@ -10,7 +10,7 @@ use crate::arena::ArenaAllocatable;
use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
use crate::mir::{self, interpret::Allocation}; use crate::mir::{self, interpret::Allocation};
use crate::ty::subst::SubstsRef; 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_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::def_id::{CrateNum, DefId};
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
@ -95,23 +95,6 @@ where
Ok(()) 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<ty::Predicate<'tcx>, 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 { pub trait TyDecoder<'tcx>: Decoder {
fn tcx(&self) -> TyCtxt<'tcx>; fn tcx(&self) -> TyCtxt<'tcx>;
@ -127,6 +110,14 @@ pub trait TyDecoder<'tcx>: Decoder {
where where
F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>; F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;
fn cached_predicate_for_shorthand<F>(
&mut self,
shorthand: usize,
or_insert_with: F,
) -> Result<ty::Predicate<'tcx>, Self::Error>
where
F: FnOnce(&mut Self) -> Result<ty::Predicate<'tcx>, Self::Error>;
fn with_position<F, R>(&mut self, pos: usize, f: F) -> R fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
where where
F: FnOnce(&mut Self) -> R; F: FnOnce(&mut Self) -> R;
@ -188,6 +179,26 @@ where
} }
} }
#[inline]
pub fn decode_predicate<D>(decoder: &mut D) -> Result<ty::Predicate<'tcx>, 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] #[inline]
pub fn decode_spanned_predicates<D>( pub fn decode_spanned_predicates<D>(
decoder: &mut D, decoder: &mut D,
@ -198,20 +209,7 @@ where
let tcx = decoder.tcx(); let tcx = decoder.tcx();
Ok(tcx.arena.alloc_from_iter( Ok(tcx.arena.alloc_from_iter(
(0..decoder.read_usize()?) (0..decoder.read_usize()?)
.map(|_| { .map(|_| Decodable::decode(decoder))
// 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)?))
})
.collect::<Result<Vec<_>, _>>()?, .collect::<Result<Vec<_>, _>>()?,
)) ))
} }
@ -421,7 +419,6 @@ macro_rules! implement_ty_decoder {
// FIXME(#36588): These impls are horribly unsound as they allow // FIXME(#36588): These impls are horribly unsound as they allow
// the caller to pick any lifetime for `'tcx`, including `'static`. // 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); arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
impl<$($typaram),*> SpecializedDecoder<CrateNum> impl<$($typaram),*> SpecializedDecoder<CrateNum>
@ -436,7 +433,24 @@ macro_rules! implement_ty_decoder {
where &'_x ty::TyS<'_y>: UseSpecializedDecodable where &'_x ty::TyS<'_y>: UseSpecializedDecodable
{ {
fn specialized_decode(&mut self) -> Result<&'_x ty::TyS<'_y>, Self::Error> { fn specialized_decode(&mut self) -> Result<&'_x ty::TyS<'_y>, Self::Error> {
unsafe { transmute::<Result<ty::Ty<'tcx>, Self::Error>, Result<&'_x ty::TyS<'_y>, Self::Error>>(decode_ty(self)) } unsafe {
transmute::<
Result<ty::Ty<'tcx>, Self::Error>,
Result<&'_x ty::TyS<'_y>, Self::Error>,
>(decode_ty(self))
}
}
}
impl<'_x, $($typaram),*> SpecializedDecoder<ty::Predicate<'_x>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<ty::Predicate<'_x>, Self::Error> {
unsafe {
transmute::<
Result<ty::Predicate<'tcx>, Self::Error>,
Result<ty::Predicate<'_x>, Self::Error>,
>(decode_predicate(self))
}
} }
} }

View file

@ -938,8 +938,9 @@ pub struct GlobalCtxt<'tcx> {
/// via `extern crate` item and not `--extern` option or compiler built-in. /// via `extern crate` item and not `--extern` option or compiler built-in.
pub extern_prelude: FxHashMap<Symbol, bool>, pub extern_prelude: FxHashMap<Symbol, bool>,
// Internal cache for metadata decoding. No need to track deps on this. // Internal caches for metadata decoding. No need to track deps on this.
pub rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>, pub ty_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
pub pred_rcache: Lock<FxHashMap<ty::CReaderCacheKey, Predicate<'tcx>>>,
/// Caches the results of trait selection. This cache is used /// Caches the results of trait selection. This cache is used
/// for things that do not have to do with the parameters in scope. /// for things that do not have to do with the parameters in scope.
@ -1128,7 +1129,8 @@ impl<'tcx> TyCtxt<'tcx> {
definitions, definitions,
def_path_hash_to_def_id, def_path_hash_to_def_id,
queries: query::Queries::new(providers, extern_providers, on_disk_query_result_cache), 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(), selection_cache: Default::default(),
evaluation_cache: Default::default(), evaluation_cache: Default::default(),
crate_name: Symbol::intern(crate_name), crate_name: Symbol::intern(crate_name),

View file

@ -524,16 +524,39 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
let cache_key = let cache_key =
ty::CReaderCacheKey { cnum: CrateNum::ReservedForIncrCompCache, pos: shorthand }; 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); return Ok(ty);
} }
let ty = or_insert_with(self)?; let ty = or_insert_with(self)?;
// This may overwrite the entry, but it should overwrite with the same value. // 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) Ok(ty)
} }
fn cached_predicate_for_shorthand<F>(
&mut self,
shorthand: usize,
or_insert_with: F,
) -> Result<ty::Predicate<'tcx>, Self::Error>
where
F: FnOnce(&mut Self) -> Result<ty::Predicate<'tcx>, 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<F, R>(&mut self, pos: usize, f: F) -> R fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
where where
F: FnOnce(&mut Self) -> R, F: FnOnce(&mut Self) -> R,
@ -820,24 +843,16 @@ where
} }
} }
impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b [(ty::Predicate<'c>, Span)]> impl<'a, 'b, 'tcx, E> SpecializedEncoder<ty::Predicate<'b>> for CacheEncoder<'a, 'tcx, E>
for CacheEncoder<'a, 'tcx, E>
where where
E: 'a + TyEncoder, E: 'a + TyEncoder,
{ {
#[inline] #[inline]
fn specialized_encode( fn specialized_encode(&mut self, predicate: &ty::Predicate<'b>) -> Result<(), Self::Error> {
&mut self, debug_assert!(self.tcx.lift(predicate).is_some());
predicates: &&'b [(ty::Predicate<'c>, Span)], let predicate =
) -> Result<(), Self::Error> { unsafe { std::mem::transmute::<&ty::Predicate<'b>, &ty::Predicate<'tcx>>(predicate) };
debug_assert!(self.tcx.lift(*predicates).is_some()); ty_codec::encode_with_shorthand(self, predicate, |encoder| {
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| {
&mut encoder.predicate_shorthands &mut encoder.predicate_shorthands
}) })
} }