Skip to content

Commit 22ba9dd

Browse files
committed
---
yaml --- r: 4085 b: refs/heads/master c: 0cacbe9 h: refs/heads/master i: 4083: c74d2d7 v: v3
1 parent 4146edc commit 22ba9dd

File tree

3 files changed

+40
-27
lines changed

3 files changed

+40
-27
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: 2bf50114eb18a434c143b51beb9b4dc3ce9400ea
2+
refs/heads/master: 0cacbe901d0defe79188b08e6b8d224456a34653

trunk/src/comp/middle/freevars.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@ import syntax::codemap::span;
1616
export annotate_freevars;
1717
export freevar_set;
1818
export freevar_map;
19+
export get_freevar_info;
1920
export get_freevars;
21+
export get_freevar_uses;
2022
export has_freevars;
2123
export is_freevar_of;
2224
export def_lookup;
2325

24-
type freevar_set = @ast::node_id[];
25-
type freevar_map = hashmap[ast::node_id, freevar_set];
26+
type freevar_set = hashset[ast::node_id];
27+
type freevar_info = rec(freevar_set defs, @ast::node_id[] uses);
28+
type freevar_map = hashmap[ast::node_id, freevar_info];
2629

2730
// Searches through part of the AST for all references to locals or
2831
// upvars in this frame and returns the list of definition IDs thus found.
@@ -31,7 +34,7 @@ type freevar_map = hashmap[ast::node_id, freevar_set];
3134
// in order to start the search.
3235
fn collect_freevars(&resolve::def_map def_map, &session::session sess,
3336
&fn (&walk::ast_visitor) walker,
34-
ast::node_id[] initial_decls) -> freevar_set {
37+
ast::node_id[] initial_decls) -> freevar_info {
3538
type env =
3639
@rec(mutable ast::node_id[] refs,
3740
hashset[ast::node_id] decls,
@@ -50,9 +53,9 @@ fn collect_freevars(&resolve::def_map def_map, &session::session sess,
5053
"internal error in collect_freevars");
5154
}
5255
alt (e.def_map.get(expr.id)) {
53-
case (ast::def_arg(?did)) { e.refs += ~[did._1]; }
54-
case (ast::def_local(?did)) { e.refs += ~[did._1]; }
55-
case (ast::def_binding(?did)) { e.refs += ~[did._1]; }
56+
case (ast::def_arg(?did)) { e.refs += ~[expr.id]; }
57+
case (ast::def_local(?did)) { e.refs += ~[expr.id]; }
58+
case (ast::def_binding(?did)) { e.refs += ~[expr.id]; }
5659
case (_) { /* no-op */ }
5760
}
5861
}
@@ -87,12 +90,19 @@ fn collect_freevars(&resolve::def_map def_map, &session::session sess,
8790
walker(*visitor);
8891

8992
// Calculate (refs - decls). This is the set of captured upvars.
90-
auto result = ~[];
93+
// We build a vec of the node ids of the uses and a set of the
94+
// node ids of the definitions.
95+
auto uses = ~[];
96+
auto defs = new_int_hash();
9197
for (ast::node_id ref_id_ in e.refs) {
9298
auto ref_id = ref_id_;
93-
if (!decls.contains_key(ref_id)) { result += ~[ref_id]; }
99+
auto def_id = ast::def_id_of_def(def_map.get(ref_id))._1;
100+
if !decls.contains_key(def_id) {
101+
uses += ~[ref_id];
102+
set_add(defs, def_id);
103+
}
94104
}
95-
ret @result;
105+
ret rec(defs=defs, uses=@uses);
96106
}
97107

98108
// Build a map from every function and for-each body to a set of the
@@ -136,19 +146,25 @@ fn annotate_freevars(&session::session sess, &resolve::def_map def_map,
136146
ret e.freevars;
137147
}
138148

