mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 14:57:14 +00:00
auto merge of #11841 : huonw/rust/noinline-fail, r=alexcrichton
In two ways: - for a plain `fail!(a)` we make the generic part of `begin_unwind` as small as possible (makes `fn main() { fail!() }` compile 2-3x faster, due to less monomorphisation bloat) - for `fail!("format {}", "string")`, we avoid touching the generics completely by doing the formatting in a specialised function, which (with optimisations) saves a function call at the call-site of `fail!`. (This one has significantly less benefit than the first.)
This commit is contained in:
commit
feacb59466
@ -48,8 +48,18 @@ macro_rules! fail(
|
||||
::std::rt::begin_unwind($msg, file!(), line!())
|
||||
);
|
||||
($fmt:expr, $($arg:tt)*) => (
|
||||
::std::rt::begin_unwind(format!($fmt, $($arg)*), file!(), line!())
|
||||
)
|
||||
{
|
||||
// a closure can't have return type !, so we need a full
|
||||
// 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]
|
||||
fn run_fmt(fmt: &::std::fmt::Arguments) -> ! {
|
||||
::std::rt::begin_unwind_fmt(fmt, file!(), line!())
|
||||
}
|
||||
format_args!(run_fmt, $fmt, $($arg)*)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
#[macro_export]
|
||||
|
@ -69,7 +69,7 @@ use self::task::{Task, BlockedTask};
|
||||
pub use self::util::default_sched_threads;
|
||||
|
||||
// Export unwinding facilities used by the failure macros
|
||||
pub use self::unwind::{begin_unwind, begin_unwind_raw};
|
||||
pub use self::unwind::{begin_unwind, begin_unwind_raw, begin_unwind_fmt};
|
||||
|
||||
// FIXME: these probably shouldn't be public...
|
||||
#[doc(hidden)]
|
||||
|
@ -58,6 +58,7 @@
|
||||
use any::{Any, AnyRefExt};
|
||||
use c_str::CString;
|
||||
use cast;
|
||||
use fmt;
|
||||
use kinds::Send;
|
||||
use option::{Some, None, Option};
|
||||
use prelude::drop;
|
||||
@ -382,17 +383,43 @@ pub fn begin_unwind_raw(msg: *u8, file: *u8, line: uint) -> ! {
|
||||
begin_unwind(msg, file, line as uint)
|
||||
}
|
||||
|
||||
/// The entry point for unwinding with a formatted message.
|
||||
///
|
||||
/// This is designed to reduce the amount of code required at the call
|
||||
/// site as much as possible (so that `fail!()` has as low an implact
|
||||
/// on (e.g.) the inlining of other functions as possible), by moving
|
||||
/// the actual formatting into this shared place.
|
||||
#[inline(never)] #[cold]
|
||||
pub fn begin_unwind_fmt(msg: &fmt::Arguments, file: &'static str, line: uint) -> ! {
|
||||
begin_unwind_inner(~fmt::format(msg), file, line)
|
||||
}
|
||||
|
||||
/// This is the entry point of unwinding for fail!() and assert!().
|
||||
#[inline(never)] #[cold] // this is the slow path, please never inline this
|
||||
#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
|
||||
pub fn begin_unwind<M: Any + Send>(msg: M, file: &'static str, line: uint) -> ! {
|
||||
// Note that this should be the only allocation performed in this block.
|
||||
// Note that this should be the only allocation performed in this code path.
|
||||
// Currently this means that fail!() on OOM will invoke this code path,
|
||||
// but then again we're not really ready for failing on OOM anyway. If
|
||||
// we do start doing this, then we should propagate this allocation to
|
||||
// be performed in the parent of this task instead of the task that's
|
||||
// failing.
|
||||
let msg = ~msg as ~Any;
|
||||
|
||||
// see below for why we do the `Any` coercion here.
|
||||
begin_unwind_inner(~msg, file, line)
|
||||
}
|
||||
|
||||
|
||||
/// The core of the unwinding.
|
||||
///
|
||||
/// This is non-generic to avoid instantiation bloat in other crates
|
||||
/// (which makes compilation of small crates noticably slower). (Note:
|
||||
/// we need the `Any` object anyway, we're not just creating it to
|
||||
/// avoid being generic.)
|
||||
///
|
||||
/// Do this split took the LLVM IR line counts of `fn main() { fail!()
|
||||
/// }` from ~1900/3700 (-O/no opts) to 180/590.
|
||||
#[inline(never)] #[cold] // this is the slow path, please never inline this
|
||||
fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! {
|
||||
let mut task;
|
||||
{
|
||||
let msg_s = match msg.as_ref::<&'static str>() {
|
||||
|
Loading…
Reference in New Issue
Block a user