]> git.lizzy.rs Git - rust.git/commitdiff
rustc_metadata: use the shorthand encoding for predicates also.
authorEduard Burtescu <edy.burt@gmail.com>
Thu, 8 Sep 2016 18:36:22 +0000 (21:36 +0300)
committerEduard Burtescu <edy.burt@gmail.com>
Tue, 20 Sep 2016 17:08:04 +0000 (20:08 +0300)
src/librustc_metadata/common.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/encoder.rs
src/librustc_metadata/index.rs

index e068395f729a46e1203abec1afe005c86f5dcaca..f30551cadd97adfca0afc5bcafd092e7613a204d 100644 (file)
@@ -72,8 +72,6 @@ pub mod root_tag {
     pub const crate_info: usize = 0x104;
 
     pub const index: usize = 0x110;
-    pub const xref_index: usize = 0x111;
-    pub const xref_data: usize = 0x112;
     pub const crate_deps: usize = 0x102;
     pub const dylib_dependency_formats: usize = 0x106;
     pub const native_libraries: usize = 0x10a;
@@ -202,7 +200,7 @@ pub mod item_tag {
     pub const fn_arg_names: usize = 0x85;
 }
 
-/// The shorthand encoding of `Ty` uses `TypeVariants`' variant `usize`
+/// The shorthand encoding uses an enum's variant index `usize`
 /// and is offset by this value so it never matches a real variant.
 /// This offset is also chosen so that the first byte is never < 0x80.
-pub const TYPE_SHORTHAND_OFFSET: usize = 0x80;
+pub const SHORTHAND_OFFSET: usize = 0x80;
index dd6ef73ccdbd7e0f2f230f01d28506735ede1c30..73dcf9470183b7311d18a5cbfed67185c689ed02 100644 (file)
@@ -329,7 +329,6 @@ fn register_crate(&mut self,
             extern_crate: Cell::new(None),
             info: crate_info,
             index: decoder::load_index(metadata.as_slice()),
-            xref_index: decoder::load_xrefs(metadata.as_slice()),
             key_map: decoder::load_key_map(metadata.as_slice()),
             data: metadata,
             cnum_map: RefCell::new(cnum_map),
index c6cbe6db9098b00aa84db10e01b4b5a498a22104..44fdf29aa73c461efaa1e7c2871f431b0c5c2026 100644 (file)
@@ -80,7 +80,6 @@ pub struct CrateMetadata {
 
     pub info: common::CrateInfo,
     pub index: index::Index,
-    pub xref_index: index::DenseIndex,
 
     /// For each public item in this crate, we encode a key.  When the
     /// crate is loaded, we read all the keys and put them in this
index f3283451b93b8efee4ba920fc8e80d84df1f47db..c665a7be955dc372dee451d79719c7ca9c06b5bf 100644 (file)
@@ -243,10 +243,10 @@ fn specialized_decode(&mut self) -> Result<Ty<'tcx>, Self::Error> {
         // Handle shorthands first, if we have an usize > 0x80.
         if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
             let pos = self.read_usize()?;
-            assert!(pos >= TYPE_SHORTHAND_OFFSET);
+            assert!(pos >= SHORTHAND_OFFSET);
             let key = ty::CReaderCacheKey {
                 cnum: self.cdata().cnum,
-                pos: pos - TYPE_SHORTHAND_OFFSET
+                pos: pos - SHORTHAND_OFFSET
             };
             if let Some(ty) = tcx.rcache.borrow().get(&key).cloned() {
                 return Ok(ty);
@@ -333,11 +333,6 @@ pub fn crate_rustc_version(data: &[u8]) -> Option<String> {
     })
 }
 
-pub fn load_xrefs(data: &[u8]) -> index::DenseIndex {
-    let index = rbml::Doc::new(data).get(root_tag::xref_index);
-    index::DenseIndex::from_buf(index.data, index.start, index.end)
-}
-
 // Go through each item in the metadata and create a map from that
 // item's def-key to the item's DefIndex.
 pub fn load_key_map(data: &[u8]) -> FnvHashMap<DefKey, DefIndex> {
@@ -1099,20 +1094,28 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc,
 {
     let mut dcx = base_doc.get(tag).decoder();
     dcx.cdata = Some(cdata);
+    dcx.tcx = Some(tcx);
 
     ty::GenericPredicates {
         parent: dcx.decode(),
-        predicates: dcx.seq().map(|offset| {
-            let predicate_pos = cdata.xref_index.lookup(
-                cdata.data(), offset).unwrap() as usize;
-            let mut dcx = rbml::Doc {
-                data: cdata.data(),
-                start: predicate_pos,
-                end: cdata.data().len(),
-            }.decoder();
-            dcx.tcx = Some(tcx);
-            dcx.cdata = Some(cdata);
-            dcx.decode()
+        predicates: (0..dcx.decode::<usize>()).map(|_| {
+            // Handle shorthands first, if we have an usize > 0x80.
+            if dcx.opaque.data[dcx.opaque.position()] & 0x80 != 0 {
+                let pos = dcx.decode::<usize>();
+                assert!(pos >= SHORTHAND_OFFSET);
+                let pos = pos - SHORTHAND_OFFSET;
+
+                let mut dcx = rbml::Doc {
+                    data: cdata.data(),
+                    start: pos,
+                    end: cdata.data().len(),
+                }.decoder();
+                dcx.tcx = Some(tcx);
+                dcx.cdata = Some(cdata);
+                dcx.decode()
+            } else {
+                dcx.decode()
+            }
         }).collect()
     }
 }
index 3ad9251b0721666d9c5569063ce4983847141032..637228725e0be18b3d90843eaae1dc6462890ac7 100644 (file)
@@ -16,7 +16,7 @@
 use astencode::encode_inlined_item;
 use common::*;
 use cstore;
-use index::{self, IndexData};
+use index::IndexData;
 
 use rustc::middle::cstore::{InlinedItemRef, LinkMeta, LinkagePreference};
 use rustc::hir::def;
 use rustc::util::nodemap::{FnvHashMap, NodeSet};
 
 use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
-use std::cell::RefCell;
+use std::hash::Hash;
 use std::intrinsics;
 use std::io::prelude::*;
 use std::io::Cursor;
-use std::mem;
 use std::ops::{Deref, DerefMut};
 use std::rc::Rc;
 use std::u32;
@@ -58,14 +57,10 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
     reachable: &'a NodeSet,
     mir_map: &'a MirMap<'tcx>,
 
-    type_shorthands: RefCell<FnvHashMap<Ty<'tcx>, usize>>,
-    xrefs: FnvHashMap<XRef<'tcx>, u32>, // sequentially-assigned
+    type_shorthands: FnvHashMap<Ty<'tcx>, usize>,
+    predicate_shorthands: FnvHashMap<ty::Predicate<'tcx>, usize>,
 }
 
-/// "interned" entries referenced by id
-#[derive(PartialEq, Eq, Hash)]
-enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) }
-
 impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> {
     type Target = rbml::writer::Encoder<'a>;
     fn deref(&self) -> &Self::Target {
@@ -117,20 +112,49 @@ fn emit_nil(&mut self) -> Result<(), Self::Error> {
 
 impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
     fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
-        let existing_shorthand = self.type_shorthands.borrow().get(ty).cloned();
+        self.encode_with_shorthand(ty, &ty.sty, |ecx| &mut ecx.type_shorthands)
+    }
+}
+
+impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
+    fn seq<I, F, T>(&mut self, iter: I, mut f: F)
+    where I: IntoIterator,
+          I::IntoIter: ExactSizeIterator,
+          F: FnMut(&mut Self, I::Item) -> T,
+          T: Encodable {
+        let iter = iter.into_iter();
+        self.emit_seq(iter.len(), move |ecx| {
+            for (i, elem) in iter.enumerate() {
+                ecx.emit_seq_elt(i, |ecx| {
+                    f(ecx, elem).encode(ecx)
+                })?;
+            }
+            Ok(())
+        }).unwrap();
+    }
+
+    /// Encode the given value or a previously cached shorthand.
+    fn encode_with_shorthand<T, U, M>(&mut self, value: &T, variant: &U, map: M)
+                                      -> Result<(), <Self as Encoder>::Error>
+    where M: for<'b> Fn(&'b mut Self) -> &'b mut FnvHashMap<T, usize>,
+          T: Clone + Eq + Hash,
+          U: Encodable {
+        let existing_shorthand = map(self).get(value).cloned();
         if let Some(shorthand) = existing_shorthand {
             return self.emit_usize(shorthand);
         }
 
         let start = self.mark_stable_position();
-        ty.sty.encode(self)?;
+        variant.encode(self)?;
         let len = self.mark_stable_position() - start;
 
         // The shorthand encoding uses the same usize as the
         // discriminant, with an offset so they can't conflict.
-        let discriminant = unsafe { intrinsics::discriminant_value(&ty.sty) };
-        assert!(discriminant < TYPE_SHORTHAND_OFFSET as u64);
-        let shorthand = start + TYPE_SHORTHAND_OFFSET;
+        let discriminant = unsafe {
+            intrinsics::discriminant_value(variant)
+        };
+        assert!(discriminant < SHORTHAND_OFFSET as u64);
+        let shorthand = start + SHORTHAND_OFFSET;
 
         // Get the number of bits that leb128 could fit
         // in the same space as the fully encoded type.
@@ -139,29 +163,11 @@ fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
         // Check that the shorthand is a not longer than the
         // full encoding itself, i.e. it's an obvious win.
         if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
-            self.type_shorthands.borrow_mut().insert(*ty, shorthand);
+            map(self).insert(value.clone(), shorthand);
         }
 
         Ok(())
     }
-}
-
-impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-    fn seq<I, F, T>(&mut self, iter: I, mut f: F)
-    where I: IntoIterator,
-          I::IntoIter: ExactSizeIterator,
-          F: FnMut(&mut Self, I::Item) -> T,
-          T: Encodable {
-        let iter = iter.into_iter();
-        self.emit_seq(iter.len(), move |ecx| {
-            for (i, elem) in iter.enumerate() {
-                ecx.emit_seq_elt(i, |ecx| {
-                    f(ecx, elem).encode(ecx)
-                })?;
-            }
-            Ok(())
-        }).unwrap();
-    }
 
     /// For every DefId that we create a metadata item for, we include a
     /// serialized copy of its DefKey, which allows us to recreate a path.
