@@ -2188,19 +2188,20 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span,
2188
2188
let s = mangle_internal_name_by_path ( ccx, sub_cx. path ) ;
2189
2189
let llfn = decl_internal_cdecl_fn ( ccx. llmod , s, llfnty) ;
2190
2190
2191
- let copying = alt f. proto {
2192
- ast:: proto_shared ( _) | ast:: proto_send. { true }
2193
- ast:: proto_bare. | ast:: proto_block. { false }
2191
+ let mode = alt f. proto {
2192
+ ast:: proto_shared ( _) { for_closure }
2193
+ ast:: proto_send. { for_send }
2194
+ ast:: proto_bare. | ast:: proto_block. { for_block }
2194
2195
} ;
2195
2196
let env;
2196
2197
alt f. proto {
2197
2198
ast:: proto_block. | ast:: proto_shared ( _) | ast:: proto_send. {
2198
2199
let upvars = get_freevars ( ccx. tcx , id) ;
2199
- let env_r = build_closure ( bcx, upvars, copying ) ;
2200
+ let env_r = build_closure ( bcx, upvars, mode ) ;
2200
2201
env = env_r. ptr ;
2201
2202
bcx = env_r. bcx ;
2202
2203
trans_closure ( sub_cx, sp, f, llfn, none, [ ] , id, { |fcx|
2203
- load_environment ( bcx, fcx, env_r. ptrty , upvars, copying ) ;
2204
+ load_environment ( bcx, fcx, env_r. ptrty , upvars, mode ) ;
2204
2205
} ) ;
2205
2206
}
2206
2207
ast:: proto_bare. {
@@ -2560,7 +2561,7 @@ tag environment_value {
2560
2561
// Otherwise, it is stack allocated and copies pointers to the upvars.
2561
2562
fn build_environment ( bcx : @block_ctxt , lltydescs : [ ValueRef ] ,
2562
2563
bound_values : [ environment_value ] ,
2563
- copying : bool ) ->
2564
+ mode : closure_constr_mode ) ->
2564
2565
{ ptr : ValueRef , ptrty : ty:: t , bcx : @block_ctxt } {
2565
2566
let ccx = bcx_ccx ( bcx) ;
2566
2567
let tcx = bcx_tcx ( bcx) ;
@@ -2602,13 +2603,15 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
2602
2603
2603
2604
let temp_cleanups = [ ] , bcx = bcx;
2604
2605
// Allocate a box that can hold something closure-sized.
2605
- let ( closure, box) = if copying {
2606
+ let ( closure, box) = alt mode {
2607
+ for_closure. | for_send. {
2606
2608
let r = trans_malloc_boxed ( bcx, closure_ty) ;
2607
2609
add_clean_free ( bcx, r. box , false ) ;
2608
2610
temp_cleanups += [ r. box ] ;
2609
2611
bcx = r. bcx ;
2610
2612
( r. body , r. box )
2611
- } else {
2613
+ }
2614
+ for_block. {
2612
2615
// We need to dummy up a box on the stack
2613
2616
let ty = ty:: mk_tup ( tcx, [ ty:: mk_int ( tcx) , closure_ty] ) ;
2614
2617
let r = alloc_ty ( bcx, ty) ;
@@ -2618,10 +2621,12 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
2618
2621
C_int ( ccx, 2 ) ,
2619
2622
GEPi ( bcx, r. val , [ 0 , abi:: box_rc_field_refcnt] ) ) ;
2620
2623
( GEPi ( bcx, r. val , [ 0 , abi:: box_rc_field_body] ) , r. val )
2624
+ }
2621
2625
} ;
2622
2626
2623
2627
// Store bindings tydesc.
2624
- if copying {
2628
+ alt mode {
2629
+ for_closure. | for_send. {
2625
2630
let bound_tydesc = GEPi ( bcx, closure, [ 0 , abi:: closure_elt_tydesc] ) ;
2626
2631
let ti = none;
2627
2632
let bindings_tydesc =
@@ -2630,6 +2635,8 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
2630
2635
lazily_emit_tydesc_glue ( bcx, abi:: tydesc_field_free_glue, ti) ;
2631
2636
bcx = bindings_tydesc. bcx ;
2632
2637
Store ( bcx, bindings_tydesc. val , bound_tydesc) ;
2638
+ }
2639
+ for_block. { }
2633
2640
}
2634
2641
2635
2642
// Copy expr values into boxed bindings.
@@ -2651,12 +2658,15 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
2651
2658
temp_cleanups += [ bound. val ] ;
2652
2659
}
2653
2660
env_direct ( val, ty, is_mem) {
2654
- if copying {
2661
+ alt mode {
2662
+ for_closure. | for_send. {
2655
2663
let val1 = is_mem ? load_if_immediate ( bcx, val, ty) : val;
2656
2664
bcx = copy_val ( bcx, INIT , bound. val , val1, ty) ;
2657
- } else {
2665
+ }
2666
+ for_block. {
2658
2667
let addr = is_mem ? val : do_spill_noroot ( bcx , val ) ;
2659
2668
Store ( bcx, addr, bound. val ) ;
2669
+ }
2660
2670
}
2661
2671
}
2662
2672
}
@@ -2675,28 +2685,47 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
2675
2685
i = 0 u;
2676
2686
for td: ValueRef in lltydescs {
2677
2687
let ty_param_slot = GEPi ( bcx, ty_params_slot. val , [ 0 , i as int ] ) ;
2678
- Store ( bcx, td, ty_param_slot) ;
2688
+ alt mode {
2689
+ for_closure. | for_block. {
2690
+ Store ( bcx, td, ty_param_slot) ;
2691
+ }
2692
+ for_send. {
2693
+ let cloned_td = Call ( bcx, ccx. upcalls . clone_type_desc , [ td] ) ;
2694
+ Store ( bcx, cloned_td, ty_param_slot) ;
2695
+ }
2696
+ }
2679
2697
i += 1 u;
2680
2698
}
2681
2699
2682
2700
ret { ptr : box, ptrty : closure_ty, bcx : bcx} ;
2683
2701
}
2684
2702
2703
+ tag closure_constr_mode {
2704
+ for_block;
2705
+ for_closure;
2706
+ for_send;
2707
+ }
2708
+
2685
2709
// Given a context and a list of upvars, build a closure. This just
2686
2710
// collects the upvars and packages them up for build_environment.
2687
- fn build_closure ( cx : @block_ctxt , upvars : @[ ast:: def ] , copying : bool ) ->
2688
- { ptr : ValueRef , ptrty : ty:: t , bcx : @block_ctxt } {
2711
+ fn build_closure ( cx : @block_ctxt ,
2712
+ upvars : @[ ast:: def ] ,
2713
+ mode : closure_constr_mode )
2714
+ -> { ptr : ValueRef , ptrty : ty:: t , bcx : @block_ctxt } {
2689
2715
// If we need to, package up the iterator body to call
2690
2716
let env_vals = [ ] ;
2691
2717
// Package up the upvars
2692
2718
for def in * upvars {
2693
2719
let lv = trans_local_var ( cx, def) ;
2694
2720
let nid = ast_util:: def_id_of_def ( def) . node ;
2695
2721
let ty = ty:: node_id_to_monotype ( bcx_tcx ( cx) , nid) ;
2696
- if !copying { ty = ty:: mk_mut_ptr ( bcx_tcx ( cx) , ty) ; }
2722
+ alt mode {
2723
+ for_block. { ty = ty:: mk_mut_ptr ( bcx_tcx ( cx) , ty) ; }
2724
+ for_send. | for_closure . { }
2725
+ }
2697
2726
env_vals += [ env_direct ( lv. val , ty, lv. kind == owned) ] ;
2698
2727
}
2699
- ret build_environment ( cx, copy cx. fcx . lltydescs , env_vals, copying ) ;
2728
+ ret build_environment ( cx, copy cx. fcx . lltydescs , env_vals, mode ) ;
2700
2729
}
2701
2730
2702
2731
// Return a pointer to the stored typarams in a closure.
@@ -2734,7 +2763,7 @@ fn find_environment_tydescs(bcx: @block_ctxt, envty: ty::t, closure: ValueRef)
2734
2763
// and a list of upvars, generate code to load and populate the environment
2735
2764
// with the upvars and type descriptors.
2736
2765
fn load_environment ( enclosing_cx : @block_ctxt , fcx : @fn_ctxt , envty : ty:: t ,
2737
- upvars : @[ ast:: def ] , copying : bool ) {
2766
+ upvars : @[ ast:: def ] , mode : closure_constr_mode ) {
2738
2767
let bcx = new_raw_block_ctxt ( fcx, fcx. llloadenv ) ;
2739
2768
2740
2769
let ty = ty:: mk_imm_box ( bcx_tcx ( bcx) , envty) ;
@@ -2769,7 +2798,10 @@ fn load_environment(enclosing_cx: @block_ctxt, fcx: @fn_ctxt, envty: ty::t,
2769
2798
let upvarptr = GEP_tup_like ( bcx, ty, llclosure, path + [ i as int ] ) ;
2770
2799
bcx = upvarptr. bcx ;
2771
2800
let llupvarptr = upvarptr. val ;
2772
- if !copying { llupvarptr = Load ( bcx, llupvarptr) ; }
2801
+ alt mode {
2802
+ for_block. { llupvarptr = Load ( bcx, llupvarptr) ; }
2803
+ for_send. | for_closure . { }
2804
+ }
2773
2805
let def_id = ast_util:: def_id_of_def ( upvar_def) ;
2774
2806
fcx. llupvars . insert ( def_id. node , llupvarptr) ;
2775
2807
i += 1 u;
@@ -3532,7 +3564,8 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
3532
3564
3533
3565
// Actually construct the closure
3534
3566
let closure = build_environment ( bcx, lltydescs, env_vals +
3535
- vec:: map ( { |x| env_expr ( x) } , bound) , true ) ;
3567
+ vec:: map ( { |x| env_expr ( x) } , bound) ,
3568
+ for_closure) ;
3536
3569
bcx = closure. bcx ;
3537
3570
3538
3571
// Make thunk
0 commit comments