Skip to content

Commit b8045c5

Browse files
committed
---
yaml --- r: 6692 b: refs/heads/master c: 6a8cb70 h: refs/heads/master v: v3
1 parent 118970c commit b8045c5

File tree

5 files changed

+114
-34
lines changed

5 files changed

+114
-34
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 36177dd3e986199f4f6cb669423ca9cf78ff8d74
2+
refs/heads/master: 6a8cb704d9c2543cb30df2e26b992c17e3bc488d

trunk/src/comp/back/upcall.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type upcalls =
1717
shared_malloc: ValueRef,
1818
shared_free: ValueRef,
1919
mark: ValueRef,
20+
clone_type_desc: ValueRef,
2021
get_type_desc: ValueRef,
2122
vec_grow: ValueRef,
2223
vec_push: ValueRef,
@@ -54,21 +55,26 @@ fn declare_upcalls(targ_cfg: @session::config,
5455
malloc:
5556
d("malloc", [size_t, T_ptr(tydesc_type)],
5657
T_ptr(T_i8())),
57-
free: dv("free", [T_ptr(T_i8()), int_t]),
58+
free:
59+
dv("free", [T_ptr(T_i8()), int_t]),
5860
shared_malloc:
5961
d("shared_malloc", [size_t, T_ptr(tydesc_type)],
6062
T_ptr(T_i8())),
61-
shared_free: dv("shared_free", [T_ptr(T_i8())]),
62-
mark: d("mark", [T_ptr(T_i8())], int_t),
63+
shared_free:
64+
dv("shared_free", [T_ptr(T_i8())]),
65+
mark:
66+
d("mark", [T_ptr(T_i8())], int_t),
67+
clone_type_desc:
68+
d("clone_type_desc", [T_ptr(tydesc_type)],
69+
T_ptr(tydesc_type)),
6370
get_type_desc:
6471
d("get_type_desc",
6572
[T_ptr(T_nil()), size_t,
6673
size_t, size_t,
6774
T_ptr(T_ptr(tydesc_type)), int_t],
6875
T_ptr(tydesc_type)),
6976
vec_grow:
70-
dv("vec_grow", [T_ptr(T_ptr(opaque_vec_t)),
71-
int_t]),
77+
dv("vec_grow", [T_ptr(T_ptr(opaque_vec_t)), int_t]),
7278
vec_push:
7379
dv("vec_push",
7480
[T_ptr(T_ptr(opaque_vec_t)), T_ptr(tydesc_type),
@@ -80,18 +86,24 @@ fn declare_upcalls(targ_cfg: @session::config,
8086
T_i8()]),
8187
log_type:
8288
dv("log_type", [T_ptr(tydesc_type), T_ptr(T_i8()), T_i32()]),
83-
dynastack_mark: d("dynastack_mark", [], T_ptr(T_i8())),
89+
dynastack_mark:
90+
d("dynastack_mark", [], T_ptr(T_i8())),
8491
dynastack_alloc:
8592
d("dynastack_alloc_2", [size_t, T_ptr(tydesc_type)],
8693
T_ptr(T_i8())),
87-
dynastack_free: dv("dynastack_free", [T_ptr(T_i8())]),
88-
alloc_c_stack: d("alloc_c_stack", [size_t], T_ptr(T_i8())),
89-
call_shim_on_c_stack: d("call_shim_on_c_stack",
90-
// arguments: void *args, void *fn_ptr
91-
[T_ptr(T_i8()), T_ptr(T_i8())],
92-
int_t),
93-
rust_personality: d("rust_personality", [], T_i32()),
94-
reset_stack_limit: dv("reset_stack_limit", [])
94+
dynastack_free:
95+
dv("dynastack_free", [T_ptr(T_i8())]),
96+
alloc_c_stack:
97+
d("alloc_c_stack", [size_t], T_ptr(T_i8())),
98+
call_shim_on_c_stack:
99+
d("call_shim_on_c_stack",
100+
// arguments: void *args, void *fn_ptr
101+
[T_ptr(T_i8()), T_ptr(T_i8())],
102+
int_t),
103+
rust_personality:
104+
d("rust_personality", [], T_i32()),
105+
reset_stack_limit:
106+
dv("reset_stack_limit", [])
95107
};
96108
}
97109
//

