rewrite metadata indexing
this improves the compilation time for small crates by ~20%
This commit is contained in:
parent
fcad49e416
commit
cde09e7ca3
@ -51,7 +51,6 @@
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(scoped_tls)]
|
||||
#![feature(slice_bytes)]
|
||||
#![feature(slice_splits)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(staged_api)]
|
||||
|
@ -45,13 +45,7 @@ pub const tag_items_data_item_is_tuple_struct_ctor: usize = 0x29;
|
||||
|
||||
pub const tag_index: usize = 0x2a;
|
||||
|
||||
pub const tag_index_buckets: usize = 0x2b;
|
||||
|
||||
pub const tag_index_buckets_bucket: usize = 0x2c;
|
||||
|
||||
pub const tag_index_buckets_bucket_elt: usize = 0x2d;
|
||||
|
||||
pub const tag_index_table: usize = 0x2e;
|
||||
// GAP 0x2b, 0x2c, 0x2d, 0x2e
|
||||
|
||||
pub const tag_meta_item_name_value: usize = 0x2f;
|
||||
|
||||
|
@ -304,6 +304,7 @@ impl<'a> CrateReader<'a> {
|
||||
let cmeta = Rc::new(cstore::crate_metadata {
|
||||
name: name.to_string(),
|
||||
local_path: RefCell::new(SmallVector::zero()),
|
||||
index: decoder::load_index(metadata.as_slice()),
|
||||
data: metadata,
|
||||
cnum_map: RefCell::new(cnum_map),
|
||||
cnum: cnum,
|
||||
@ -521,7 +522,7 @@ impl<'a> CrateReader<'a> {
|
||||
}
|
||||
|
||||
let registrar = decoder::get_plugin_registrar_fn(ekrate.metadata.as_slice())
|
||||
.map(|id| decoder::get_symbol(ekrate.metadata.as_slice(), id));
|
||||
.map(|id| decoder::get_symbol_from_buf(ekrate.metadata.as_slice(), id));
|
||||
|
||||
match (ekrate.dylib.as_ref(), registrar) {
|
||||
(Some(dylib), Some(reg)) => Some((dylib.to_path_buf(), reg)),
|
||||
|
@ -11,23 +11,18 @@
|
||||
// Searching for information from the cstore
|
||||
|
||||
use front::map as ast_map;
|
||||
use metadata::common::*;
|
||||
use metadata::cstore;
|
||||
use metadata::decoder;
|
||||
use metadata::inline::InlinedItem;
|
||||
use middle::def_id::DefId;
|
||||
use middle::lang_items;
|
||||
use middle::ty;
|
||||
use util::nodemap::FnvHashMap;
|
||||
|
||||
use rbml;
|
||||
use rbml::reader;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use rustc_front::attr;
|
||||
use rustc_front::hir;
|
||||
use syntax::diagnostic::expect;
|
||||
|
||||
use std::collections::hash_map::HashMap;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct MethodInfo {
|
||||
@ -38,7 +33,7 @@ pub struct MethodInfo {
|
||||
|
||||
pub fn get_symbol(cstore: &cstore::CStore, def: DefId) -> String {
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::get_symbol(cdata.data(), def.node)
|
||||
decoder::get_symbol(&cdata, def.node)
|
||||
}
|
||||
|
||||
/// Iterates over all the language items in the given crate.
|
||||
@ -201,7 +196,7 @@ pub fn get_struct_field_names(cstore: &cstore::CStore, def: DefId) -> Vec<ast::N
|
||||
decoder::get_struct_field_names(&cstore.intr, &*cdata, def.node)
|
||||
}
|
||||
|
||||
pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: DefId) -> HashMap<ast::NodeId,
|
||||
pub fn get_struct_field_attrs(cstore: &cstore::CStore, def: DefId) -> FnvHashMap<ast::NodeId,
|
||||
Vec<hir::Attribute>> {
|
||||
let cdata = cstore.get_crate_data(def.krate);
|
||||
decoder::get_struct_field_attrs(&*cdata)
|
||||
@ -243,31 +238,6 @@ pub fn get_super_predicates<'tcx>(tcx: &ty::ctxt<'tcx>, def: DefId)
|
||||
decoder::get_super_predicates(&*cdata, def.node, tcx)
|
||||
}
|
||||
|
||||
pub fn get_field_type<'tcx>(tcx: &ty::ctxt<'tcx>, class_id: DefId,
|
||||
def: DefId) -> ty::TypeScheme<'tcx> {
|
||||
let cstore = &tcx.sess.cstore;
|
||||
let cdata = cstore.get_crate_data(class_id.krate);
|
||||
let all_items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
|
||||
let class_doc = expect(tcx.sess.diagnostic(),
|
||||
decoder::maybe_find_item(class_id.node, all_items),
|
||||
|| {
|
||||
(format!("get_field_type: class ID {:?} not found",
|
||||
class_id)).to_string()
|
||||
});
|
||||
let the_field = expect(tcx.sess.diagnostic(),
|
||||
decoder::maybe_find_item(def.node, class_doc),
|
||||
|| {
|
||||
(format!("get_field_type: in class {:?}, field ID {:?} not found",
|
||||
class_id,
|
||||
def)).to_string()
|
||||
});
|
||||
let ty = decoder::item_type(def, the_field, tcx, &*cdata);
|
||||
ty::TypeScheme {
|
||||
generics: ty::Generics::empty(),
|
||||
ty: ty,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_impl_polarity<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
def: DefId)
|
||||
-> Option<hir::ImplPolarity>
|
||||
|
@ -18,7 +18,7 @@ pub use self::LinkagePreference::*;
|
||||
pub use self::NativeLibraryKind::*;
|
||||
|
||||
use back::svh::Svh;
|
||||
use metadata::{creader, decoder, loader};
|
||||
use metadata::{creader, decoder, index, loader};
|
||||
use session::search_paths::PathKind;
|
||||
use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||
|
||||
@ -65,6 +65,7 @@ pub struct crate_metadata {
|
||||
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
|
||||
pub span: codemap::Span,
|
||||
pub staged_api: bool,
|
||||
pub index: index::Index,
|
||||
|
||||
/// Flag if this crate is required by an rlib version of this crate, or in
|
||||
/// other words whether it was explicitly linked to. An example of a crate
|
||||
|
@ -26,6 +26,7 @@ use metadata::csearch::MethodInfo;
|
||||
use metadata::csearch;
|
||||
use metadata::cstore;
|
||||
use metadata::encoder::def_to_u64;
|
||||
use metadata::index;
|
||||
use metadata::inline::InlinedItem;
|
||||
use metadata::tydecode::TyDecoder;
|
||||
use middle::def;
|
||||
@ -37,12 +38,9 @@ use middle::ty::{self, RegionEscape, Ty};
|
||||
use util::nodemap::FnvHashMap;
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, SipHasher, Hasher};
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::rc::Rc;
|
||||
use std::slice::bytes;
|
||||
use std::str;
|
||||
|
||||
use rbml::reader;
|
||||
@ -59,57 +57,24 @@ use syntax::ptr::P;
|
||||
|
||||
pub type Cmd<'a> = &'a crate_metadata;
|
||||
|
||||
// A function that takes a def_id relative to the crate being searched and
|
||||
// returns a def_id relative to the compilation environment, i.e. if we hit a
|
||||
// def_id for an item defined in another crate, somebody needs to figure out
|
||||
// what crate that's in and give us a def_id that makes sense for the current
|
||||
// build.
|
||||
|
||||
fn u32_from_be_bytes(bytes: &[u8]) -> u32 {
|
||||
let mut b = [0; 4];
|
||||
bytes::copy_memory(&bytes[..4], &mut b);
|
||||
unsafe { (*(b.as_ptr() as *const u32)).to_be() }
|
||||
}
|
||||
|
||||
fn lookup_hash<'a, F>(d: rbml::Doc<'a>, mut eq_fn: F, hash: u64) -> Option<rbml::Doc<'a>> where
|
||||
F: FnMut(&[u8]) -> bool,
|
||||
{
|
||||
let index = reader::get_doc(d, tag_index);
|
||||
let table = reader::get_doc(index, tag_index_table);
|
||||
let hash_pos = table.start + (hash % 256 * 4) as usize;
|
||||
let pos = u32_from_be_bytes(&d.data[hash_pos..]) as usize;
|
||||
let tagged_doc = reader::doc_at(d.data, pos).unwrap();
|
||||
|
||||
reader::tagged_docs(tagged_doc.doc, tag_index_buckets_bucket_elt).find(|elt| {
|
||||
eq_fn(&elt.data[elt.start + 4 .. elt.end])
|
||||
}).map(|elt| {
|
||||
let pos = u32_from_be_bytes(&elt.data[elt.start..]) as usize;
|
||||
reader::doc_at(d.data, pos).unwrap().doc
|
||||
})
|
||||
}
|
||||
|
||||
pub fn maybe_find_item<'a>(item_id: ast::NodeId,
|
||||
items: rbml::Doc<'a>) -> Option<rbml::Doc<'a>> {
|
||||
fn eq_item(bytes: &[u8], item_id: ast::NodeId) -> bool {
|
||||
u32_from_be_bytes(bytes) == item_id
|
||||
impl crate_metadata {
|
||||
fn get_item(&self, item_id: ast::NodeId) -> Option<rbml::Doc> {
|
||||
self.index.lookup_item(self.data(), item_id).map(|pos| {
|
||||
reader::doc_at(self.data(), pos as usize).unwrap().doc
|
||||
})
|
||||
}
|
||||
let mut s = SipHasher::new_with_keys(0, 0);
|
||||
(item_id as i64).hash(&mut s);
|
||||
lookup_hash(items, |a| eq_item(a, item_id), s.finish())
|
||||
}
|
||||
|
||||
fn find_item<'a>(item_id: ast::NodeId, items: rbml::Doc<'a>) -> rbml::Doc<'a> {
|
||||
match maybe_find_item(item_id, items) {
|
||||
None => panic!("lookup_item: id not found: {}", item_id),
|
||||
Some(d) => d
|
||||
fn lookup_item(&self, item_id: ast::NodeId) -> rbml::Doc {
|
||||
match self.get_item(item_id) {
|
||||
None => panic!("lookup_item: id not found: {}", item_id),
|
||||
Some(d) => d
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Looks up an item in the given metadata and returns an rbml doc pointing
|
||||
// to the item data.
|
||||
fn lookup_item<'a>(item_id: ast::NodeId, data: &'a [u8]) -> rbml::Doc<'a> {
|
||||
let items = reader::get_doc(rbml::Doc::new(data), tag_items);
|
||||
find_item(item_id, items)
|
||||
pub fn load_index(data: &[u8]) -> index::Index {
|
||||
let index = reader::get_doc(rbml::Doc::new(data), tag_index);
|
||||
index::Index::from_buf(index.data, index.start, index.end)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@ -380,7 +345,7 @@ pub fn get_trait_def<'tcx>(cdata: Cmd,
|
||||
item_id: ast::NodeId,
|
||||
tcx: &ty::ctxt<'tcx>) -> ty::TraitDef<'tcx>
|
||||
{
|
||||
let item_doc = lookup_item(item_id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(item_id);
|
||||
let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
|
||||
let unsafety = parse_unsafety(item_doc);
|
||||
let associated_type_names = parse_associated_type_names(item_doc);
|
||||
@ -410,7 +375,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
|
||||
let mut disr_val = 0;
|
||||
reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| {
|
||||
let did = translated_def_id(cdata, p);
|
||||
let item = lookup_item(did.node, cdata.data());
|
||||
let item = cdata.lookup_item(did.node);
|
||||
|
||||
if let Some(disr) = variant_disr_val(item) {
|
||||
disr_val = disr;
|
||||
@ -459,7 +424,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
|
||||
}
|
||||
}
|
||||
|
||||
let doc = lookup_item(item_id, cdata.data());
|
||||
let doc = cdata.lookup_item(item_id);
|
||||
let did = DefId { krate: cdata.cnum, node: item_id };
|
||||
let (kind, variants) = match item_family(doc) {
|
||||
Enum => (ty::AdtKind::Enum,
|
||||
@ -516,7 +481,7 @@ pub fn get_predicates<'tcx>(cdata: Cmd,
|
||||
tcx: &ty::ctxt<'tcx>)
|
||||
-> ty::GenericPredicates<'tcx>
|
||||
{
|
||||
let item_doc = lookup_item(item_id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(item_id);
|
||||
doc_predicates(item_doc, tcx, cdata, tag_item_generics)
|
||||
}
|
||||
|
||||
@ -525,14 +490,14 @@ pub fn get_super_predicates<'tcx>(cdata: Cmd,
|
||||
tcx: &ty::ctxt<'tcx>)
|
||||
-> ty::GenericPredicates<'tcx>
|
||||
{
|
||||
let item_doc = lookup_item(item_id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(item_id);
|
||||
doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates)
|
||||
}
|
||||
|
||||
pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
|
||||
-> ty::TypeScheme<'tcx>
|
||||
{
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
let t = item_type(DefId { krate: cdata.cnum, node: id }, item_doc, tcx,
|
||||
cdata);
|
||||
let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
|
||||
@ -543,7 +508,7 @@ pub fn get_type<'tcx>(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt<'tcx>)
|
||||
}
|
||||
|
||||
pub fn get_stability(cdata: Cmd, id: ast::NodeId) -> Option<attr::Stability> {
|
||||
let item = lookup_item(id, cdata.data());
|
||||
let item = cdata.lookup_item(id);
|
||||
reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| {
|
||||
let mut decoder = reader::Decoder::new(doc);
|
||||
Decodable::decode(&mut decoder).unwrap()
|
||||
@ -551,7 +516,7 @@ pub fn get_stability(cdata: Cmd, id: ast::NodeId) -> Option<attr::Stability> {
|
||||
}
|
||||
|
||||
pub fn get_repr_attrs(cdata: Cmd, id: ast::NodeId) -> Vec<attr::ReprAttr> {
|
||||
let item = lookup_item(id, cdata.data());
|
||||
let item = cdata.lookup_item(id);
|
||||
match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| {
|
||||
let mut decoder = reader::Decoder::new(doc);
|
||||
Decodable::decode(&mut decoder).unwrap()
|
||||
@ -565,7 +530,7 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd,
|
||||
id: ast::NodeId)
|
||||
-> Option<hir::ImplPolarity>
|
||||
{
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
let fam = item_family(item_doc);
|
||||
match fam {
|
||||
Family::Impl => {
|
||||
@ -578,7 +543,7 @@ pub fn get_impl_polarity<'tcx>(cdata: Cmd,
|
||||
pub fn get_custom_coerce_unsized_kind<'tcx>(cdata: Cmd,
|
||||
id: ast::NodeId)
|
||||
-> Option<ty::CustomCoerceUnsized> {
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| {
|
||||
let mut decoder = reader::Decoder::new(kind_doc);
|
||||
Decodable::decode(&mut decoder).unwrap()
|
||||
@ -590,7 +555,7 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
|
||||
tcx: &ty::ctxt<'tcx>)
|
||||
-> Option<ty::TraitRef<'tcx>>
|
||||
{
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
let fam = item_family(item_doc);
|
||||
match fam {
|
||||
Family::Impl | Family::DefaultImpl => {
|
||||
@ -602,8 +567,16 @@ pub fn get_impl_trait<'tcx>(cdata: Cmd,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_symbol(data: &[u8], id: ast::NodeId) -> String {
|
||||
return item_symbol(lookup_item(id, data));
|
||||
pub fn get_symbol(cdata: Cmd, id: ast::NodeId) -> String {
|
||||
return item_symbol(cdata.lookup_item(id));
|
||||
}
|
||||
|
||||
/// If you have a crate_metadata, call get_symbol instead
|
||||
pub fn get_symbol_from_buf(data: &[u8], id: ast::NodeId) -> String {
|
||||
let index = load_index(data);
|
||||
let pos = index.lookup_item(data, id).unwrap();
|
||||
let doc = reader::doc_at(data, pos as usize).unwrap().doc;
|
||||
item_symbol(doc)
|
||||
}
|
||||
|
||||
// Something that a name can resolve to.
|
||||
@ -655,10 +628,8 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
|
||||
None => cdata
|
||||
};
|
||||
|
||||
let other_crates_items = reader::get_doc(rbml::Doc::new(crate_data.data()), tag_items);
|
||||
|
||||
// Get the item.
|
||||
match maybe_find_item(child_def_id.node, other_crates_items) {
|
||||
match crate_data.get_item(child_def_id.node) {
|
||||
None => {}
|
||||
Some(child_item_doc) => {
|
||||
// Hand off the item to the callback.
|
||||
@ -676,13 +647,12 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
|
||||
for inherent_impl_def_id_doc in reader::tagged_docs(item_doc,
|
||||
tag_items_data_item_inherent_impl) {
|
||||
let inherent_impl_def_id = item_def_id(inherent_impl_def_id_doc, cdata);
|
||||
let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
|
||||
if let Some(inherent_impl_doc) = maybe_find_item(inherent_impl_def_id.node, items) {
|
||||
if let Some(inherent_impl_doc) = cdata.get_item(inherent_impl_def_id.node) {
|
||||
for impl_item_def_id_doc in reader::tagged_docs(inherent_impl_doc,
|
||||
tag_item_impl_item) {
|
||||
let impl_item_def_id = item_def_id(impl_item_def_id_doc,
|
||||
cdata);
|
||||
if let Some(impl_method_doc) = maybe_find_item(impl_item_def_id.node, items) {
|
||||
if let Some(impl_method_doc) = cdata.get_item(impl_item_def_id.node) {
|
||||
if let StaticMethod = item_family(impl_method_doc) {
|
||||
// Hand off the static method to the callback.
|
||||
let static_method_name = item_name(&*intr, impl_method_doc);
|
||||
@ -717,10 +687,8 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
|
||||
None => cdata
|
||||
};
|
||||
|
||||
let other_crates_items = reader::get_doc(rbml::Doc::new(crate_data.data()), tag_items);
|
||||
|
||||
// Get the item.
|
||||
if let Some(child_item_doc) = maybe_find_item(child_def_id.node, other_crates_items) {
|
||||
if let Some(child_item_doc) = crate_data.get_item(child_def_id.node) {
|
||||
// Hand off the item to the callback.
|
||||
let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
|
||||
// These items have a public visibility because they're part of
|
||||
@ -740,9 +708,7 @@ pub fn each_child_of_item<F, G>(intr: Rc<IdentInterner>,
|
||||
G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
|
||||
{
|
||||
// Find the item.
|
||||
let root_doc = rbml::Doc::new(cdata.data());
|
||||
let items = reader::get_doc(root_doc, tag_items);
|
||||
let item_doc = match maybe_find_item(id, items) {
|
||||
let item_doc = match cdata.get_item(id) {
|
||||
None => return,
|
||||
Some(item_doc) => item_doc,
|
||||
};
|
||||
@ -775,11 +741,11 @@ pub fn each_top_level_item_of_crate<F, G>(intr: Rc<IdentInterner>,
|
||||
}
|
||||
|
||||
pub fn get_item_path(cdata: Cmd, id: ast::NodeId) -> Vec<ast_map::PathElem> {
|
||||
item_path(lookup_item(id, cdata.data()))
|
||||
item_path(cdata.lookup_item(id))
|
||||
}
|
||||
|
||||
pub fn get_item_name(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId) -> ast::Name {
|
||||
item_name(intr, lookup_item(id, cdata.data()))
|
||||
item_name(intr, cdata.lookup_item(id))
|
||||
}
|
||||
|
||||
pub type DecodeInlinedItem<'a> =
|
||||
@ -793,14 +759,14 @@ pub fn maybe_get_item_ast<'tcx>(cdata: Cmd, tcx: &ty::ctxt<'tcx>, id: ast::NodeI
|
||||
mut decode_inlined_item: DecodeInlinedItem)
|
||||
-> csearch::FoundAst<'tcx> {
|
||||
debug!("Looking up item: {}", id);
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
let path = item_path(item_doc).split_last().unwrap().1.to_vec();
|
||||
match decode_inlined_item(cdata, tcx, path, item_doc) {
|
||||
Ok(ii) => csearch::FoundAst::Found(ii),
|
||||
Err(path) => {
|
||||
match item_parent_item(cdata, item_doc) {
|
||||
Some(did) => {
|
||||
let parent_item = lookup_item(did.node, cdata.data());
|
||||
let parent_item = cdata.lookup_item(did.node);
|
||||
match decode_inlined_item(cdata, tcx, path, parent_item) {
|
||||
Ok(ii) => csearch::FoundAst::FoundParent(did, ii),
|
||||
Err(_) => csearch::FoundAst::NotFound
|
||||
@ -842,7 +808,7 @@ fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
|
||||
/// Returns the def IDs of all the items in the given implementation.
|
||||
pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
|
||||
-> Vec<ty::ImplOrTraitItemId> {
|
||||
reader::tagged_docs(lookup_item(impl_id, cdata.data()), tag_item_impl_item).map(|doc| {
|
||||
reader::tagged_docs(cdata.lookup_item(impl_id), tag_item_impl_item).map(|doc| {
|
||||
let def_id = item_def_id(doc, cdata);
|
||||
match item_sort(doc) {
|
||||
Some('C') => ty::ConstTraitItemId(def_id),
|
||||
@ -857,12 +823,12 @@ pub fn get_trait_name(intr: Rc<IdentInterner>,
|
||||
cdata: Cmd,
|
||||
id: ast::NodeId)
|
||||
-> ast::Name {
|
||||
let doc = lookup_item(id, cdata.data());
|
||||
let doc = cdata.lookup_item(id);
|
||||
item_name(&*intr, doc)
|
||||
}
|
||||
|
||||
pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
let doc = lookup_item(id, cdata.data());
|
||||
let doc = cdata.lookup_item(id);
|
||||
match item_sort(doc) {
|
||||
Some('r') | Some('p') => {
|
||||
get_explicit_self(doc) == ty::StaticExplicitSelfCategory
|
||||
@ -876,12 +842,12 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
|
||||
id: ast::NodeId,
|
||||
tcx: &ty::ctxt<'tcx>)
|
||||
-> ty::ImplOrTraitItem<'tcx> {
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
|
||||
let def_id = item_def_id(item_doc, cdata);
|
||||
|
||||
let container_id = item_require_parent_item(cdata, item_doc);
|
||||
let container_doc = lookup_item(container_id.node, cdata.data());
|
||||
let container_doc = cdata.lookup_item(container_id.node);
|
||||
let container = match item_family(container_doc) {
|
||||
Trait => TraitContainer(container_id),
|
||||
_ => ImplContainer(container_id),
|
||||
@ -936,8 +902,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
|
||||
|
||||
pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
|
||||
-> Vec<ty::ImplOrTraitItemId> {
|
||||
let data = cdata.data();
|
||||
let item = lookup_item(id, data);
|
||||
let item = cdata.lookup_item(id);
|
||||
reader::tagged_docs(item, tag_item_trait_item).map(|mth| {
|
||||
let def_id = item_def_id(mth, cdata);
|
||||
match item_sort(mth) {
|
||||
@ -950,8 +915,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
|
||||
}
|
||||
|
||||
pub fn get_item_variances(cdata: Cmd, id: ast::NodeId) -> ty::ItemVariances {
|
||||
let data = cdata.data();
|
||||
let item_doc = lookup_item(id, data);
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
let variance_doc = reader::get_doc(item_doc, tag_item_variances);
|
||||
let mut decoder = reader::Decoder::new(variance_doc);
|
||||
Decodable::decode(&mut decoder).unwrap()
|
||||
@ -962,12 +926,11 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
|
||||
id: ast::NodeId,
|
||||
tcx: &ty::ctxt<'tcx>)
|
||||
-> Vec<Rc<ty::Method<'tcx>>> {
|
||||
let data = cdata.data();
|
||||
let item = lookup_item(id, data);
|
||||
let item = cdata.lookup_item(id);
|
||||
|
||||
reader::tagged_docs(item, tag_item_trait_item).filter_map(|mth_id| {
|
||||
let did = item_def_id(mth_id, cdata);
|
||||
let mth = lookup_item(did.node, data);
|
||||
let mth = cdata.lookup_item(did.node);
|
||||
|
||||
if item_sort(mth) == Some('p') {
|
||||
let trait_item = get_impl_or_trait_item(intr.clone(),
|
||||
@ -990,13 +953,12 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
|
||||
id: ast::NodeId,
|
||||
tcx: &ty::ctxt<'tcx>)
|
||||
-> Vec<Rc<ty::AssociatedConst<'tcx>>> {
|
||||
let data = cdata.data();
|
||||
let item = lookup_item(id, data);
|
||||
let item = cdata.lookup_item(id);
|
||||
|
||||
[tag_item_trait_item, tag_item_impl_item].iter().flat_map(|&tag| {
|
||||
reader::tagged_docs(item, tag).filter_map(|ac_id| {
|
||||
let did = item_def_id(ac_id, cdata);
|
||||
let ac_doc = lookup_item(did.node, data);
|
||||
let ac_doc = cdata.lookup_item(did.node);
|
||||
|
||||
if item_sort(ac_doc) == Some('C') {
|
||||
let trait_item = get_impl_or_trait_item(intr.clone(),
|
||||
@ -1017,7 +979,7 @@ pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
|
||||
|
||||
pub fn get_type_name_if_impl(cdata: Cmd,
|
||||
node_id: ast::NodeId) -> Option<ast::Name> {
|
||||
let item = lookup_item(node_id, cdata.data());
|
||||
let item = cdata.lookup_item(node_id);
|
||||
if item_family(item) != Impl {
|
||||
return None;
|
||||
}
|
||||
@ -1031,7 +993,7 @@ pub fn get_methods_if_impl(intr: Rc<IdentInterner>,
|
||||
cdata: Cmd,
|
||||
node_id: ast::NodeId)
|
||||
-> Option<Vec<MethodInfo> > {
|
||||
let item = lookup_item(node_id, cdata.data());
|
||||
let item = cdata.lookup_item(node_id);
|
||||
if item_family(item) != Impl {
|
||||
return None;
|
||||
}
|
||||
@ -1046,7 +1008,7 @@ pub fn get_methods_if_impl(intr: Rc<IdentInterner>,
|
||||
|
||||
let mut impl_methods = Vec::new();
|
||||
for impl_method_id in impl_method_ids {
|
||||
let impl_method_doc = lookup_item(impl_method_id.node, cdata.data());
|
||||
let impl_method_doc = cdata.lookup_item(impl_method_id.node);
|
||||
let family = item_family(impl_method_doc);
|
||||
match family {
|
||||
StaticMethod | Method => {
|
||||
@ -1069,7 +1031,7 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
|
||||
node_id: ast::NodeId)
|
||||
-> Option<DefId>
|
||||
{
|
||||
let item = lookup_item(node_id, cdata.data());
|
||||
let item = cdata.lookup_item(node_id);
|
||||
reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor).next().map(|_| {
|
||||
item_require_parent_item(cdata, item)
|
||||
})
|
||||
@ -1083,11 +1045,11 @@ pub fn get_item_attrs(cdata: Cmd,
|
||||
// look at the definition
|
||||
let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id);
|
||||
let node_id = node_id.map(|x| x.node).unwrap_or(orig_node_id);
|
||||
let item = lookup_item(node_id, cdata.data());
|
||||
let item = cdata.lookup_item(node_id);
|
||||
get_attributes(item)
|
||||
}
|
||||
|
||||
pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<hir::Attribute>> {
|
||||
pub fn get_struct_field_attrs(cdata: Cmd) -> FnvHashMap<ast::NodeId, Vec<hir::Attribute>> {
|
||||
let data = rbml::Doc::new(cdata.data());
|
||||
let fields = reader::get_doc(data, tag_struct_fields);
|
||||
reader::tagged_docs(fields, tag_struct_field).map(|field| {
|
||||
@ -1107,8 +1069,7 @@ fn struct_field_family_to_visibility(family: Family) -> hir::Visibility {
|
||||
|
||||
pub fn get_struct_field_names(intr: &IdentInterner, cdata: Cmd, id: ast::NodeId)
|
||||
-> Vec<ast::Name> {
|
||||
let data = cdata.data();
|
||||
let item = lookup_item(id, data);
|
||||
let item = cdata.lookup_item(id);
|
||||
reader::tagged_docs(item, tag_item_field).map(|an_item| {
|
||||
item_name(intr, an_item)
|
||||
}).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| {
|
||||
@ -1299,7 +1260,7 @@ pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
|
||||
mut callback: F)
|
||||
where F: FnMut(DefId),
|
||||
{
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl) {
|
||||
if reader::maybe_get_doc(impl_doc, tag_item_trait_ref).is_none() {
|
||||
callback(item_def_id(impl_doc, cdata));
|
||||
@ -1313,7 +1274,7 @@ pub fn each_implementation_for_trait<F>(cdata: Cmd,
|
||||
F: FnMut(DefId),
|
||||
{
|
||||
if cdata.cnum == def_id.krate {
|
||||
let item_doc = lookup_item(def_id.node, cdata.data());
|
||||
let item_doc = cdata.lookup_item(def_id.node);
|
||||
for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_extension_impl) {
|
||||
callback(item_def_id(impl_doc, cdata));
|
||||
}
|
||||
@ -1337,12 +1298,12 @@ pub fn each_implementation_for_trait<F>(cdata: Cmd,
|
||||
|
||||
pub fn get_trait_of_item(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt)
|
||||
-> Option<DefId> {
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
let parent_item_id = match item_parent_item(cdata, item_doc) {
|
||||
None => return None,
|
||||
Some(item_id) => item_id,
|
||||
};
|
||||
let parent_item_doc = lookup_item(parent_item_id.node, cdata.data());
|
||||
let parent_item_doc = cdata.lookup_item(parent_item_id.node);
|
||||
match item_family(parent_item_doc) {
|
||||
Trait => Some(item_def_id(parent_item_doc, cdata)),
|
||||
Impl | DefaultImpl => {
|
||||
@ -1423,7 +1384,7 @@ pub fn get_missing_lang_items(cdata: Cmd)
|
||||
}
|
||||
|
||||
pub fn get_method_arg_names(cdata: Cmd, id: ast::NodeId) -> Vec<String> {
|
||||
let method_doc = lookup_item(id, cdata.data());
|
||||
let method_doc = cdata.lookup_item(id);
|
||||
match reader::maybe_get_doc(method_doc, tag_method_argument_names) {
|
||||
Some(args_doc) => {
|
||||
reader::tagged_docs(args_doc, tag_method_argument_name).map(|name_doc| {
|
||||
@ -1446,7 +1407,7 @@ pub fn get_reachable_ids(cdata: Cmd) -> Vec<DefId> {
|
||||
}
|
||||
|
||||
pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
match item_family(item_doc) {
|
||||
Type => true,
|
||||
_ => false,
|
||||
@ -1454,7 +1415,7 @@ pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
}
|
||||
|
||||
pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
match fn_constness(item_doc) {
|
||||
hir::Constness::Const => true,
|
||||
hir::Constness::NotConst => false,
|
||||
@ -1462,7 +1423,7 @@ pub fn is_const_fn(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
}
|
||||
|
||||
pub fn is_impl(cdata: Cmd, id: ast::NodeId) -> bool {
|
||||
let item_doc = lookup_item(id, cdata.data());
|
||||
let item_doc = cdata.lookup_item(id);
|
||||
match item_family(item_doc) {
|
||||
Impl => true,
|
||||
_ => false,
|
||||
@ -1543,14 +1504,14 @@ fn doc_predicates<'tcx>(base_doc: rbml::Doc,
|
||||
}
|
||||
|
||||
pub fn is_defaulted_trait(cdata: Cmd, trait_id: ast::NodeId) -> bool {
|
||||
let trait_doc = lookup_item(trait_id, cdata.data());
|
||||
let trait_doc = cdata.lookup_item(trait_id);
|
||||
assert!(item_family(trait_doc) == Family::Trait);
|
||||
let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait);
|
||||
reader::doc_as_u8(defaulted_doc) != 0
|
||||
}
|
||||
|
||||
pub fn is_default_impl(cdata: Cmd, impl_id: ast::NodeId) -> bool {
|
||||
let impl_doc = lookup_item(impl_id, cdata.data());
|
||||
let impl_doc = cdata.lookup_item(impl_id);
|
||||
item_family(impl_doc) == Family::DefaultImpl
|
||||
}
|
||||
|
||||
@ -1565,9 +1526,7 @@ pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<codemap::FileMap> {
|
||||
}
|
||||
|
||||
pub fn is_extern_fn(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) -> bool {
|
||||
let root_doc = rbml::Doc::new(cdata.data());
|
||||
let items = reader::get_doc(root_doc, tag_items);
|
||||
let item_doc = match maybe_find_item(id, items) {
|
||||
let item_doc = match cdata.get_item(id) {
|
||||
Some(doc) => doc,
|
||||
None => return false,
|
||||
};
|
||||
|
@ -19,6 +19,7 @@ use metadata::common::*;
|
||||
use metadata::cstore;
|
||||
use metadata::decoder;
|
||||
use metadata::tyencode;
|
||||
use metadata::index::{self, IndexEntry};
|
||||
use metadata::inline::InlinedItemRef;
|
||||
use middle::def;
|
||||
use middle::def_id::{DefId, LOCAL_CRATE};
|
||||
@ -29,7 +30,6 @@ use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
|
||||
|
||||
use serialize::Encodable;
|
||||
use std::cell::RefCell;
|
||||
use std::hash::{Hash, Hasher, SipHasher};
|
||||
use std::io::prelude::*;
|
||||
use std::io::{Cursor, SeekFrom};
|
||||
use std::rc::Rc;
|
||||
@ -86,12 +86,6 @@ fn encode_def_id(rbml_w: &mut Encoder, id: DefId) {
|
||||
rbml_w.wr_tagged_u64(tag_def_id, def_to_u64(id));
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct entry<T> {
|
||||
val: T,
|
||||
pos: u64
|
||||
}
|
||||
|
||||
fn encode_trait_ref<'a, 'tcx>(rbml_w: &mut Encoder,
|
||||
ecx: &EncodeContext<'a, 'tcx>,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
@ -279,7 +273,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
id: NodeId,
|
||||
vis: ast::Visibility,
|
||||
index: &mut Vec<entry<i64>>) {
|
||||
index: &mut Vec<IndexEntry>) {
|
||||
debug!("encode_enum_variant_info(id={})", id);
|
||||
|
||||
let mut disr_val = 0;
|
||||
@ -296,8 +290,8 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
|
||||
}
|
||||
}
|
||||
|
||||
index.push(entry {
|
||||
val: vid.node as i64,
|
||||
index.push(IndexEntry {
|
||||
node: vid.node,
|
||||
pos: rbml_w.mark_stable_position(),
|
||||
});
|
||||
rbml_w.start_tag(tag_items_data_item);
|
||||
@ -625,13 +619,13 @@ fn encode_provided_source(rbml_w: &mut Encoder,
|
||||
fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
|
||||
rbml_w: &mut Encoder,
|
||||
field: ty::FieldDef<'tcx>,
|
||||
global_index: &mut Vec<entry<i64>>) {
|
||||
global_index: &mut Vec<IndexEntry>) {
|
||||
let nm = field.name;
|
||||
let id = field.did.node;
|
||||
|
||||
let pos = rbml_w.mark_stable_position();
|
||||
global_index.push(entry {
|
||||
val: id as i64,
|
||||
global_index.push(IndexEntry {
|
||||
node: id,
|
||||
pos: pos,
|
||||
});
|
||||
rbml_w.start_tag(tag_items_data_item);
|
||||
@ -651,10 +645,10 @@ fn encode_info_for_struct_ctor(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
name: Name,
|
||||
ctor_id: NodeId,
|
||||
index: &mut Vec<entry<i64>>,
|
||||
index: &mut Vec<IndexEntry>,
|
||||
struct_id: NodeId) {
|
||||
index.push(entry {
|
||||
val: ctor_id as i64,
|
||||
index.push(IndexEntry {
|
||||
node: ctor_id,
|
||||
pos: rbml_w.mark_stable_position(),
|
||||
});
|
||||
|
||||
@ -989,15 +983,15 @@ fn encode_stability(rbml_w: &mut Encoder, stab_opt: Option<&attr::Stability>) {
|
||||
fn encode_info_for_item(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
item: &ast::Item,
|
||||
index: &mut Vec<entry<i64>>,
|
||||
index: &mut Vec<IndexEntry>,
|
||||
path: PathElems,
|
||||
vis: ast::Visibility) {
|
||||
let tcx = ecx.tcx;
|
||||
|
||||
fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
|
||||
index: &mut Vec<entry<i64>>) {
|
||||
index.push(entry {
|
||||
val: item.id as i64,
|
||||
index: &mut Vec<IndexEntry>) {
|
||||
index.push(IndexEntry {
|
||||
node: item.id,
|
||||
pos: rbml_w.mark_stable_position(),
|
||||
});
|
||||
}
|
||||
@ -1261,8 +1255,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
None
|
||||
};
|
||||
|
||||
index.push(entry {
|
||||
val: trait_item_def_id.def_id().node as i64,
|
||||
index.push(IndexEntry {
|
||||
node: trait_item_def_id.def_id().node,
|
||||
pos: rbml_w.mark_stable_position(),
|
||||
});
|
||||
|
||||
@ -1352,8 +1346,8 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
for (i, &item_def_id) in r.iter().enumerate() {
|
||||
assert_eq!(item_def_id.def_id().krate, LOCAL_CRATE);
|
||||
|
||||
index.push(entry {
|
||||
val: item_def_id.def_id().node as i64,
|
||||
index.push(IndexEntry {
|
||||
node: item_def_id.def_id().node,
|
||||
pos: rbml_w.mark_stable_position(),
|
||||
});
|
||||
|
||||
@ -1474,11 +1468,11 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
||||
fn encode_info_for_foreign_item(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
nitem: &ast::ForeignItem,
|
||||
index: &mut Vec<entry<i64>>,
|
||||
index: &mut Vec<IndexEntry>,
|
||||
path: PathElems,
|
||||
abi: abi::Abi) {
|
||||
index.push(entry {
|
||||
val: nitem.id as i64,
|
||||
index.push(IndexEntry {
|
||||
node: nitem.id,
|
||||
pos: rbml_w.mark_stable_position(),
|
||||
});
|
||||
|
||||
@ -1522,7 +1516,7 @@ fn my_visit_expr(_e: &ast::Expr) { }
|
||||
fn my_visit_item(i: &ast::Item,
|
||||
rbml_w: &mut Encoder,
|
||||
ecx: &EncodeContext,
|
||||
index: &mut Vec<entry<i64>>) {
|
||||
index: &mut Vec<IndexEntry>) {
|
||||
ecx.tcx.map.with_path(i.id, |path| {
|
||||
encode_info_for_item(ecx, rbml_w, i, index, path, i.vis);
|
||||
});
|
||||
@ -1531,7 +1525,7 @@ fn my_visit_item(i: &ast::Item,
|
||||
fn my_visit_foreign_item(ni: &ast::ForeignItem,
|
||||
rbml_w: &mut Encoder,
|
||||
ecx: &EncodeContext,
|
||||
index: &mut Vec<entry<i64>>) {
|
||||
index: &mut Vec<IndexEntry>) {
|
||||
debug!("writing foreign item {}::{}",
|
||||
ecx.tcx.map.path_to_string(ni.id),
|
||||
ni.ident);
|
||||
@ -1547,7 +1541,7 @@ fn my_visit_foreign_item(ni: &ast::ForeignItem,
|
||||
struct EncodeVisitor<'a, 'b:'a, 'c:'a, 'tcx:'c> {
|
||||
rbml_w_for_visit_item: &'a mut Encoder<'b>,
|
||||
ecx: &'a EncodeContext<'c,'tcx>,
|
||||
index: &'a mut Vec<entry<i64>>,
|
||||
index: &'a mut Vec<IndexEntry>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
|
||||
@ -1574,11 +1568,11 @@ impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for EncodeVisitor<'a, 'b, 'c, 'tcx> {
|
||||
fn encode_info_for_items(ecx: &EncodeContext,
|
||||
rbml_w: &mut Encoder,
|
||||
krate: &ast::Crate)
|
||||
-> Vec<entry<i64>> {
|
||||
-> Vec<IndexEntry> {
|
||||
let mut index = Vec::new();
|
||||
rbml_w.start_tag(tag_items_data);
|
||||
index.push(entry {
|
||||
val: CRATE_NODE_ID as i64,
|
||||
index.push(IndexEntry {
|
||||
node: CRATE_NODE_ID,
|
||||
pos: rbml_w.mark_stable_position(),
|
||||
});
|
||||
encode_info_for_mod(ecx,
|
||||
@ -1601,62 +1595,13 @@ fn encode_info_for_items(ecx: &EncodeContext,
|
||||
}
|
||||
|
||||
|
||||
// Path and definition ID indexing
|
||||
|
||||
fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
|
||||
F: FnMut(&mut Cursor<Vec<u8>>, &T),
|
||||
T: Hash,
|
||||
|
||||
fn encode_index(rbml_w: &mut Encoder, index: Vec<IndexEntry>)
|
||||
{
|
||||
let mut buckets: Vec<Vec<entry<T>>> = (0..256u16).map(|_| Vec::new()).collect();
|
||||
for elt in index {
|
||||
let mut s = SipHasher::new();
|
||||
elt.val.hash(&mut s);
|
||||
let h = s.finish() as usize;
|
||||
(&mut buckets[h % 256]).push(elt);
|
||||
}
|
||||
|
||||
rbml_w.start_tag(tag_index);
|
||||
let mut bucket_locs = Vec::new();
|
||||
rbml_w.start_tag(tag_index_buckets);
|
||||
for bucket in &buckets {
|
||||
bucket_locs.push(rbml_w.mark_stable_position());
|
||||
rbml_w.start_tag(tag_index_buckets_bucket);
|
||||
for elt in bucket {
|
||||
rbml_w.start_tag(tag_index_buckets_bucket_elt);
|
||||
assert!(elt.pos < 0xffff_ffff);
|
||||
{
|
||||
let wr: &mut Cursor<Vec<u8>> = rbml_w.writer;
|
||||
write_be_u32(wr, elt.pos as u32);
|
||||
}
|
||||
write_fn(rbml_w.writer, &elt.val);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
index::write_index(index, rbml_w.writer);
|
||||
rbml_w.end_tag();
|
||||
rbml_w.start_tag(tag_index_table);
|
||||
for pos in &bucket_locs {
|
||||
assert!(*pos < 0xffff_ffff);
|
||||
let wr: &mut Cursor<Vec<u8>> = rbml_w.writer;
|
||||
write_be_u32(wr, *pos as u32);
|
||||
}
|
||||
rbml_w.end_tag();
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
|
||||
fn write_i64(writer: &mut Cursor<Vec<u8>>, &n: &i64) {
|
||||
let wr: &mut Cursor<Vec<u8>> = writer;
|
||||
assert!(n < 0x7fff_ffff);
|
||||
write_be_u32(wr, n as u32);
|
||||
}
|
||||
|
||||
fn write_be_u32(w: &mut Write, u: u32) {
|
||||
w.write_all(&[
|
||||
(u >> 24) as u8,
|
||||
(u >> 16) as u8,
|
||||
(u >> 8) as u8,
|
||||
(u >> 0) as u8,
|
||||
]);
|
||||
}
|
||||
|
||||
fn encode_meta_item(rbml_w: &mut Encoder, mi: &ast::MetaItem) {
|
||||
@ -2160,11 +2105,11 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
|
||||
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
|
||||
let items_index = encode_info_for_items(&ecx, &mut rbml_w, krate);
|
||||
stats.item_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
|
||||
rbml_w.end_tag();
|
||||
|
||||
i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
|
||||
encode_index(&mut rbml_w, items_index, write_i64);
|
||||
encode_index(&mut rbml_w, items_index);
|
||||
stats.index_bytes = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap() - i;
|
||||
rbml_w.end_tag();
|
||||
|
||||
encode_struct_field_attrs(&mut rbml_w, krate);
|
||||
|
||||
|
208
src/librustc/metadata/index.rs
Normal file
208
src/librustc/metadata/index.rs
Normal file
@ -0,0 +1,208 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::io::{Cursor, Write};
|
||||
use std::slice;
|
||||
use std::u32;
|
||||
use syntax::ast::NodeId;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
|
||||
pub struct IndexEntry {
|
||||
pub node: NodeId,
|
||||
pub pos: u64
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IndexArrayEntry {
|
||||
bits: u32,
|
||||
first_pos: u32
|
||||
}
|
||||
|
||||
impl IndexArrayEntry {
|
||||
fn encode_to<W: Write>(&self, b: &mut W) {
|
||||
write_be_u32(b, self.bits);
|
||||
write_be_u32(b, self.first_pos);
|
||||
}
|
||||
|
||||
fn decode_from(b: &[u32]) -> Self {
|
||||
IndexArrayEntry {
|
||||
bits: b[0].to_be(),
|
||||
first_pos: b[1].to_be()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The Item Index
|
||||
///
|
||||
/// This index maps the NodeId of each item to its location in the
|
||||
/// metadata.
|
||||
///
|
||||
/// The index is a sparse bit-vector consisting of a index-array
|
||||
/// and a position-array. Each entry in the index-array handles 32 nodes.
|
||||
/// The first word is a bit-array consisting of the nodes that hold items,
|
||||
/// the second is the index of the first of the items in the position-array.
|
||||
/// If there is a large set of non-item trailing nodes, they can be omitted
|
||||
/// from the index-array.
|
||||
///
|
||||
/// The index is serialized as an array of big-endian 32-bit words.
|
||||
/// The first word is the number of items in the position-array.
|
||||
/// Then, for each item, its position in the metadata follows.
|
||||
/// After that the index-array is stored.
|
||||
///
|
||||
/// struct index {
|
||||
/// u32 item_count;
|
||||
/// u32 items[self.item_count];
|
||||
/// struct { u32 bits; u32 offset; } positions[..];
|
||||
/// }
|
||||
pub struct Index {
|
||||
position_start: usize,
|
||||
index_start: usize,
|
||||
index_end: usize,
|
||||
}
|
||||
|
||||
pub fn write_index(mut entries: Vec<IndexEntry>, buf: &mut Cursor<Vec<u8>>) {
|
||||
assert!(entries.len() < u32::MAX as usize);
|
||||
entries.sort();
|
||||
|
||||
let mut last_entry = IndexArrayEntry { bits: 0, first_pos: 0 };
|
||||
|
||||
write_be_u32(buf, entries.len() as u32);
|
||||
for &IndexEntry { pos, .. } in &entries {
|
||||
assert!(pos < u32::MAX as u64);
|
||||
write_be_u32(buf, pos as u32);
|
||||
}
|
||||
|
||||
let mut pos_in_index_array = 0;
|
||||
for (i, &IndexEntry { node, .. }) in entries.iter().enumerate() {
|
||||
let (x, s) = (node / 32 as u32, node % 32 as u32);
|
||||
while x > pos_in_index_array {
|
||||
pos_in_index_array += 1;
|
||||
last_entry.encode_to(buf);
|
||||
last_entry = IndexArrayEntry { bits: 0, first_pos: i as u32 };
|
||||
}
|
||||
last_entry.bits |= 1<<s;
|
||||
}
|
||||
last_entry.encode_to(buf);
|
||||
|
||||
info!("write_index: {} items, {} array entries",
|
||||
entries.len(), pos_in_index_array);
|
||||
}
|
||||
|
||||
impl Index {
|
||||
fn lookup_index(&self, index: &[u32], i: u32) -> Option<IndexArrayEntry> {
|
||||
let ix = (i as usize)*2;
|
||||
if ix >= index.len() {
|
||||
None
|
||||
} else {
|
||||
Some(IndexArrayEntry::decode_from(&index[ix..ix+2]))
|
||||
}
|
||||
}
|
||||
|
||||
fn item_from_pos(&self, positions: &[u32], pos: u32) -> u32 {
|
||||
positions[pos as usize].to_be()
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
pub fn lookup_item(&self, buf: &[u8], node: NodeId) -> Option<u32> {
|
||||
let index = bytes_to_words(&buf[self.index_start..self.index_end]);
|
||||
let positions = bytes_to_words(&buf[self.position_start..self.index_start]);
|
||||
let (x, s) = (node / 32 as u32, node % 32 as u32);
|
||||
let result = match self.lookup_index(index, x) {
|
||||
Some(IndexArrayEntry { bits, first_pos }) => {
|
||||
let bit = 1<<s;
|
||||
if bits & bit == 0 {
|
||||
None
|
||||
} else {
|
||||
let prev_nodes_for_entry = (bits&(bit-1)).count_ones();
|
||||
Some(self.item_from_pos(
|
||||
positions,
|
||||
first_pos+prev_nodes_for_entry))
|
||||
}
|
||||
}
|
||||
None => None // trailing zero
|
||||
};
|
||||
debug!("lookup_item({:?}) = {:?}", node, result);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn from_buf(buf: &[u8], start: usize, end: usize) -> Self {
|
||||
let buf = bytes_to_words(&buf[start..end]);
|
||||
let position_count = buf[0].to_be() as usize;
|
||||
let position_len = position_count*4;
|
||||
info!("loaded index - position: {}-{}-{}", start, start+position_len, end);
|
||||
debug!("index contents are {:?}",
|
||||
buf.iter().map(|b| format!("{:08x}", b)).collect::<Vec<_>>().concat());
|
||||
assert!(end-4-start >= position_len);
|
||||
assert_eq!((end-4-start-position_len)%8, 0);
|
||||
Index {
|
||||
position_start: start+4,
|
||||
index_start: start+position_len+4,
|
||||
index_end: end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn write_be_u32<W: Write>(w: &mut W, u: u32) {
|
||||
let _ = w.write_all(&[
|
||||
(u >> 24) as u8,
|
||||
(u >> 16) as u8,
|
||||
(u >> 8) as u8,
|
||||
(u >> 0) as u8,
|
||||
]);
|
||||
}
|
||||
|
||||
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) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_index() {
|
||||
let entries = vec![
|
||||
IndexEntry { node: 0, pos: 17 },
|
||||
IndexEntry { node: 31, pos: 29 },
|
||||
IndexEntry { node: 32, pos: 1175 },
|
||||
IndexEntry { node: 191, pos: 21 },
|
||||
IndexEntry { node: 128, pos: 34 },
|
||||
IndexEntry { node: 145, pos: 70 },
|
||||
IndexEntry { node: 305, pos: 93214 },
|
||||
IndexEntry { node: 138, pos: 64 },
|
||||
IndexEntry { node: 129, pos: 53 },
|
||||
IndexEntry { node: 192, pos: 33334 },
|
||||
IndexEntry { node: 200, pos: 80123 },
|
||||
];
|
||||
let mut c = Cursor::new(vec![]);
|
||||
write_index(entries.clone(), &mut c);
|
||||
let mut buf = c.into_inner();
|
||||
let expected: &[u8] = &[
|
||||
0, 0, 0, 11, // # entries
|
||||
// values:
|
||||
0,0,0,17, 0,0,0,29, 0,0,4,151, 0,0,0,34,
|
||||
0,0,0,53, 0,0,0,64, 0,0,0,70, 0,0,0,21,
|
||||
0,0,130,54, 0,1,56,251, 0,1,108,30,
|
||||
// index:
|
||||
128,0,0,1,0,0,0,0, 0,0,0,1,0,0,0,2,
|
||||
0,0,0,0,0,0,0,3, 0,0,0,0,0,0,0,3,
|
||||
0,2,4,3,0,0,0,3, 128,0,0,0,0,0,0,7,
|
||||
0,0,1,1,0,0,0,8, 0,0,0,0,0,0,0,10,
|
||||
0,0,0,0,0,0,0,10, 0,2,0,0,0,0,0,10
|
||||
];
|
||||
assert_eq!(buf, expected);
|
||||
|
||||
// insert some junk padding
|
||||
for i in 0..17 { buf.insert(0, i); buf.push(i) }
|
||||
let index = Index::from_buf(&buf, 17, buf.len()-17);
|
||||
|
||||
// test round-trip
|
||||
for i in 0..4096 {
|
||||
assert_eq!(index.lookup_item(&buf, i),
|
||||
entries.iter().find(|e| e.node == i).map(|n| n.pos as u32));
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@ pub mod decoder;
|
||||
pub mod creader;
|
||||
pub mod cstore;
|
||||
pub mod csearch;
|
||||
pub mod index;
|
||||
pub mod loader;
|
||||
pub mod filesearch;
|
||||
pub mod macro_import;
|
||||
|
Loading…
Reference in New Issue
Block a user