about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-04-02 16:20:02 -0700
committerPatrick Walton <pcwalton@mimiga.net>2013-04-19 11:53:33 -0700
commit4c29b4cb93ee090a22d27faf4e700bfc2364ebc5 (patch)
tree081bb9803f1887746caa5e510916a6ed3a588d59 /src
parent53f54dda60a769fa6b3d325f5787134bc9d90c6b (diff)
downloadrust-4c29b4cb93ee090a22d27faf4e700bfc2364ebc5.tar.gz
rust-4c29b4cb93ee090a22d27faf4e700bfc2364ebc5.zip
librustc: Optimize metadata::decoder::item_name.
Diffstat (limited to 'src')
-rw-r--r--src/libcore/str.rs9
-rw-r--r--src/librustc/metadata/decoder.rs10
-rw-r--r--src/libsyntax/parse/token.rs22
-rw-r--r--src/libsyntax/util/interner.rs9
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<Q:Hash + IterBytes + Equiv<@~str>>(&self, val: &Q)
+                                                  -> Option<ast::ident> {
+        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<T> {
@@ -67,6 +68,14 @@ pub impl<T:Eq + IterBytes + Hash + Const + Copy> Interner<T> {
     fn get(&self, idx: uint) -> T { self.vect[idx] }
 
     fn len(&self) -> uint { let vect = &*self.vect; vect.len() }
+
+    fn find_equiv<Q:Hash + IterBytes + Equiv<T>>(&self, val: &Q)
+                                              -> Option<uint> {
+        match self.map.find_equiv(val) {
+            Some(v) => Some(*v),
+            None => None,
+        }
+    }
 }
 
 /* Key for thread-local data for sneaking interner information to the