librustc: Encode language items into a special lookup table. 9% improvement in hello world compile time.
This commit is contained in:
parent
0ab7f9129e
commit
d2d1d98968
5 changed files with 134 additions and 32 deletions
|
|
@ -139,5 +139,17 @@ const tag_item_trait_method_sort: uint = 0x70;
|
|||
|
||||
const tag_item_impl_type_basename: uint = 0x71;
|
||||
|
||||
// Language items are a top-level directory (for speed). Hierarchy:
|
||||
//
|
||||
// tag_lang_items
|
||||
// - tag_lang_items_item
|
||||
// - tag_lang_items_item_id: u32
|
||||
// - tag_lang_items_item_node_id: u32
|
||||
|
||||
const tag_lang_items: uint = 0x72;
|
||||
const tag_lang_items_item: uint = 0x73;
|
||||
const tag_lang_items_item_id: uint = 0x74;
|
||||
const tag_lang_items_item_node_id: uint = 0x75;
|
||||
|
||||
type link_meta = {name: ~str, vers: ~str, extras_hash: ~str};
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ export get_method_names_if_trait;
|
|||
export get_type_name_if_impl;
|
||||
export get_static_methods_if_impl;
|
||||
export get_item_attrs;
|
||||
export each_lang_item;
|
||||
export each_path;
|
||||
export get_type;
|
||||
export get_impl_traits;
|
||||
|
|
@ -74,6 +75,14 @@ fn get_type_param_count(cstore: cstore::CStore, def: ast::def_id) -> uint {
|
|||
return decoder::get_type_param_count(cdata, def.node);
|
||||
}
|
||||
|
||||
/// Iterates over all the language items in the given crate.
|
||||
fn each_lang_item(cstore: cstore::CStore,
|
||||
cnum: ast::crate_num,
|
||||
f: &fn(ast::node_id, uint) -> bool) {
|
||||
let crate_data = cstore::get_crate_data(cstore, cnum);
|
||||
decoder::each_lang_item(crate_data, f)
|
||||
}
|
||||
|
||||
/// Iterates over all the paths in the given crate.
|
||||
fn each_path(cstore: cstore::CStore, cnum: ast::crate_num,
|
||||
f: fn(decoder::path_entry) -> bool) {
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ export dl_def;
|
|||
export dl_impl;
|
||||
export dl_field;
|
||||
export path_entry;
|
||||
export each_lang_item;
|
||||
export each_path;
|
||||
export get_item_path;
|
||||
export maybe_find_item; // sketchy
|
||||
|
|
@ -479,6 +480,23 @@ fn path_entry(path_string: ~str, def_like: def_like) -> path_entry {
|
|||
}
|
||||
}
|
||||
|
||||
/// Iterates over the language items in the given crate.
|
||||
fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) {
|
||||
let root = reader::Doc(cdata.data);
|
||||
let lang_items = reader::get_doc(root, tag_lang_items);
|
||||
for 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 = reader::doc_as_u32(id_doc) as uint;
|
||||
let node_id_doc = reader::get_doc(item_doc,
|
||||
tag_lang_items_item_node_id);
|
||||
let node_id = reader::doc_as_u32(node_id_doc) as ast::node_id;
|
||||
|
||||
if !f(node_id, id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterates over all the paths in the given crate.
|
||||
fn each_path(intr: @ident_interner, cdata: cmd,
|
||||
get_crate_data: GetCrateDataCb,
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ type stats = {
|
|||
mut inline_bytes: uint,
|
||||
mut attr_bytes: uint,
|
||||
mut dep_bytes: uint,
|
||||
mut lang_item_bytes: uint,
|
||||
mut item_bytes: uint,
|
||||
mut index_bytes: uint,
|
||||
mut zero_bytes: uint,
|
||||
|
|
@ -1088,6 +1089,30 @@ fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: writer::Encoder,
|
|||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_lang_items(ecx: @encode_ctxt, ebml_w: writer::Encoder) {
|
||||
ebml_w.start_tag(tag_lang_items);
|
||||
|
||||
for ecx.tcx.lang_items.each_item |def_id, i| {
|
||||
if def_id.crate != local_crate {
|
||||
loop;
|
||||
}
|
||||
|
||||
ebml_w.start_tag(tag_lang_items_item);
|
||||
|
||||
ebml_w.start_tag(tag_lang_items_item_id);
|
||||
ebml_w.writer.write_be_u32(i as u32);
|
||||
ebml_w.end_tag(); // tag_lang_items_item_id
|
||||
|
||||
ebml_w.start_tag(tag_lang_items_item_node_id);
|
||||
ebml_w.writer.write_be_u32(def_id.node as u32);
|
||||
ebml_w.end_tag(); // tag_lang_items_item_node_id
|
||||
|
||||
ebml_w.end_tag(); // tag_lang_items_item
|
||||
}
|
||||
|
||||
ebml_w.end_tag(); // tag_lang_items
|
||||
}
|
||||
|
||||
fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: writer::Encoder,
|
||||
dep: decoder::crate_dep) {
|
||||
ebml_w.start_tag(tag_crate_dep);
|
||||
|
|
@ -1122,6 +1147,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] {
|
|||
{mut inline_bytes: 0,
|
||||
mut attr_bytes: 0,
|
||||
mut dep_bytes: 0,
|
||||
mut lang_item_bytes: 0,
|
||||
mut item_bytes: 0,
|
||||
mut index_bytes: 0,
|
||||
mut zero_bytes: 0,
|
||||
|
|
@ -1154,6 +1180,11 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] {
|
|||
encode_crate_deps(ecx, ebml_w, ecx.cstore);
|
||||
ecx.stats.dep_bytes = wr.pos - i;
|
||||
|
||||
// Encode the language items.
|
||||
i = wr.pos;
|
||||
encode_lang_items(ecx, ebml_w);
|
||||
ecx.stats.lang_item_bytes = wr.pos - i;
|
||||
|
||||
// Encode and index the items.
|
||||
ebml_w.start_tag(tag_items);
|
||||
i = wr.pos;
|
||||
|
|
@ -1183,6 +1214,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] {
|
|||
io::println(fmt!(" inline bytes: %u", ecx.stats.inline_bytes));
|
||||
io::println(fmt!(" attribute bytes: %u", ecx.stats.attr_bytes));
|
||||
io::println(fmt!(" dep bytes: %u", ecx.stats.dep_bytes));
|
||||
io::println(fmt!(" lang item bytes: %u", ecx.stats.lang_item_bytes));
|
||||
io::println(fmt!(" item bytes: %u", ecx.stats.item_bytes));
|
||||
io::println(fmt!(" index bytes: %u", ecx.stats.index_bytes));
|
||||
io::println(fmt!(" zero bytes: %u", ecx.stats.zero_bytes));
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
// * Functions called by the compiler itself.
|
||||
|
||||
use driver::session::Session;
|
||||
use metadata::csearch::{each_path, get_item_attrs};
|
||||
use metadata::csearch::{each_lang_item, get_item_attrs};
|
||||
use metadata::cstore::{iter_crate_data};
|
||||
use metadata::decoder::{dl_def, dl_field, dl_impl};
|
||||
use syntax::ast::{crate, def_fn, def_id, def_ty, lit_str, meta_item};
|
||||
|
|
@ -74,6 +74,47 @@ impl LanguageItems {
|
|||
}
|
||||
}
|
||||
|
||||
fn each_item(&self, f: &fn(def_id: def_id, i: uint) -> bool) {
|
||||
for self.items.eachi |i, &item| {
|
||||
if !f(item.get(), i) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static pub fn item_name(index: uint) -> &static/str {
|
||||
match index {
|
||||
0 => "const",
|
||||
1 => "copy",
|
||||
2 => "owned",
|
||||
3 => "durable",
|
||||
|
||||
4 => "drop",
|
||||
|
||||
5 => "add",
|
||||
6 => "sub",
|
||||
7 => "mul",
|
||||
8 => "div",
|
||||
9 => "modulo",
|
||||
10 => "neg",
|
||||
11 => "bitxor",
|
||||
12 => "bitand",
|
||||
13 => "bitor",
|
||||
14 => "shl",
|
||||
15 => "shr",
|
||||
16 => "index",
|
||||
17 => "eq",
|
||||
18 => "ord",
|
||||
|
||||
19 => "str_eq",
|
||||
20 => "uniq_str_eq",
|
||||
21 => "annihilate",
|
||||
22 => "log_type",
|
||||
|
||||
_ => "???"
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: Method macros sure would be nice here.
|
||||
|
||||
pub fn const_trait(&const self) -> def_id {
|
||||
|
|
@ -220,6 +261,22 @@ impl LanguageItemCollector {
|
|||
}
|
||||
}
|
||||
|
||||
fn collect_item(item_index: uint, item_def_id: def_id) {
|
||||
// Check for duplicates.
|
||||
match self.items.items[item_index] {
|
||||
Some(original_def_id) if original_def_id != item_def_id => {
|
||||
self.session.err(fmt!("duplicate entry for `%s`",
|
||||
LanguageItems::item_name(item_index)));
|
||||
}
|
||||
Some(_) | None => {
|
||||
// OK.
|
||||
}
|
||||
}
|
||||
|
||||
// Matched.
|
||||
self.items.items[item_index] = Some(item_def_id);
|
||||
}
|
||||
|
||||
fn match_and_collect_item(item_def_id: def_id, key: ~str, value: ~str) {
|
||||
if key != ~"lang" {
|
||||
return; // Didn't match.
|
||||
|
|
@ -230,20 +287,7 @@ impl LanguageItemCollector {
|
|||
// Didn't match.
|
||||
}
|
||||
Some(item_index) => {
|
||||
// Check for duplicates.
|
||||
match self.items.items[item_index] {
|
||||
Some(original_def_id)
|
||||
if original_def_id != item_def_id => {
|
||||
self.session.err(fmt!("duplicate entry for `%s`",
|
||||
value));
|
||||
}
|
||||
Some(_) | None => {
|
||||
// OK.
|
||||
}
|
||||
}
|
||||
|
||||
// Matched.
|
||||
self.items.items[item_index] = Some(item_def_id);
|
||||
self.collect_item(item_index, item_def_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -268,23 +312,10 @@ impl LanguageItemCollector {
|
|||
fn collect_external_language_items() {
|
||||
let crate_store = self.session.cstore;
|
||||
do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
|
||||
for each_path(crate_store, crate_number) |path_entry| {
|
||||
let def_id;
|
||||
match path_entry.def_like {
|
||||
dl_def(def_ty(did)) | dl_def(def_fn(did, _)) => {
|
||||
def_id = did;
|
||||
}
|
||||
dl_def(_) | dl_impl(_) | dl_field => {
|
||||
// Skip this.
|
||||
loop;
|
||||
}
|
||||
}
|
||||
|
||||
do get_item_attrs(crate_store, def_id) |meta_items| {
|
||||
for meta_items.each |meta_item| {
|
||||
self.match_and_collect_meta_item(def_id, **meta_item);
|
||||
}
|
||||
}
|
||||
for each_lang_item(crate_store, crate_number)
|
||||
|node_id, item_index| {
|
||||
let def_id = { crate: crate_number, node: node_id };
|
||||
self.collect_item(item_index, def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue