Skip to content

Commit be79f49

Browse files
committed
rustc_serialize: specialize opaque decoding of some u8 sequences
1 parent 7c6274d commit be79f49

File tree

5 files changed

+42
-26
lines changed

5 files changed

+42
-26
lines changed

compiler/rustc_middle/src/ty/query/on_disk_cache.rs

+9
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,15 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
807807

808808
crate::implement_ty_decoder!(CacheDecoder<'a, 'tcx>);
809809

810+
// This ensures that the `Decodable<opaque::Decoder>::decode` specialization for `Vec<u8>` is used
811+
// when a `CacheDecoder` is passed to `Decodable::decode`. Unfortunately, we have to manually opt
812+
// into specializations this way, given how `CacheDecoder` and the decoding traits currently work.
813+
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Vec<u8> {
814+
fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
815+
Decodable::decode(&mut d.opaque)
816+
}
817+
}
818+
810819
impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for SyntaxContext {
811820
fn decode(decoder: &mut CacheDecoder<'a, 'tcx>) -> Result<Self, String> {
812821
let syntax_contexts = decoder.syntax_contexts;

compiler/rustc_serialize/src/collection_impls.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -295,13 +295,8 @@ impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
295295

296296
impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> {
297297
fn decode(d: &mut D) -> Result<Rc<[T]>, D::Error> {
298-
d.read_seq(|d, len| {
299-
let mut vec = Vec::with_capacity(len);
300-
for index in 0..len {
301-
vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
302-
}
303-
Ok(vec.into())
304-
})
298+
let vec: Vec<T> = Decodable::decode(d)?;
299+
Ok(vec.into())
305300
}
306301
}
307302

@@ -314,12 +309,7 @@ impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
314309

315310
impl<D: Decoder, T: Decodable<D>> Decodable<D> for Arc<[T]> {
316311
fn decode(d: &mut D) -> Result<Arc<[T]>, D::Error> {
317-
d.read_seq(|d, len| {
318-
let mut vec = Vec::with_capacity(len);
319-
for index in 0..len {
320-
vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?);
321-
}
322-
Ok(vec.into())
323-
})
312+
let vec: Vec<T> = Decodable::decode(d)?;
313+
Ok(vec.into())
324314
}
325315
}

compiler/rustc_serialize/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Core encoding and decoding interfaces.
1515
#![feature(associated_type_bounds)]
1616
#![cfg_attr(bootstrap, feature(min_const_generics))]
1717
#![feature(min_specialization)]
18+
#![feature(vec_spare_capacity)]
1819
#![cfg_attr(test, feature(test))]
1920
#![allow(rustc::internal)]
2021

compiler/rustc_serialize/src/opaque.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -327,14 +327,35 @@ impl<'a> serialize::Decoder for Decoder<'a> {
327327
}
328328
}
329329

330-
// Specialize encoding byte slices. The default implementation for slices encodes and emits each
331-
// element individually. This isn't necessary for `u8` slices encoded with an `opaque::Encoder`,
332-
// because each `u8` is emitted as-is. Therefore, we can use a more efficient implementation. This
333-
// specialization applies to encoding `Vec<u8>`s, etc., since they call `encode` on their slices.
330+
// Specializations for contiguous byte sequences follow. The default implementations for slices
331+
// encode and decode each element individually. This isn't necessary for `u8` slices when using
332+
// opaque encoders and decoders, because each `u8` is unchanged by encoding and decoding.
333+
// Therefore, we can use more efficient implementations that process the entire sequence at once.
334+
335+
// Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
336+
// since the default implementations call `encode` on their slices internally.
334337
impl serialize::Encodable<Encoder> for [u8] {
335338
fn encode(&self, e: &mut Encoder) -> EncodeResult {
336339
serialize::Encoder::emit_usize(e, self.len())?;
337340
e.emit_raw_bytes(self);
338341
Ok(())
339342
}
340343
}
344+
345+
// Specialize decoding `Vec<u8>`. This specialization also applies to decoding `Box<[u8]>`s, etc.,
346+
// since the default implementations call `decode` to produce a `Vec<u8>` internally.
347+
impl<'a> serialize::Decodable<Decoder<'a>> for Vec<u8> {
348+
fn decode(d: &mut Decoder<'a>) -> Result<Self, String> {
349+
let len = serialize::Decoder::read_usize(d)?;
350+
351+
let mut v = Vec::with_capacity(len);
352+
let buf = &mut v.spare_capacity_mut()[..len];
353+
d.read_raw_bytes(buf)?;
354+
355+
unsafe {
356+
v.set_len(len);
357+
}
358+
359+
Ok(v)
360+
}
361+
}

compiler/rustc_serialize/src/serialize.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> {
545545
}
546546

547547
impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
548-
fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
548+
default fn decode(d: &mut D) -> Result<Vec<T>, D::Error> {
549549
d.read_seq(|d, len| {
550550
let mut v = Vec::with_capacity(len);
551551
for i in 0..len {
@@ -591,13 +591,8 @@ where
591591
[T]: ToOwned<Owned = Vec<T>>,
592592
{
593593
fn decode(d: &mut D) -> Result<Cow<'static, [T]>, D::Error> {
594-
d.read_seq(|d, len| {
595-
let mut v = Vec::with_capacity(len);
596-
for i in 0..len {
597-
v.push(d.read_seq_elt(i, |d| Decodable::decode(d))?);
598-
}
599-
Ok(Cow::Owned(v))
600-
})
594+
let v: Vec<T> = Decodable::decode(d)?;
595+
Ok(Cow::Owned(v))
601596
}
602597
}
603598

0 commit comments

Comments
 (0)