about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBjörn Steinbrink <bsteinbr@gmail.com>2013-06-19 20:28:42 +0200
committerBjörn Steinbrink <bsteinbr@gmail.com>2013-06-20 23:53:26 +0200
commitdc262d9aa742adadb92558a588aeaa57267fdee4 (patch)
treedf5a5944b64e3b24f3548f5ce5c79bc32a528e42
parentf348465283d6cd85b69bcdc1711d14985d154c39 (diff)
Avoid unnecessary scratch datums for by-copy function arguments
Currently, by-copy function arguments are always stored into a scratch
datum, which serves two purposes.  First, it is required to be able to
have a temporary cleanup, in case that the call fails before the callee
actually takes ownership of the value. Second, if the argument is to be
passed by reference, the copy is required, so that the function doesn't
get a reference to the original value.

But in case that the datum does not need a drop glue call and it is
passed by value, there's no need to perform the extra copy.
-rw-r--r--src/librustc/middle/trans/callee.rs45
1 files changed, 27 insertions, 18 deletions
diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs
index bfbe078c4f5..47e5f9bf35f 100644
--- a/src/librustc/middle/trans/callee.rs
+++ b/src/librustc/middle/trans/callee.rs
@@ -826,24 +826,33 @@ pub fn trans_arg_expr(bcx: block,
                         val = arg_datum.to_ref_llval(bcx);
                     }
                     ty::ByCopy => {
-                        debug!("by copy arg with type %s, storing to scratch",
-                               bcx.ty_to_str(arg_datum.ty));
-                        let scratch = scratch_datum(bcx, arg_datum.ty, false);
-
-                        arg_datum.store_to_datum(bcx,
-                                                 arg_expr.id,
-                                                 INIT,
-                                                 scratch);
-
-                        // Technically, ownership of val passes to the callee.
-                        // However, we must cleanup should we fail before the
-                        // callee is actually invoked.
-                        scratch.add_clean(bcx);
-                        temp_cleanups.push(scratch.val);
-
-                        match arg_datum.appropriate_mode() {
-                            ByValue => val = Load(bcx, scratch.val),
-                            ByRef(_) => val = scratch.val,
+                        if ty::type_needs_drop(bcx.tcx(), arg_datum.ty) ||
+                                arg_datum.appropriate_mode().is_by_ref() {
+                            debug!("by copy arg with type %s, storing to scratch",
+                                   bcx.ty_to_str(arg_datum.ty));
+                            let scratch = scratch_datum(bcx, arg_datum.ty, false);
+
+                            arg_datum.store_to_datum(bcx,
+                                                     arg_expr.id,
+                                                     INIT,
+                                                     scratch);
+
+                            // Technically, ownership of val passes to the callee.
+                            // However, we must cleanup should we fail before the
+                            // callee is actually invoked.
+                            scratch.add_clean(bcx);
+                            temp_cleanups.push(scratch.val);
+
+                            match scratch.appropriate_mode() {
+                                ByValue => val = Load(bcx, scratch.val),
+                                ByRef(_) => val = scratch.val,
+                            }
+                        } else {
+                            debug!("by copy arg with type %s");
+                            match arg_datum.mode {
+                                ByRef(_) => val = Load(bcx, arg_datum.val),
+                                ByValue => val = arg_datum.val,
+                            }
                         }
                     }
                 }