about summary refs log tree commit diff
path: root/src/librustc_metadata/decoder.rs
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-09-17 10:33:47 +0300
committerEduard Burtescu <edy.burt@gmail.com>2016-09-20 20:08:05 +0300
commitdc26a23301d8c435fae647174bd2906babbdb2f9 (patch)
treec155d3b587c5a96c3a4182e36c3dd41db9f619a0 /src/librustc_metadata/decoder.rs
parenta96abca2a4ec14df912b7ebee69dbeac19d630c4 (diff)
downloadrust-dc26a23301d8c435fae647174bd2906babbdb2f9.tar.gz
rust-dc26a23301d8c435fae647174bd2906babbdb2f9.zip
rustc_metadata: reduce Lazy{,Seq} overhead by using a relative encoding.
Diffstat (limited to 'src/librustc_metadata/decoder.rs')
-rw-r--r--src/librustc_metadata/decoder.rs47
1 files changed, 40 insertions, 7 deletions
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 7a4d3ed657a..973ef6030a3 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -52,8 +52,11 @@ pub struct DecodeContext<'a, 'tcx: 'a> {
     cdata: Option<&'a CrateMetadata>,
     from_id_range: IdRange,
     to_id_range: IdRange,
+
     // Cache the last used filemap for translating spans as an optimization.
     last_filemap_index: usize,
+
+    lazy_state: LazyState
 }
 
 /// Abstract over the various ways one can create metadata decoders.
@@ -73,7 +76,8 @@ pub trait Metadata<'a, 'tcx>: Copy {
             tcx: self.tcx(),
             from_id_range: id_range,
             to_id_range: id_range,
-            last_filemap_index: 0
+            last_filemap_index: 0,
+            lazy_state: LazyState::NoNode
         }
     }
 }
@@ -114,13 +118,16 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>
 
 impl<'a, 'tcx: 'a, T: Decodable> Lazy<T> {
     pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
-        T::decode(&mut meta.decoder(self.position)).unwrap()
+        let mut dcx = meta.decoder(self.position);
+        dcx.lazy_state = LazyState::NodeStart(self.position);
+        T::decode(&mut dcx).unwrap()
     }
 }
 
 impl<'a, 'tcx: 'a, T: Decodable> LazySeq<T> {
     pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> impl Iterator<Item=T> + 'a {
         let mut dcx = meta.decoder(self.position);
+        dcx.lazy_state = LazyState::NodeStart(self.position);
         (0..self.len).map(move |_| {
             T::decode(&mut dcx).unwrap()
         })
@@ -137,12 +144,33 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
     }
 
     fn with_position<F: FnOnce(&mut Self) -> R, R>(&mut self, pos: usize, f: F) -> R {
-        let new = opaque::Decoder::new(self.opaque.data, pos);
-        let old = mem::replace(&mut self.opaque, new);
+        let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
+        let old_opaque = mem::replace(&mut self.opaque, new_opaque);
+        let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
         let r = f(self);
-        self.opaque = old;
+        self.opaque = old_opaque;
+        self.lazy_state = old_state;
         r
     }
+
+    fn read_lazy_distance(&mut self, min_size: usize)
+                          -> Result<usize, <Self as Decoder>::Error> {
+        let distance = self.read_usize()?;
+        let position = match self.lazy_state {
+            LazyState::NoNode => {
+                bug!("read_lazy_distance: outside of a metadata node")
+            }
+            LazyState::NodeStart(start) => {
+                assert!(distance + min_size <= start);
+                start - distance - min_size
+            }
+            LazyState::Previous(last_min_end) => {
+                last_min_end + distance
+            }
+        };
+        self.lazy_state = LazyState::Previous(position + min_size);
+        Ok(position)
+    }
 }
 
 macro_rules! decoder_methods {
@@ -185,14 +213,19 @@ impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> {
 
 impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
-        Ok(Lazy::with_position(self.read_usize()?))
+        Ok(Lazy::with_position(self.read_lazy_distance(Lazy::<T>::min_size())?))
     }
 }
 
 impl<'a, 'tcx, T> SpecializedDecoder<LazySeq<T>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<LazySeq<T>, Self::Error> {
         let len = self.read_usize()?;
-        Ok(LazySeq::with_position_and_length(self.read_usize()?, len))
+        let position = if len == 0 {
+            0
+        } else {
+            self.read_lazy_distance(LazySeq::<T>::min_size(len))?
+        };
+        Ok(LazySeq::with_position_and_length(position, len))
     }
 }