|
58 | 58 | use any::{Any, AnyRefExt};
|
59 | 59 | use c_str::CString;
|
60 | 60 | use cast;
|
| 61 | +use fmt; |
61 | 62 | use kinds::Send;
|
62 | 63 | use option::{Some, None, Option};
|
63 | 64 | use prelude::drop;
|
@@ -382,17 +383,43 @@ pub fn begin_unwind_raw(msg: *u8, file: *u8, line: uint) -> ! {
|
382 | 383 | begin_unwind(msg, file, line as uint)
|
383 | 384 | }
|
384 | 385 |
|
| 386 | +/// The entry point for unwinding with a formatted message. |
| 387 | +/// |
| 388 | +/// This is designed to reduce the amount of code required at the call |
| 389 | +/// site as much as possible (so that `fail!()` has as low an implact |
| 390 | +/// on (e.g.) the inlining of other functions as possible), by moving |
| 391 | +/// the actual formatting into this shared place. |
| 392 | +#[inline(never)] #[cold] |
| 393 | +pub fn begin_unwind_fmt(msg: &fmt::Arguments, file: &'static str, line: uint) -> ! { |
| 394 | + begin_unwind_inner(~fmt::format(msg), file, line) |
| 395 | +} |
| 396 | + |
385 | 397 | /// This is the entry point of unwinding for fail!() and assert!().
|
386 |
| -#[inline(never)] #[cold] // this is the slow path, please never inline this |
| 398 | +#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible |
387 | 399 | pub fn begin_unwind<M: Any + Send>(msg: M, file: &'static str, line: uint) -> ! {
|
388 |
| - // Note that this should be the only allocation performed in this block. |
| 400 | + // Note that this should be the only allocation performed in this code path. |
389 | 401 | // Currently this means that fail!() on OOM will invoke this code path,
|
390 | 402 | // but then again we're not really ready for failing on OOM anyway. If
|
391 | 403 | // we do start doing this, then we should propagate this allocation to
|
392 | 404 | // be performed in the parent of this task instead of the task that's
|
393 | 405 | // failing.
|
394 |
| - let msg = ~msg as ~Any; |
395 | 406 |
|
| 407 | + // see below for why we do the `Any` coercion here. |
| 408 | + begin_unwind_inner(~msg, file, line) |
| 409 | +} |
| 410 | + |
| 411 | + |
| 412 | +/// The core of the unwinding. |
| 413 | +/// |
| 414 | +/// This is non-generic to avoid instantiation bloat in other crates |
| 415 | +/// (which makes compilation of small crates noticably slower). (Note: |
| 416 | +/// we need the `Any` object anyway, we're not just creating it to |
| 417 | +/// avoid being generic.) |
| 418 | +/// |
| 419 | +/// Do this split took the LLVM IR line counts of `fn main() { fail!() |
| 420 | +/// }` from ~1900/3700 (-O/no opts) to 180/590. |
| 421 | +#[inline(never)] #[cold] // this is the slow path, please never inline this |
| 422 | +fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! { |
396 | 423 | let mut task;
|
397 | 424 | {
|
398 | 425 | let msg_s = match msg.as_ref::<&'static str>() {
|
|
0 commit comments