trunk/src/comp/middle/trans.rs

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2188,19 +2188,20 @@ fn trans_expr_fn(bcx: @block_ctxt, f: ast::_fn, sp: span,
21882188
let s = mangle_internal_name_by_path(ccx, sub_cx.path);
21892189
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
21902190

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 }
21942195
};
21952196
let env;
21962197
alt f.proto {
21972198
ast::proto_block. | ast::proto_shared(_) | ast::proto_send. {
21982199
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);
22002201
env = env_r.ptr;
22012202
bcx = env_r.bcx;
22022203
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);
22042205
});
22052206
}
22062207
ast::proto_bare. {
@@ -2560,7 +2561,7 @@ tag environment_value {
25602561
// Otherwise, it is stack allocated and copies pointers to the upvars.
25612562
fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
25622563
bound_values: [environment_value],
2563-
copying: bool) ->
2564+
mode: closure_constr_mode) ->
25642565
{ptr: ValueRef, ptrty: ty::t, bcx: @block_ctxt} {
25652566
let ccx = bcx_ccx(bcx);
25662567
let tcx = bcx_tcx(bcx);
@@ -2602,13 +2603,15 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
26022603

26032604
let temp_cleanups = [], bcx = bcx;
26042605
// 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. {
26062608
let r = trans_malloc_boxed(bcx, closure_ty);
26072609
add_clean_free(bcx, r.box, false);
26082610
temp_cleanups += [r.box];
26092611
bcx = r.bcx;
26102612
(r.body, r.box)
2611-
} else {
2613+
}
2614+
for_block. {
26122615
// We need to dummy up a box on the stack
26132616
let ty = ty::mk_tup(tcx, [ty::mk_int(tcx), closure_ty]);
26142617
let r = alloc_ty(bcx, ty);
@@ -2618,10 +2621,12 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
26182621
C_int(ccx, 2),
26192622
GEPi(bcx, r.val, [0, abi::box_rc_field_refcnt]));
26202623
(GEPi(bcx, r.val, [0, abi::box_rc_field_body]), r.val)
2624+
}
26212625
};
26222626

26232627
// Store bindings tydesc.
2624-
if copying {
2628+
alt mode {
2629+
for_closure. | for_send. {
26252630
let bound_tydesc = GEPi(bcx, closure, [0, abi::closure_elt_tydesc]);
26262631
let ti = none;
26272632
let bindings_tydesc =
@@ -2630,6 +2635,8 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
26302635
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
26312636
bcx = bindings_tydesc.bcx;
26322637
Store(bcx, bindings_tydesc.val, bound_tydesc);
2638+
}
2639+
for_block. {}
26332640
}
26342641

26352642
// Copy expr values into boxed bindings.
@@ -2651,12 +2658,15 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
26512658
temp_cleanups += [bound.val];
26522659
}
26532660
env_direct(val, ty, is_mem) {
2654-
if copying {
2661+
alt mode {
2662+
for_closure. | for_send. {
26552663
let val1 = is_mem ? load_if_immediate(bcx, val, ty) : val;
26562664
bcx = copy_val(bcx, INIT, bound.val, val1, ty);
2657-
} else {
2665+
}
2666+
for_block. {
26582667
let addr = is_mem ? val : do_spill_noroot(bcx, val);
26592668
Store(bcx, addr, bound.val);
2669+
}
26602670
}
26612671
}
26622672
}
@@ -2675,28 +2685,47 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
26752685
i = 0u;
26762686
for td: ValueRef in lltydescs {
26772687
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+
}
26792697
i += 1u;
26802698
}
26812699

