Skip to content

Commit a9c46e2

Browse files
committed
Don't put the target in the bind closure if it is statically known. Closes rust-lang#177.
1 parent 2f61848 commit a9c46e2

File tree

1 file changed

+33
-19
lines changed

1 file changed

+33
-19
lines changed

src/comp/middle/trans.rs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4212,7 +4212,9 @@ fn trans_cast(cx: &@block_ctxt, e: &@ast::expr, id: ast::node_id) -> result {
42124212
fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t,
42134213
outgoing_fty: &ty::t, args: &[option::t[@ast::expr]],
42144214
env_ty: &ty::t, bound_tys: &[ty::t],
4215-
ty_param_count: uint) -> {val: ValueRef, ty: TypeRef} {
4215+
ty_param_count: uint,
4216+
target_fn: &option::t[ValueRef]) ->
4217+
{val: ValueRef, ty: TypeRef} {
42164218

42174219
// Here we're not necessarily constructing a thunk in the sense of
42184220
// "function with no arguments". The result of compiling 'bind f(foo,
@@ -4270,16 +4272,22 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t,
42704272
// creating. (In our running example, target is the function f.) Pick
42714273
// out the pointer to the target function from the environment. The
42724274
// target function lives in the first binding spot.
4273-
let lltarget =
4274-
GEP_tup_like(bcx, closure_ty, llclosure,
4275-
~[0, abi::box_rc_field_body,
4276-
abi::closure_elt_bindings, 0]);
4277-
bcx = lltarget.bcx;
4275+
let (lltarget, starting_idx) = alt target_fn {
4276+
some(lltarget) { (lltarget, 0) }
4277+
none. {
4278+
let lltarget =
4279+
GEP_tup_like(bcx, closure_ty, llclosure,
4280+
~[0, abi::box_rc_field_body,
4281+
abi::closure_elt_bindings, 0]);
4282+
bcx = lltarget.bcx;
4283+
(lltarget.val, 1)
4284+
}
4285+
};
42784286

42794287
// And then, pick out the target function's own environment. That's what
42804288
// we'll use as the environment the thunk gets.
42814289
let lltargetclosure =
4282-
bcx.build.GEP(lltarget.val, ~[C_int(0), C_int(abi::fn_field_box)]);
4290+
bcx.build.GEP(lltarget, ~[C_int(0), C_int(abi::fn_field_box)]);
42834291
lltargetclosure = bcx.build.Load(lltargetclosure);
42844292

42854293
// Get f's return type, which will also be the return type of the entire
@@ -4315,7 +4323,7 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t,
43154323
}
43164324

43174325
let a: uint = 3u; // retptr, task ptr, env come first
4318-
let b: int = 1;
4326+
let b: int = starting_idx;
43194327
let outgoing_arg_index: uint = 0u;
43204328
let llout_arg_tys: [TypeRef] =
43214329
type_of_explicit_args(cx.ccx, sp, outgoing_args);
@@ -4377,7 +4385,7 @@ fn trans_bind_thunk(cx: &@local_ctxt, sp: &span, incoming_fty: &ty::t,
43774385
}
43784386

43794387
let lltargetfn =
4380-
bcx.build.GEP(lltarget.val, ~[C_int(0), C_int(abi::fn_field_code)]);
4388+
bcx.build.GEP(lltarget, ~[C_int(0), C_int(abi::fn_field_code)]);
43814389

43824390
// Cast the outgoing function to the appropriate type.
43834391
// This is necessary because the type of the function that we have
@@ -4427,16 +4435,21 @@ fn trans_bind_1(cx: &@block_ctxt, f: &@ast::expr, f_res: &lval_result,
44274435
}
44284436
let bcx = f_res.res.bcx;
44294437

4430-
// Cast the function we are binding to be the type that the closure
4431-
// will expect it to have. The type the closure knows about has the
4432-
// type parameters substituted with the real types.
4433-
let llclosurety = T_ptr(type_of(bcx_ccx(cx), cx.sp, outgoing_fty));
4434-
let src_loc = bcx.build.PointerCast(f_res.res.val, llclosurety);
4435-
let bound_f = {res: {bcx: bcx, val: src_loc} with f_res};
44364438

4437-
// Arrange for the bound function to live in the first binding spot.
4438-
let bound_tys: [ty::t] = ~[outgoing_fty];
4439-
let bound_vals: [lval_result] = ~[bound_f];
4439+
// Arrange for the bound function to live in the first binding spot
4440+
// if the function is not statically known.
4441+
let (bound_tys, bound_vals, target_res) = if f_res.is_mem {
4442+
// Cast the function we are binding to be the type that the closure
4443+
// will expect it to have. The type the closure knows about has the
4444+
// type parameters substituted with the real types.
4445+
let llclosurety = T_ptr(type_of(bcx_ccx(cx), cx.sp, outgoing_fty));
4446+
let src_loc = bcx.build.PointerCast(f_res.res.val, llclosurety);
4447+
let bound_f = {res: {bcx: bcx, val: src_loc} with f_res};
4448+
(~[outgoing_fty], ~[bound_f], none)
4449+
} else {
4450+
(~[], ~[], some(f_res.res.val))
4451+
};
4452+
44404453
// Translate the bound expressions.
44414454
for e: @ast::expr in bound {
44424455
let lv = trans_lval(bcx, e);
@@ -4455,7 +4468,8 @@ fn trans_bind_1(cx: &@block_ctxt, f: &@ast::expr, f_res: &lval_result,
44554468
let pair_ty = node_id_type(bcx_ccx(cx), id);
44564469
let llthunk =
44574470
trans_bind_thunk(cx.fcx.lcx, cx.sp, pair_ty, outgoing_fty_real,
4458-
args, closure.ptrty, bound_tys, ty_param_count);
4471+
args, closure.ptrty, bound_tys, ty_param_count,
4472+
target_res);
44594473

44604474
// Construct the function pair
44614475
let pair_v = create_real_fn_pair(bcx, llthunk.ty, llthunk.val,

0 commit comments

Comments
 (0)