From 4c29b4cb93ee090a22d27faf4e700bfc2364ebc5 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Tue, 2 Apr 2013 16:20:02 -0700 Subject: [PATCH] librustc: Optimize metadata::decoder::item_name. --- src/libcore/str.rs | 9 +++++++++ src/librustc/metadata/decoder.rs | 10 ++++++++-- src/libsyntax/parse/token.rs | 22 ++++++++++++++++++++++ src/libsyntax/util/interner.rs | 9 +++++++++ 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/libcore/str.rs b/src/libcore/str.rs index cb362b2e6c0..6bde7d33849 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -67,6 +67,15 @@ pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str { return unsafe { raw::from_bytes_with_null(vv) }; } +pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str { + unsafe { + assert!(is_utf8(vector)); + let (ptr, len): (*u8, uint) = ::cast::transmute(vector); + let string: &'a str = ::cast::transmute((ptr, len + 1)); + string + } +} + /// Copy a slice into a new unique str pub fn from_slice(s: &str) -> ~str { unsafe { raw::slice_bytes_owned(s, 0, len(s)) } diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 5b19834b31c..248d847f89d 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -37,7 +37,7 @@ use std::serialize::Decodable; use syntax::ast_map; use syntax::attr; use syntax::diagnostic::span_handler; -use syntax::parse::token::{ident_interner, special_idents}; +use syntax::parse::token::{StringRef, ident_interner, special_idents}; use syntax::print::pprust; use syntax::{ast, ast_util}; use syntax::codemap; @@ -322,7 +322,13 @@ fn item_path(intr: @ident_interner, 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); - intr.intern(@str::from_bytes(reader::doc_data(name))) + do reader::with_doc_data(name) |data| { + let string = str::from_bytes_slice(data); + match intr.find_equiv(&StringRef(string)) { + None => intr.intern(@(string.to_owned())), + Some(val) => val, + } + } } fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index cf05a4375a8..b94b53076ec 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -18,9 +18,11 @@ use util::interner; use core::cast; use core::char; +use core::cmp::Equiv; use core::hashmap::HashSet; use core::str; use core::task; +use core::to_bytes; #[auto_encode] #[auto_decode] @@ -355,6 +357,19 @@ pub mod special_idents { pub static type_self: ident = ident { repr: 36u, ctxt: 0}; // `Self` } +pub struct StringRef<'self>(&'self str); + +impl<'self> Equiv<@~str> for StringRef<'self> { + #[inline(always)] + fn equiv(&self, other: &@~str) -> bool { str::eq_slice(**self, **other) } +} + +impl<'self> to_bytes::IterBytes for StringRef<'self> { + fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) { + (**self).iter_bytes(lsb0, f); + } +} + pub struct ident_interner { priv interner: Interner<@~str>, } @@ -372,6 +387,13 @@ pub impl ident_interner { fn len(&self) -> uint { self.interner.len() } + fn find_equiv>(&self, val: &Q) + -> Option { + match self.interner.find_equiv(val) { + Some(v) => Some(ast::ident { repr: v }), + None => None, + } + } } pub fn mk_ident_interner() -> @ident_interner { diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 75bcac1b163..cda1c6c0df3 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -16,6 +16,7 @@ #[macro_escape]; use core::prelude::*; +use core::cmp::Equiv; use core::hashmap::HashMap; pub struct Interner { @@ -67,6 +68,14 @@ pub impl Interner { fn get(&self, idx: uint) -> T { self.vect[idx] } fn len(&self) -> uint { let vect = &*self.vect; vect.len() } + + fn find_equiv>(&self, val: &Q) + -> Option { + match self.map.find_equiv(val) { + Some(v) => Some(*v), + None => None, + } + } } /* Key for thread-local data for sneaking interner information to the