@@ -393,7 +399,8 @@ fn encode_predicates(&mut self,
         self.start_tag(tag);
         predicates.parent.encode(self).unwrap();
         self.seq(&predicates.predicates, |ecx, predicate| {
-            ecx.add_xref(XRef::Predicate(predicate.clone()))
+            ecx.encode_with_shorthand(predicate, predicate,
+                                      |ecx| &mut ecx.predicate_shorthands).unwrap()
         });
         self.end_tag();
     }
@@ -575,34 +582,6 @@ fn encode_stability(ecx: &mut EncodeContext, def_id: DefId) {
 }
 
 impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
-    fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 {
-        let old_len = self.xrefs.len() as u32;
-        *self.xrefs.entry(xref).or_insert(old_len)
-    }
-
-    fn encode_xrefs(&mut self) {
-        let xrefs = mem::replace(&mut self.xrefs, Default::default());
-        let mut xref_positions = vec![0; xrefs.len()];
-
-        // Encode XRefs sorted by their ID
-        let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect();
-        sorted_xrefs.sort_by_key(|&(_, id)| id);
-
-        self.start_tag(root_tag::xref_data);
-        for (xref, id) in sorted_xrefs.into_iter() {
-            xref_positions[id as usize] = self.mark_stable_position() as u32;
-            match xref {
-                XRef::Predicate(p) => p.encode(self).unwrap()
-            }
-        }
-        self.mark_stable_position();
-        self.end_tag();
-
-        self.start_tag(root_tag::xref_index);
-        index::write_dense_index(xref_positions, &mut self.opaque.cursor);
-        self.end_tag();
-    }
-
     fn encode_info_for_item(&mut self,
                             (def_id, item): (DefId, &hir::Item)) {
         let tcx = self.tcx;
@@ -1233,7 +1212,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         reachable: reachable,
         mir_map: mir_map,
         type_shorthands: Default::default(),
-        xrefs: Default::default()
+        predicate_shorthands: Default::default()
     });
 
     // RBML compacts the encoded bytes whenever appropriate,
