about summary refs log tree commit diff
path: root/compiler/rustc_query_impl/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-04-26 02:36:42 +0000
committerbors <bors@rust-lang.org>2023-04-26 02:36:42 +0000
commitadaac6b166df57ea5a20d56e4cce503b55aca927 (patch)
tree2a058aa7f4bc9cc6cf3586c7dcb24afa19bdbf86 /compiler/rustc_query_impl/src
parent84d4f16728ed2e5a90c800d6d84225be3ca7c3c8 (diff)
parent1f67ba61a985c621cb10ae091aaa5c2b009aa721 (diff)
downloadrust-adaac6b166df57ea5a20d56e4cce503b55aca927.tar.gz
rust-adaac6b166df57ea5a20d56e4cce503b55aca927.zip
Auto merge of #110634 - saethlin:pointy-decoder, r=cjgillot
Rewrite MemDecoder around pointers not a slice

This is basically https://github.com/rust-lang/rust/pull/109910 but I'm being a lot more aggressive. The pointer-based structure means that it makes a lot more sense to absorb more complexity into `MemDecoder`, most of the diff is just complexity moving from one place to another.

The primary argument for this structure is that we only incur a single bounds check when doing multi-byte reads from a `MemDecoder`. With the slice-based implementation we need to do those with `data[position..position + len]` , which needs to account for `position + len` wrapping. It would be possible to dodge the first bounds check if we stored a slice that starts at `position`, but that would require updating the pointer and length on every read.

This PR also embeds the failure path in a separate function, which means that this PR should subsume all the perf wins observed in https://github.com/rust-lang/rust/pull/109867.
Diffstat (limited to 'compiler/rustc_query_impl/src')
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs56
1 files changed, 12 insertions, 44 deletions
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 91b56660b15..c0f2d7803d4 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -169,13 +169,12 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
 
             // Decode the *position* of the footer, which can be found in the
             // last 8 bytes of the file.
-            decoder.set_position(data.len() - IntEncodedWithFixedSize::ENCODED_SIZE);
-            let footer_pos = IntEncodedWithFixedSize::decode(&mut decoder).0 as usize;
-
+            let footer_pos = decoder
+                .with_position(decoder.len() - IntEncodedWithFixedSize::ENCODED_SIZE, |decoder| {
+                    IntEncodedWithFixedSize::decode(decoder).0 as usize
+                });
             // Decode the file footer, which contains all the lookup tables, etc.
-            decoder.set_position(footer_pos);
-
-            decode_tagged(&mut decoder, TAG_FILE_FOOTER)
+            decoder.with_position(footer_pos, |decoder| decode_tagged(decoder, TAG_FILE_FOOTER))
         };
 
         Self {
@@ -522,29 +521,13 @@ impl<'a, 'tcx> CacheDecoder<'a, 'tcx> {
     }
 }
 
-trait DecoderWithPosition: Decoder {
-    fn position(&self) -> usize;
-}
-
-impl<'a> DecoderWithPosition for MemDecoder<'a> {
-    fn position(&self) -> usize {
-        self.position()
-    }
-}
-
-impl<'a, 'tcx> DecoderWithPosition for CacheDecoder<'a, 'tcx> {
-    fn position(&self) -> usize {
-        self.opaque.position()
-    }
-}
-
 // Decodes something that was encoded with `encode_tagged()` and verify that the
 // tag matches and the correct amount of bytes was read.
 fn decode_tagged<D, T, V>(decoder: &mut D, expected_tag: T) -> V
 where
     T: Decodable<D> + Eq + std::fmt::Debug,
     V: Decodable<D>,
-    D: DecoderWithPosition,
+    D: Decoder,
 {
     let start_pos = decoder.position();
 
@@ -568,16 +551,6 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> {
         self.tcx
     }
 
-    #[inline]
-    fn position(&self) -> usize {
-        self.opaque.position()
-    }
-
-    #[inline]
-    fn peek_byte(&self) -> u8 {
-        self.opaque.data[self.opaque.position()]
-    }
-
     fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
     where
         F: FnOnce(&mut Self) -> Ty<'tcx>,
@@ -600,9 +573,9 @@ impl<'a, 'tcx> TyDecoder for CacheDecoder<'a, 'tcx> {
     where
         F: FnOnce(&mut Self) -> R,
     {
-        debug_assert!(pos < self.opaque.data.len());
+        debug_assert!(pos < self.opaque.len());
 
-        let new_opaque = MemDecoder::new(self.opaque.data, pos);
+        let new_opaque = MemDecoder::new(self.opaque.data(), pos);
         let old_opaque = mem::replace(&mut self.opaque, new_opaque);
         let r = f(self);
         self.opaque = old_opaque;
@@ -743,17 +716,12 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Symbol {
             SYMBOL_OFFSET => {
                 // read str offset
                 let pos = d.read_usize();
-                let old_pos = d.opaque.position();
 
                 // move to str offset and read
-                d.opaque.set_position(pos);
-                let s = d.read_str();
-                let sym = Symbol::intern(s);
-
-                // restore position
-                d.opaque.set_position(old_pos);
-
-                sym
+                d.opaque.with_position(pos, |d| {
+                    let s = d.read_str();
+                    Symbol::intern(s)
+                })
             }
             SYMBOL_PREINTERNED => {
                 let symbol_index = d.read_u32();