Move finish out of the Encoder trait.

This simplifies things, but requires making `CacheEncoder` non-generic.

(This was previously merged as commit 4 in #94732 and then was reverted
in #97905 because it caused a perf regression.)
This commit is contained in:
Nicholas Nethercote 2022-06-16 16:00:25 +10:00
parent ca983054e1
commit bb02cc47c4
13 changed files with 51 additions and 111 deletions

View file

@ -211,7 +211,7 @@ impl CodegenResults {
encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes()); encoder.emit_raw_bytes(&RLINK_VERSION.to_be_bytes());
encoder.emit_str(RUSTC_VERSION.unwrap()); encoder.emit_str(RUSTC_VERSION.unwrap());
Encodable::encode(codegen_results, &mut encoder); Encodable::encode(codegen_results, &mut encoder);
encoder.finish().unwrap() encoder.finish()
} }
pub fn deserialize_rlink(data: Vec<u8>) -> Result<Self, String> { pub fn deserialize_rlink(data: Vec<u8>) -> Result<Self, String> {

View file

@ -3,7 +3,7 @@ use rustc_data_structures::sync::join;
use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId}; use rustc_middle::dep_graph::{DepGraph, SerializedDepGraph, WorkProduct, WorkProductId};
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
use rustc_serialize::{Encodable as RustcEncodable, Encoder}; use rustc_serialize::Encodable as RustcEncodable;
use rustc_session::Session; use rustc_session::Session;
use std::fs; use std::fs;

View file

@ -94,9 +94,6 @@ macro_rules! encoder_methods {
} }
impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
type Ok = <MemEncoder as Encoder>::Ok;
type Err = <MemEncoder as Encoder>::Err;
encoder_methods! { encoder_methods! {
emit_usize(usize); emit_usize(usize);
emit_u128(u128); emit_u128(u128);
@ -119,10 +116,6 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
emit_str(&str); emit_str(&str);
emit_raw_bytes(&[u8]); emit_raw_bytes(&[u8]);
} }
fn finish(self) -> Result<Self::Ok, Self::Err> {
self.opaque.finish()
}
} }
impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> { impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> {
@ -2216,7 +2209,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
// culminating in the `CrateRoot` which points to all of it. // culminating in the `CrateRoot` which points to all of it.
let root = ecx.encode_crate_root(); let root = ecx.encode_crate_root();
let mut result = ecx.opaque.finish().unwrap(); let mut result = ecx.opaque.finish();
// Encode the root position. // Encode the root position.
let header = METADATA_HEADER.len(); let header = METADATA_HEADER.len();

View file

@ -25,6 +25,7 @@ use rustc_span::hygiene::{
use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::source_map::{SourceMap, StableSourceFileId};
use rustc_span::CachingSourceMapView; use rustc_span::CachingSourceMapView;
use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span}; use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
use std::io;
use std::mem; use std::mem;
const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
@ -807,21 +808,10 @@ impl_ref_decoder! {<'tcx>
//- ENCODING ------------------------------------------------------------------- //- ENCODING -------------------------------------------------------------------
pub trait OpaqueEncoder: Encoder {
fn position(&self) -> usize;
}
impl OpaqueEncoder for FileEncoder {
#[inline]
fn position(&self) -> usize {
FileEncoder::position(self)
}
}
/// An encoder that can write to the incremental compilation cache. /// An encoder that can write to the incremental compilation cache.
pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> { pub struct CacheEncoder<'a, 'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
encoder: E, encoder: FileEncoder,
type_shorthands: FxHashMap<Ty<'tcx>, usize>, type_shorthands: FxHashMap<Ty<'tcx>, usize>,
predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>, predicate_shorthands: FxHashMap<ty::PredicateKind<'tcx>, usize>,
interpret_allocs: FxIndexSet<interpret::AllocId>, interpret_allocs: FxIndexSet<interpret::AllocId>,
@ -830,10 +820,7 @@ pub struct CacheEncoder<'a, 'tcx, E: OpaqueEncoder> {
hygiene_context: &'a HygieneEncodeContext, hygiene_context: &'a HygieneEncodeContext,
} }
impl<'a, 'tcx, E> CacheEncoder<'a, 'tcx, E> impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
where
E: OpaqueEncoder,
{
fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex { fn source_file_index(&mut self, source_file: Lrc<SourceFile>) -> SourceFileIndex {
self.file_to_file_index[&(&*source_file as *const SourceFile)] self.file_to_file_index[&(&*source_file as *const SourceFile)]
} }
@ -852,32 +839,27 @@ where
let end_pos = self.position(); let end_pos = self.position();
((end_pos - start_pos) as u64).encode(self); ((end_pos - start_pos) as u64).encode(self);
} }
fn finish(self) -> Result<usize, io::Error> {
self.encoder.finish()
}
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for SyntaxContext impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for SyntaxContext {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: OpaqueEncoder,
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s); rustc_span::hygiene::raw_encode_syntax_context(*self, s.hygiene_context, s);
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for ExpnId impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for ExpnId {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: OpaqueEncoder,
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
s.hygiene_context.schedule_expn_data_for_encoding(*self); s.hygiene_context.schedule_expn_data_for_encoding(*self);
self.expn_hash().encode(s); self.expn_hash().encode(s);
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for Span impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for Span {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: OpaqueEncoder,
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
let span_data = self.data_untracked(); let span_data = self.data_untracked();
span_data.ctxt.encode(s); span_data.ctxt.encode(s);
span_data.parent.encode(s); span_data.parent.encode(s);
@ -920,10 +902,7 @@ where
} }
} }
impl<'a, 'tcx, E> TyEncoder for CacheEncoder<'a, 'tcx, E> impl<'a, 'tcx> TyEncoder for CacheEncoder<'a, 'tcx> {
where
E: OpaqueEncoder,
{
type I = TyCtxt<'tcx>; type I = TyCtxt<'tcx>;
const CLEAR_CROSS_CRATE: bool = false; const CLEAR_CROSS_CRATE: bool = false;
@ -943,29 +922,20 @@ where
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for CrateNum impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for CrateNum {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: OpaqueEncoder,
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
s.tcx.stable_crate_id(*self).encode(s); s.tcx.stable_crate_id(*self).encode(s);
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefId impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for DefId {
where fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
E: OpaqueEncoder,
{
fn encode(&self, s: &mut CacheEncoder<'a, 'tcx, E>) {
s.tcx.def_path_hash(*self).encode(s); s.tcx.def_path_hash(*self).encode(s);
} }
} }
impl<'a, 'tcx, E> Encodable<CacheEncoder<'a, 'tcx, E>> for DefIndex impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for DefIndex {
where fn encode(&self, _: &mut CacheEncoder<'a, 'tcx>) {
E: OpaqueEncoder,
{
fn encode(&self, _: &mut CacheEncoder<'a, 'tcx, E>) {
bug!("encoding `DefIndex` without context"); bug!("encoding `DefIndex` without context");
} }
} }
@ -979,13 +949,7 @@ macro_rules! encoder_methods {
} }
} }
impl<'a, 'tcx, E> Encoder for CacheEncoder<'a, 'tcx, E> impl<'a, 'tcx> Encoder for CacheEncoder<'a, 'tcx> {
where
E: OpaqueEncoder,
{
type Ok = E::Ok;
type Err = E::Err;
encoder_methods! { encoder_methods! {
emit_usize(usize); emit_usize(usize);
emit_u128(u128); emit_u128(u128);
@ -1008,30 +972,26 @@ where
emit_str(&str); emit_str(&str);
emit_raw_bytes(&[u8]); emit_raw_bytes(&[u8]);
} }
fn finish(self) -> Result<E::Ok, E::Err> {
self.encoder.finish()
}
} }
// This ensures that the `Encodable<opaque::FileEncoder>::encode` specialization for byte slices // This ensures that the `Encodable<opaque::FileEncoder>::encode` specialization for byte slices
// is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`. // is used when a `CacheEncoder` having an `opaque::FileEncoder` is passed to `Encodable::encode`.
// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder` // Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
// and the encoding traits currently work. // and the encoding traits currently work.
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, FileEncoder>> for [u8] { impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for [u8] {
fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, FileEncoder>) { fn encode(&self, e: &mut CacheEncoder<'a, 'tcx>) {
self.encode(&mut e.encoder); self.encode(&mut e.encoder);
} }
} }
pub fn encode_query_results<'a, 'tcx, CTX, Q>( pub fn encode_query_results<'a, 'tcx, CTX, Q>(
tcx: CTX, tcx: CTX,
encoder: &mut CacheEncoder<'a, 'tcx, FileEncoder>, encoder: &mut CacheEncoder<'a, 'tcx>,
query_result_index: &mut EncodedDepNodeIndex, query_result_index: &mut EncodedDepNodeIndex,
) where ) where
CTX: QueryContext + 'tcx, CTX: QueryContext + 'tcx,
Q: super::QueryDescription<CTX>, Q: super::QueryDescription<CTX>,
Q::Value: Encodable<CacheEncoder<'a, 'tcx, FileEncoder>>, Q::Value: Encodable<CacheEncoder<'a, 'tcx>>,
{ {
let _timer = tcx let _timer = tcx
.dep_context() .dep_context()

View file

@ -12,7 +12,6 @@ use rustc_query_system::query::{QueryContext, QueryJobId, QueryMap, QuerySideEff
use rustc_data_structures::sync::Lock; use rustc_data_structures::sync::Lock;
use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::thin_vec::ThinVec;
use rustc_errors::{Diagnostic, Handler}; use rustc_errors::{Diagnostic, Handler};
use rustc_serialize::opaque;
use std::any::Any; use std::any::Any;
use std::num::NonZeroU64; use std::num::NonZeroU64;
@ -140,7 +139,7 @@ impl<'tcx> QueryCtxt<'tcx> {
pub(super) fn encode_query_results( pub(super) fn encode_query_results(
self, self,
encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx, opaque::FileEncoder>, encoder: &mut on_disk_cache::CacheEncoder<'_, 'tcx>,
query_result_index: &mut on_disk_cache::EncodedDepNodeIndex, query_result_index: &mut on_disk_cache::EncodedDepNodeIndex,
) { ) {
macro_rules! encode_queries { macro_rules! encode_queries {

View file

@ -20,7 +20,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::sync::Lock; use rustc_data_structures::sync::Lock;
use rustc_index::vec::{Idx, IndexVec}; use rustc_index::vec::{Idx, IndexVec};
use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder}; use rustc_serialize::opaque::{FileEncodeResult, FileEncoder, IntEncodedWithFixedSize, MemDecoder};
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_serialize::{Decodable, Decoder, Encodable};
use smallvec::SmallVec; use smallvec::SmallVec;
use std::convert::TryInto; use std::convert::TryInto;

View file

@ -24,6 +24,10 @@ impl MemEncoder {
pub fn position(&self) -> usize { pub fn position(&self) -> usize {
self.data.len() self.data.len()
} }
pub fn finish(self) -> Vec<u8> {
self.data
}
} }
macro_rules! write_leb128 { macro_rules! write_leb128 {
@ -54,9 +58,6 @@ macro_rules! write_leb128 {
const STR_SENTINEL: u8 = 0xC1; const STR_SENTINEL: u8 = 0xC1;
impl Encoder for MemEncoder { impl Encoder for MemEncoder {
type Ok = Vec<u8>;
type Err = !;
#[inline] #[inline]
fn emit_usize(&mut self, v: usize) { fn emit_usize(&mut self, v: usize) {
write_leb128!(self, v, usize, write_usize_leb128) write_leb128!(self, v, usize, write_usize_leb128)
@ -150,10 +151,6 @@ impl Encoder for MemEncoder {
fn emit_raw_bytes(&mut self, s: &[u8]) { fn emit_raw_bytes(&mut self, s: &[u8]) {
self.data.extend_from_slice(s); self.data.extend_from_slice(s);
} }
fn finish(self) -> Result<Self::Ok, Self::Err> {
Ok(self.data)
}
} }
pub type FileEncodeResult = Result<usize, io::Error>; pub type FileEncodeResult = Result<usize, io::Error>;
@ -389,6 +386,13 @@ impl FileEncoder {
} }
} }
} }
pub fn finish(mut self) -> Result<usize, io::Error> {
self.flush();
let res = std::mem::replace(&mut self.res, Ok(()));
res.map(|()| self.position())
}
} }
impl Drop for FileEncoder { impl Drop for FileEncoder {
@ -426,9 +430,6 @@ macro_rules! file_encoder_write_leb128 {
} }
impl Encoder for FileEncoder { impl Encoder for FileEncoder {
type Ok = usize;
type Err = io::Error;
#[inline] #[inline]
fn emit_usize(&mut self, v: usize) { fn emit_usize(&mut self, v: usize) {
file_encoder_write_leb128!(self, v, usize, write_usize_leb128) file_encoder_write_leb128!(self, v, usize, write_usize_leb128)
@ -522,13 +523,6 @@ impl Encoder for FileEncoder {
fn emit_raw_bytes(&mut self, s: &[u8]) { fn emit_raw_bytes(&mut self, s: &[u8]) {
self.write_all(s); self.write_all(s);
} }
fn finish(mut self) -> Result<usize, io::Error> {
self.flush();
let res = std::mem::replace(&mut self.res, Ok(()));
res.map(|()| self.position())
}
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View file

@ -18,13 +18,10 @@ use std::sync::Arc;
/// is pervasive and has non-trivial cost. Instead, impls of this trait must /// is pervasive and has non-trivial cost. Instead, impls of this trait must
/// implement a delayed error handling strategy. If a failure occurs, they /// implement a delayed error handling strategy. If a failure occurs, they
/// should record this internally, and all subsequent encoding operations can /// should record this internally, and all subsequent encoding operations can
/// be processed or ignored, whichever is appropriate. Then when `finish()` is /// be processed or ignored, whichever is appropriate. Then they should provide
/// called, an error result should be returned to indicate the failure. If no /// a `finish` method that finishes up encoding. If the encoder is fallible,
/// failures occurred, then `finish()` should return a success result. /// `finish` should return a `Result` that indicates success or failure.
pub trait Encoder { pub trait Encoder {
type Ok;
type Err;
// Primitive types: // Primitive types:
fn emit_usize(&mut self, v: usize); fn emit_usize(&mut self, v: usize);
fn emit_u128(&mut self, v: u128); fn emit_u128(&mut self, v: u128);
@ -64,9 +61,6 @@ pub trait Encoder {
fn emit_fieldless_enum_variant<const ID: usize>(&mut self) { fn emit_fieldless_enum_variant<const ID: usize>(&mut self) {
self.emit_usize(ID) self.emit_usize(ID)
} }
// Consume the encoder, getting the result.
fn finish(self) -> Result<Self::Ok, Self::Err>;
} }
// Note: all the methods in this trait are infallible, which may be surprising. // Note: all the methods in this trait are infallible, which may be surprising.

View file

@ -2,7 +2,7 @@
use rustc_macros::{Decodable, Encodable}; use rustc_macros::{Decodable, Encodable};
use rustc_serialize::opaque::{MemDecoder, MemEncoder}; use rustc_serialize::opaque::{MemDecoder, MemEncoder};
use rustc_serialize::{Decodable, Encodable, Encoder as EncoderTrait}; use rustc_serialize::{Decodable, Encodable};
use std::fmt::Debug; use std::fmt::Debug;
#[derive(PartialEq, Clone, Debug, Encodable, Decodable)] #[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
@ -38,7 +38,7 @@ fn check_round_trip<
Encodable::encode(value, &mut encoder); Encodable::encode(value, &mut encoder);
} }
let data = encoder.finish().unwrap(); let data = encoder.finish();
let mut decoder = MemDecoder::new(&data[..], 0); let mut decoder = MemDecoder::new(&data[..], 0);
for value in values { for value in values {

View file

@ -18,7 +18,7 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_serialize::{ use rustc_serialize::{
opaque::{FileEncoder, MemDecoder}, opaque::{FileEncoder, MemDecoder},
Decodable, Encodable, Encoder, Decodable, Encodable,
}; };
use rustc_session::getopts; use rustc_session::getopts;
use rustc_span::{ use rustc_span::{

View file

@ -20,7 +20,7 @@ fn main() {
let mut encoder = MemEncoder::new(); let mut encoder = MemEncoder::new();
obj.encode(&mut encoder); obj.encode(&mut encoder);
let data = encoder.finish().unwrap(); let data = encoder.finish();
let mut decoder = MemDecoder::new(&data, 0); let mut decoder = MemDecoder::new(&data, 0);
let obj2 = A::decode(&mut decoder); let obj2 = A::decode(&mut decoder);

View file

@ -29,7 +29,7 @@ fn main() {
let mut encoder = MemEncoder::new(); let mut encoder = MemEncoder::new();
obj.encode(&mut encoder); obj.encode(&mut encoder);
let data = encoder.finish().unwrap(); let data = encoder.finish();
let mut decoder = MemDecoder::new(&data, 0); let mut decoder = MemDecoder::new(&data, 0);
let obj2 = B::decode(&mut decoder); let obj2 = B::decode(&mut decoder);

View file

@ -19,7 +19,7 @@ pub fn main() {
let mut encoder = MemEncoder::new(); let mut encoder = MemEncoder::new();
obj.encode(&mut encoder); obj.encode(&mut encoder);
let data = encoder.finish().unwrap(); let data = encoder.finish();
let mut decoder = MemDecoder::new(&data, 0); let mut decoder = MemDecoder::new(&data, 0);
let obj2 = UnitLikeStruct::decode(&mut decoder); let obj2 = UnitLikeStruct::decode(&mut decoder);