Skip to content

Commit 6890354

Browse files
committed
rustc_metadata: use the shorthand encoding for predicates also.
1 parent cc47dc5 commit 6890354

File tree

6 files changed

+65
-122
lines changed

6 files changed

+65
-122
lines changed

src/librustc_metadata/common.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,6 @@ pub mod root_tag {
7272
pub const crate_info: usize = 0x104;
7373

7474
pub const index: usize = 0x110;
75-
pub const xref_index: usize = 0x111;
76-
pub const xref_data: usize = 0x112;
7775
pub const crate_deps: usize = 0x102;
7876
pub const dylib_dependency_formats: usize = 0x106;
7977
pub const native_libraries: usize = 0x10a;
@@ -202,7 +200,7 @@ pub mod item_tag {
202200
pub const fn_arg_names: usize = 0x85;
203201
}
204202

205-
/// The shorthand encoding of `Ty` uses `TypeVariants`' variant `usize`
203+
/// The shorthand encoding uses an enum's variant index `usize`
206204
/// and is offset by this value so it never matches a real variant.
207205
/// This offset is also chosen so that the first byte is never < 0x80.
208-
pub const TYPE_SHORTHAND_OFFSET: usize = 0x80;
206+
pub const SHORTHAND_OFFSET: usize = 0x80;

src/librustc_metadata/creader.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,6 @@ impl<'a> CrateReader<'a> {
329329
extern_crate: Cell::new(None),
330330
info: crate_info,
331331
index: decoder::load_index(metadata.as_slice()),
332-
xref_index: decoder::load_xrefs(metadata.as_slice()),
333332
key_map: decoder::load_key_map(metadata.as_slice()),
334333
data: metadata,
335334
cnum_map: RefCell::new(cnum_map),

src/librustc_metadata/cstore.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ pub struct CrateMetadata {
8080

8181
pub info: common::CrateInfo,
8282
pub index: index::Index,
83-
pub xref_index: index::DenseIndex,
8483

8584
/// For each public item in this crate, we encode a key. When the
8685
/// crate is loaded, we read all the keys and put them in this

src/librustc_metadata/decoder.rs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,10 @@ impl<'a, 'tcx> SpecializedDecoder<Ty<'tcx>> for DecodeContext<'a, 'tcx> {
243243
// Handle shorthands first, if we have an usize > 0x80.
244244
if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
245245
let pos = self.read_usize()?;
246-
assert!(pos >= TYPE_SHORTHAND_OFFSET);
246+
assert!(pos >= SHORTHAND_OFFSET);
247247
let key = ty::CReaderCacheKey {
248248
cnum: self.cdata().cnum,
249-
pos: pos - TYPE_SHORTHAND_OFFSET
249+
pos: pos - SHORTHAND_OFFSET
250250
};
251251
if let Some(ty) = tcx.rcache.borrow().get(&key).cloned() {
252252
return Ok(ty);
@@ -333,11 +333,6 @@ pub fn crate_rustc_version(data: &[u8]) -> Option<String> {
333333
})
334334
}
335335

336-
pub fn load_xrefs(data: &[u8]) -> index::DenseIndex {
337-
let index = rbml::Doc::new(data).get(root_tag::xref_index);
338-
index::DenseIndex::from_buf(index.data, index.start, index.end)
339-
}
340-
341336
// Go through each item in the metadata and create a map from that
342337
// item's def-key to the item's DefIndex.
343338
pub fn load_key_map(data: &[u8]) -> FnvHashMap<DefKey, DefIndex> {
@@ -1099,20 +1094,28 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc,
10991094
{
11001095
let mut dcx = base_doc.get(tag).decoder();
11011096
dcx.cdata = Some(cdata);
1097+
dcx.tcx = Some(tcx);
11021098

11031099
ty::GenericPredicates {
11041100
parent: dcx.decode(),
1105-
predicates: dcx.seq().map(|offset| {
1106-
let predicate_pos = cdata.xref_index.lookup(
1107-
cdata.data(), offset).unwrap() as usize;
1108-
let mut dcx = rbml::Doc {
1109-
data: cdata.data(),
1110-
start: predicate_pos,
1111-
end: cdata.data().len(),
1112-
}.decoder();
1113-
dcx.tcx = Some(tcx);
1114-
dcx.cdata = Some(cdata);
1115-
dcx.decode()
1101+
predicates: (0..dcx.decode::<usize>()).map(|_| {
1102+
// Handle shorthands first, if we have an usize > 0x80.
1103+
if dcx.opaque.data[dcx.opaque.position()] & 0x80 != 0 {
1104+
let pos = dcx.decode::<usize>();
1105+
assert!(pos >= SHORTHAND_OFFSET);
1106+
let pos = pos - SHORTHAND_OFFSET;
1107+
1108+
let mut dcx = rbml::Doc {
1109+
data: cdata.data(),
1110+
start: pos,
1111+
end: cdata.data().len(),
1112+
}.decoder();
1113+
dcx.tcx = Some(tcx);
1114+
dcx.cdata = Some(cdata);
1115+
dcx.decode()
1116+
} else {
1117+
dcx.decode()
1118+
}
11161119
}).collect()
11171120
}
11181121
}

src/librustc_metadata/encoder.rs

Lines changed: 42 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use astencode::encode_inlined_item;
1717
use common::*;
1818
use cstore;
19-
use index::{self, IndexData};
19+
use index::IndexData;
2020

2121
use rustc::middle::cstore::{InlinedItemRef, LinkMeta, LinkagePreference};
2222
use rustc::hir::def;
@@ -30,11 +30,10 @@ use rustc::session::config::{self, CrateTypeRustcMacro};
3030
use rustc::util::nodemap::{FnvHashMap, NodeSet};
3131

3232
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
33-
use std::cell::RefCell;
33+
use std::hash::Hash;
3434
use std::intrinsics;
3535
use std::io::prelude::*;
3636
use std::io::Cursor;
37-
use std::mem;
3837
use std::ops::{Deref, DerefMut};
3938
use std::rc::Rc;
4039
use std::u32;
@@ -58,14 +57,10 @@ pub struct EncodeContext<'a, 'tcx: 'a> {
5857
reachable: &'a NodeSet,
5958
mir_map: &'a MirMap<'tcx>,
6059

61-
type_shorthands: RefCell<FnvHashMap<Ty<'tcx>, usize>>,
62-
xrefs: FnvHashMap<XRef<'tcx>, u32>, // sequentially-assigned
60+
type_shorthands: FnvHashMap<Ty<'tcx>, usize>,
61+
predicate_shorthands: FnvHashMap<ty::Predicate<'tcx>, usize>,
6362
}
6463

65-
/// "interned" entries referenced by id
66-
#[derive(PartialEq, Eq, Hash)]
67-
enum XRef<'tcx> { Predicate(ty::Predicate<'tcx>) }
68-
6964
impl<'a, 'tcx> Deref for EncodeContext<'a, 'tcx> {
7065
type Target = rbml::writer::Encoder<'a>;
7166
fn deref(&self) -> &Self::Target {
@@ -117,20 +112,49 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
117112

118113
impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
119114
fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
120-
let existing_shorthand = self.type_shorthands.borrow().get(ty).cloned();
115+
self.encode_with_shorthand(ty, &ty.sty, |ecx| &mut ecx.type_shorthands)
116+
}
117+
}
118+
119+
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
120+
fn seq<I, F, T>(&mut self, iter: I, mut f: F)
121+
where I: IntoIterator,
122+
I::IntoIter: ExactSizeIterator,
123+
F: FnMut(&mut Self, I::Item) -> T,
124+
T: Encodable {
125+
let iter = iter.into_iter();
126+
self.emit_seq(iter.len(), move |ecx| {
127+
for (i, elem) in iter.enumerate() {
128+
ecx.emit_seq_elt(i, |ecx| {
129+
f(ecx, elem).encode(ecx)
130+
})?;
131+
}
132+
Ok(())
133+
}).unwrap();
134+
}
135+
136+
/// Encode the given value or a previously cached shorthand.
137+
fn encode_with_shorthand<T, U, M>(&mut self, value: &T, variant: &U, map: M)
138+
-> Result<(), <Self as Encoder>::Error>
139+
where M: for<'b> Fn(&'b mut Self) -> &'b mut FnvHashMap<T, usize>,
140+
T: Clone + Eq + Hash,
141+
U: Encodable {
142+
let existing_shorthand = map(self).get(value).cloned();
121143
if let Some(shorthand) = existing_shorthand {
122144
return self.emit_usize(shorthand);
123145
}
124146

125147
let start = self.mark_stable_position();
126-
ty.sty.encode(self)?;
148+
variant.encode(self)?;
127149
let len = self.mark_stable_position() - start;
128150

129151
// The shorthand encoding uses the same usize as the
130152
// discriminant, with an offset so they can't conflict.
131-
let discriminant = unsafe { intrinsics::discriminant_value(&ty.sty) };
132-
assert!(discriminant < TYPE_SHORTHAND_OFFSET as u64);
133-
let shorthand = start + TYPE_SHORTHAND_OFFSET;
153+
let discriminant = unsafe {
154+
intrinsics::discriminant_value(variant)
155+
};
156+
assert!(discriminant < SHORTHAND_OFFSET as u64);
157+
let shorthand = start + SHORTHAND_OFFSET;
134158

135159
// Get the number of bits that leb128 could fit
136160
// in the same space as the fully encoded type.
@@ -139,29 +163,11 @@ impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
139163
// Check that the shorthand is a not longer than the
140164
// full encoding itself, i.e. it's an obvious win.
141165
if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
142-
self.type_shorthands.borrow_mut().insert(*ty, shorthand);
166+
map(self).insert(value.clone(), shorthand);
143167
}
144168

145169
Ok(())
146170
}
147-
}
148-
149-
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
150-
fn seq<I, F, T>(&mut self, iter: I, mut f: F)
151-
where I: IntoIterator,
152-
I::IntoIter: ExactSizeIterator,
153-
F: FnMut(&mut Self, I::Item) -> T,
154-
T: Encodable {
155-
let iter = iter.into_iter();
156-
self.emit_seq(iter.len(), move |ecx| {
157-
for (i, elem) in iter.enumerate() {
158-
ecx.emit_seq_elt(i, |ecx| {
159-
f(ecx, elem).encode(ecx)
160-
})?;
161-
}
162-
Ok(())
163-
}).unwrap();
164-
}
165171

