diff options
| author | bors <bors@rust-lang.org> | 2014-02-28 13:26:30 -0800 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2014-02-28 13:26:30 -0800 |
| commit | 5b4a141b6adceeb82f5a2c97cdf55224fa56826e (patch) | |
| tree | bc3e975c830c50d72ae5ac89c339a9ef43d70a2c /src/libstd | |
| parent | 84ebf74ee2f163461cf021b3d415171e8b5ef8be (diff) | |
| parent | ddc1c21264898f6a5d12cf03bba30f1f08b73665 (diff) | |
| download | rust-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.rs | 9 | ||||
| -rw-r--r-- | src/libstd/num/strconv.rs | 10 | ||||
| -rw-r--r-- | src/libstd/rt/crate_map.rs | 4 | ||||
| -rw-r--r-- | src/libstd/rt/logging.rs | 194 | ||||
| -rw-r--r-- | src/libstd/sync/arc.rs | 12 |
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); } |
