about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-02-28 13:26:30 -0800
committerbors <bors@rust-lang.org>2014-02-28 13:26:30 -0800
commit5b4a141b6adceeb82f5a2c97cdf55224fa56826e (patch)
treebc3e975c830c50d72ae5ac89c339a9ef43d70a2c /src/libstd
parent84ebf74ee2f163461cf021b3d415171e8b5ef8be (diff)
parentddc1c21264898f6a5d12cf03bba30f1f08b73665 (diff)
downloadrust-5b4a141b6adceeb82f5a2c97cdf55224fa56826e.tar.gz
rust-5b4a141b6adceeb82f5a2c97cdf55224fa56826e.zip
auto merge of #12616 : alexcrichton/rust/size, r=huonw
I've been playing around with code size when linking to libstd recently, and these were some findings I found that really helped code size. I started out by eliminating all I/O implementations from libnative and instead just return an unimplemented error.

In doing so, a `fn main() {}` executable was ~378K before this patch, and about 170K after the patch. These size wins are all pretty minor, but they all seemed pretty reasonable to me. With native I/O not stubbed out, this takes the size of an LTO executable from 675K to 400K.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/macros.rs9
-rw-r--r--src/libstd/num/strconv.rs10
-rw-r--r--src/libstd/rt/crate_map.rs4
-rw-r--r--src/libstd/rt/logging.rs194
-rw-r--r--src/libstd/sync/arc.rs12
5 files changed, 117 insertions, 112 deletions
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index e16d944fb46..6f584991f85 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -149,7 +149,14 @@ macro_rules! fail(
         // function to pass to format_args!, *and* we need the
         // file and line numbers right here; so an inner bare fn
         // is our only choice.
-        #[inline]
+        //
+        // LLVM doesn't tend to inline this, presumably because begin_unwind_fmt
+        // is #[cold] and #[inline(never)] and because this is flagged as cold
+        // as returning !. We really do want this to be inlined, however,
+        // because it's just a tiny wrapper. Small wins (156K to 149K in size)
+        // were seen when forcing this to be inlined, and that number just goes
+        // up with the number of calls to fail!()
+        #[inline(always)]
         fn run_fmt(fmt: &::std::fmt::Arguments) -> ! {
             ::std::rt::begin_unwind_fmt(fmt, file!(), line!())
         }
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
index 153c042c6a8..00497b6f0ea 100644
--- a/src/libstd/num/strconv.rs
+++ b/src/libstd/num/strconv.rs
@@ -532,19 +532,19 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
         ) -> Option<T> {
     match exponent {
         ExpDec if radix >= DIGIT_E_RADIX       // decimal exponent 'e'
-          => fail!("from_str_bytes_common: radix {:?} incompatible with \
+          => fail!("from_str_bytes_common: radix {} incompatible with \
                     use of 'e' as decimal exponent", radix),
         ExpBin if radix >= DIGIT_P_RADIX       // binary exponent 'p'
-          => fail!("from_str_bytes_common: radix {:?} incompatible with \
+          => fail!("from_str_bytes_common: radix {} incompatible with \
                     use of 'p' as binary exponent", radix),
         _ if special && radix >= DIGIT_I_RADIX // first digit of 'inf'
-          => fail!("from_str_bytes_common: radix {:?} incompatible with \
+          => fail!("from_str_bytes_common: radix {} incompatible with \
                     special values 'inf' and 'NaN'", radix),
         _ if (radix as int) < 2
-          => fail!("from_str_bytes_common: radix {:?} to low, \
+          => fail!("from_str_bytes_common: radix {} to low, \
                     must lie in the range [2, 36]", radix),
         _ if (radix as int) > 36
-          => fail!("from_str_bytes_common: radix {:?} to high, \
+          => fail!("from_str_bytes_common: radix {} to high, \
                     must lie in the range [2, 36]", radix),
         _ => ()
     }
diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs
index 409b77d1a3f..ff54a80ce99 100644
--- a/src/libstd/rt/crate_map.rs
+++ b/src/libstd/rt/crate_map.rs
@@ -123,7 +123,7 @@ fn version(crate_map: &CrateMap) -> i32 {
 
 fn do_iter_crate_map<'a>(
                      crate_map: &'a CrateMap<'a>,
-                     f: |&ModEntry|,
+                     f: |&'a ModEntry<'a>|,
                      visited: &mut ~[*CrateMap<'a>]) {
     let raw = crate_map as *CrateMap<'a>;
     if visited.bsearch(|a| (*a as uint).cmp(&(raw as uint))).is_some() {
@@ -149,7 +149,7 @@ fn do_iter_crate_map<'a>(
 }
 
 /// Iterates recursively over `crate_map` and all child crate maps
-pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: |&ModEntry|) {
+pub fn iter_crate_map<'a>(crate_map: &'a CrateMap<'a>, f: |&'a ModEntry<'a>|) {
     let mut v = ~[];
     do_iter_crate_map(crate_map, f, &mut v);
 }
diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs
index b86a9612d70..aa024a53b89 100644
--- a/src/libstd/rt/logging.rs
+++ b/src/libstd/rt/logging.rs
@@ -13,13 +13,14 @@ use from_str::from_str;
 use iter::Iterator;
 use libc::exit;
 use option::{Some, None, Option};
+use os;
 use rt::crate_map::{ModEntry, CrateMap, iter_crate_map, get_crate_map};
-use str::StrSlice;
+use str::{Str, StrSlice};
 use vec::{ImmutableVector, MutableTotalOrdVector, OwnedVector};
-#[cfg(test)] use cast::transmute;
+use vec_ng::Vec;
 
-struct LogDirective {
-    name: Option<~str>,
+struct LogDirective<'a> {
+    name: Option<&'a str>,
     level: u32
 }
 
@@ -58,36 +59,39 @@ fn parse_log_level(level: &str) -> Option<u32> {
 /// and return a vector with log directives.
 /// Valid log levels are 0-255, with the most likely ones being 1-4 (defined in std::).
 /// Also supports string log levels of error, warn, info, and debug
-fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
-    let mut dirs = ~[];
+fn parse_logging_spec<'a>(spec: &'a str) -> Vec<LogDirective<'a>> {
+    let mut dirs = Vec::new();
     for s in spec.split(',') {
-        let parts: ~[&str] = s.split('=').collect();
-        let mut log_level;
-        let mut name = Some(parts[0].to_owned());
-        match parts.len() {
-            1 => {
+        if s.len() == 0 { continue }
+        let mut parts = s.split('=');
+        let log_level;
+        let name;
+        match (parts.next(), parts.next(), parts.next()) {
+            (Some(part0), None, None) => {
                 //if the single argument is a log-level string or number,
                 //treat that as a global fallback
-                let possible_log_level = parse_log_level(parts[0]);
+                let possible_log_level = parse_log_level(part0);
                 match possible_log_level {
                     Some(num) => {
                         name = None;
                         log_level = num;
                     },
-                    _ => {
-                        log_level = MAX_LOG_LEVEL
+                    None => {
+                        log_level = MAX_LOG_LEVEL;
+                        name = Some(part0);
                     }
                 }
             }
-            2 => {
-                let possible_log_level = parse_log_level(parts[1]);
+            (Some(part0), Some(part1), None) => {
+                let possible_log_level = parse_log_level(part1);
                 match possible_log_level {
                     Some(num) => {
+                        name = Some(part0);
                         log_level = num;
                     },
                     _ => {
                         rterrln!("warning: invalid logging spec '{}', \
-                                  ignoring it", parts[1]);
+                                  ignoring it", part1);
                         continue
                     }
                 }
@@ -98,8 +102,7 @@ fn parse_logging_spec(spec: ~str) -> ~[LogDirective]{
                 continue
             }
         }
-        let dir = LogDirective {name: name, level: log_level};
-        dirs.push(dir);
+        dirs.push(LogDirective { name: name, level: log_level });
     }
     return dirs;
 }
@@ -134,27 +137,24 @@ fn update_entry(dirs: &[LogDirective], entry: &ModEntry) -> u32 {
 
 /// Set log level for every entry in crate_map according to the sepecification
 /// in settings
-fn update_log_settings(crate_map: &CrateMap, settings: ~str) {
-    let mut dirs = ~[];
-    if settings.len() > 0 {
-        if settings == ~"::help" || settings == ~"?" {
-            rterrln!("\nCrate log map:\n");
+fn update_log_settings(crate_map: &CrateMap, settings: &str) {
+    if settings == "::help" || settings == "?" {
+        rterrln!("\nCrate log map:\n");
 
-            let mut entries = ~[];
-            iter_crate_map(crate_map, |entry| entries.push(entry.name.to_owned()));
-            entries.sort();
+        let mut entries = Vec::new();
+        iter_crate_map(crate_map, |entry| entries.push(entry.name));
+        entries.as_mut_slice().sort();
 
-            for name in entries.iter() {
-                rterrln!(" {}", *name);
-            }
-            unsafe { exit(1); }
+        for name in entries.iter() {
+            rterrln!(" {}", *name);
         }
-        dirs = parse_logging_spec(settings);
+        unsafe { exit(1); }
     }
+    let dirs = parse_logging_spec(settings);
 
     let mut n_matches: u32 = 0;
     iter_crate_map(crate_map, |entry| {
-        let m = update_entry(dirs, entry);
+        let m = update_entry(dirs.as_slice(), entry);
         n_matches += m;
     });
 
@@ -169,18 +169,12 @@ fn update_log_settings(crate_map: &CrateMap, settings: ~str) {
 /// Configure logging by traversing the crate map and setting the
 /// per-module global logging flags based on the logging spec
 pub fn init() {
-    use os;
-
     let log_spec = os::getenv("RUST_LOG");
     match get_crate_map() {
         Some(crate_map) => {
             match log_spec {
-                Some(spec) => {
-                    update_log_settings(crate_map, spec);
-                }
-                None => {
-                    update_log_settings(crate_map, ~"");
-                }
+                Some(spec) => update_log_settings(crate_map, spec.as_slice()),
+                None => update_log_settings(crate_map, ""),
             }
         },
         _ => {
@@ -197,124 +191,124 @@ pub fn init() {
 // Tests for parse_logging_spec()
 #[test]
 fn parse_logging_spec_valid() {
-    let dirs = parse_logging_spec(~"crate1::mod1=1,crate1::mod2,crate2=4");
+    let dirs = parse_logging_spec("crate1::mod1=1,crate1::mod2,crate2=4");
+    let dirs = dirs.as_slice();
     assert_eq!(dirs.len(), 3);
-    assert!(dirs[0].name == Some(~"crate1::mod1"));
+    assert_eq!(dirs[0].name, Some("crate1::mod1"));
     assert_eq!(dirs[0].level, 1);
 
-    assert!(dirs[1].name == Some(~"crate1::mod2"));
+    assert_eq!(dirs[1].name, Some("crate1::mod2"));
     assert_eq!(dirs[1].level, MAX_LOG_LEVEL);
 
-    assert!(dirs[2].name == Some(~"crate2"));
+    assert_eq!(dirs[2].name, Some("crate2"));
     assert_eq!(dirs[2].level, 4);
 }
 
 #[test]
 fn parse_logging_spec_invalid_crate() {
     // test parse_logging_spec with multiple = in specification
-    let dirs = parse_logging_spec(~"crate1::mod1=1=2,crate2=4");
+    let dirs = parse_logging_spec("crate1::mod1=1=2,crate2=4");
+    let dirs = dirs.as_slice();
     assert_eq!(dirs.len(), 1);
-    assert!(dirs[0].name == Some(~"crate2"));
+    assert_eq!(dirs[0].name, Some("crate2"));
     assert_eq!(dirs[0].level, 4);
 }
 
 #[test]
 fn parse_logging_spec_invalid_log_level() {
     // test parse_logging_spec with 'noNumber' as log level
-    let dirs = parse_logging_spec(~"crate1::mod1=noNumber,crate2=4");
+    let dirs = parse_logging_spec("crate1::mod1=noNumber,crate2=4");
+    let dirs = dirs.as_slice();
     assert_eq!(dirs.len(), 1);
-    assert!(dirs[0].name == Some(~"crate2"));
+    assert_eq!(dirs[0].name, Some("crate2"));
     assert_eq!(dirs[0].level, 4);
 }
 
 #[test]
 fn parse_logging_spec_string_log_level() {
     // test parse_logging_spec with 'warn' as log level
-    let dirs = parse_logging_spec(~"crate1::mod1=wrong,crate2=warn");
+    let dirs = parse_logging_spec("crate1::mod1=wrong,crate2=warn");
+    let dirs = dirs.as_slice();
     assert_eq!(dirs.len(), 1);
-    assert!(dirs[0].name == Some(~"crate2"));
+    assert_eq!(dirs[0].name, Some("crate2"));
     assert_eq!(dirs[0].level, 2);
 }
 
 #[test]
 fn parse_logging_spec_global() {
     // test parse_logging_spec with no crate
-    let dirs = parse_logging_spec(~"warn,crate2=4");
+    let dirs = parse_logging_spec("warn,crate2=4");
+    let dirs = dirs.as_slice();
     assert_eq!(dirs.len(), 2);
-    assert!(dirs[0].name == None);
+    assert_eq!(dirs[0].name, None);
     assert_eq!(dirs[0].level, 2);
-    assert!(dirs[1].name == Some(~"crate2"));
+    assert_eq!(dirs[1].name, Some("crate2"));
     assert_eq!(dirs[1].level, 4);
 }
 
 // Tests for update_entry
 #[test]
 fn update_entry_match_full_path() {
-    let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
-                 LogDirective {name: Some(~"crate2"), level: 3}];
-    let level = &mut 0;
-    unsafe {
-        let entry= &ModEntry {name:"crate1::mod1", log_level: level};
-        let m = update_entry(dirs, transmute(entry));
-        assert!(*entry.log_level == 2);
-        assert!(m == 1);
+    let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
+                LogDirective { name: Some("crate2"), level: 3 }];
+    let mut level = 0;
+    {
+        let entry = &ModEntry { name: "crate1::mod1", log_level: &mut level };
+        assert_eq!(update_entry(dirs, entry), 1);
     }
+    assert_eq!(level, 2);
 }
 
 #[test]
 fn update_entry_no_match() {
-    let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
-                 LogDirective {name: Some(~"crate2"), level: 3}];
-    let level = &mut 0;
-    unsafe {
-        let entry= &ModEntry {name: "crate3::mod1", log_level: level};
-        let m = update_entry(dirs, transmute(entry));
-        assert!(*entry.log_level == DEFAULT_LOG_LEVEL);
-        assert!(m == 0);
+    let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
+                LogDirective { name: Some("crate2"), level: 3 }];
+    let mut level = 0;
+    {
+        let entry = &ModEntry { name: "crate3::mod1", log_level: &mut level };
+        assert_eq!(update_entry(dirs, entry), 0);
     }
+    assert_eq!(level, DEFAULT_LOG_LEVEL);
 }
 
 #[test]
 fn update_entry_match_beginning() {
-    let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
-                 LogDirective {name: Some(~"crate2"), level: 3}];
-    let level = &mut 0;
-    unsafe {
-        let entry= &ModEntry {name: "crate2::mod1", log_level: level};
-        let m = update_entry(dirs, transmute(entry));
-        assert!(*entry.log_level == 3);
-        assert!(m == 1);
+    let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
+                LogDirective { name: Some("crate2"), level: 3 }];
+    let mut level = 0;
+    {
+        let entry= &ModEntry {name: "crate2::mod1", log_level: &mut level};
+        assert_eq!(update_entry(dirs, entry), 1);
     }
+    assert_eq!(level, 3);
 }
 
 #[test]
 fn update_entry_match_beginning_longest_match() {
-    let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
-                 LogDirective {name: Some(~"crate2"), level: 3},
-                 LogDirective {name: Some(~"crate2::mod"), level: 4}];
-    let level = &mut 0;
-    unsafe {
-        let entry = &ModEntry {name: "crate2::mod1", log_level: level};
-        let m = update_entry(dirs, transmute(entry));
-        assert!(*entry.log_level == 4);
-        assert!(m == 1);
+    let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
+                LogDirective { name: Some("crate2"), level: 3 },
+                LogDirective { name: Some("crate2::mod"), level: 4 }];
+    let mut level = 0;
+    {
+        let entry = &ModEntry { name: "crate2::mod1", log_level: &mut level };
+        assert_eq!(update_entry(dirs, entry), 1);
     }
+    assert_eq!(level, 4);
 }
 
 #[test]
 fn update_entry_match_default() {
-    let dirs = ~[LogDirective {name: Some(~"crate1::mod1"), level: 2 },
-                 LogDirective {name: None, level: 3}
-                ];
-    let level = &mut 0;
-    unsafe {
-        let entry= &ModEntry {name: "crate1::mod1", log_level: level};
-        let m = update_entry(dirs, transmute(entry));
-        assert!(*entry.log_level == 2);
-        assert!(m == 1);
-        let entry= &ModEntry {name: "crate2::mod2", log_level: level};
-        let m = update_entry(dirs, transmute(entry));
-        assert!(*entry.log_level == 3);
-        assert!(m == 1);
+    let dirs = [LogDirective { name: Some("crate1::mod1"), level: 2 },
+                LogDirective { name: None, level: 3 }];
+    let mut level = 0;
+    {
+        let entry = &ModEntry { name: "crate1::mod1", log_level: &mut level };
+        assert_eq!(update_entry(dirs, entry), 1);
+    }
+    assert_eq!(level, 2);
+    {
+        let entry = &ModEntry { name: "crate2::mod2", log_level: &mut level };
+        assert_eq!(update_entry(dirs, entry), 1);
     }
+    assert_eq!(level, 3);
 }
diff --git a/src/libstd/sync/arc.rs b/src/libstd/sync/arc.rs
index 5c452018b9b..10369a52f0f 100644
--- a/src/libstd/sync/arc.rs
+++ b/src/libstd/sync/arc.rs
@@ -80,7 +80,8 @@ impl<T: Send> UnsafeArc<T> {
     #[inline]
     pub fn get(&self) -> *mut T {
         unsafe {
-            assert!((*self.data).count.load(Relaxed) > 0);
+            // FIXME(#12049): this needs some sort of debug assertion
+            if cfg!(test) { assert!((*self.data).count.load(Relaxed) > 0); }
             return &mut (*self.data).data as *mut T;
         }
     }
@@ -90,7 +91,8 @@ impl<T: Send> UnsafeArc<T> {
     #[inline]
     pub fn get_immut(&self) -> *T {
         unsafe {
-            assert!((*self.data).count.load(Relaxed) > 0);
+            // FIXME(#12049): this needs some sort of debug assertion
+            if cfg!(test) { assert!((*self.data).count.load(Relaxed) > 0); }
             return &(*self.data).data as *T;
         }
     }
@@ -109,7 +111,8 @@ impl<T: Send> Clone for UnsafeArc<T> {
         unsafe {
             // This barrier might be unnecessary, but I'm not sure...
             let old_count = (*self.data).count.fetch_add(1, Acquire);
-            assert!(old_count >= 1);
+            // FIXME(#12049): this needs some sort of debug assertion
+            if cfg!(test) { assert!(old_count >= 1); }
             return UnsafeArc { data: self.data };
         }
     }
@@ -127,7 +130,8 @@ impl<T> Drop for UnsafeArc<T>{
             // Must be acquire+release, not just release, to make sure this
             // doesn't get reordered to after the unwrapper pointer load.
             let old_count = (*self.data).count.fetch_sub(1, SeqCst);
-            assert!(old_count >= 1);
+            // FIXME(#12049): this needs some sort of debug assertion
+            if cfg!(test) { assert!(old_count >= 1); }
             if old_count == 1 {
                 let _: ~ArcData<T> = cast::transmute(self.data);
             }