166172
/// For every DefId that we create a metadata item for, we include a
167173
/// serialized copy of its DefKey, which allows us to recreate a path.
@@ -393,7 +399,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
393399
self.start_tag(tag);
394400
predicates.parent.encode(self).unwrap();
395401
self.seq(&predicates.predicates, |ecx, predicate| {
396-
ecx.add_xref(XRef::Predicate(predicate.clone()))
402+
ecx.encode_with_shorthand(predicate, predicate,
403+
|ecx| &mut ecx.predicate_shorthands).unwrap()
397404
});
398405
self.end_tag();
399406
}
@@ -575,34 +582,6 @@ fn encode_stability(ecx: &mut EncodeContext, def_id: DefId) {
575582
}
576583

577584
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
578-
fn add_xref(&mut self, xref: XRef<'tcx>) -> u32 {
579-
let old_len = self.xrefs.len() as u32;
580-
*self.xrefs.entry(xref).or_insert(old_len)
581-
}
582-
583-
fn encode_xrefs(&mut self) {
584-
let xrefs = mem::replace(&mut self.xrefs, Default::default());
585-
let mut xref_positions = vec![0; xrefs.len()];
586-
587-
// Encode XRefs sorted by their ID
588-
let mut sorted_xrefs: Vec<_> = xrefs.into_iter().collect();
589-
sorted_xrefs.sort_by_key(|&(_, id)| id);
590-
591-
self.start_tag(root_tag::xref_data);
592-
for (xref, id) in sorted_xrefs.into_iter() {
593-
xref_positions[id as usize] = self.mark_stable_position() as u32;
594-
match xref {
595-
XRef::Predicate(p) => p.encode(self).unwrap()
596-
}
597-
}
598-
self.mark_stable_position();
599-
self.end_tag();
600-
601-
self.start_tag(root_tag::xref_index);
602-
index::write_dense_index(xref_positions, &mut self.opaque.cursor);
603-
self.end_tag();
604-
}
605-
606585
fn encode_info_for_item(&mut self,
607586
(def_id, item): (DefId, &hir::Item)) {
608587
let tcx = self.tcx;
@@ -1233,7 +1212,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12331212
reachable: reachable,
12341213
mir_map: mir_map,
12351214
type_shorthands: Default::default(),
1236-
xrefs: Default::default()
1215+
predicate_shorthands: Default::default()
12371216
});
12381217