139-
fn get_freevars(&ty::ctxt tcx, ast::node_id fid) -> freevar_set {
149+
fn get_freevar_info(&ty::ctxt tcx, ast::node_id fid) -> freevar_info {
140150
alt (tcx.freevars.find(fid)) {
141151
none {
142152
fail "get_freevars: " + int::str(fid) + " has no freevars";
143153
}
144154
some(?d) { ret d; }
145155
}
146156
}
157+
fn get_freevars(&ty::ctxt tcx, ast::node_id fid) -> freevar_set {
158+
ret get_freevar_info(tcx, fid).defs;
159+
}
160+
fn get_freevar_uses(&ty::ctxt tcx, ast::node_id fid) -> @ast::node_id[] {
161+
ret get_freevar_info(tcx, fid).uses;
162+
}
147163
fn has_freevars(&ty::ctxt tcx, ast::node_id fid) -> bool {
148-
ret ivec::len(*get_freevars(tcx, fid)) != 0u;
164+
ret get_freevars(tcx, fid).size() != 0u;
149165
}
150166
fn is_freevar_of(&ty::ctxt tcx, ast::node_id var, ast::node_id f) -> bool {
151-
ret ivec::member(var, *get_freevars(tcx, f));
167+
ret get_freevars(tcx, f).contains_key(var);
152168
}
153169
fn def_lookup(&ty::ctxt tcx, ast::node_id f, ast::node_id id) ->
154170
option::t[ast::def] {

trunk/src/comp/middle/trans.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3792,29 +3792,28 @@ fn find_variable(&@fn_ctxt fcx, ast::node_id nid) -> ValueRef {
37923792
// Given a block context and a list of upvars, construct a closure that
37933793
// contains pointers to all of the upvars and all of the tydescs in
37943794
// scope. Return the ValueRef and TypeRef corresponding to the closure.
3795-
fn build_environment(&@block_ctxt cx, &ast::node_id[] upvars) ->
3795+
fn build_environment(&@block_ctxt cx, &freevar_set upvars) ->
37963796
rec(ValueRef ptr, TypeRef ptrty) {
3797-
auto upvar_count = std::ivec::len(upvars);
37983797
auto has_iterbody = !option::is_none(cx.fcx.lliterbody);
3799-
if (has_iterbody) { upvar_count += 1u; }
38003798
auto llbindingsptr;
38013799

3802-
if (upvar_count > 0u) {
3800+
if (upvars.size() > 0u || has_iterbody) {
38033801
// Gather up the upvars.
38043802
let ValueRef[] llbindings = ~[];
38053803
let TypeRef[] llbindingtys = ~[];
38063804
if (has_iterbody) {
38073805
llbindings += ~[option::get(cx.fcx.lliterbody)];
38083806
llbindingtys += ~[val_ty(llbindings.(0))];
38093807
}
3810-
for (ast::node_id nid in upvars) {
3808+
for each (ast::node_id nid in upvars.keys()) {
38113809
auto llbinding = find_variable(cx.fcx, nid);
38123810
llbindings += ~[llbinding];
38133811
llbindingtys += ~[val_ty(llbinding)];
38143812
}
38153813

38163814
// Create an array of bindings and copy in aliases to the upvars.
38173815
llbindingsptr = alloca(cx, T_struct(llbindingtys));
3816+
auto upvar_count = std::ivec::len(llbindings);
38183817
auto i = 0u;
38193818
while (i < upvar_count) {
38203819
auto llbindingptr =
@@ -3859,7 +3858,7 @@ fn build_environment(&@block_ctxt cx, &ast::node_id[] upvars) ->
38593858
// and a list of upvars, generate code to load and populate the environment
38603859
// with the upvars and type descriptors.
38613860
fn load_environment(&@block_ctxt cx, &@fn_ctxt fcx,
3862-
TypeRef llenvptrty, &ast::node_id[] upvars) {
3861+
TypeRef llenvptrty, &freevar_set upvars) {
38633862
auto copy_args_bcx = new_raw_block_ctxt(fcx, fcx.llcopyargs);
38643863

38653864
// Populate the upvars from the environment.
@@ -3871,22 +3870,20 @@ fn load_environment(&@block_ctxt cx, &@fn_ctxt fcx,
38713870
C_int(abi::closure_elt_bindings)]);
38723871
auto llremotebindingsptr =
38733872
copy_args_bcx.build.Load(llremotebindingsptrptr);
3874-
auto base = 0u;
3873+
38753874
auto i = 0u;
3876-
auto end = std::ivec::len(upvars);
38773875
if (!option::is_none(cx.fcx.lliterbody)) {
3878-
base += 1u;
3876+
i += 1u;
38793877
auto lliterbodyptr =
38803878
copy_args_bcx.build.GEP(llremotebindingsptr,
38813879
~[C_int(0), C_int(0)]);
38823880
auto lliterbody = copy_args_bcx.build.Load(lliterbodyptr);
38833881
fcx.lliterbody = some(lliterbody);
38843882
}
3885-
while (i < end) {
3886-
auto upvar_id = upvars.(i);
3883+
for each (ast::node_id upvar_id in upvars.keys()) {
38873884
auto llupvarptrptr =
38883885
copy_args_bcx.build.GEP(llremotebindingsptr,
3889-
~[C_int(0), C_int(base+i as int)]);
3886+
~[C_int(0), C_int(i as int)]);
38903887
auto llupvarptr = copy_args_bcx.build.Load(llupvarptrptr);
38913888
fcx.llupvars.insert(upvar_id, llupvarptr);
38923889
i += 1u;
@@ -3943,7 +3940,7 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
39433940
auto decl_id = local.node.id;
39443941
auto upvars = get_freevars(lcx.ccx.tcx, body.node.id);
39453942

3946-
auto llenv = build_environment(cx, *upvars);
3943+
auto llenv = build_environment(cx, upvars);
39473944

39483945
// Step 2: Declare foreach body function.
39493946
let str s =
@@ -3964,7 +3961,7 @@ fn trans_for_each(&@block_ctxt cx, &@ast::local local, &@ast::expr seq,
39643961

39653962
// Generate code to load the environment out of the
39663963
// environment pointer.
3967-
load_environment(cx, fcx, llenv.ptrty, *upvars);
3964+
load_environment(cx, fcx, llenv.ptrty, upvars);
39683965

39693966
// Add an upvar for the loop variable alias.
39703967
fcx.llupvars.insert(decl_id, llvm::LLVMGetParam(fcx.llfn, 3u));

0 commit comments

Comments
 (0)