From 4db68e644e2e7bef55ed536ac77f87292260527c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 29 Jul 2014 16:40:59 -0700 Subject: [PATCH] Modify failure lang items to take less pointers. Divide-by-zero before: ``` leaq "str\"str\"(1762)"(%rip), %rax movq %rax, 16(%rsp) movq $27, 24(%rsp) leaq "str\"str\"(1542)"(%rip), %rax movq %rax, (%rsp) movq $19, 8(%rsp) leaq 16(%rsp), %rdi leaq (%rsp), %rsi movl $32, %edx callq _ZN7failure5fail_20hc04408f955ce60aaqWjE@PLT ``` After: ``` leaq .Lconst(%rip), %rdi callq _ZN7failure5fail_20haf918a97c8f7f2bfqWjE@PLT ``` Bounds check before: ``` leaq "str\"str\"(1542)"(%rip), %rax movq %rax, 8(%rsp) movq $19, 16(%rsp) leaq 8(%rsp), %rdi movl $38, %esi movl $1, %edx movl $1, %ecx callq _ZN7failure17fail_bounds_check20hf4bc3c69e96caf41RXjE@PLT ``` Bounds check after: ``` leaq .Lconst2(%rip), %rdi movl $1, %esi movl $1, %edx callq _ZN7failure17fail_bounds_check20h5267276a537a7de22XjE@PLT ``` Size before: 21277995 librustc-4e7c5e5c.s ``` text data 12554881 6089335 ``` Size after: 21247617 librustc-4e7c5e5c.so ``` text data 12518497 6095748 ``` --- src/libcore/failure.rs | 26 ++++++++++++++++++++++ src/librustc/middle/trans/consts.rs | 2 +- src/librustc/middle/trans/controlflow.rs | 28 +++++++++++------------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/src/libcore/failure.rs b/src/libcore/failure.rs index 5965603770ba..6a638b5618ca 100644 --- a/src/libcore/failure.rs +++ b/src/libcore/failure.rs @@ -33,6 +33,7 @@ use fmt; use intrinsics; +#[cfg(stage0)] #[cold] #[inline(never)] // this is the slow path, always #[lang="fail_"] fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! { @@ -43,6 +44,7 @@ fn fail_(expr: &'static str, file: &'static str, line: uint) -> ! { unsafe { intrinsics::abort() } } +#[cfg(stage0)] #[cold] #[lang="fail_bounds_check"] fn fail_bounds_check(file: &'static str, line: uint, @@ -53,6 +55,30 @@ fn fail_bounds_check(file: &'static str, line: uint, unsafe { intrinsics::abort() } } +#[cfg(not(stage0))] +#[cold] #[inline(never)] // this is the slow path, always +#[lang="fail_"] +fn fail_(expr_file_line: &(&'static str, &'static str, uint)) -> ! { + let (expr, file, line) = *expr_file_line; + let ref file_line = (file, line); + format_args!(|args| -> () { + begin_unwind(args, file_line); + }, "{}", expr); + + unsafe { intrinsics::abort() } +} + +#[cfg(not(stage0))] +#[cold] +#[lang="fail_bounds_check"] +fn fail_bounds_check(file_line: &(&'static str, uint), + index: uint, len: uint) -> ! { + format_args!(|args| -> () { + begin_unwind(args, file_line); + }, "index out of bounds: the len is {} but the index is {}", len, index); + unsafe { intrinsics::abort() } +} + #[cold] pub fn begin_unwind(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! { #[allow(ctypes)] diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 2fd468d8fda8..7d546aac0cba 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -109,7 +109,7 @@ fn const_vec(cx: &CrateContext, e: &ast::Expr, (v, llunitty, inlineable.iter().fold(true, |a, &b| a && b)) } -fn const_addr_of(cx: &CrateContext, cv: ValueRef) -> ValueRef { +pub fn const_addr_of(cx: &CrateContext, cv: ValueRef) -> ValueRef { unsafe { let gv = "const".with_c_str(|name| { llvm::LLVMAddGlobal(cx.llmod, val_ty(cv).to_ref(), name) diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index dd8fe5e9303a..2fd2e69cfc3b 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -20,6 +20,7 @@ use middle::trans::callee; use middle::trans::cleanup::CleanupMethods; use middle::trans::cleanup; use middle::trans::common::*; +use middle::trans::consts; use middle::trans::datum; use middle::trans::debuginfo; use middle::trans::expr; @@ -477,14 +478,6 @@ pub fn trans_ret<'a>(bcx: &'a Block<'a>, return bcx; } -fn str_slice_arg<'a>(bcx: &'a Block<'a>, s: InternedString) -> ValueRef { - let ccx = bcx.ccx(); - let s = C_str_slice(ccx, s); - let slot = alloca(bcx, val_ty(s), "__temp"); - Store(bcx, s, slot); - slot -} - pub fn trans_fail<'a>( bcx: &'a Block<'a>, sp: Span, @@ -493,12 +486,14 @@ pub fn trans_fail<'a>( let ccx = bcx.ccx(); let _icx = push_ctxt("trans_fail_value"); - let v_str = str_slice_arg(bcx, fail_str); + let v_str = C_str_slice(ccx, fail_str); let loc = bcx.sess().codemap().lookup_char_pos(sp.lo); let filename = token::intern_and_get_ident(loc.file.name.as_slice()); - let v_filename = str_slice_arg(bcx, filename); - let v_line = loc.line as int; - let args = vec!(v_str, v_filename, C_int(ccx, v_line)); + let filename = C_str_slice(ccx, filename); + let line = C_int(ccx, loc.line as int); + let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false); + let expr_file_line = consts::const_addr_of(ccx, expr_file_line_const); + let args = vec!(expr_file_line); let did = langcall(bcx, Some(sp), "", FailFnLangItem); let bcx = callee::trans_lang_call(bcx, did, @@ -514,6 +509,7 @@ pub fn trans_fail_bounds_check<'a>( index: ValueRef, len: ValueRef) -> &'a Block<'a> { + let ccx = bcx.ccx(); let _icx = push_ctxt("trans_fail_bounds_check"); // Extract the file/line from the span @@ -521,9 +517,11 @@ pub fn trans_fail_bounds_check<'a>( let filename = token::intern_and_get_ident(loc.file.name.as_slice()); // Invoke the lang item - let filename = str_slice_arg(bcx, filename); - let line = C_int(bcx.ccx(), loc.line as int); - let args = vec!(filename, line, index, len); + let filename = C_str_slice(ccx, filename); + let line = C_int(ccx, loc.line as int); + let file_line_const = C_struct(ccx, &[filename, line], false); + let file_line = consts::const_addr_of(ccx, file_line_const); + let args = vec!(file_line, index, len); let did = langcall(bcx, Some(sp), "", FailBoundsCheckFnLangItem); let bcx = callee::trans_lang_call(bcx, did,