From fafe136c2d3bf62d5449b024516bd5439bbd0da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Mon, 13 Oct 2014 16:12:38 +0200 Subject: [PATCH] Emit lifetime end markers for function arguments Function arguments are (hopefully!) the last places where allocas don't get proper markers for the end of their lifetimes. This means that this code using 64 bytes of stack for the function arguments: ````rust std::io::println("1"); std::io::println("2"); std::io::println("3"); std::io::println("4"); ```` But with the proper lifetime markers, the slots can be reused, and the arguments only need 16 bytes of stack. --- src/librustc/middle/trans/callee.rs | 7 +++++-- src/librustc/middle/trans/cleanup.rs | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index bc562b39c98f..1b23841c913c 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -788,7 +788,7 @@ pub fn trans_call_inner<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llself.is_some(), abi); - fcx.pop_custom_cleanup_scope(arg_cleanup_scope); + fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean(); // Invoke the actual rust fn and update bcx/llresult. let (llret, b) = base::invoke(bcx, @@ -829,12 +829,15 @@ pub fn trans_call_inner<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, cleanup::CustomScope(arg_cleanup_scope), false, abi); - fcx.pop_custom_cleanup_scope(arg_cleanup_scope); + fcx.scopes.borrow_mut().last_mut().unwrap().drop_non_lifetime_clean(); + bcx = foreign::trans_native_call(bcx, callee_ty, llfn, opt_llretslot.unwrap(), llargs.as_slice(), arg_tys); } + fcx.pop_and_trans_custom_cleanup_scope(bcx, arg_cleanup_scope); + // If the caller doesn't care about the result of this fn call, // drop the temporary slot we made. match (dest, opt_llretslot) { diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index 392436d3a806..f3844a956fad 100644 --- a/src/librustc/middle/trans/cleanup.rs +++ b/src/librustc/middle/trans/cleanup.rs @@ -74,6 +74,7 @@ pub struct CachedEarlyExit { pub trait Cleanup { fn must_unwind(&self) -> bool; fn clean_on_unwind(&self) -> bool; + fn is_lifetime_end(&self) -> bool; fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option) @@ -875,6 +876,10 @@ impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> { LoopScopeKind(id, _) => format!("{}_loop_{}_", prefix, id), } } + + pub fn drop_non_lifetime_clean(&mut self) { + self.cleanups.retain(|c| c.is_lifetime_end()); + } } impl<'blk, 'tcx> CleanupScopeKind<'blk, 'tcx> { @@ -943,6 +948,10 @@ impl Cleanup for DropValue { self.must_unwind } + fn is_lifetime_end(&self) -> bool { + false + } + fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option) @@ -978,6 +987,10 @@ impl Cleanup for FreeValue { true } + fn is_lifetime_end(&self) -> bool { + false + } + fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option) @@ -1008,6 +1021,10 @@ impl Cleanup for FreeSlice { true } + fn is_lifetime_end(&self) -> bool { + false + } + fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option) @@ -1035,6 +1052,10 @@ impl Cleanup for LifetimeEnd { true } + fn is_lifetime_end(&self) -> bool { + true + } + fn trans<'blk, 'tcx>(&self, bcx: Block<'blk, 'tcx>, debug_loc: Option)