12391218
// RBML compacts the encoded bytes whenever appropriate,
@@ -1345,10 +1324,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) {
13451324
encode_item_index(ecx, items);
13461325
let index_bytes = ecx.position() - i;
13471326

1348-
i = ecx.position();
1349-
ecx.encode_xrefs();
1350-
let xref_bytes = ecx.position() - i;
1351-
13521327
let total_bytes = ecx.position();
13531328

13541329
if ecx.tcx.sess.meta_stats() {
@@ -1369,7 +1344,6 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) {
13691344
println!(" reachable bytes: {}", reachable_bytes);
13701345
println!(" item bytes: {}", item_bytes);
13711346
println!(" index bytes: {}", index_bytes);
1372-
println!(" xref bytes: {}", xref_bytes);
13731347
println!(" zero bytes: {}", zero_bytes);
13741348
println!(" total bytes: {}", total_bytes);
13751349
}

src/librustc_metadata/index.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -108,36 +108,6 @@ impl IndexData {
108108
}
109109
}
110110

111-
/// A dense index with integer keys. Different API from IndexData (should
112-
/// these be merged?)
113-
pub struct DenseIndex {
114-
start: usize,
115-
end: usize
116-
}
117-
118-
impl DenseIndex {
119-
pub fn lookup(&self, buf: &[u8], ix: u32) -> Option<u32> {
120-
let data = bytes_to_words(&buf[self.start..self.end]);
121-
data.get(ix as usize).map(|d| u32::from_le(*d))
122-
}
123-
pub fn from_buf(buf: &[u8], start: usize, end: usize) -> Self {
124-
assert!((end-start)%4 == 0 && start <= end && end <= buf.len());
125-
DenseIndex {
126-
start: start,
127-
end: end
128-
}
129-
}
130-
}
131-
132-
pub fn write_dense_index(entries: Vec<u32>, buf: &mut Cursor<Vec<u8>>) {
133-
let elen = entries.len();
134-
assert!(elen < u32::MAX as usize);
135-
136-
buf.write_all(words_to_bytes(&entries)).unwrap();
137-
138-
info!("write_dense_index: {} entries", elen);
139-
}
140-
141111
fn bytes_to_words(b: &[u8]) -> &[u32] {
142112
assert!(b.len() % 4 == 0);
143113
unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len()/4) }

0 commit comments

Comments
 (0)