auto merge of #8745 : brson/rust/metadata, r=cmr

This does two things: 1) stops compressing metadata, 2) stops copying the metadata section, instead holding a reference to the buffer returned by the LLVM section iterator.

Not compressing metadata requires something like 7x the storage space, but makes running tests about 9% faster. This has been a time improvement on all platforms I've tested, including windows. I considered leaving compression as an option but it doesn't seem to be worth the complexity since we don't currently have any use cases where we need to save that space.

In order to avoid copying the metadata section I had to hack up extra::ebml a bit to support unsafe buffers. We should probably move it into librustc so that it can evolve to support the compiler without worrying about having a crummy interface.

r? @graydon
This commit is contained in:
bors 2013-08-25 13:36:14 -07:00
commit 491bc3568c
10 changed files with 133 additions and 90 deletions

3
configure vendored
View File

@ -381,7 +381,8 @@ opt mingw-cross 0 "cross-compile for win32 using mingw"
opt clang 0 "prefer clang to gcc for building the runtime" opt clang 0 "prefer clang to gcc for building the runtime"
opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds" opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
opt local-rust 0 "use an installed rustc rather than downloading a snapshot" opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
opt pax-flags 0 "apply PaX flags to rustc binaries (required for GRSecurity/PaX-patched kernels)" opt pax-flags 0 "apply PaX flags to rustc binaries (required for GRSecurity/PaX-patched
kernels)"
valopt prefix "/usr/local" "set installation prefix" valopt prefix "/usr/local" "set installation prefix"
valopt local-rust-root "/usr/local" "set prefix for local rust binary" valopt local-rust-root "/usr/local" "set prefix for local rust binary"
valopt llvm-root "" "set LLVM root" valopt llvm-root "" "set LLVM root"

View File

