about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBjörn Steinbrink <bsteinbr@gmail.com>2014-10-13 16:12:38 +0200
committerBjörn Steinbrink <bsteinbr@gmail.com>2014-10-13 16:16:16 +0200
commitfafe136c2d3bf62d5449b024516bd5439bbd0da1 (patch)
tree11ec9e174335a46b7daf030becd1a4116943ecca
parent70d8b8ddc547d51f2aadef3d9e489e998f578970 (diff)
downloadrust-fafe136c2d3bf62d5449b024516bd5439bbd0da1.tar.gz
rust-fafe136c2d3bf62d5449b024516bd5439bbd0da1.zip
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.
-rw-r--r--src/librustc/middle/trans/callee.rs7
-rw-r--r--src/librustc/middle/trans/cleanup.rs21
2 files changed, 26 insertions, 2 deletions
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index bc562b39c98..1b23841c913 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 392436d3a80..f3844a956fa 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<NodeInfo>)
@@ -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<NodeInfo>)
@@ -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<NodeInfo>)
@@ -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<NodeInfo>)
@@ -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<NodeInfo>)