librustc: Encode language items into a special lookup table. 9% improvement in hello world compile time.

This commit is contained in:
Patrick Walton 2013-01-07 10:51:53 -08:00
parent 0ab7f9129e
commit d2d1d98968
5 changed files with 134 additions and 32 deletions

View file

@ -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};

View file

@ -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) {

View file

@ -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,

View file

@ -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));

View file

@ -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);
}
}
}