@@ -1345,10 +1324,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) {
     encode_item_index(ecx, items);
     let index_bytes = ecx.position() - i;
 
-    i = ecx.position();
-    ecx.encode_xrefs();
-    let xref_bytes = ecx.position() - i;
-
     let total_bytes = ecx.position();
 
     if ecx.tcx.sess.meta_stats() {
@@ -1369,7 +1344,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) {
         println!("       reachable bytes: {}", reachable_bytes);
         println!("            item bytes: {}", item_bytes);
         println!("           index bytes: {}", index_bytes);
-        println!("            xref bytes: {}", xref_bytes);
         println!("            zero bytes: {}", zero_bytes);
         println!("           total bytes: {}", total_bytes);
     }
index 80d5141c99ca5568363407410db4d7e748afba09..2c16411c37bdf349435b5fe848aa54da3eec4104 100644 (file)
@@ -108,36 +108,6 @@ pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) {
     }
 }
 
-/// A dense index with integer keys. Different API from IndexData (should
-/// these be merged?)
-pub struct DenseIndex {
-    start: usize,
-    end: usize
-}
-
-impl DenseIndex {
-    pub fn lookup(&self, buf: &[u8], ix: u32) -> Option<u32> {
-        let data = bytes_to_words(&buf[self.start..self.end]);
-        data.get(ix as usize).map(|d| u32::from_le(*d))
-    }
-    pub fn from_buf(buf: &[u8], start: usize, end: usize) -> Self {
-        assert!((end-start)%4 == 0 && start <= end && end <= buf.len());
-        DenseIndex {
-            start: start,
-            end: end
-        }
-    }
-}
-
-pub fn write_dense_index(entries: Vec<u32>, buf: &mut Cursor<Vec<u8>>) {
-    let elen = entries.len();
-    assert!(elen < u32::MAX as usize);
-
-    buf.write_all(words_to_bytes(&entries)).unwrap();
-
-    info!("write_dense_index: {} entries", elen);
-}
-
 fn bytes_to_words(b: &[u8]) -> &[u32] {
     assert!(b.len() % 4 == 0);
     unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len()/4) }