Avoid unnecessary allocations in the metadata decoder

This commit is contained in:
Björn Steinbrink 2013-06-08 02:37:17 +02:00
parent 29e5aa0942
commit 2096d79626
2 changed files with 40 additions and 39 deletions

View File

@ -93,6 +93,14 @@ pub mod reader {
pub fn get(&self, tag: uint) -> Doc {
get_doc(*self, tag)
}
pub fn as_str_slice<'a>(&'a self) -> &'a str {
str::from_bytes_slice(self.data.slice(self.start, self.end))
}
pub fn as_str(&self) -> ~str {
self.as_str_slice().to_owned()
}
}
struct Res {
@ -239,15 +247,10 @@ pub mod reader {
return true;
}
pub fn doc_data(d: Doc) -> ~[u8] {
vec::slice::<u8>(*d.data, d.start, d.end).to_vec()
}
pub fn with_doc_data<T>(d: Doc, f: &fn(x: &[u8]) -> T) -> T {
f(vec::slice(*d.data, d.start, d.end))
}
pub fn doc_as_str(d: Doc) -> ~str { str::from_bytes(doc_data(d)) }
pub fn doc_as_u8(d: Doc) -> u8 {
assert_eq!(d.end, d.start + 1u);
@ -294,7 +297,7 @@ pub mod reader {
if r_tag == (EsLabel as uint) {
self.pos = r_doc.end;
let str = doc_as_str(r_doc);
let str = r_doc.as_str_slice();
if lbl != str {
fail!("Expected label %s but found %s", lbl, str);
}
@ -415,7 +418,9 @@ pub mod reader {
fn read_char(&mut self) -> char {
doc_as_u32(self.next_doc(EsChar)) as char
}
fn read_str(&mut self) -> ~str { doc_as_str(self.next_doc(EsStr)) }
fn read_str(&mut self) -> ~str {
self.next_doc(EsStr).as_str()
}
// Compound types:
fn read_enum<T>(&mut self,

View File

@ -162,14 +162,13 @@ fn item_visibility(item: ebml::Doc) -> ast::visibility {
fn item_method_sort(item: ebml::Doc) -> char {
for reader::tagged_docs(item, tag_item_trait_method_sort) |doc| {
return str::from_bytes(reader::doc_data(doc))[0] as char;
return doc.as_str_slice()[0] as char;
}
return 'r';
}
fn item_symbol(item: ebml::Doc) -> ~str {
let sym = reader::get_doc(item, tag_items_data_item_symbol);
return str::from_bytes(reader::doc_data(sym));
reader::get_doc(item, tag_items_data_item_symbol).as_str()
}
fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> {
@ -209,7 +208,7 @@ fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) -> bool {
fn variant_disr_val(d: ebml::Doc) -> Option<int> {
do reader::maybe_get_doc(d, tag_disr_val).chain |val_doc| {
int::parse_bytes(reader::doc_data(val_doc), 10u)
do reader::with_doc_data(val_doc) |data| { int::parse_bytes(data, 10u) }
}
}
@ -296,10 +295,10 @@ fn item_path(item_doc: ebml::Doc) -> ast_map::path {
let mut result = vec::with_capacity(len);
for reader::docs(path_doc) |tag, elt_doc| {
if tag == tag_path_elt_mod {
let str = reader::doc_as_str(elt_doc);
let str = elt_doc.as_str_slice();
result.push(ast_map::path_mod(token::str_to_ident(str)));
} else if tag == tag_path_elt_name {
let str = reader::doc_as_str(elt_doc);
let str = elt_doc.as_str_slice();
result.push(ast_map::path_name(token::str_to_ident(str)));
} else {
// ignore tag_path_len element
@ -311,12 +310,10 @@ fn item_path(item_doc: ebml::Doc) -> ast_map::path {
fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident {
let name = reader::get_doc(item, tag_paths_data_name);
do reader::with_doc_data(name) |data| {
let string = str::from_bytes_slice(data);
match intr.find_equiv(&StringRef(string)) {
None => token::str_to_ident(string),
Some(val) => ast::new_ident(val),
}
let string = name.as_str_slice();
match intr.find_equiv(&StringRef(string)) {
None => token::str_to_ident(string),
Some(val) => ast::new_ident(val),
}
}
@ -506,19 +503,17 @@ pub fn each_path(intr: @ident_interner,
let def_id_doc =
reader::get_doc(reexport_doc,
tag_items_data_item_reexport_def_id);
let def_id =
reader::with_doc_data(def_id_doc,
|d| parse_def_id(d));
let def_id = reader::with_doc_data(def_id_doc, parse_def_id);
let def_id = translate_def_id(cdata, def_id);
let reexport_name_doc =
reader::get_doc(reexport_doc,
tag_items_data_item_reexport_name);
let reexport_name = reader::doc_as_str(reexport_name_doc);
let reexport_name = reexport_name_doc.as_str_slice();
let reexport_path;
if path_is_empty {
reexport_path = reexport_name;
reexport_path = reexport_name.to_owned();
} else {
reexport_path = path + "::" + reexport_name;
}
@ -639,7 +634,7 @@ fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ {
}
let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self);
let string = reader::doc_as_str(explicit_self_doc);
let string = explicit_self_doc.as_str_slice();
let explicit_self_kind = string[0];
match explicit_self_kind as char {
@ -824,7 +819,7 @@ pub fn get_type_name_if_impl(cdata: cmd,
}
for reader::tagged_docs(item, tag_item_impl_type_basename) |doc| {
return Some(token::str_to_ident(str::from_bytes(reader::doc_data(doc))));
return Some(token::str_to_ident(doc.as_str_slice()));
}
return None;
@ -846,7 +841,7 @@ pub fn get_static_methods_if_impl(intr: @ident_interner,
let mut impl_method_ids = ~[];
for reader::tagged_docs(item, tag_item_impl_method) |impl_method_doc| {
impl_method_ids.push(parse_def_id(reader::doc_data(impl_method_doc)));
impl_method_ids.push(reader::with_doc_data(impl_method_doc, parse_def_id));
}
let mut static_impl_methods = ~[];
@ -943,12 +938,13 @@ fn family_names_type(fam: Family) -> bool {
}
fn read_path(d: ebml::Doc) -> (~str, uint) {
let desc = reader::doc_data(d);
let pos = io::u64_from_be_bytes(desc, 0u, 4u) as uint;
let pathbytes = vec::slice::<u8>(desc, 4u, vec::len::<u8>(desc));
let path = str::from_bytes(pathbytes);
do reader::with_doc_data(d) |desc| {
let pos = io::u64_from_be_bytes(desc, 0u, 4u) as uint;
let pathbytes = desc.slice(4u, desc.len());
let path = str::from_bytes(pathbytes);
(path, pos)
(path, pos)
}
}
fn describe_def(items: ebml::Doc, id: ast::def_id) -> ~str {
@ -989,21 +985,21 @@ fn get_meta_items(md: ebml::Doc) -> ~[@ast::meta_item] {
let mut items: ~[@ast::meta_item] = ~[];
for reader::tagged_docs(md, tag_meta_item_word) |meta_item_doc| {
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
let n = str::from_bytes(reader::doc_data(nd));
let n = nd.as_str();
items.push(attr::mk_word_item(@n));
};
for reader::tagged_docs(md, tag_meta_item_name_value) |meta_item_doc| {
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
let vd = reader::get_doc(meta_item_doc, tag_meta_item_value);
let n = str::from_bytes(reader::doc_data(nd));
let v = str::from_bytes(reader::doc_data(vd));
let n = nd.as_str();
let v = vd.as_str();
// FIXME (#623): Should be able to decode meta_name_value variants,
// but currently the encoder just drops them
items.push(attr::mk_name_value_item_str(@n, @v));
};
for reader::tagged_docs(md, tag_meta_item_list) |meta_item_doc| {
let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
let n = str::from_bytes(reader::doc_data(nd));
let n = nd.as_str();
let subitems = get_meta_items(meta_item_doc);
items.push(attr::mk_list_item(@n, subitems));
};
@ -1072,7 +1068,7 @@ pub fn get_crate_deps(data: @~[u8]) -> ~[crate_dep] {
let depsdoc = reader::get_doc(cratedoc, tag_crate_deps);
let mut crate_num = 1;
fn docstr(doc: ebml::Doc, tag_: uint) -> ~str {
str::from_bytes(reader::doc_data(reader::get_doc(doc, tag_)))
reader::get_doc(doc, tag_).as_str()
}
for reader::tagged_docs(depsdoc, tag_crate_dep) |depdoc| {
deps.push(crate_dep {cnum: crate_num,
@ -1099,7 +1095,7 @@ fn list_crate_deps(data: @~[u8], out: @io::Writer) {
pub fn get_crate_hash(data: @~[u8]) -> @~str {
let cratedoc = reader::Doc(data);
let hashdoc = reader::get_doc(cratedoc, tag_crate_hash);
@str::from_bytes(reader::doc_data(hashdoc))
@hashdoc.as_str()
}
pub fn get_crate_vers(data: @~[u8]) -> @~str {
@ -1154,7 +1150,7 @@ pub fn get_link_args_for_crate(cdata: cmd) -> ~[~str] {
let link_args = reader::get_doc(reader::Doc(cdata.data), tag_link_args);
let mut result = ~[];
for reader::tagged_docs(link_args, tag_link_args_arg) |arg_doc| {
result.push(reader::doc_as_str(arg_doc));
result.push(arg_doc.as_str());
}
result
}