about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-01-29 19:59:52 -0800
committerPatrick Walton <pcwalton@mimiga.net>2013-01-29 22:14:08 -0800
commit1b613ff9fcec4b4468de76779ccd37c7281e09b5 (patch)
tree22bc7903829928ad17cd5bc7203df6978e2731f3
parenta47fa9b32f664beb4a50527e547c81cf6d6629bf (diff)
downloadrust-1b613ff9fcec4b4468de76779ccd37c7281e09b5.tar.gz
rust-1b613ff9fcec4b4468de76779ccd37c7281e09b5.zip
librustc: Strdup unique strings instead of copying in byte by byte. Shaves 2MB off librustc at -O0.
-rw-r--r--src/libcore/rt.rs7
-rw-r--r--src/librustc/middle/lang_items.rs10
-rw-r--r--src/librustc/middle/trans/tvec.rs35
3 files changed, 45 insertions, 7 deletions
diff --git a/src/libcore/rt.rs b/src/libcore/rt.rs
index 2d2d24e6018..f9de0bc91fd 100644
--- a/src/libcore/rt.rs
+++ b/src/libcore/rt.rs
@@ -14,7 +14,7 @@
 //! Runtime calls emitted by the compiler.
 
 use cast::transmute;
-use libc::{c_char, c_void, size_t, uintptr_t};
+use libc::{c_char, c_uchar, c_void, size_t, uintptr_t};
 use managed::raw::BoxRepr;
 use str;
 use sys;
@@ -123,6 +123,11 @@ pub unsafe fn check_not_borrowed(a: *u8) {
     }
 }
 
+#[lang="strdup_uniq"]
+pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str {
+    str::raw::from_buf_len(ptr, len)
+}
+
 // Local Variables:
 // mode: rust;
 // fill-column: 78;
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index df7b7196a24..dcfa1755d09 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -74,16 +74,17 @@ pub enum LangItem {
     BorrowAsImmFnLangItem,      // 30
     ReturnToMutFnLangItem,      // 31
     CheckNotBorrowedFnLangItem, // 32
+    StrDupUniqFnLangItem,       // 33
 }
 
 struct LanguageItems {
-    items: [ Option<def_id> * 33 ]
+    items: [ Option<def_id> * 34 ]
 }
 
 impl LanguageItems {
     static pub fn new() -> LanguageItems {
         LanguageItems {
-            items: [ None, ..33 ]
+            items: [ None, ..34 ]
         }
     }
 
@@ -133,6 +134,7 @@ impl LanguageItems {
             30 => "borrow_as_imm",
             31 => "return_to_mut",
             32 => "check_not_borrowed",
+            33 => "strdup_uniq",
 
             _ => "???"
         }
@@ -243,6 +245,9 @@ impl LanguageItems {
     pub fn check_not_borrowed_fn(&const self) -> def_id {
         self.items[CheckNotBorrowedFnLangItem as uint].get()
     }
+    pub fn strdup_uniq_fn(&const self) -> def_id {
+        self.items[StrDupUniqFnLangItem as uint].get()
+    }
 }
 
 fn LanguageItemCollector(crate: @crate,
@@ -289,6 +294,7 @@ fn LanguageItemCollector(crate: @crate,
     item_refs.insert(~"return_to_mut", ReturnToMutFnLangItem as uint);
     item_refs.insert(~"check_not_borrowed",
                      CheckNotBorrowedFnLangItem as uint);
+    item_refs.insert(~"strdup_uniq", StrDupUniqFnLangItem as uint);
 
     LanguageItemCollector {
         crate: crate,
diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs
index eb2fd91e605..54e6d25718b 100644
--- a/src/librustc/middle/trans/tvec.rs
+++ b/src/librustc/middle/trans/tvec.rs
@@ -276,10 +276,9 @@ fn trans_lit_str(bcx: block,
 
 
 fn trans_uniq_or_managed_vstore(bcx: block,
-                            heap: heap,
-                            vstore_expr: @ast::expr,
-                            content_expr: @ast::expr) -> DatumBlock
-{
+                                heap: heap,
+                                vstore_expr: @ast::expr,
+                                content_expr: @ast::expr) -> DatumBlock {
     //!
     //
     // @[...] or ~[...] (also @"..." or ~"...") allocate boxes in the
@@ -289,6 +288,34 @@ fn trans_uniq_or_managed_vstore(bcx: block,
            bcx.expr_to_str(vstore_expr), heap);
     let _indenter = indenter();
 
+    // Handle ~"".
+    match heap {
+        heap_exchange => {
+            match content_expr.node {
+                ast::expr_lit(@ast::spanned {
+                    node: ast::lit_str(s), _
+                }) => {
+                    let llptrval = C_cstr(bcx.ccx(), copy *s);
+                    let llptrval = PointerCast(bcx, llptrval, T_ptr(T_i8()));
+                    let llsizeval = C_uint(bcx.ccx(), s.len());
+                    let typ = ty::mk_estr(bcx.tcx(), ty::vstore_uniq);
+                    let lldestval = datum::scratch_datum(bcx, typ, false);
+                    let bcx = callee::trans_rtcall_or_lang_call(
+                        bcx,
+                        bcx.tcx().lang_items.strdup_uniq_fn(),
+                        ~[ llptrval, llsizeval ],
+                        expr::SaveIn(lldestval.to_ref_llval(bcx)));
+                    return datum::DatumBlock {
+                        bcx: bcx,
+                        datum: lldestval
+                    };
+                }
+                _ => {}
+            }
+        }
+        heap_shared => {}
+    }
+
     let vt = vec_types_from_expr(bcx, vstore_expr);
     let count = elements_required(bcx, content_expr);