]> git.lizzy.rs Git - rust.git/commitdiff
translate unique closure env better
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 14 Dec 2011 00:50:11 +0000 (16:50 -0800)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 14 Dec 2011 22:32:23 +0000 (14:32 -0800)
src/comp/middle/trans.rs
src/comp/middle/trans_uniq.rs

index 05f9f3934725d16353773b416ae9c92b9390757e..40625b993b169626d239375bf5b6694d1cea6929 100644 (file)
@@ -2553,9 +2553,27 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
                      bound_values: [environment_value],
                      mode: closure_constr_mode) ->
    {ptr: ValueRef, ptrty: ty::t, bcx: @block_ctxt} {
-    let ccx = bcx_ccx(bcx);
+
+    fn dummy_environment_box(bcx: @block_ctxt, r: result)
+        -> (@block_ctxt, ValueRef, ValueRef) {
+        // Prevent glue from trying to free this.
+        let ccx = bcx_ccx(bcx);
+        let ref_cnt = GEPi(bcx, r.val, [0, abi::box_rc_field_refcnt]);
+        Store(r.bcx, C_int(ccx, 2), ref_cnt);
+        let closure = GEPi(r.bcx, r.val, [0, abi::box_rc_field_body]);
+        (r.bcx, closure, r.val)
+    }
+
+    fn clone_tydesc(bcx: @block_ctxt,
+                    mode: closure_constr_mode,
+                    td: ValueRef) -> ValueRef {
+        ret alt mode {
+          for_block. | for_closure. { td }
+          for_send. { Call(bcx, bcx_ccx(bcx).upcalls.clone_type_desc, [td]) }
+        };
+    }
+
     let tcx = bcx_tcx(bcx);
-    // Synthesize a closure type.
 
     // First, synthesize a tuple type containing the types of all the
     // bound expressions.
@@ -2591,26 +2609,37 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
     // Finally, synthesize a type for that whole vector.
     let closure_ty: ty::t = ty::mk_tup(tcx, closure_tys);
 
-    let temp_cleanups = [], bcx = bcx;
+    let temp_cleanups = [];
+
     // Allocate a box that can hold something closure-sized.
-    let (closure, box) = alt mode {
-      for_closure. | for_send. {
+    //
+    // For now, no matter what kind of closure we have, we always allocate
+    // space for a ref cnt in the closure.  If the closure is a block or
+    // unique closure, this ref count isn't really used: we initialize it to 2
+    // so that it will never drop to zero.  This is a hack and could go away
+    // but then we'd have to modify the code to do the right thing when
+    // casting from a shared closure to a block.
+    let (bcx, closure, box) = alt mode {
+      for_closure. {
         let r = trans_malloc_boxed(bcx, closure_ty);
         add_clean_free(bcx, r.box, false);
         temp_cleanups += [r.box];
-        bcx = r.bcx;
-        (r.body, r.box)
+        (r.bcx, r.body, r.box)
+      }
+      for_send. {
+        // Dummy up a box in the exchange heap.
+        let tup_ty = ty::mk_tup(tcx, [ty::mk_int(tcx), closure_ty]);
+        let box_ty = ty::mk_uniq(tcx, {ty: tup_ty, mut: ast::imm});
+        check trans_uniq::type_is_unique_box(bcx, box_ty);
+        let r = trans_uniq::alloc_uniq(bcx, box_ty);
+        add_clean_free(bcx, r.val, true);
+        dummy_environment_box(bcx, r)
       }
       for_block. {
-        // We need to dummy up a box on the stack
+        // Dummy up a box on the stack,
         let ty = ty::mk_tup(tcx, [ty::mk_int(tcx), closure_ty]);
         let r = alloc_ty(bcx, ty);
-        bcx = r.bcx;
-        // Prevent glue from trying to free this.
-        Store(bcx,
-              C_int(ccx, 2),
-              GEPi(bcx, r.val, [0, abi::box_rc_field_refcnt]));
-        (GEPi(bcx, r.val, [0, abi::box_rc_field_body]), r.val)
+        dummy_environment_box(bcx, r)
       }
     };
 
@@ -2624,7 +2653,8 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
         lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
         lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
         bcx = bindings_tydesc.bcx;
-        Store(bcx, bindings_tydesc.val, bound_tydesc);
+        let td = clone_tydesc(bcx, mode, bindings_tydesc.val);
+        Store(bcx, td, bound_tydesc);
       }
       for_block. {}
     }
@@ -2675,15 +2705,8 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
     i = 0u;
     for td: ValueRef in lltydescs {
         let ty_param_slot = GEPi(bcx, ty_params_slot.val, [0, i as int]);
-        alt mode {
-          for_closure. | for_block. {
-            Store(bcx, td, ty_param_slot);
-          }
-          for_send. {
-            let cloned_td = Call(bcx, ccx.upcalls.clone_type_desc, [td]);
-            Store(bcx, cloned_td, ty_param_slot);
-          }
-        }
+        let cloned_td = clone_tydesc(bcx, mode, td);
+        Store(bcx, cloned_td, ty_param_slot);
         i += 1u;
     }
 
index f1df608e8bf7c5fd7b2578c06be340874204e9cf..6b420a43091991006b23ee013fd5d66e8ac3b876 100644 (file)
@@ -15,7 +15,8 @@
     dest
 };
 
-export trans_uniq, make_free_glue, type_is_unique_box, autoderef, duplicate;
+export trans_uniq, make_free_glue, type_is_unique_box, autoderef, duplicate,
+       alloc_uniq;
 
 pure fn type_is_unique_box(bcx: @block_ctxt, ty: ty::t) -> bool {
     ty::type_is_unique_box(bcx_tcx(bcx), ty)