Skip to content

Commit 279a780

Browse files
committedJul 28, 2014
auto merge of #15983 : brson/rust/fail, r=alexcrichton
A few refactorings to decrease text size and increase data size. I'm not sure about this tradeoff. Various stats below. cc @pcwalton This reduces the code needed to pass arguments for `fail!()`, `fail!("{}", ...)`, and to a lesser extent `fail!("...")`. Still more work to be done on compiler-generated failures and the `fail!("...")` case. do_fail_empty: ``` #[inline(never)] fn do_fail_empty() { fail!() } ``` do_fail_empty before: ``` leaq 8(%rsp), %rdi movabsq $13, %rsi leaq "str\"str\"(1494)"(%rip), %rax movq %rax, 8(%rsp) movq $19, 16(%rsp) callq _ZN6unwind31begin_unwind_no_time_to_explain20h57030457935ab6111SdE@PLT ``` do_fail_empty after: ``` leaq _ZN13do_fail_empty9file_line20h339df6a0541e837eIaaE(%rip), %rdi callq _ZN6unwind31begin_unwind_no_time_to_explain20h33184cfdcce4dfd8QTdE@PLT ``` do_fail_fmt: ``` #[inline(never)] fn do_fail_fmt() { fail!("guh{}", "faw") } ``` do_fail_fmt before: ``` ... (snip lots of fmt stuff) callq _ZN3fmt22Arguments$LT$$x27a$GT$3new20he09b3a3f473879c41paE leaq 144(%rsp), %rsi movabsq $23, %rdx leaq "str\"str\"(1494)"(%rip), %rax leaq 32(%rsp), %rcx movq %rcx, 160(%rsp) movq 160(%rsp), %rdi movq %rax, 144(%rsp) movq $19, 152(%rsp) callq _ZN6unwind16begin_unwind_fmt20h3ebeb42f4d189b2buQdE@PLT ``` do_fail_fmt after: ``` ... (snip lots of fmt stuff) callq _ZN3fmt22Arguments$LT$$x27a$GT$3new20h42e5bb8d1711ee61OqaE leaq _ZN11do_fail_fmt7run_fmt9file_line20h339df6a0541e837eFbaE(%rip), %rsi leaq 32(%rsp), %rax movq %rax, 144(%rsp) movq 144(%rsp), %rdi callq _ZN6unwind16begin_unwind_fmt20hfdcadc14d188656biRdE@PLT ``` File size increases. file size before: ``` -rw-rw-r-- 1 brian brian 100501740 Jul 24 23:28 /home/brian/dev/rust2/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc-4e7c5e5c.rlib -rwxrwxr-x 1 brian brian 21201780 Jul 24 23:27 /home/brian/dev/rust2/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc-4e7c5e5c.so ``` file size after: ``` -rw-rw-r-- 1 brian brian 101542484 Jul 25 00:34 x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc-4e7c5e5c.rlib -rwxrwxr-x 1 brian brian 21348862 Jul 25 00:34 x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc-4e7c5e5c.so ``` Text size decreases by 52486 while data size increases by 143686. section size before: ``` text data bss dec hex filename 12712262 5924997 368 18637627 11c633b x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc-4e7c5e5c.so ``` section size after: ``` text data bss dec hex filename 12659776 6068683 368 18728827 11dc77b /home/brian/dev/rust/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc-4e7c5e5c.so ``` I don't know if anything can be learned from these benchmarks. Looks like a wash. std bench before: ``` test collections::hashmap::bench::find_existing ... bench: 43452 ns/iter (+/- 2423) test collections::hashmap::bench::find_nonexisting ... bench: 42416 ns/iter (+/- 3996) test collections::hashmap::bench::find_pop_insert ... bench: 214 ns/iter (+/- 11) test collections::hashmap::bench::hashmap_as_queue ... bench: 123 ns/iter (+/- 6) test collections::hashmap::bench::insert ... bench: 153 ns/iter (+/- 14) test collections::hashmap::bench::new_drop ... bench: 547 ns/iter (+/- 259) test collections::hashmap::bench::new_insert_drop ... bench: 682 ns/iter (+/- 366) test io::buffered::test::bench_buffered_reader ... bench: 1046 ns/iter (+/- 86) test io::buffered::test::bench_buffered_stream ... bench: 2156 ns/iter (+/- 801) test io::buffered::test::bench_buffered_writer ... bench: 1057 ns/iter (+/- 75) test io::extensions::bench::u64_from_be_bytes_4_aligned ... bench: 80 ns/iter (+/- 5) test io::extensions::bench::u64_from_be_bytes_4_unaligned ... bench: 81 ns/iter (+/- 6) test io::extensions::bench::u64_from_be_bytes_7_aligned ... bench: 80 ns/iter (+/- 4) test io::extensions::bench::u64_from_be_bytes_7_unaligned ... bench: 69 ns/iter (+/- 4) test io::extensions::bench::u64_from_be_bytes_8_aligned ... bench: 69 ns/iter (+/- 3) test io::extensions::bench::u64_from_be_bytes_8_unaligned ... bench: 81 ns/iter (+/- 4) test io::mem::test::bench_buf_reader ... bench: 628 ns/iter (+/- 18) test io::mem::test::bench_buf_writer ... bench: 478 ns/iter (+/- 19) test io::mem::test::bench_mem_reader ... bench: 712 ns/iter (+/- 44) test io::mem::test::bench_mem_writer_001_0000 ... bench: 31 ns/iter (+/- 1) test io::mem::test::bench_mem_writer_001_0010 ... bench: 51 ns/iter (+/- 3) test io::mem::test::bench_mem_writer_001_0100 ... bench: 121 ns/iter (+/- 8) test io::mem::test::bench_mem_writer_001_1000 ... bench: 774 ns/iter (+/- 47) test io::mem::test::bench_mem_writer_100_0000 ... bench: 756 ns/iter (+/- 50) test io::mem::test::bench_mem_writer_100_0010 ... bench: 2726 ns/iter (+/- 198) test io::mem::test::bench_mem_writer_100_0100 ... bench: 8961 ns/iter (+/- 712) test io::mem::test::bench_mem_writer_100_1000 ... bench: 105673 ns/iter (+/- 24711) test num::bench::bench_pow_function ... bench: 5849 ns/iter (+/- 371) test num::strconv::bench::f64::float_to_string ... bench: 662 ns/iter (+/- 202) test num::strconv::bench::int::to_str_base_36 ... bench: 424 ns/iter (+/- 7) test num::strconv::bench::int::to_str_bin ... bench: 1227 ns/iter (+/- 80) test num::strconv::bench::int::to_str_dec ... bench: 466 ns/iter (+/- 13) test num::strconv::bench::int::to_str_hex ... bench: 498 ns/iter (+/- 22) test num::strconv::bench::int::to_str_oct ... bench: 502 ns/iter (+/- 229) test num::strconv::bench::uint::to_str_base_36 ... bench: 375 ns/iter (+/- 7) test num::strconv::bench::uint::to_str_bin ... bench: 1011 ns/iter (+/- 590) test num::strconv::bench::uint::to_str_dec ... bench: 407 ns/iter (+/- 17) test num::strconv::bench::uint::to_str_hex ... bench: 442 ns/iter (+/- 7) test num::strconv::bench::uint::to_str_oct ... bench: 433 ns/iter (+/- 46) test path::posix::bench::ends_with_path_home_dir ... bench: 167 ns/iter (+/- 10) test path::posix::bench::ends_with_path_missmatch_jome_home ... bench: 148 ns/iter (+/- 6) test path::posix::bench::is_ancestor_of_path_with_10_dirs ... bench: 221 ns/iter (+/- 31) test path::posix::bench::join_abs_path_home_dir ... bench: 144 ns/iter (+/- 23) test path::posix::bench::join_home_dir ... bench: 196 ns/iter (+/- 9) test path::posix::bench::join_many_abs_path_home_dir ... bench: 143 ns/iter (+/- 6) test path::posix::bench::join_many_home_dir ... bench: 195 ns/iter (+/- 8) test path::posix::bench::path_relative_from_backward ... bench: 248 ns/iter (+/- 10) test path::posix::bench::path_relative_from_forward ... bench: 241 ns/iter (+/- 13) test path::posix::bench::path_relative_from_same_level ... bench: 296 ns/iter (+/- 11) test path::posix::bench::push_abs_path_home_dir ... bench: 104 ns/iter (+/- 7) test path::posix::bench::push_home_dir ... bench: 27311 ns/iter (+/- 2727) test path::posix::bench::push_many_abs_path_home_dir ... bench: 109 ns/iter (+/- 5) test path::posix::bench::push_many_home_dir ... bench: 23263 ns/iter (+/- 1726) test rand::bench::rand_isaac ... bench: 884 ns/iter (+/- 31) = 904 MB/s test rand::bench::rand_isaac64 ... bench: 440 ns/iter (+/- 126) = 1818 MB/s test rand::bench::rand_shuffle_100 ... bench: 2518 ns/iter (+/- 1371) test rand::bench::rand_std ... bench: 429 ns/iter (+/- 17) = 1864 MB/s test rand::bench::rand_xorshift ... bench: 0 ns/iter (+/- 0) = 800000 MB/s ``` std bench after: ``` test collections::hashmap::bench::find_existing ... bench: 43635 ns/iter (+/- 4508) test collections::hashmap::bench::find_nonexisting ... bench: 42323 ns/iter (+/- 1753) test collections::hashmap::bench::find_pop_insert ... bench: 216 ns/iter (+/- 11) test collections::hashmap::bench::hashmap_as_queue ... bench: 125 ns/iter (+/- 8) test collections::hashmap::bench::insert ... bench: 153 ns/iter (+/- 63) test collections::hashmap::bench::new_drop ... bench: 517 ns/iter (+/- 282) test collections::hashmap::bench::new_insert_drop ... bench: 734 ns/iter (+/- 264) test io::buffered::test::bench_buffered_reader ... bench: 1063 ns/iter (+/- 206) test io::buffered::test::bench_buffered_stream ... bench: 2321 ns/iter (+/- 2302) test io::buffered::test::bench_buffered_writer ... bench: 1060 ns/iter (+/- 24) test io::extensions::bench::u64_from_be_bytes_4_aligned ... bench: 69 ns/iter (+/- 2) test io::extensions::bench::u64_from_be_bytes_4_unaligned ... bench: 81 ns/iter (+/- 7) test io::extensions::bench::u64_from_be_bytes_7_aligned ... bench: 70 ns/iter (+/- 5) test io::extensions::bench::u64_from_be_bytes_7_unaligned ... bench: 69 ns/iter (+/- 5) test io::extensions::bench::u64_from_be_bytes_8_aligned ... bench: 80 ns/iter (+/- 6) test io::extensions::bench::u64_from_be_bytes_8_unaligned ... bench: 81 ns/iter (+/- 5) test io::mem::test::bench_buf_reader ... bench: 663 ns/iter (+/- 44) test io::mem::test::bench_buf_writer ... bench: 489 ns/iter (+/- 17) test io::mem::test::bench_mem_reader ... bench: 700 ns/iter (+/- 23) test io::mem::test::bench_mem_writer_001_0000 ... bench: 31 ns/iter (+/- 3) test io::mem::test::bench_mem_writer_001_0010 ... bench: 49 ns/iter (+/- 5) test io::mem::test::bench_mem_writer_001_0100 ... bench: 112 ns/iter (+/- 6) test io::mem::test::bench_mem_writer_001_1000 ... bench: 765 ns/iter (+/- 59) test io::mem::test::bench_mem_writer_100_0000 ... bench: 727 ns/iter (+/- 54) test io::mem::test::bench_mem_writer_100_0010 ... bench: 2586 ns/iter (+/- 215) test io::mem::test::bench_mem_writer_100_0100 ... bench: 8846 ns/iter (+/- 439) test io::mem::test::bench_mem_writer_100_1000 ... bench: 105747 ns/iter (+/- 17443) test num::bench::bench_pow_function ... bench: 5844 ns/iter (+/- 421) test num::strconv::bench::f64::float_to_string ... bench: 669 ns/iter (+/- 571) test num::strconv::bench::int::to_str_base_36 ... bench: 417 ns/iter (+/- 24) test num::strconv::bench::int::to_str_bin ... bench: 1216 ns/iter (+/- 36) test num::strconv::bench::int::to_str_dec ... bench: 466 ns/iter (+/- 24) test num::strconv::bench::int::to_str_hex ... bench: 492 ns/iter (+/- 8) test num::strconv::bench::int::to_str_oct ... bench: 496 ns/iter (+/- 295) test num::strconv::bench::uint::to_str_base_36 ... bench: 366 ns/iter (+/- 8) test num::strconv::bench::uint::to_str_bin ... bench: 1005 ns/iter (+/- 69) test num::strconv::bench::uint::to_str_dec ... bench: 396 ns/iter (+/- 20) test num::strconv::bench::uint::to_str_hex ... bench: 435 ns/iter (+/- 4) test num::strconv::bench::uint::to_str_oct ... bench: 436 ns/iter (+/- 451) test path::posix::bench::ends_with_path_home_dir ... bench: 171 ns/iter (+/- 6) test path::posix::bench::ends_with_path_missmatch_jome_home ... bench: 152 ns/iter (+/- 6) test path::posix::bench::is_ancestor_of_path_with_10_dirs ... bench: 215 ns/iter (+/- 8) test path::posix::bench::join_abs_path_home_dir ... bench: 143 ns/iter (+/- 6) test path::posix::bench::join_home_dir ... bench: 192 ns/iter (+/- 29) test path::posix::bench::join_many_abs_path_home_dir ... bench: 144 ns/iter (+/- 9) test path::posix::bench::join_many_home_dir ... bench: 194 ns/iter (+/- 19) test path::posix::bench::path_relative_from_backward ... bench: 254 ns/iter (+/- 15) test path::posix::bench::path_relative_from_forward ... bench: 244 ns/iter (+/- 17) test path::posix::bench::path_relative_from_same_level ... bench: 293 ns/iter (+/- 27) test path::posix::bench::push_abs_path_home_dir ... bench: 108 ns/iter (+/- 5) test path::posix::bench::push_home_dir ... bench: 32292 ns/iter (+/- 4361) test path::posix::bench::push_many_abs_path_home_dir ... bench: 108 ns/iter (+/- 6) test path::posix::bench::push_many_home_dir ... bench: 20305 ns/iter (+/- 1331) test rand::bench::rand_isaac ... bench: 888 ns/iter (+/- 35) = 900 MB/s test rand::bench::rand_isaac64 ... bench: 439 ns/iter (+/- 17) = 1822 MB/s test rand::bench::rand_shuffle_100 ... bench: 2582 ns/iter (+/- 1001) test rand::bench::rand_std ... bench: 431 ns/iter (+/- 93) = 1856 MB/s test rand::bench::rand_xorshift ... bench: 0 ns/iter (+/- 0) = 800000 MB/s ```
2 parents 8d2e716 + f49f157 commit 279a780

