incr.comp.: Factor some persistence functionality out of crate metadata code.
This commit is contained in:
parent
a789fa0440
commit
686d2a7f14
6 changed files with 317 additions and 115 deletions
243
src/librustc/ty/codec.rs
Normal file
243
src/librustc/ty/codec.rs
Normal file
|
@ -0,0 +1,243 @@
|
|||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// This module contains some shared code for encoding and decoding various
|
||||
// things from the `ty` module, and in particular implements support for
|
||||
// "shorthands" which allow to have pointers back into the already encoded
|
||||
// stream instead of re-encoding the same thing twice.
|
||||
//
|
||||
// The functionality in here is shared between persisting to crate metadata and
|
||||
// persisting to incr. comp. caches.
|
||||
|
||||
use hir::def_id::{DefId, CrateNum};
|
||||
use middle::const_val::ByteArray;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_serialize::{Decodable, Decoder, Encoder, Encodable};
|
||||
use std::hash::Hash;
|
||||
use std::intrinsics;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::subst::Substs;
|
||||
|
||||
/// The shorthand encoding uses an enum's variant index `usize`
|
||||
/// and is offset by this value so it never matches a real variant.
|
||||
/// This offset is also chosen so that the first byte is never < 0x80.
|
||||
pub const SHORTHAND_OFFSET: usize = 0x80;
|
||||
|
||||
pub trait EncodableWithShorthand: Clone + Eq + Hash {
|
||||
type Variant: Encodable;
|
||||
fn variant(&self) -> &Self::Variant;
|
||||
}
|
||||
|
||||
impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
|
||||
type Variant = ty::TypeVariants<'tcx>;
|
||||
fn variant(&self) -> &Self::Variant {
|
||||
&self.sty
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
|
||||
type Variant = ty::Predicate<'tcx>;
|
||||
fn variant(&self) -> &Self::Variant {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub trait TyEncoder: Encoder {
|
||||
fn position(&self) -> usize;
|
||||
}
|
||||
|
||||
/// Encode the given value or a previously cached shorthand.
|
||||
pub fn encode_with_shorthand<E, T, M>(encoder: &mut E,
|
||||
value: &T,
|
||||
cache: M)
|
||||
-> Result<(), E::Error>
|
||||
where E: TyEncoder,
|
||||
M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
|
||||
T: EncodableWithShorthand,
|
||||
{
|
||||
let existing_shorthand = cache(encoder).get(value).cloned();
|
||||
if let Some(shorthand) = existing_shorthand {
|
||||
return encoder.emit_usize(shorthand);
|
||||
}
|
||||
|
||||
let variant = value.variant();
|
||||
|
||||
let start = encoder.position();
|
||||
variant.encode(encoder)?;
|
||||
let len = encoder.position() - start;
|
||||
|
||||
// The shorthand encoding uses the same usize as the
|
||||
// discriminant, with an offset so they can't conflict.
|
||||
let discriminant = unsafe { intrinsics::discriminant_value(variant) };
|
||||
assert!(discriminant < SHORTHAND_OFFSET as u64);
|
||||
let shorthand = start + SHORTHAND_OFFSET;
|
||||
|
||||
// Get the number of bits that leb128 could fit
|
||||
// in the same space as the fully encoded type.
|
||||
let leb128_bits = len * 7;
|
||||
|
||||
// Check that the shorthand is a not longer than the
|
||||
// full encoding itself, i.e. it's an obvious win.
|
||||
if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
|
||||
cache(encoder).insert(value.clone(), shorthand);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn encode_predicates<'tcx, E, C>(encoder: &mut E,
|
||||
predicates: &ty::GenericPredicates<'tcx>,
|
||||
cache: C)
|
||||
-> Result<(), E::Error>
|
||||
where E: TyEncoder,
|
||||
C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<ty::Predicate<'tcx>, usize>,
|
||||
{
|
||||
predicates.parent.encode(encoder)?;
|
||||
predicates.predicates.len().encode(encoder)?;
|
||||
for predicate in &predicates.predicates {
|
||||
encode_with_shorthand(encoder, predicate, &cache)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub trait TyDecoder<'a, 'tcx: 'a>: Decoder {
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
|
||||
|
||||
fn peek_byte(&self) -> u8;
|
||||
|
||||
fn cached_ty_for_shorthand<F>(&mut self,
|
||||
shorthand: usize,
|
||||
or_insert_with: F)
|
||||
-> Result<Ty<'tcx>, Self::Error>
|
||||
where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;
|
||||
|
||||
fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
|
||||
where F: FnOnce(&mut Self) -> R;
|
||||
|
||||
fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;
|
||||
|
||||
fn positioned_at_shorthand(&self) -> bool {
|
||||
(self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_cnum<'a, 'tcx, D>(decoder: &mut D) -> Result<CrateNum, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
let cnum = CrateNum::from_u32(u32::decode(decoder)?);
|
||||
Ok(decoder.map_encoded_cnum_to_current(cnum))
|
||||
}
|
||||
|
||||
pub fn decode_ty<'a, 'tcx, D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
// Handle shorthands first, if we have an usize > 0x80.
|
||||
// if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
|
||||
if decoder.positioned_at_shorthand() {
|
||||
let pos = decoder.read_usize()?;
|
||||
assert!(pos >= SHORTHAND_OFFSET);
|
||||
let shorthand = pos - SHORTHAND_OFFSET;
|
||||
|
||||
decoder.cached_ty_for_shorthand(shorthand, |decoder| {
|
||||
decoder.with_position(shorthand, Ty::decode)
|
||||
})
|
||||
} else {
|
||||
let tcx = decoder.tcx();
|
||||
Ok(tcx.mk_ty(ty::TypeVariants::decode(decoder)?))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<ty::GenericPredicates<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
Ok(ty::GenericPredicates {
|
||||
parent: Decodable::decode(decoder)?,
|
||||
predicates: (0..decoder.read_usize()?).map(|_| {
|
||||
// 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.with_position(shorthand, ty::Predicate::decode)
|
||||
} else {
|
||||
ty::Predicate::decode(decoder)
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn decode_substs<'a, 'tcx, D>(decoder: &mut D) -> Result<&'tcx Substs<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
let len = decoder.read_usize()?;
|
||||
let tcx = decoder.tcx();
|
||||
Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
|
||||
}
|
||||
|
||||
pub fn decode_region<'a, 'tcx, D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
|
||||
}
|
||||
|
||||
pub fn decode_ty_slice<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::Slice<Ty<'tcx>>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
let len = decoder.read_usize()?;
|
||||
Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
|
||||
}
|
||||
|
||||
pub fn decode_adt_def<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::AdtDef, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
let def_id = DefId::decode(decoder)?;
|
||||
Ok(decoder.tcx().adt_def(def_id))
|
||||
}
|
||||
|
||||
pub fn decode_existential_predicate_slice<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
let len = decoder.read_usize()?;
|
||||
Ok(decoder.tcx()
|
||||
.mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
|
||||
}
|
||||
|
||||
pub fn decode_byte_array<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<ByteArray<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
Ok(ByteArray {
|
||||
data: decoder.tcx().alloc_byte_array(&Vec::decode(decoder)?)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
|
||||
-> Result<&'tcx ty::Const<'tcx>, D::Error>
|
||||
where D: TyDecoder<'a, 'tcx>,
|
||||
'tcx: 'a,
|
||||
{
|
||||
Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
|
||||
}
|
|
@ -89,6 +89,7 @@ pub use self::maps::queries;
|
|||
pub mod adjustment;
|
||||
pub mod binding;
|
||||
pub mod cast;
|
||||
pub mod codec;
|
||||
pub mod error;
|
||||
mod erase_regions;
|
||||
pub mod fast_reject;
|
||||
|
|
|
@ -25,6 +25,7 @@ use rustc::ich::Fingerprint;
|
|||
use rustc::middle::lang_items;
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::codec::{self as ty_codec, TyDecoder};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::util::nodemap::DefIdSet;
|
||||
|
||||
|
@ -143,16 +144,6 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
|
|||
self.cdata.expect("missing CrateMetadata in DecodeContext")
|
||||
}
|
||||
|
||||
fn with_position<F: FnOnce(&mut Self) -> R, R>(&mut self, pos: usize, f: F) -> R {
|
||||
let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
|
||||
let old_opaque = mem::replace(&mut self.opaque, new_opaque);
|
||||
let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
|
||||
let r = f(self);
|
||||
self.opaque = old_opaque;
|
||||
self.lazy_state = old_state;
|
||||
r
|
||||
}
|
||||
|
||||
fn read_lazy_distance(&mut self, min_size: usize) -> Result<usize, <Self as Decoder>::Error> {
|
||||
let distance = self.read_usize()?;
|
||||
let position = match self.lazy_state {
|
||||
|
@ -208,6 +199,60 @@ impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, 'tcx: 'a> TyDecoder<'a, 'tcx> for DecodeContext<'a, 'tcx> {
|
||||
|
||||
fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
|
||||
self.tcx.expect("missing TyCtxt in DecodeContext")
|
||||
}
|
||||
|
||||
fn peek_byte(&self) -> u8 {
|
||||
self.opaque.data[self.opaque.position()]
|
||||
}
|
||||
|
||||
fn cached_ty_for_shorthand<F>(&mut self,
|
||||
shorthand: usize,
|
||||
or_insert_with: F)
|
||||
-> Result<Ty<'tcx>, Self::Error>
|
||||
where F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
||||
let key = ty::CReaderCacheKey {
|
||||
cnum: self.cdata().cnum,
|
||||
pos: shorthand,
|
||||
};
|
||||
|
||||
if let Some(&ty) = tcx.rcache.borrow().get(&key) {
|
||||
return Ok(ty);
|
||||
}
|
||||
|
||||
let ty = or_insert_with(self)?;
|
||||
tcx.rcache.borrow_mut().insert(key, ty);
|
||||
Ok(ty)
|
||||
}
|
||||
|
||||
fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
|
||||
where F: FnOnce(&mut Self) -> R
|
||||
{
|
||||
let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
|
||||
let old_opaque = mem::replace(&mut self.opaque, new_opaque);
|
||||
let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
|
||||
let r = f(self);
|
||||
self.opaque = old_opaque;
|
||||
self.lazy_state = old_state;
|
||||
r
|
||||
}
|
||||
|
||||
fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum {
|
||||
if cnum == LOCAL_CRATE {
|
||||
self.cdata().cnum
|
||||
} else {
|
||||
self.cdata().cnum_map.borrow()[cnum]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
|
||||
Ok(Lazy::with_position(self.read_lazy_distance(Lazy::<T>::min_size())?))
|
||||
|
@ -302,73 +347,37 @@ impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> SpecializedDecoder<Ty<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<Ty<'tcx>, Self::Error> {
|
||||
let tcx = self.tcx();
|
||||
|
||||
// Handle shorthands first, if we have an usize > 0x80.
|
||||
if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
|
||||
let pos = self.read_usize()?;
|
||||
assert!(pos >= SHORTHAND_OFFSET);
|
||||
let key = ty::CReaderCacheKey {
|
||||
cnum: self.cdata().cnum,
|
||||
pos: pos - SHORTHAND_OFFSET,
|
||||
};
|
||||
if let Some(ty) = tcx.rcache.borrow().get(&key).cloned() {
|
||||
return Ok(ty);
|
||||
}
|
||||
|
||||
let ty = self.with_position(key.pos, Ty::decode)?;
|
||||
tcx.rcache.borrow_mut().insert(key, ty);
|
||||
Ok(ty)
|
||||
} else {
|
||||
Ok(tcx.mk_ty(ty::TypeVariants::decode(self)?))
|
||||
}
|
||||
ty_codec::decode_ty(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<ty::GenericPredicates<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<ty::GenericPredicates<'tcx>, Self::Error> {
|
||||
Ok(ty::GenericPredicates {
|
||||
parent: Decodable::decode(self)?,
|
||||
predicates: (0..self.read_usize()?).map(|_| {
|
||||
// Handle shorthands first, if we have an usize > 0x80.
|
||||
if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
|
||||
let pos = self.read_usize()?;
|
||||
assert!(pos >= SHORTHAND_OFFSET);
|
||||
let pos = pos - SHORTHAND_OFFSET;
|
||||
|
||||
self.with_position(pos, ty::Predicate::decode)
|
||||
} else {
|
||||
ty::Predicate::decode(self)
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
})
|
||||
ty_codec::decode_predicates(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
|
||||
Ok(self.tcx().mk_substs((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
|
||||
ty_codec::decode_substs(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<ty::Region<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
|
||||
Ok(self.tcx().mk_region(Decodable::decode(self)?))
|
||||
ty_codec::decode_region(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<Ty<'tcx>>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<Ty<'tcx>>, Self::Error> {
|
||||
Ok(self.tcx().mk_type_list((0..self.read_usize()?).map(|_| Decodable::decode(self)))?)
|
||||
ty_codec::decode_ty_slice(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::AdtDef> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
|
||||
let def_id = DefId::decode(self)?;
|
||||
Ok(self.tcx().adt_def(def_id))
|
||||
ty_codec::decode_adt_def(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,22 +385,19 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>
|
|||
for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self)
|
||||
-> Result<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>>, Self::Error> {
|
||||
Ok(self.tcx().mk_existential_predicates((0..self.read_usize()?)
|
||||
.map(|_| Decodable::decode(self)))?)
|
||||
ty_codec::decode_existential_predicate_slice(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<ByteArray<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<ByteArray<'tcx>, Self::Error> {
|
||||
Ok(ByteArray {
|
||||
data: self.tcx().alloc_byte_array(&Vec::decode(self)?)
|
||||
})
|
||||
ty_codec::decode_byte_array(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Const<'tcx>> for DecodeContext<'a, 'tcx> {
|
||||
fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
|
||||
Ok(self.tcx().mk_const(Decodable::decode(self)?))
|
||||
ty_codec::decode_const(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,14 +25,13 @@ use rustc::middle::lang_items;
|
|||
use rustc::mir;
|
||||
use rustc::traits::specialization_graph;
|
||||
use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
|
||||
use rustc::ty::codec::{self as ty_codec, TyEncoder};
|
||||
|
||||
use rustc::session::config::{self, CrateTypeProcMacro};
|
||||
use rustc::util::nodemap::{FxHashMap, NodeSet};
|
||||
|
||||
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
|
||||
|
||||
use std::hash::Hash;
|
||||
use std::intrinsics;
|
||||
use std::io::prelude::*;
|
||||
use std::io::Cursor;
|
||||
use std::path::Path;
|
||||
|
@ -119,7 +118,7 @@ impl<'a, 'tcx, T> SpecializedEncoder<LazySeq<T>> for EncodeContext<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
|
||||
fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
|
||||
self.encode_with_shorthand(ty, &ty.sty, |ecx| &mut ecx.type_shorthands)
|
||||
ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,21 +126,18 @@ impl<'a, 'tcx> SpecializedEncoder<ty::GenericPredicates<'tcx>> for EncodeContext
|
|||
fn specialized_encode(&mut self,
|
||||
predicates: &ty::GenericPredicates<'tcx>)
|
||||
-> Result<(), Self::Error> {
|
||||
predicates.parent.encode(self)?;
|
||||
predicates.predicates.len().encode(self)?;
|
||||
for predicate in &predicates.predicates {
|
||||
self.encode_with_shorthand(predicate, predicate, |ecx| &mut ecx.predicate_shorthands)?
|
||||
}
|
||||
Ok(())
|
||||
ty_codec::encode_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
|
||||
fn position(&self) -> usize {
|
||||
self.opaque.position()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
|
||||
pub fn position(&self) -> usize {
|
||||
self.opaque.position()
|
||||
}
|
||||
|
||||
fn emit_node<F: FnOnce(&mut Self, usize) -> R, R>(&mut self, f: F) -> R {
|
||||
assert_eq!(self.lazy_state, LazyState::NoNode);
|
||||
let pos = self.position();
|
||||
|
@ -204,44 +200,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Encode the given value or a previously cached shorthand.
|
||||
fn encode_with_shorthand<T, U, M>(&mut self,
|
||||
value: &T,
|
||||
variant: &U,
|
||||
map: M)
|
||||
-> Result<(), <Self as Encoder>::Error>
|
||||
where M: for<'b> Fn(&'b mut Self) -> &'b mut FxHashMap<T, usize>,
|
||||
T: Clone + Eq + Hash,
|
||||
U: Encodable
|
||||
{
|
||||
let existing_shorthand = map(self).get(value).cloned();
|
||||
if let Some(shorthand) = existing_shorthand {
|
||||
return self.emit_usize(shorthand);
|
||||
}
|
||||
|
||||
let start = self.position();
|
||||
variant.encode(self)?;
|
||||
let len = self.position() - start;
|
||||
|
||||
// The shorthand encoding uses the same usize as the
|
||||
// discriminant, with an offset so they can't conflict.
|
||||
let discriminant = unsafe { intrinsics::discriminant_value(variant) };
|
||||
assert!(discriminant < SHORTHAND_OFFSET as u64);
|
||||
let shorthand = start + SHORTHAND_OFFSET;
|
||||
|
||||
// Get the number of bits that leb128 could fit
|
||||
// in the same space as the fully encoded type.
|
||||
let leb128_bits = len * 7;
|
||||
|
||||
// Check that the shorthand is a not longer than the
|
||||
// full encoding itself, i.e. it's an obvious win.
|
||||
if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
|
||||
map(self).insert(value.clone(), shorthand);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Encodes something that corresponds to a single DepNode::GlobalMetaData
|
||||
// and registers the Fingerprint in the `metadata_hashes` map.
|
||||
pub fn tracked<'x, DATA, R>(&'x mut self,
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#![feature(box_patterns)]
|
||||
#![feature(conservative_impl_trait)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(i128_type)]
|
||||
#![feature(proc_macro_internals)]
|
||||
#![feature(quote)]
|
||||
|
|
|
@ -53,11 +53,6 @@ pub const METADATA_VERSION: u8 = 4;
|
|||
pub const METADATA_HEADER: &'static [u8; 12] =
|
||||
&[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
|
||||
|
||||
/// The shorthand encoding uses an enum's variant index `usize`
|
||||
/// and is offset by this value so it never matches a real variant.
|
||||
/// This offset is also chosen so that the first byte is never < 0x80.
|
||||
pub const SHORTHAND_OFFSET: usize = 0x80;
|
||||
|
||||
/// A value of type T referred to by its absolute position
|
||||
/// in the metadata, and which can be decoded lazily.
|
||||
///
|
||||
|
|
Loading…
Reference in a new issue