提交 929f66af 编写于 作者: B bors

Auto merge of #80115 - tgnottingham:specialize_opaque_u8_sequences, r=oli-obk

rustc_serialize: specialize opaque encoding and decoding of some u8 sequences

This specializes encoding and decoding of some contiguous u8 sequences to use a more efficient implementation. The default implementations process each u8 individually, but that isn't necessary for the opaque encoder and decoder. The opaque encoding for u8s is a no-op, so we can just copy entire sequences as-is, rather than process them byte by byte.

This also changes some encode and decode implementations for contiguous sequences to forward to the slice and vector implementations, so that they can take advantage of the new specialization when applicable.
......@@ -4,7 +4,7 @@
Decodable, Encodable,
};
use std::hash::{Hash, Hasher};
use std::mem;
use std::mem::{self, MaybeUninit};
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Clone, Copy)]
pub struct Fingerprint(u64, u64);
......@@ -61,7 +61,7 @@ pub fn encode_opaque(&self, encoder: &mut opaque::Encoder) -> EncodeResult {
}
pub fn decode_opaque(decoder: &mut opaque::Decoder<'_>) -> Result<Fingerprint, String> {
let mut bytes = [0; 16];
let mut bytes: [MaybeUninit<u8>; 16] = MaybeUninit::uninit_array();
decoder.read_raw_bytes(&mut bytes)?;
......
......@@ -203,7 +203,7 @@ fn encodable_body(
#field_name,
#field_idx,
|__encoder|
::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
) {
::std::result::Result::Ok(()) => (),
::std::result::Result::Err(__err)
......@@ -237,7 +237,7 @@ fn encodable_body(
__encoder,
#field_idx,
|__encoder|
::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
) {
::std::result::Result::Ok(()) => (),
::std::result::Result::Err(__err)
......
......@@ -807,6 +807,15 @@ fn decode_alloc_id(&mut self) -> Result<interpret::AllocId, Self::Error> {
crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
// This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
// when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt
// into specializations this way, given how `CacheDecoder` and the decoding traits currently work.
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
Decodable::decode(&mut d.opaque)
}
}
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
let syntax_contexts = decoder.syntax_contexts;
......@@ -1149,6 +1158,16 @@ fn emit_unit(&mut self) -> Result<(), Self::Error> {
}
}
// This ensures that the `Encodable<opaque::Encoder>::encode` specialization for byte slices
// is used when a `CacheEncoder` having an `opaque::Encoder` is passed to `Encodable::encode`.
// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
// and the encoding traits currently work.
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, opaque::Encoder>> for [u8] {
fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, opaque::Encoder>) -> opaque::EncodeResult {
self.encode(e.encoder)
}
}
// An integer that will always encode to 8 bytes.
struct IntEncodedWithFixedSize(u64);
......
......@@ -11,12 +11,8 @@
impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?;
}
Ok(())
})
let slice: &[A::Item] = self;
slice.encode(s)
}
}
......@@ -292,46 +288,28 @@ fn decode(d: &mut D) -> Result<indexmap::IndexSet<T, S>, D::Error> {
impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
fn encode(&self, s: &mut E) -> Result<(), E::Error> {
s.emit_seq(self.len(), |s| {
for (index, e) in self.iter().enumerate() {
s.emit_seq_elt(index, |s| e.encode(s))?;
}
Ok(())
})
let slice: &[T] = self;
slice.encode(s)
}
}
impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> {
fn decode(d: &mut D) -> Result<Rc<[T]>, D::Error> {
d.read_seq(|d, len| {
let mut vec = Vec::with_capacity(len);
for index in 0..len {
vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
}
Ok(vec.into())
})
let vec: Vec<T> = Decodable::decode(d)?;
Ok(vec.into())
}
}
impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
fn encode(&self, s: &mut E) -> Result<(), E::Error> {
s.emit_seq(self.len(), |s| {
for (index, e) in self.iter().enumerate() {
s.emit_seq_elt(index, |s| e.encode(s))?;
}
Ok(())
})
let slice: &[T] = self;
slice.encode(s)
}
}
impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<[T]> {
fn decode(d: &mut D) -> Result<Arc<[T]>, D::Error> {
d.read_seq(|d, len| {
let mut vec = Vec::with_capacity(len);
for index in 0..len {
vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
}
Ok(vec.into())
})
let vec: Vec<T> = Decodable::decode(d)?;
Ok(vec.into())
}
}
......@@ -14,6 +14,8 @@
#![feature(nll)]
#![feature(associated_type_bounds)]
#![cfg_attr(bootstrap, feature(min_const_generics))]
#![feature(min_specialization)]
#![feature(vec_spare_capacity)]
#![cfg_attr(test, feature(test))]
#![allow(rustc::internal)]
......
use crate::leb128::{self, read_signed_leb128, write_signed_leb128};
use crate::serialize;
use std::borrow::Cow;
use std::mem::MaybeUninit;
use std::ptr;
// -----------------------------------------------------------------------------
// Encoder
......@@ -179,11 +181,19 @@ pub fn advance(&mut self, bytes: usize) {
}
#[inline]
pub fn read_raw_bytes(&mut self, s: &mut [u8]) -> Result<(), String> {
pub fn read_raw_bytes(&mut self, s: &mut [MaybeUninit<u8>]) -> Result<(), String> {
let start = self.position;
let end = start + s.len();
assert!(end <= self.data.len());
s.copy_from_slice(&self.data[start..end]);
// SAFETY: Both `src` and `dst` point to at least `s.len()` elements:
// `src` points to at least `s.len()` elements by above assert, and
// `dst` points to `s.len()` elements by derivation from `s`.
unsafe {
let src = self.data.as_ptr().add(start);
let dst = s.as_mut_ptr() as *mut u8;
ptr::copy_nonoverlapping(src, dst, s.len());
}
self.position = end;
......@@ -316,3 +326,36 @@ fn error(&mut self, err: &str) -> Self::Error {
err.to_string()
}
}
// Specializations for contiguous byte sequences follow. The default implementations for slices
// encode and decode each element individually. This isn't necessary for `u8` slices when using
// opaque encoders and decoders, because each `u8` is unchanged by encoding and decoding.
// Therefore, we can use more efficient implementations that process the entire sequence at once.
// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
// since the default implementations call `encode` on their slices internally.
impl serialize::Encodable<Encoder> for [u8] {
fn encode(&self, e: &mut Encoder) -> EncodeResult {
serialize::Encoder::emit_usize(e, self.len())?;
e.emit_raw_bytes(self);
Ok(())
}
}
// Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc.,
// since the default implementations call `decode` to produce a `Vec<u8>` internally.
impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> {
fn decode(d: &mut Decoder<'a>) -> Result<Self, String> {
let len = serialize::Decoder::read_usize(d)?;
let mut v = Vec::with_capacity(len);
let buf = &mut v.spare_capacity_mut()[..len];
d.read_raw_bytes(buf)?;
unsafe {
v.set_len(len);
}
Ok(v)
}
}
......@@ -527,7 +527,7 @@ fn decode(d: &mut D) -> Result<Rc<T>, D::Error> {
}
impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
default fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
s.emit_seq_elt(i, |s| e.encode(s))?
......@@ -545,7 +545,7 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> {
}
impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
default fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
d.read_seq(|d, len| {
let mut v = Vec::with_capacity(len);
for i in 0..len {
......@@ -591,13 +591,8 @@ impl<D: Decoder, T: Decodable<D> + ToOwned> Decodable<D> for Cow<'static, [T]>
[T]: ToOwned<Owned = Vec<T>>,
{
fn decode(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
d.read_seq(|d, len| {
let mut v = Vec::with_capacity(len);
for i in 0..len {
v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
}
Ok(Cow::Owned(v))
})
let v: Vec<T> = Decodable::decode(d)?;
Ok(Cow::Owned(v))
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册