1
Fork 0

std: reduce the generic code instantiated by fail!().

This splits the vast majority of the code path taken by
`fail!()` (`begin_unwind`) into a separate non-generic inline(never)
function, so that uses of `fail!()` only monomorphise a small amount of
code, reducing code bloat and making very small crates compile faster.
This commit is contained in:
Huon Wilson 2014-01-27 18:03:37 +11:00
parent 0119e46204
commit e5abe66983

View file

@ -383,16 +383,31 @@ pub fn begin_unwind_raw(msg: *u8, file: *u8, line: uint) -> ! {
}
/// 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>() {