@ -12,6 +12,8 @@
use std::str; use std::str;
use std::cast;
use std::vec;
// Simple Extensible Binary Markup Language (ebml) reader and writer on a // Simple Extensible Binary Markup Language (ebml) reader and writer on a
// cursor model. See the specification here: // cursor model. See the specification here:
@ -29,9 +31,42 @@ struct EbmlState {
data_pos: uint, data_pos: uint,
} }
#[deriving(Clone)]
pub enum EbmlData {
SafeData(@~[u8]),
UnsafeData(*u8, uint)
}
impl EbmlData {
#[inline]
pub fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [u8] {
match *self {
SafeData(@ref v) => v.slice(start, end),
UnsafeData(buf, len) => unsafe {
do vec::raw::buf_as_slice(buf, len) |s| {
cast::transmute(s.slice(start, end))
}
}
}
}
#[inline]
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
self.slice(0, self.len())
}
#[inline]
pub fn len(&self) -> uint {
match *self {
SafeData(@ref v) => v.len(),
UnsafeData(_, len) => len
}
}
}
#[deriving(Clone)] #[deriving(Clone)]
pub struct Doc { pub struct Doc {
data: @~[u8], data: EbmlData,
start: uint, start: uint,
end: uint, end: uint,
} }
@ -185,24 +220,28 @@ pub mod reader {
} }
pub fn Doc(data: @~[u8]) -> Doc { pub fn Doc(data: @~[u8]) -> Doc {
Doc { data: data, start: 0u, end: data.len() } Doc { data: SafeData(data), start: 0u, end: data.len() }
} }
pub fn doc_at(data: @~[u8], start: uint) -> TaggedDoc { pub fn unsafe_Doc(buf: *u8, len: uint) -> Doc {
let elt_tag = vuint_at(*data, start); Doc { data: UnsafeData(buf, len), start: 0u, end: len }
let elt_size = vuint_at(*data, elt_tag.next); }
pub fn doc_at(data: &EbmlData, start: uint) -> TaggedDoc {
let elt_tag = vuint_at(data.as_slice(), start);
let elt_size = vuint_at(data.as_slice(), elt_tag.next);
let end = elt_size.next + elt_size.val; let end = elt_size.next + elt_size.val;
TaggedDoc { TaggedDoc {
tag: elt_tag.val, tag: elt_tag.val,
doc: Doc { data: data, start: elt_size.next, end: end } doc: Doc { data: data.clone(), start: elt_size.next, end: end }
} }
} }
pub fn maybe_get_doc(d: Doc, tg: uint) -> Option<Doc> { pub fn maybe_get_doc(d: Doc, tg: uint) -> Option<Doc> {
let mut pos = d.start; let mut pos = d.start;
while pos < d.end { while pos < d.end {
let elt_tag = vuint_at(*d.data, pos); let elt_tag = vuint_at(d.data.as_slice(), pos);
let elt_size = vuint_at(*d.data, elt_tag.next); let elt_size = vuint_at(d.data.as_slice(), elt_tag.next);
pos = elt_size.next + elt_size.val; pos = elt_size.next + elt_size.val;
if elt_tag.val == tg { if elt_tag.val == tg {
return Some(Doc { data: d.data, start: elt_size.next, return Some(Doc { data: d.data, start: elt_size.next,
@ -225,8 +264,8 @@ pub mod reader {
pub fn docs(d: Doc, it: &fn(uint, Doc) -> bool) -> bool { pub fn docs(d: Doc, it: &fn(uint, Doc) -> bool) -> bool {
let mut pos = d.start; let mut pos = d.start;
while pos < d.end { while pos < d.end {
let elt_tag = vuint_at(*d.data, pos); let elt_tag = vuint_at(d.data.as_slice(), pos);
let elt_size = vuint_at(*d.data, elt_tag.next); let elt_size = vuint_at(d.data.as_slice(), elt_tag.next);
pos = elt_size.next + elt_size.val; pos = elt_size.next + elt_size.val;
let doc = Doc { data: d.data, start: elt_size.next, end: pos }; let doc = Doc { data: d.data, start: elt_size.next, end: pos };
if !it(elt_tag.val, doc) { if !it(elt_tag.val, doc) {
@ -239,8 +278,8 @@ pub mod reader {
pub fn tagged_docs(d: Doc, tg: uint, it: &fn(Doc) -> bool) -> bool { pub fn tagged_docs(d: Doc, tg: uint, it: &fn(Doc) -> bool) -> bool {
let mut pos = d.start; let mut pos = d.start;
while pos < d.end { while pos < d.end {
let elt_tag = vuint_at(*d.data, pos); let elt_tag = vuint_at(d.data.as_slice(), pos);
let elt_size = vuint_at(*d.data, elt_tag.next); let elt_size = vuint_at(d.data.as_slice(), elt_tag.next);
pos = elt_size.next + elt_size.val; pos = elt_size.next + elt_size.val;
if elt_tag.val == tg { if elt_tag.val == tg {
let doc = Doc { data: d.data, start: elt_size.next, let doc = Doc { data: d.data, start: elt_size.next,
@ -260,22 +299,22 @@ pub mod reader {
pub fn doc_as_u8(d: Doc) -> u8 { pub fn doc_as_u8(d: Doc) -> u8 {
assert_eq!(d.end, d.start + 1u); assert_eq!(d.end, d.start + 1u);
(*d.data)[d.start] d.data.as_slice()[d.start]
} }
pub fn doc_as_u16(d: Doc) -> u16 { pub fn doc_as_u16(d: Doc) -> u16 {
assert_eq!(d.end, d.start + 2u); assert_eq!(d.end, d.start + 2u);
io::u64_from_be_bytes(*d.data, d.start, 2u) as u16 io::u64_from_be_bytes(d.data.as_slice(), d.start, 2u) as u16
} }
pub fn doc_as_u32(d: Doc) -> u32 { pub fn doc_as_u32(d: Doc) -> u32 {
assert_eq!(d.end, d.start + 4u); assert_eq!(d.end, d.start + 4u);
io::u64_from_be_bytes(*d.data, d.start, 4u) as u32 io::u64_from_be_bytes(d.data.as_slice(), d.start, 4u) as u32
} }
pub fn doc_as_u64(d: Doc) -> u64 { pub fn doc_as_u64(d: Doc) -> u64 {
assert_eq!(d.end, d.start + 8u); assert_eq!(d.end, d.start + 8u);
io::u64_from_be_bytes(*d.data, d.start, 8u) io::u64_from_be_bytes(d.data.as_slice(), d.start, 8u)
} }
pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 } pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
@ -298,8 +337,7 @@ pub mod reader {
impl Decoder { impl Decoder {
fn _check_label(&mut self, lbl: &str) { fn _check_label(&mut self, lbl: &str) {
if self.pos < self.parent.end { if self.pos < self.parent.end {
let TaggedDoc { tag: r_tag, doc: r_doc } = let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(&self.parent.data, self.pos);
doc_at(self.parent.data, self.pos);
if r_tag == (EsLabel as uint) { if r_tag == (EsLabel as uint) {
self.pos = r_doc.end; self.pos = r_doc.end;
@ -316,8 +354,7 @@ pub mod reader {
if self.pos >= self.parent.end { if self.pos >= self.parent.end {
fail!("no more documents in current node!"); fail!("no more documents in current node!");
} }
let TaggedDoc { tag: r_tag, doc: r_doc } = let TaggedDoc { tag: r_tag, doc: r_doc } = doc_at(&self.parent.data, self.pos);
doc_at(self.parent.data, self.pos);
debug!("self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?", debug!("self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?",
self.parent.start, self.parent.start,
self.parent.end, self.parent.end,

View File

@ -763,7 +763,7 @@ pub fn build_session_options(binary: @str,
parse_only: parse_only, parse_only: parse_only,
no_trans: no_trans, no_trans: no_trans,
debugging_opts: debugging_opts, debugging_opts: debugging_opts,
android_cross_path: android_cross_path android_cross_path: android_cross_path,
}; };
return sopts; return sopts;
} }

View File

@ -15,6 +15,7 @@ use metadata::cstore;
use metadata::decoder; use metadata::decoder;
use metadata::filesearch::FileSearch; use metadata::filesearch::FileSearch;
use metadata::loader; use metadata::loader;
use metadata::loader::MetadataSection;
use std::hashmap::HashMap; use std::hashmap::HashMap;
use syntax::ast; use syntax::ast;
@ -308,7 +309,7 @@ fn resolve_crate(e: @mut Env,
} }
// Go through the crate metadata and load any crates that it references // Go through the crate metadata and load any crates that it references
fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map { fn resolve_crate_deps(e: @mut Env, cdata: MetadataSection) -> cstore::cnum_map {
debug!("resolving deps of external crate"); debug!("resolving deps of external crate");
// The map from crate numbers in the crate we're resolving to local crate // The map from crate numbers in the crate we're resolving to local crate
// numbers // numbers

View File

@ -188,7 +188,7 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::def_id,
def: ast::def_id) -> ty::ty_param_bounds_and_ty { def: ast::def_id) -> ty::ty_param_bounds_and_ty {
let cstore = tcx.cstore; let cstore = tcx.cstore;
let cdata = cstore::get_crate_data(cstore, class_id.crate); let cdata = cstore::get_crate_data(cstore, class_id.crate);
let all_items = reader::get_doc(reader::Doc(cdata.data), tag_items); let all_items = reader::get_doc(decoder::section_to_ebml_doc(cdata.data), tag_items);
debug!("Looking up %?", class_id); debug!("Looking up %?", class_id);
let class_doc = expect(tcx.diag, let class_doc = expect(tcx.diag,
decoder::maybe_find_item(class_id.node, all_items), decoder::maybe_find_item(class_id.node, all_items),

View File

@ -15,6 +15,7 @@
use metadata::cstore; use metadata::cstore;
use metadata::decoder; use metadata::decoder;
use metadata::loader::MetadataSection;
use std::hashmap::HashMap; use std::hashmap::HashMap;
use extra; use extra;
@ -29,7 +30,7 @@ pub type cnum_map = @mut HashMap<ast::CrateNum, ast::CrateNum>;
pub struct crate_metadata { pub struct crate_metadata {
name: @str, name: @str,
data: @~[u8], data: MetadataSection,
cnum_map: cnum_map, cnum_map: cnum_map,
cnum: ast::CrateNum cnum: ast::CrateNum
} }

View File

@ -20,6 +20,7 @@ use metadata::decoder;
use metadata::tydecode::{parse_ty_data, parse_def_id, use metadata::tydecode::{parse_ty_data, parse_def_id,
parse_type_param_def_data, parse_type_param_def_data,
parse_bare_fn_ty_data, parse_trait_ref_data}; parse_bare_fn_ty_data, parse_trait_ref_data};
use metadata::loader::{MetadataSection, UnsafeSection};
use middle::ty; use middle::ty;
use middle::typeck; use middle::typeck;
use middle::astencode::vtable_decoder_helpers; use middle::astencode::vtable_decoder_helpers;
@ -56,16 +57,16 @@ fn lookup_hash(d: ebml::Doc, eq_fn: &fn(x:&[u8]) -> bool, hash: u64) ->
let index = reader::get_doc(d, tag_index); let index = reader::get_doc(d, tag_index);
let table = reader::get_doc(index, tag_index_table); let table = reader::get_doc(index, tag_index_table);
let hash_pos = table.start + (hash % 256 * 4) as uint; let hash_pos = table.start + (hash % 256 * 4) as uint;
let pos = io::u64_from_be_bytes(*d.data, hash_pos, 4) as uint; let pos = io::u64_from_be_bytes(d.data.as_slice(), hash_pos, 4) as uint;
let tagged_doc = reader::doc_at(d.data, pos); let tagged_doc = reader::doc_at(&d.data, pos);
let belt = tag_index_buckets_bucket_elt; let belt = tag_index_buckets_bucket_elt;
let mut ret = None; let mut ret = None;
do reader::tagged_docs(tagged_doc.doc, belt) |elt| { do reader::tagged_docs(tagged_doc.doc, belt) |elt| {
let pos = io::u64_from_be_bytes(*elt.data, elt.start, 4) as uint; let pos = io::u64_from_be_bytes(elt.data.as_slice(), elt.start, 4) as uint;
if eq_fn(elt.data.slice(elt.start + 4, elt.end)) { if eq_fn(elt.data.slice(elt.start + 4, elt.end)) {
ret = Some(reader::doc_at(d.data, pos).doc); ret = Some(reader::doc_at(&d.data, pos).doc);
false false
} else { } else {
true true
@ -96,8 +97,8 @@ fn find_item(item_id: int, items: ebml::Doc) -> ebml::Doc {
// Looks up an item in the given metadata and returns an ebml doc pointing // Looks up an item in the given metadata and returns an ebml doc pointing
// to the item data. // to the item data.
fn lookup_item(item_id: int, data: @~[u8]) -> ebml::Doc { fn lookup_item(item_id: int, data: MetadataSection) -> ebml::Doc {
let items = reader::get_doc(reader::Doc(data), tag_items); let items = reader::get_doc(section_to_ebml_doc(data), tag_items);
find_item(item_id, items) find_item(item_id, items)
} }
@ -215,13 +216,13 @@ fn variant_disr_val(d: ebml::Doc) -> Option<uint> {
fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t { fn doc_type(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::t {
let tp = reader::get_doc(doc, tag_items_data_item_type); let tp = reader::get_doc(doc, tag_items_data_item_type);
parse_ty_data(*tp.data, cdata.cnum, tp.start, tcx, parse_ty_data(tp.data.as_slice(), cdata.cnum, tp.start, tcx,
|_, did| translate_def_id(cdata, did)) |_, did| translate_def_id(cdata, did))
} }
fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::BareFnTy { fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::BareFnTy {
let tp = reader::get_doc(doc, tag_item_method_fty); let tp = reader::get_doc(doc, tag_item_method_fty);
parse_bare_fn_ty_data(*tp.data, cdata.cnum, tp.start, tcx, parse_bare_fn_ty_data(tp.data.as_slice(), cdata.cnum, tp.start, tcx,
|_, did| translate_def_id(cdata, did)) |_, did| translate_def_id(cdata, did))
} }
@ -230,7 +231,7 @@ fn doc_transformed_self_ty(doc: ebml::Doc,
cdata: cmd) -> Option<ty::t> cdata: cmd) -> Option<ty::t>
{ {
do reader::maybe_get_doc(doc, tag_item_method_transformed_self_ty).map |tp| { do reader::maybe_get_doc(doc, tag_item_method_transformed_self_ty).map |tp| {
parse_ty_data(*tp.data, cdata.cnum, tp.start, tcx, parse_ty_data(tp.data.as_slice(), cdata.cnum, tp.start, tcx,
|_, did| translate_def_id(cdata, did)) |_, did| translate_def_id(cdata, did))
} }
} }
@ -241,7 +242,7 @@ pub fn item_type(_item_id: ast::def_id, item: ebml::Doc,
} }
fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef { fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef {
parse_trait_ref_data(*doc.data, cdata.cnum, doc.start, tcx, parse_trait_ref_data(doc.data.as_slice(), cdata.cnum, doc.start, tcx,
|_, did| translate_def_id(cdata, did)) |_, did| translate_def_id(cdata, did))
} }
@ -256,7 +257,7 @@ fn item_ty_param_defs(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd,
let mut bounds = ~[]; let mut bounds = ~[];
do reader::tagged_docs(item, tag) |p| { do reader::tagged_docs(item, tag) |p| {
let bd = parse_type_param_def_data( let bd = parse_type_param_def_data(
*p.data, p.start, cdata.cnum, tcx, p.data.as_slice(), p.start, cdata.cnum, tcx,
|_, did| translate_def_id(cdata, did)); |_, did| translate_def_id(cdata, did));
bounds.push(bd); bounds.push(bd);
true true
@ -359,7 +360,7 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::CrateNum)
} }
} }
pub fn lookup_def(cnum: ast::CrateNum, data: @~[u8], did_: ast::def_id) -> pub fn lookup_def(cnum: ast::CrateNum, data: MetadataSection, did_: ast::def_id) ->
ast::def { ast::def {
let item = lookup_item(did_.node, data); let item = lookup_item(did_.node, data);
let did = ast::def_id { crate: cnum, node: did_.node }; let did = ast::def_id { crate: cnum, node: did_.node };
@ -418,7 +419,7 @@ pub fn get_region_param(cdata: cmd, id: ast::NodeId)
return item_ty_region_param(item); return item_ty_region_param(item);
} }
pub fn get_type_param_count(data: @~[u8], id: ast::NodeId) -> uint { pub fn get_type_param_count(data: MetadataSection, id: ast::NodeId) -> uint {
item_ty_param_count(lookup_item(id, data)) item_ty_param_count(lookup_item(id, data))
} }
@ -449,7 +450,7 @@ pub fn get_impl_vtables(cdata: cmd,
pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::NodeId, pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
name: ast::ident) -> Option<ast::def_id> { name: ast::ident) -> Option<ast::def_id> {
let items = reader::get_doc(reader::Doc(cdata.data), tag_items); let items = reader::get_doc(section_to_ebml_doc(cdata.data), tag_items);
let mut found = None; let mut found = None;
do reader::tagged_docs(find_item(id, items), tag_item_impl_method) |mid| { do reader::tagged_docs(find_item(id, items), tag_item_impl_method) |mid| {
let m_did = reader::with_doc_data(mid, parse_def_id); let m_did = reader::with_doc_data(mid, parse_def_id);
@ -461,7 +462,7 @@ pub fn get_impl_method(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
found found
} }
pub fn get_symbol(data: @~[u8], id: ast::NodeId) -> ~str { pub fn get_symbol(data: MetadataSection, id: ast::NodeId) -> ~str {
return item_symbol(lookup_item(id, data)); return item_symbol(lookup_item(id, data));
} }
@ -482,7 +483,7 @@ fn def_like_to_def(def_like: def_like) -> ast::def {
/// Iterates over the language items in the given crate. /// Iterates over the language items in the given crate.
pub fn each_lang_item(cdata: cmd, f: &fn(ast::NodeId, uint) -> bool) -> bool { pub fn each_lang_item(cdata: cmd, f: &fn(ast::NodeId, uint) -> bool) -> bool {
let root = reader::Doc(cdata.data); let root = section_to_ebml_doc(cdata.data);
let lang_items = reader::get_doc(root, tag_lang_items); let lang_items = reader::get_doc(root, tag_lang_items);
do reader::tagged_docs(lang_items, tag_lang_items_item) |item_doc| { do reader::tagged_docs(lang_items, tag_lang_items_item) |item_doc| {
let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id); let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id);
@ -577,10 +578,10 @@ impl<'self> EachItemContext<'self> {
fn each_item_of_module(&mut self, def_id: ast::def_id) -> bool { fn each_item_of_module(&mut self, def_id: ast::def_id) -> bool {
// This item might not be in this crate. If it's not, look it up. // This item might not be in this crate. If it's not, look it up.
let items = if def_id.crate == self.cdata.cnum { let items = if def_id.crate == self.cdata.cnum {
reader::get_doc(reader::Doc(self.cdata.data), tag_items) reader::get_doc(section_to_ebml_doc(self.cdata.data), tag_items)
} else { } else {
let crate_data = (self.get_crate_data)(def_id.crate); let crate_data = (self.get_crate_data)(def_id.crate);
let root = reader::Doc(crate_data.data); let root = section_to_ebml_doc(crate_data.data);
reader::get_doc(root, tag_items) reader::get_doc(root, tag_items)
}; };
@ -606,10 +607,10 @@ impl<'self> EachItemContext<'self> {
// a reexport. // a reexport.
let other_crates_items = if child_def_id.crate == let other_crates_items = if child_def_id.crate ==
self.cdata.cnum { self.cdata.cnum {
reader::get_doc(reader::Doc(self.cdata.data), tag_items) reader::get_doc(section_to_ebml_doc(self.cdata.data), tag_items)
} else { } else {
let crate_data = (self.get_crate_data)(child_def_id.crate); let crate_data = (self.get_crate_data)(child_def_id.crate);
let root = reader::Doc(crate_data.data); let root = section_to_ebml_doc(crate_data.data);
reader::get_doc(root, tag_items) reader::get_doc(root, tag_items)
}; };
@ -673,10 +674,10 @@ impl<'self> EachItemContext<'self> {
// This reexport may be in yet another crate. // This reexport may be in yet another crate.
let other_crates_items = if def_id.crate == self.cdata.cnum { let other_crates_items = if def_id.crate == self.cdata.cnum {
reader::get_doc(reader::Doc(self.cdata.data), tag_items) reader::get_doc(section_to_ebml_doc(self.cdata.data), tag_items)
} else { } else {
let crate_data = (self.get_crate_data)(def_id.crate); let crate_data = (self.get_crate_data)(def_id.crate);
let root = reader::Doc(crate_data.data); let root = section_to_ebml_doc(crate_data.data);
reader::get_doc(root, tag_items) reader::get_doc(root, tag_items)
}; };
@ -708,7 +709,7 @@ pub fn each_path(intr: @ident_interner,
// make fast. It's the source of most of the performance problems when // make fast. It's the source of most of the performance problems when
// compiling small crates. // compiling small crates.
let root_doc = reader::Doc(cdata.data); let root_doc = section_to_ebml_doc(cdata.data);
let misc_info_doc = reader::get_doc(root_doc, tag_misc_info); let misc_info_doc = reader::get_doc(root_doc, tag_misc_info);
let crate_items_doc = reader::get_doc(misc_info_doc, let crate_items_doc = reader::get_doc(misc_info_doc,
tag_misc_info_crate_items); tag_misc_info_crate_items);
@ -768,7 +769,7 @@ pub fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt,
pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::NodeId, pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::NodeId,
tcx: ty::ctxt) -> ~[@ty::VariantInfo] { tcx: ty::ctxt) -> ~[@ty::VariantInfo] {
let data = cdata.data; let data = cdata.data;
let items = reader::get_doc(reader::Doc(data), tag_items); let items = reader::get_doc(section_to_ebml_doc(data), tag_items);
let item = find_item(id, items); let item = find_item(id, items);
let mut infos: ~[@ty::VariantInfo] = ~[]; let mut infos: ~[@ty::VariantInfo] = ~[];
let variant_ids = enum_variant_ids(item, cdata); let variant_ids = enum_variant_ids(item, cdata);
@ -1206,8 +1207,14 @@ fn list_crate_attributes(intr: @ident_interner, md: ebml::Doc, hash: &str,
out.write_str("\n\n"); out.write_str("\n\n");
} }
pub fn get_crate_attributes(data: @~[u8]) -> ~[ast::Attribute] { pub fn get_crate_attributes(data: MetadataSection) -> ~[ast::Attribute] {
return get_attributes(reader::Doc(data)); return get_attributes(section_to_ebml_doc(data));
}
pub fn section_to_ebml_doc(data: MetadataSection) -> ebml::Doc {
match data {
UnsafeSection(_, buf, len) => reader::unsafe_Doc(buf, len)
}
} }
#[deriving(Clone)] #[deriving(Clone)]
@ -1218,9 +1225,9 @@ pub struct crate_dep {
hash: @str hash: @str
} }
pub fn get_crate_deps(data: @~[u8]) -> ~[crate_dep] { pub fn get_crate_deps(data: MetadataSection) -> ~[crate_dep] {
let mut deps: ~[crate_dep] = ~[]; let mut deps: ~[crate_dep] = ~[];
let cratedoc = reader::Doc(data); let cratedoc = section_to_ebml_doc(data);
let depsdoc = reader::get_doc(cratedoc, tag_crate_deps); let depsdoc = reader::get_doc(cratedoc, tag_crate_deps);
let mut crate_num = 1; let mut crate_num = 1;
fn docstr(doc: ebml::Doc, tag_: uint) -> @str { fn docstr(doc: ebml::Doc, tag_: uint) -> @str {
@ -1238,7 +1245,7 @@ pub fn get_crate_deps(data: @~[u8]) -> ~[crate_dep] {
return deps; return deps;
} }
fn list_crate_deps(data: @~[u8], out: @io::Writer) { fn list_crate_deps(data: MetadataSection, out: @io::Writer) {
out.write_str("=External Dependencies=\n"); out.write_str("=External Dependencies=\n");
let r = get_crate_deps(data); let r = get_crate_deps(data);
@ -1251,13 +1258,13 @@ fn list_crate_deps(data: @~[u8], out: @io::Writer) {
out.write_str("\n"); out.write_str("\n");
} }
pub fn get_crate_hash(data: @~[u8]) -> @str { pub fn get_crate_hash(data: MetadataSection) -> @str {
let cratedoc = reader::Doc(data); let cratedoc = section_to_ebml_doc(data);
let hashdoc = reader::get_doc(cratedoc, tag_crate_hash); let hashdoc = reader::get_doc(cratedoc, tag_crate_hash);
hashdoc.as_str_slice().to_managed() hashdoc.as_str_slice().to_managed()
} }
pub fn get_crate_vers(data: @~[u8]) -> @str { pub fn get_crate_vers(data: MetadataSection) -> @str {
let attrs = decoder::get_crate_attributes(data); let attrs = decoder::get_crate_attributes(data);
let linkage_attrs = attr::find_linkage_metas(attrs); let linkage_attrs = attr::find_linkage_metas(attrs);
@ -1282,10 +1289,10 @@ fn iter_crate_items(intr: @ident_interner, cdata: cmd,
}; };
} }
pub fn list_crate_metadata(intr: @ident_interner, bytes: @~[u8], pub fn list_crate_metadata(intr: @ident_interner, bytes: MetadataSection,
out: @io::Writer) { out: @io::Writer) {
let hash = get_crate_hash(bytes); let hash = get_crate_hash(bytes);
let md = reader::Doc(bytes); let md = section_to_ebml_doc(bytes);
list_crate_attributes(intr, md, hash, out); list_crate_attributes(intr, md, hash, out);
list_crate_deps(bytes, out); list_crate_deps(bytes, out);
} }
@ -1307,7 +1314,7 @@ pub fn translate_def_id(cdata: cmd, did: ast::def_id) -> ast::def_id {
} }
pub fn get_link_args_for_crate(cdata: cmd) -> ~[~str] { pub fn get_link_args_for_crate(cdata: cmd) -> ~[~str] {
let link_args = reader::get_doc(reader::Doc(cdata.data), tag_link_args); let link_args = reader::get_doc(section_to_ebml_doc(cdata.data), tag_link_args);
let mut result = ~[]; let mut result = ~[];
do reader::tagged_docs(link_args, tag_link_args_arg) |arg_doc| { do reader::tagged_docs(link_args, tag_link_args_arg) |arg_doc| {
result.push(arg_doc.as_str()); result.push(arg_doc.as_str());

View File

@ -26,7 +26,6 @@ use std::hashmap::{HashMap, HashSet};
use std::io; use std::io;
use std::str; use std::str;
use std::vec; use std::vec;
use extra::flate;
use extra::serialize::Encodable; use extra::serialize::Encodable;
use extra; use extra;
use syntax::abi::AbiSet; use syntax::abi::AbiSet;
@ -1570,7 +1569,7 @@ pub static metadata_encoding_version : &'static [u8] =
0x75, //'u' as u8, 0x75, //'u' as u8,
0x73, //'s' as u8, 0x73, //'s' as u8,
0x74, //'t' as u8, 0x74, //'t' as u8,
0, 0, 0, 1 ]; 0, 0, 0, 2 ];
pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] { pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
let wr = @io::BytesWriter::new(); let wr = @io::BytesWriter::new();
@ -1683,8 +1682,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
let writer_bytes: &mut ~[u8] = wr.bytes; let writer_bytes: &mut ~[u8] = wr.bytes;
metadata_encoding_version.to_owned() + return metadata_encoding_version.to_owned() + *writer_bytes;
flate::deflate_bytes(*writer_bytes)
} }
// Get the encoded string for a type // Get the encoded string for a type

View File

@ -11,7 +11,7 @@
//! Finds crate binaries and loads their metadata //! Finds crate binaries and loads their metadata
use lib::llvm::{False, llvm, mk_object_file, mk_section_iter}; use lib::llvm::{False, llvm, mk_object_file, mk_section_iter, ObjectFile};
use metadata::decoder; use metadata::decoder;
use metadata::encoder; use metadata::encoder;
use metadata::filesearch::FileSearch; use metadata::filesearch::FileSearch;
@ -32,7 +32,6 @@ use std::os::consts::{macos, freebsd, linux, android, win32};
use std::ptr; use std::ptr;
use std::str; use std::str;
use std::vec; use std::vec;
use extra::flate;
pub enum os { pub enum os {
os_macos, os_macos,
@ -54,7 +53,14 @@ pub struct Context {
intr: @ident_interner intr: @ident_interner
} }
pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) { #[deriving(Clone)]
pub enum MetadataSection {
// A pointer to the object file metadata section, along with
// the ObjectFile handle that keeps it from being destructed
UnsafeSection(@ObjectFile, *u8, uint)
}
pub fn load_library_crate(cx: &Context) -> (~str, MetadataSection) {
match find_library_crate(cx) { match find_library_crate(cx) {
Some(t) => t, Some(t) => t,
None => { None => {
@ -65,7 +71,7 @@ pub fn load_library_crate(cx: &Context) -> (~str, @~[u8]) {
} }
} }
fn find_library_crate(cx: &Context) -> Option<(~str, @~[u8])> { fn find_library_crate(cx: &Context) -> Option<(~str, MetadataSection)> {
attr::require_unique_names(cx.diag, cx.metas); attr::require_unique_names(cx.diag, cx.metas);
find_library_crate_aux(cx, libname(cx), cx.filesearch) find_library_crate_aux(cx, libname(cx), cx.filesearch)
} }
@ -87,7 +93,7 @@ fn find_library_crate_aux(
cx: &Context, cx: &Context,
(prefix, suffix): (~str, ~str), (prefix, suffix): (~str, ~str),
filesearch: @filesearch::FileSearch filesearch: @filesearch::FileSearch
) -> Option<(~str, @~[u8])> { ) -> Option<(~str, MetadataSection)> {
let crate_name = crate_name_from_metas(cx.metas); let crate_name = crate_name_from_metas(cx.metas);
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-" // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
let prefix = fmt!("%s%s-", prefix, crate_name); let prefix = fmt!("%s%s-", prefix, crate_name);
@ -171,7 +177,7 @@ pub fn note_linkage_attrs(intr: @ident_interner,
} }
} }
fn crate_matches(crate_data: @~[u8], fn crate_matches(crate_data: MetadataSection,
metas: &[@ast::MetaItem], metas: &[@ast::MetaItem],
hash: @str) -> bool { hash: @str) -> bool {
let attrs = decoder::get_crate_attributes(crate_data); let attrs = decoder::get_crate_attributes(crate_data);
@ -197,17 +203,17 @@ pub fn metadata_matches(extern_metas: &[@ast::MetaItem],
} }
fn get_metadata_section(os: os, fn get_metadata_section(os: os,
filename: &Path) -> Option<@~[u8]> { filename: &Path) -> Option<MetadataSection> {
unsafe { unsafe {
let mb = do filename.with_c_str |buf| { let mb = do filename.with_c_str |buf| {
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf) llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
}; };
if mb as int == 0 { return option::None::<@~[u8]>; } if mb as int == 0 { return None; }
let of = match mk_object_file(mb) { let of = @match mk_object_file(mb) {
option::Some(of) => of, option::Some(of) => of,
_ => return option::None::<@~[u8]> _ => return None
}; };
let si = mk_section_iter(of.llof); let si = mk_section_iter((*of).llof);
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False { while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
let name_buf = llvm::LLVMGetSectionName(si.llsi); let name_buf = llvm::LLVMGetSectionName(si.llsi);
let name = str::raw::from_c_str(name_buf); let name = str::raw::from_c_str(name_buf);
@ -215,7 +221,6 @@ fn get_metadata_section(os: os,
if name == read_meta_section_name(os) { if name == read_meta_section_name(os) {
let cbuf = llvm::LLVMGetSectionContents(si.llsi); let cbuf = llvm::LLVMGetSectionContents(si.llsi);
let csz = llvm::LLVMGetSectionSize(si.llsi) as uint; let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
let mut found = None;
let cvbuf: *u8 = cast::transmute(cbuf); let cvbuf: *u8 = cast::transmute(cbuf);
let vlen = encoder::metadata_encoding_version.len(); let vlen = encoder::metadata_encoding_version.len();
debug!("checking %u bytes of metadata-version stamp", debug!("checking %u bytes of metadata-version stamp",
@ -229,19 +234,12 @@ fn get_metadata_section(os: os,
if !version_ok { return None; } if !version_ok { return None; }
let cvbuf1 = ptr::offset(cvbuf, vlen as int); let cvbuf1 = ptr::offset(cvbuf, vlen as int);
debug!("inflating %u bytes of compressed metadata",
csz - vlen); return Some(UnsafeSection(of, cvbuf1, csz-vlen))
do vec::raw::buf_as_slice(cvbuf1, csz-vlen) |bytes| {
let inflated = flate::inflate_bytes(bytes);
found = Some(@(inflated));
}
if found != None {
return found;
}
} }
llvm::LLVMMoveToNextSection(si.llsi); llvm::LLVMMoveToNextSection(si.llsi);
} }
return option::None::<@~[u8]>; return None;
} }
} }

View File

@ -1022,7 +1022,7 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
tcx: ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t { tcx: ty::ctxt, cdata: @cstore::crate_metadata) -> ty::t {
do self.read_opaque |_, doc| { do self.read_opaque |_, doc| {
tydecode::parse_ty_data( tydecode::parse_ty_data(
*doc.data, doc.data.as_slice(),
cdata.cnum, cdata.cnum,
doc.start, doc.start,
tcx, tcx,
@ -1044,7 +1044,7 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
return do self.read_opaque |this, doc| { return do self.read_opaque |this, doc| {
let ty = tydecode::parse_ty_data( let ty = tydecode::parse_ty_data(
*doc.data, doc.data.as_slice(),
xcx.dcx.cdata.cnum, xcx.dcx.cdata.cnum,
doc.start, doc.start,
xcx.dcx.tcx, xcx.dcx.tcx,
@ -1060,7 +1060,7 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
fn type_string(doc: ebml::Doc) -> ~str { fn type_string(doc: ebml::Doc) -> ~str {
let mut str = ~""; let mut str = ~"";
for i in range(doc.start, doc.end) { for i in range(doc.start, doc.end) {
str.push_char(doc.data[i] as char); str.push_char(doc.data.as_slice()[i] as char);
} }
str str
} }
@ -1074,7 +1074,7 @@ impl ebml_decoder_decoder_helpers for reader::Decoder {
-> ty::TypeParameterDef { -> ty::TypeParameterDef {
do self.read_opaque |this, doc| { do self.read_opaque |this, doc| {
tydecode::parse_type_param_def_data( tydecode::parse_type_param_def_data(
*doc.data, doc.data.as_slice(),
doc.start, doc.start,
xcx.dcx.cdata.cnum, xcx.dcx.cdata.cnum,
xcx.dcx.tcx, xcx.dcx.tcx,