about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorTyson Nottingham <tgnottingham@gmail.com>2020-12-16 21:03:45 -0800
committerTyson Nottingham <tgnottingham@gmail.com>2021-01-01 22:49:16 -0800
commitbe79f493fb310b3a6b01ceada32713813bb12a91 (patch)
treed13729e7f7c857bc1821b87d849fd37ac22e88ee /compiler
parent7c6274d464d729faa9bab45086df847d5374431b (diff)
downloadrust-be79f493fb310b3a6b01ceada32713813bb12a91.tar.gz
rust-be79f493fb310b3a6b01ceada32713813bb12a91.zip
rustc_serialize: specialize opaque decoding of some u8 sequences
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_middle/src/ty/query/on_disk_cache.rs9
-rw-r--r--compiler/rustc_serialize/src/collection_impls.rs18
-rw-r--r--compiler/rustc_serialize/src/lib.rs1
-rw-r--r--compiler/rustc_serialize/src/opaque.rs29
-rw-r--r--compiler/rustc_serialize/src/serialize.rs11
5 files changed, 42 insertions, 26 deletions
diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
index 4aa4ff72eb2..9b40c9a7ed8 100644
--- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
+++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs
@@ -807,6 +807,15 @@ impl<'a, 'tcx> TyDecoder<'tcx> for CacheDecoder<'a, 'tcx> {
 
 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;
diff --git a/compiler/rustc_serialize/src/collection_impls.rs b/compiler/rustc_serialize/src/collection_impls.rs
index 57082da29f2..ae6d27e037b 100644
--- a/compiler/rustc_serialize/src/collection_impls.rs
+++ b/compiler/rustc_serialize/src/collection_impls.rs
@@ -295,13 +295,8 @@ impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
 
 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())
     }
 }
 
@@ -314,12 +309,7 @@ impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
 
 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())
     }
 }
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index 0e7974afff3..f58ed14d997 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -15,6 +15,7 @@ Core encoding and decoding interfaces.
 #![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)]
 
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 5ef1c7241de..673742df7f0 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -327,10 +327,13 @@ impl<'a> serialize::Decoder for Decoder<'a> {
     }
 }
 
-// Specialize encoding byte slices. The default implementation for slices encodes and emits each
-// element individually. This isn't necessary for `u8` slices encoded with an `opaque::Encoder`,
-// because each `u8` is emitted as-is. Therefore, we can use a more efficient implementation. This
-// specialization applies to encoding `Vec<u8>`s, etc., since they call `encode` on their slices.
+// 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())?;
@@ -338,3 +341,21 @@ impl serialize::Encodable<Encoder> for [u8] {
         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)
+    }
+}
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index ee8ab0e9e40..47aad5b88c6 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -545,7 +545,7 @@ impl<S: Encoder, T: Encodable<S>> Encodable<S> for Vec<T> {
 }
 
 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 @@ where
     [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))
     }
 }