26822700
ret {ptr: box, ptrty: closure_ty, bcx: bcx};
26832701
}
26842702

2703+
tag closure_constr_mode {
2704+
for_block;
2705+
for_closure;
2706+
for_send;
2707+
}
2708+
26852709
// Given a context and a list of upvars, build a closure. This just
26862710
// 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} {
26892715
// If we need to, package up the iterator body to call
26902716
let env_vals = [];
26912717
// Package up the upvars
26922718
for def in *upvars {
26932719
let lv = trans_local_var(cx, def);
26942720
let nid = ast_util::def_id_of_def(def).node;
26952721
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+
}
26972726
env_vals += [env_direct(lv.val, ty, lv.kind == owned)];
26982727
}
2699-
ret build_environment(cx, copy cx.fcx.lltydescs, env_vals, copying);
2728+
ret build_environment(cx, copy cx.fcx.lltydescs, env_vals, mode);
27002729
}
27012730

27022731
// 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)
27342763
// and a list of upvars, generate code to load and populate the environment
27352764
// with the upvars and type descriptors.
27362765
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) {
27382767
let bcx = new_raw_block_ctxt(fcx, fcx.llloadenv);
27392768

27402769
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,
27692798
let upvarptr = GEP_tup_like(bcx, ty, llclosure, path + [i as int]);
27702799
bcx = upvarptr.bcx;
27712800
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+
}
27732805
let def_id = ast_util::def_id_of_def(upvar_def);
27742806
fcx.llupvars.insert(def_id.node, llupvarptr);
27752807
i += 1u;
@@ -3532,7 +3564,8 @@ fn trans_bind_1(cx: @block_ctxt, outgoing_fty: ty::t,
35323564

35333565
// Actually construct the closure
35343566
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);
35363569
bcx = closure.bcx;
35373570

35383571
// Make thunk

trunk/src/rt/rust_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,8 @@ struct type_desc {
279279
const type_desc *descs[];
280280
};
281281

282+
extern "C" type_desc *rust_clone_type_desc(type_desc*);
283+
282284
#include "circular_buffer.h"
283285
#include "rust_task.h"
284286
#include "rust_port.h"

trunk/src/rt/rust_upcall.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,39 @@ upcall_shared_free(void* ptr) {
195195
SWITCH_STACK(&args, upcall_s_shared_free);
196196
}
197197

198+
struct s_clone_type_desc_args {
199+
const type_desc *td;
200+
type_desc *res;
201+
};
202+
203+
void upcall_s_clone_type_desc(s_clone_type_desc_args *args)
204+
{
205+
// Copy the main part of the type descriptor:
206+
const type_desc *td = args->td;
207+
int n_descs = td->n_descs;
208+
size_t sz = sizeof(type_desc) + sizeof(type_desc*) * n_descs;
209+
args->res = (type_desc*) malloc(sz);
210+
memcpy(args->res, td, sizeof(type_desc));
211+
212+
// Recursively copy any referenced descriptors:
213+
for (int i = 0; i < n_descs; i++) {
214+
s_clone_type_desc_args rec_args = { td->descs[i], 0 };
215+
upcall_s_clone_type_desc(&rec_args);
216+
args->res->descs[i] = rec_args.res;
217+
}
218+
}
219+
220+
/**
221+
* Called to deep-clone type descriptors so they can be attached to a sendable
222+
* function. Eventually this should perhaps move to a centralized hashtable.
223+
*/
224+
type_desc *
225+
upcall_clone_type_desc(type_desc *td) {
226+
s_clone_type_desc_args args = { td, 0 };
227+
SWITCH_STACK(&args, upcall_s_clone_type_desc);
228+
return args.res;
229+
}
230+
198231
struct s_get_type_desc_args {
199232
type_desc *retval;
200233
size_t size;

0 commit comments

Comments
 (0)