Skip to content

Commit 0780eb0

Browse files
committed
more implementations moved across
1 parent 83171d0 commit 0780eb0

8 files changed

Lines changed: 482 additions & 185 deletions

File tree

compiler/rustc_middle/src/ty/codec.rs

Lines changed: 127 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66
//! The functionality in here is shared between persisting to crate metadata and
77
//! persisting to incr. comp. caches.
88
9-
use std::marker::PointeeSized;
9+
use std::hash::Hash;
10+
use std::intrinsics;
11+
use std::marker::{DiscriminantKind, PointeeSized};
1012

1113
use rustc_abi::FieldIdx;
14+
use rustc_data_structures::fx::FxHashMap;
1215
use rustc_hir::def_id::LocalDefId;
1316
use rustc_serialize::{Decodable, Encodable};
14-
use rustc_span::Span;
1517
use rustc_span::source_map::Spanned;
16-
use rustc_type_ir::codec as ir_codec;
18+
use rustc_span::{Span, SpanDecoder, SpanEncoder};
1719

1820
use crate::arena::ArenaAllocatable;
1921
use crate::infer::canonical::{CanonicalVarKind, CanonicalVarKinds};
@@ -22,13 +24,66 @@ use crate::mir::mono::MonoItem;
2224
use crate::ty::{self, AdtDef, GenericArgsRef, Ty, TyCtxt};
2325
use crate::{mir, traits};
2426

25-
pub trait TyEncoder<'tcx>: ir_codec::TyEncoder<'tcx, Interner = TyCtxt<'tcx>> {}
26-
impl<'tcx, T> TyEncoder<'tcx> for T where T: ir_codec::TyEncoder<'tcx, Interner = TyCtxt<'tcx>> {}
27+
/// The shorthand encoding uses an enum's variant index `usize`
28+
/// and is offset by this value so it never matches a real variant.
29+
/// This offset is also chosen so that the first byte is never < 0x80.
30+
pub const SHORTHAND_OFFSET: usize = 0x80;
2731

28-
pub trait TyDecoder<'tcx>: ir_codec::TyDecoder<'tcx, Interner = TyCtxt<'tcx>> {}
29-
impl<'tcx, T> TyDecoder<'tcx> for T where T: ir_codec::TyDecoder<'tcx, Interner = TyCtxt<'tcx>> {}
32+
pub trait TyEncoder<'tcx>: SpanEncoder {
33+
const CLEAR_CROSS_CRATE: bool;
3034

31-
pub use ir_codec::{EncodableWithShorthand, SHORTHAND_OFFSET, encode_with_shorthand};
35+
fn position(&self) -> usize;
36+
37+
fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
38+
39+
fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>;
40+
41+
fn encode_alloc_id(&mut self, alloc_id: &AllocId);
42+
}
43+
44+
pub trait TyDecoder<'tcx>: SpanDecoder {
45+
const CLEAR_CROSS_CRATE: bool;
46+
47+
fn interner(&self) -> TyCtxt<'tcx>;
48+
49+
fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
50+
where
51+
F: FnOnce(&mut Self) -> Ty<'tcx>;
52+
53+
fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
54+
where
55+
F: FnOnce(&mut Self) -> R;
56+
57+
fn positioned_at_shorthand(&self) -> bool {
58+
(self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
59+
}
60+
61+
fn decode_alloc_id(&mut self) -> AllocId;
62+
}
63+
64+
pub trait EncodableWithShorthand<'tcx, E: TyEncoder<'tcx>>: Copy + Eq + Hash {
65+
type Variant: Encodable<E>;
66+
fn variant(&self) -> &Self::Variant;
67+
}
68+
69+
#[allow(rustc::usage_of_ty_tykind)]
70+
impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for Ty<'tcx> {
71+
type Variant = ty::TyKind<'tcx>;
72+
73+
#[inline]
74+
fn variant(&self) -> &Self::Variant {
75+
self.kind()
76+
}
77+
}
78+
79+
impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::PredicateKind<'tcx> {
80+
type Variant = ty::PredicateKind<'tcx>;
81+
82+
#[inline]
83+
fn variant(&self) -> &Self::Variant {
84+
self
85+
}
86+
}
3287

3388
/// Trait for decoding to a reference.
3489
///
@@ -44,6 +99,51 @@ pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>>: PointeeSized {
4499
fn decode(d: &mut D) -> &'tcx Self;
45100
}
46101

