Cache decoded predicate shorthands
This commit is contained in:
parent
228a0ed7b0
commit
8ea55f1a99
5 changed files with 118 additions and 71 deletions
|
@ -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<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
|
||||
where
|
||||
F: FnOnce(&mut Self) -> R,
|
||||
|
|
|
@ -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> {
|
||||
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<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> {
|
||||
fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> {
|
||||
f.encode_opaque(&mut self.opaque)
|
||||
|
|
|
@ -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<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 {
|
||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||
|
||||
|
@ -127,6 +110,14 @@ pub trait TyDecoder<'tcx>: Decoder {
|
|||
where
|
||||
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
|
||||
where
|
||||
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]
|
||||
pub fn decode_spanned_predicates<D>(
|
||||
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::<Result<Vec<_>, _>>()?,
|
||||
))
|
||||
}
|
||||
|
@ -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<CrateNum>
|
||||
|
@ -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::<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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -938,8 +938,9 @@ pub struct GlobalCtxt<'tcx> {
|
|||
/// via `extern crate` item and not `--extern` option or compiler built-in.
|
||||
pub extern_prelude: FxHashMap<Symbol, bool>,
|
||||
|
||||
// Internal cache for metadata decoding. No need to track deps on this.
|
||||
pub rcache: Lock<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
|
||||
// Internal caches for metadata decoding. No need to track deps on this.
|
||||
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
|
||||
/// 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),
|
||||
|
|
|
@ -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<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
|
||||
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<ty::Predicate<'b>> 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
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue