Skip to content

Commit d2d1d98

Browse files
committed
librustc: Encode language items into a special lookup table. 9% improvement in hello world compile time.
1 parent 0ab7f91 commit d2d1d98

File tree

5 files changed

+134
-32
lines changed

5 files changed

+134
-32
lines changed

src/librustc/metadata/common.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,17 @@ const tag_item_trait_method_sort: uint = 0x70;
139139

140140
const tag_item_impl_type_basename: uint = 0x71;
141141

142+
// Language items are a top-level directory (for speed). Hierarchy:
143+
//
144+
// tag_lang_items
145+
// - tag_lang_items_item
146+
// - tag_lang_items_item_id: u32
147+
// - tag_lang_items_item_node_id: u32
148+
149+
const tag_lang_items: uint = 0x72;
150+
const tag_lang_items_item: uint = 0x73;
151+
const tag_lang_items_item_id: uint = 0x74;
152+
const tag_lang_items_item_node_id: uint = 0x75;
153+
142154
type link_meta = {name: ~str, vers: ~str, extras_hash: ~str};
143155

src/librustc/metadata/csearch.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export get_method_names_if_trait;
4343
export get_type_name_if_impl;
4444
export get_static_methods_if_impl;
4545
export get_item_attrs;
46+
export each_lang_item;
4647
export each_path;
4748
export get_type;
4849
export get_impl_traits;
@@ -74,6 +75,14 @@ fn get_type_param_count(cstore: cstore::CStore, def: ast::def_id) -> uint {
7475
return decoder::get_type_param_count(cdata, def.node);
7576
}
7677

78+
/// Iterates over all the language items in the given crate.
79+
fn each_lang_item(cstore: cstore::CStore,
80+
cnum: ast::crate_num,
81+
f: &fn(ast::node_id, uint) -> bool) {
82+
let crate_data = cstore::get_crate_data(cstore, cnum);
83+
decoder::each_lang_item(crate_data, f)
84+
}
85+
7786
/// Iterates over all the paths in the given crate.
7887
fn each_path(cstore: cstore::CStore, cnum: ast::crate_num,
7988
f: fn(decoder::path_entry) -> bool) {

src/librustc/metadata/decoder.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ export dl_def;
7474
export dl_impl;
7575
export dl_field;
7676
export path_entry;
77+
export each_lang_item;
7778
export each_path;
7879
export get_item_path;
7980
export maybe_find_item; // sketchy
@@ -479,6 +480,23 @@ fn path_entry(path_string: ~str, def_like: def_like) -> path_entry {
479480
}
480481
}
481482

483+
/// Iterates over the language items in the given crate.
484+
fn each_lang_item(cdata: cmd, f: &fn(ast::node_id, uint) -> bool) {
485+
let root = reader::Doc(cdata.data);
486+
let lang_items = reader::get_doc(root, tag_lang_items);
487+
for reader::tagged_docs(lang_items, tag_lang_items_item) |item_doc| {
488+
let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id);
489+
let id = reader::doc_as_u32(id_doc) as uint;
490+
let node_id_doc = reader::get_doc(item_doc,
491+
tag_lang_items_item_node_id);
492+
let node_id = reader::doc_as_u32(node_id_doc) as ast::node_id;
493+
494+
if !f(node_id, id) {
495+
break;
496+
}
497+
}
498+
}
499+
482500
/// Iterates over all the paths in the given crate.
483501
fn each_path(intr: @ident_interner, cdata: cmd,
484502
get_crate_data: GetCrateDataCb,

src/librustc/metadata/encoder.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ type stats = {
8484
mut inline_bytes: uint,
8585
mut attr_bytes: uint,
8686
mut dep_bytes: uint,
87+
mut lang_item_bytes: uint,
8788
mut item_bytes: uint,
8889
mut index_bytes: uint,
8990
mut zero_bytes: uint,
@@ -1088,6 +1089,30 @@ fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: writer::Encoder,
10881089
ebml_w.end_tag();
10891090
}
10901091

1092+
fn encode_lang_items(ecx: @encode_ctxt, ebml_w: writer::Encoder) {
1093+
ebml_w.start_tag(tag_lang_items);
1094+
1095+
for ecx.tcx.lang_items.each_item |def_id, i| {
1096+
if def_id.crate != local_crate {
1097+
loop;
1098+
}
1099+
1100+
ebml_w.start_tag(tag_lang_items_item);
1101+
1102+
ebml_w.start_tag(tag_lang_items_item_id);
1103+
ebml_w.writer.write_be_u32(i as u32);
1104+
ebml_w.end_tag(); // tag_lang_items_item_id
1105+
1106+
ebml_w.start_tag(tag_lang_items_item_node_id);
1107+
ebml_w.writer.write_be_u32(def_id.node as u32);
1108+
ebml_w.end_tag(); // tag_lang_items_item_node_id
1109+
1110+
ebml_w.end_tag(); // tag_lang_items_item
1111+
}
1112+
1113+
ebml_w.end_tag(); // tag_lang_items
1114+
}
1115+
10911116
fn encode_crate_dep(ecx: @encode_ctxt, ebml_w: writer::Encoder,
10921117
dep: decoder::crate_dep) {
10931118
ebml_w.start_tag(tag_crate_dep);
@@ -1122,6 +1147,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] {
11221147
{mut inline_bytes: 0,
11231148
mut attr_bytes: 0,
11241149
mut dep_bytes: 0,
1150+
mut lang_item_bytes: 0,
11251151
mut item_bytes: 0,
11261152
mut index_bytes: 0,
11271153
mut zero_bytes: 0,
@@ -1154,6 +1180,11 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] {
11541180
encode_crate_deps(ecx, ebml_w, ecx.cstore);
11551181
ecx.stats.dep_bytes = wr.pos - i;
11561182

1183+
// Encode the language items.
1184+
i = wr.pos;
1185+
encode_lang_items(ecx, ebml_w);
1186+
ecx.stats.lang_item_bytes = wr.pos - i;
1187+
11571188
// Encode and index the items.
11581189
ebml_w.start_tag(tag_items);
11591190
i = wr.pos;
@@ -1183,6 +1214,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] {
11831214
io::println(fmt!(" inline bytes: %u", ecx.stats.inline_bytes));
11841215
io::println(fmt!(" attribute bytes: %u", ecx.stats.attr_bytes));
11851216
io::println(fmt!(" dep bytes: %u", ecx.stats.dep_bytes));
1217+
io::println(fmt!(" lang item bytes: %u", ecx.stats.lang_item_bytes));
11861218
io::println(fmt!(" item bytes: %u", ecx.stats.item_bytes));
11871219
io::println(fmt!(" index bytes: %u", ecx.stats.index_bytes));
11881220
io::println(fmt!(" zero bytes: %u", ecx.stats.zero_bytes));

src/librustc/middle/lang_items.rs

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
// * Functions called by the compiler itself.
2121

2222
use driver::session::Session;
23-
use metadata::csearch::{each_path, get_item_attrs};
23+
use metadata::csearch::{each_lang_item, get_item_attrs};
2424
use metadata::cstore::{iter_crate_data};
2525
use metadata::decoder::{dl_def, dl_field, dl_impl};
2626
use syntax::ast::{crate, def_fn, def_id, def_ty, lit_str, meta_item};
@@ -74,6 +74,47 @@ impl LanguageItems {
7474
}
7575
}
7676

77+
fn each_item(&self, f: &fn(def_id: def_id, i: uint) -> bool) {
78+
for self.items.eachi |i, &item| {
79+
if !f(item.get(), i) {
80+
break;
81+
}
82+
}
83+
}
84+
85+
static pub fn item_name(index: uint) -> &static/str {
86+
match index {
87+
0 => "const",
88+
1 => "copy",
89+
2 => "owned",
90+
3 => "durable",
91+
92+
4 => "drop",
93+
94+
5 => "add",
95+
6 => "sub",
96+
7 => "mul",
97+
8 => "div",
98+
9 => "modulo",
99+
10 => "neg",
100+
11 => "bitxor",
101+
12 => "bitand",
102+
13 => "bitor",
103+
14 => "shl",
104+
15 => "shr",
105+
16 => "index",
106+
17 => "eq",
107+
18 => "ord",
108+
109+
19 => "str_eq",
110+
20 => "uniq_str_eq",
111+
21 => "annihilate",
112+
22 => "log_type",
113+
114+
_ => "???"
115+
}
116+
}
117+
77118
// XXX: Method macros sure would be nice here.
78119

79120
pub fn const_trait(&const self) -> def_id {
@@ -220,6 +261,22 @@ impl LanguageItemCollector {
220261
}
221262
}
222263

264+
fn collect_item(item_index: uint, item_def_id: def_id) {
265+
// Check for duplicates.
266+
match self.items.items[item_index] {
267+
Some(original_def_id) if original_def_id != item_def_id => {
268+
self.session.err(fmt!("duplicate entry for `%s`",
269+
LanguageItems::item_name(item_index)));
270+
}
271+
Some(_) | None => {
272+
// OK.
273+
}
274+
}
275+
276+
// Matched.
277+
self.items.items[item_index] = Some(item_def_id);
278+
}
279+
223280
fn match_and_collect_item(item_def_id: def_id, key: ~str, value: ~str) {
224281
if key != ~"lang" {
225282
return; // Didn't match.
@@ -230,20 +287,7 @@ impl LanguageItemCollector {
230287
// Didn't match.
231288
}
232289
Some(item_index) => {
233-
// Check for duplicates.
234-
match self.items.items[item_index] {
235-
Some(original_def_id)
236-
if original_def_id != item_def_id => {
237-
self.session.err(fmt!("duplicate entry for `%s`",
238-
value));
239-
}
240-
Some(_) | None => {
241-
// OK.
242-
}
243-
}
244-
245-
// Matched.
246-
self.items.items[item_index] = Some(item_def_id);
290+
self.collect_item(item_index, item_def_id)
247291
}
248292
}
249293
}
@@ -268,23 +312,10 @@ impl LanguageItemCollector {
268312
fn collect_external_language_items() {
269313
let crate_store = self.session.cstore;
270314
do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
271-
for each_path(crate_store, crate_number) |path_entry| {
272-
let def_id;
273-
match path_entry.def_like {
274-
dl_def(def_ty(did)) | dl_def(def_fn(did, _)) => {
275-
def_id = did;
276-
}
277-
dl_def(_) | dl_impl(_) | dl_field => {
278-
// Skip this.
279-
loop;
280-
}
281-
}
282-
283-
do get_item_attrs(crate_store, def_id) |meta_items| {
284-
for meta_items.each |meta_item| {
285-
self.match_and_collect_meta_item(def_id, **meta_item);
286-
}
287-
}
315+
for each_lang_item(crate_store, crate_number)
316+
|node_id, item_index| {
317+
let def_id = { crate: crate_number, node: node_id };
318+
self.collect_item(item_index, def_id);
288319
}
289320
}
290321
}

0 commit comments

Comments
 (0)