102+
/// Encode the given value or a previously cached shorthand.
103+
pub fn encode_with_shorthand<'tcx, E, T, M>(encoder: &mut E, value: &T, cache: M)
104+
where
105+
E: TyEncoder<'tcx>,
106+
M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
107+
T: EncodableWithShorthand<'tcx, E>,
108+
// The discriminant and shorthand must have the same size.
109+
T::Variant: DiscriminantKind<Discriminant = isize>,
110+
{
111+
let existing_shorthand = cache(encoder).get(value).copied();
112+
if let Some(shorthand) = existing_shorthand {
113+
encoder.emit_usize(shorthand);
114+
return;
115+
}
116+
117+
let variant = value.variant();
118+
119+
let start = encoder.position();
120+
variant.encode(encoder);
121+
let len = encoder.position() - start;
122+
123+
// The shorthand encoding uses the same usize as the
124+
// discriminant, with an offset so they can't conflict.
125+
let discriminant = intrinsics::discriminant_value(variant);
126+
assert!(SHORTHAND_OFFSET > discriminant as usize);
127+
128+
let shorthand = start + SHORTHAND_OFFSET;
129+
130+
// Get the number of bits that leb128 could fit
131+
// in the same space as the fully encoded type.
132+
let leb128_bits = len * 7;
133+
134+
// Check that the shorthand is a not longer than the
135+
// full encoding itself, i.e., it's an obvious win.
136+
if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
137+
cache(encoder).insert(*value, shorthand);
138+
}
139+
}
140+
141+
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
142+
fn encode(&self, e: &mut E) {
143+
encode_with_shorthand(e, self, TyEncoder::type_shorthands);
144+
}
145+
}
146+
47147
impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> {
48148
fn encode(&self, e: &mut E) {
49149
let kind = self.kind();
@@ -130,6 +230,25 @@ fn decode_arena_allocable_slice<
130230
decoder.interner().arena.alloc_from_iter(<Vec<T> as Decodable<D>>::decode(decoder))
131231
}
132232

233+
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
234+
#[allow(rustc::usage_of_ty_tykind)]
235+
fn decode(decoder: &mut D) -> Ty<'tcx> {
236+
// Handle shorthands first, if we have a usize > 0x80.
237+
if decoder.positioned_at_shorthand() {
238+
let pos = decoder.read_usize();
239+
assert!(pos >= SHORTHAND_OFFSET);
240+
let shorthand = pos - SHORTHAND_OFFSET;
241+
242+
decoder.cached_ty_for_shorthand(shorthand, |decoder| {
243+
decoder.with_position(shorthand, Ty::decode)
244+
})
245+
} else {
246+
let tcx = decoder.interner();
247+
tcx.mk_ty_from_kind(ty::TyKind::decode(decoder))
248+
}
249+
}
250+
}
251+
133252
impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
134253
fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
135254
let bound_vars = Decodable::decode(decoder);

compiler/rustc_middle/src/ty/context/impl_interner.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,30 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
803803
) -> Ty<'tcx> {
804804
self.struct_tail_raw(ty, cause, normalize, f)
805805
}
806+
807+
fn get_ty_var(self, id: usize) -> Option<&Ty<'tcx>> {
808+
self.types.ty_vars.get(id)
809+
}
810+
811+
fn get_fresh_ty(self, id: usize) -> Option<&Ty<'tcx>> {
812+
self.types.fresh_tys.get(id)
813+
}
814+
815+
fn get_fresh_ty_int(self, id: usize) -> Option<&Ty<'tcx>> {
816+
self.types.fresh_int_tys.get(id)
817+
}
818+
819+
fn get_fresh_ty_float(self, id: usize) -> Option<&Ty<'tcx>> {
820+
self.types.fresh_float_tys.get(id)
821+
}
822+
823+
fn get_anon_bound_ty(self, id: usize) -> Option<&Vec<Ty<'tcx>>> {
824+
self.types.anon_bound_tys.get(id)
825+
}
826+
827+
fn get_anon_canonical_bound_ty(self, id: usize) -> Option<&Ty<'tcx>> {
828+
self.types.anon_canonical_bound_tys.get(var.as_usize())
829+
}
806830
}
807831

808832
/// Defines trivial conversion functions between the main [`LangItem`] enum,
@@ -841,6 +865,7 @@ bidirectional_lang_item_map! {
841865
FieldBase,
842866
FieldType,
843867
FutureOutput,
868+
GlobalAlloc,
844869
Metadata,
845870
// tidy-alphabetical-end
846871
}

0 commit comments

Comments
 (0)