File tree

6 files changed

+27
-28
lines changed

6 files changed

+27
-28
lines changed
 

‎src/libcore/failure.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use intrinsics;
3737
#[lang="fail_"]
3838
fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! {
3939
format_args!(|args| -> () {
40-
begin_unwind(args, file, line);
40+
begin_unwind(args, &(file, line));
4141
}, "{}", expr);
4242

4343
unsafe { intrinsics::abort() }
@@ -48,18 +48,20 @@ fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! {
4848
fn fail_bounds_check(file: &'static str, line: uint,
4949
index: uint, len: uint) -> ! {
5050
format_args!(|args| -> () {
51-
begin_unwind(args, file, line);
51+
begin_unwind(args, &(file, line));
5252
}, "index out of bounds: the len is {} but the index is {}", len, index);
5353
unsafe { intrinsics::abort() }
5454
}
5555

5656
#[cold]
57-
pub fn begin_unwind(fmt: &fmt::Arguments, file: &'static str, line: uint) -> ! {
57+
pub fn begin_unwind(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
5858
#[allow(ctypes)]
5959
extern {
6060
#[lang = "begin_unwind"]
6161
fn begin_unwind(fmt: &fmt::Arguments, file: &'static str,
6262
line: uint) -> !;
6363
}
64+
let (file, line) = *file_line;
6465
unsafe { begin_unwind(fmt, file, line) }
6566
}
67+

‎src/libcore/macros.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ macro_rules! fail(
3333
// up with the number of calls to fail!()
3434
#[inline(always)]
3535
fn run_fmt(fmt: &::std::fmt::Arguments) -> ! {
36-
::core::failure::begin_unwind(fmt, file!(), line!())
36+
static FILE_LINE: (&'static str, uint) = (file!(), line!());
37+
::core::failure::begin_unwind(fmt, &FILE_LINE)
3738
}
3839
format_args!(run_fmt, $fmt, $($arg)*)
3940
});

‎src/librustrt/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extern crate collections;
3333
#[cfg(test)] #[phase(plugin, link)] extern crate std;
3434

3535
pub use self::util::{Stdio, Stdout, Stderr};
36-
pub use self::unwind::{begin_unwind, begin_unwind_fmt, begin_unwind_no_time_to_explain};
36+
pub use self::unwind::{begin_unwind, begin_unwind_fmt};
3737

3838
use core::prelude::*;
3939

‎src/librustrt/unwind.rs

+7-14
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ pub mod eabi {
384384
#[lang = "begin_unwind"]
385385
pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
386386
file: &'static str, line: uint) -> ! {
387-
begin_unwind_fmt(msg, file, line)
387+
begin_unwind_fmt(msg, &(file, line))
388388
}
389389

390390
/// The entry point for unwinding with a formatted message.
@@ -394,8 +394,7 @@ pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
394394
/// on (e.g.) the inlining of other functions as possible), by moving
395395
/// the actual formatting into this shared place.
396396
#[inline(never)] #[cold]
397-
pub fn begin_unwind_fmt(msg: &fmt::Arguments, file: &'static str,
398-
line: uint) -> ! {
397+
pub fn begin_unwind_fmt(msg: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
399398
use core::fmt::FormatWriter;
400399

401400
// We do two allocations here, unfortunately. But (a) they're
@@ -415,9 +414,10 @@ pub fn begin_unwind_fmt(msg: &fmt::Arguments, file: &'static str,
415414
let mut v = Vec::new();
416415
let _ = write!(&mut VecWriter { v: &mut v }, "{}", msg);
417416

418-
begin_unwind_inner(box String::from_utf8(v).unwrap(), file, line)
417+
begin_unwind_inner(box String::from_utf8(v).unwrap(), file_line)
419418
}
420419

420+
// FIXME: Need to change expr_fail in AstBuilder to change this to &(str, uint)
421421
/// This is the entry point of unwinding for fail!() and assert!().
422422
#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
423423
pub fn begin_unwind<M: Any + Send>(msg: M, file: &'static str, line: uint) -> ! {
@@ -429,13 +429,7 @@ pub fn begin_unwind<M: Any + Send>(msg: M, file: &'static str, line: uint) -> !
429429
// failing.
430430

431431
// see below for why we do the `Any` coercion here.
432-
begin_unwind_inner(box msg, file, line)
433-
}
434-
435-
/// Unwinding for `fail!()`. Saves passing a string.
436-
#[inline(never)] #[cold] #[experimental]
437-
pub fn begin_unwind_no_time_to_explain(file: &'static str, line: uint) -> ! {
438-
begin_unwind_inner(box () ("explicit failure"), file, line)
432+
begin_unwind_inner(box msg, &(file, line))
439433
}
440434

441435
/// The core of the unwinding.
@@ -448,9 +442,7 @@ pub fn begin_unwind_no_time_to_explain(file: &'static str, line: uint) -> ! {
448442
/// Do this split took the LLVM IR line counts of `fn main() { fail!()
449443
/// }` from ~1900/3700 (-O/no opts) to 180/590.
450444
#[inline(never)] #[cold] // this is the slow path, please never inline this
451-
fn begin_unwind_inner(msg: Box<Any + Send>,
452-
file: &'static str,
453-
line: uint) -> ! {
445+
fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> ! {
454446
// First, invoke call the user-defined callbacks triggered on task failure.
455447
//
456448
// By the time that we see a callback has been registered (by reading
@@ -467,6 +459,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>,
467459
0 => {}
468460
n => {
469461
let f: Callback = unsafe { mem::transmute(n) };
462+
let (file, line) = *file_line;
470463
f(msg, file, line);
471464
}
472465
}

‎src/libstd/macros.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@
3838
/// ```
3939
#[macro_export]
4040
macro_rules! fail(
41-
() => (
42-
::std::rt::begin_unwind_no_time_to_explain(file!(), line!())
43-
);
44-
($msg:expr) => (
45-
::std::rt::begin_unwind($msg, file!(), line!())
46-
);
41+
() => ({
42+
fail!("explicit failure")
43+
});
44+
($msg:expr) => ({
45+
// static requires less code at runtime, more constant data
46+
static FILE_LINE: (&'static str, uint) = (file!(), line!());
47+
let (file, line) = FILE_LINE;
48+
::std::rt::begin_unwind($msg, file, line)
49+
});
4750
($fmt:expr, $($arg:tt)*) => ({
4851
// a closure can't have return type !, so we need a full
4952
// function to pass to format_args!, *and* we need the
@@ -58,7 +61,8 @@ macro_rules! fail(
5861
// up with the number of calls to fail!()
5962
#[inline(always)]
6063
fn run_fmt(fmt: &::std::fmt::Arguments) -> ! {
61-
::std::rt::begin_unwind_fmt(fmt, file!(), line!())
64+
static FILE_LINE: (&'static str, uint) = (file!(), line!());
65+
::std::rt::begin_unwind_fmt(fmt, &FILE_LINE)
6266
}
6367
format_args!(run_fmt, $fmt, $($arg)*)
6468
});

‎src/libstd/rt/mod.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
6666
// standard library which work together to create the entire runtime.
6767
pub use alloc::{heap, libc_heap};
6868
pub use rustrt::{task, local, mutex, exclusive, stack, args, rtio, thread};
69-
pub use rustrt::{Stdio, Stdout, Stderr};
70-
pub use rustrt::{begin_unwind, begin_unwind_fmt, begin_unwind_no_time_to_explain};
69+
pub use rustrt::{Stdio, Stdout, Stderr, begin_unwind, begin_unwind_fmt};
7170
pub use rustrt::{bookkeeping, at_exit, unwind, DEFAULT_ERROR_CODE, Runtime};
7271

7372
// Simple backtrace functionality (to print on failure)

0 commit comments

Comments
 (0)
Please sign in to comment.