Skip to content

Commit 263f4c5

Browse files
committed
add tydescs into shape, rewrite walk_fn_contents()
1 parent e55aa6e commit 263f4c5

File tree

9 files changed

+108
-86
lines changed

9 files changed

+108
-86
lines changed

src/comp/middle/trans.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -959,9 +959,9 @@ fn trans_stack_local_derived_tydesc(cx: @block_ctxt, llsz: ValueRef,
959959
ret llmyroottydesc;
960960
}
961961

962-
// Objects and closures store their type parameters differently (in the object
963-
// or closure itself rather than in the type descriptor).
964-
tag ty_param_storage { tps_normal; tps_obj(uint); tps_fn(uint); }
962+
// Objects store their type parameters differently (in the object itself
963+
// rather than in the type descriptor).
964+
tag ty_param_storage { tps_normal; tps_obj(uint); }
965965

966966
fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
967967
storage: ty_param_storage,
@@ -980,7 +980,7 @@ fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
980980
let is_obj_body;
981981
alt storage {
982982
tps_normal. { is_obj_body = false; }
983-
tps_obj(_) | tps_fn(_) { is_obj_body = true; }
983+
tps_obj(_) { is_obj_body = true; }
984984
}
985985

986986
bcx_ccx(cx).stats.n_derived_tydescs += 1u;
@@ -1028,7 +1028,6 @@ fn get_derived_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool,
10281028
alt storage {
10291029
tps_normal. { obj_params = 0u; }
10301030
tps_obj(np) { obj_params = np; }
1031-
tps_fn(np) { obj_params = 0x80000000u | np; }
10321031
}
10331032

10341033
let v;

src/comp/middle/trans_closure.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -314,16 +314,8 @@ fn store_environment(
314314
let bound_tydesc = GEPi(bcx, llbox, [0, abi::cbox_elt_tydesc]);
315315
let ti = none;
316316

317-
// NDM I believe this is the correct value,
318-
// but using it exposes bugs and limitations
319-
// in the shape code. Therefore, I am using
320-
// tps_normal, which is what we used before.
321-
//
322-
// let tps = tps_fn(vec::len(lltyparams));
323-
324-
let tps = tps_normal;
325317
let {result:closure_td, _} =
326-
trans::get_tydesc(bcx, cbox_ty, true, tps, ti);
318+
trans::get_tydesc(bcx, cbox_ty, true, tps_normal, ti);
327319
trans::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_take_glue, ti);
328320
trans::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
329321
trans::lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);

src/rt/rust_cc.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ class mark : public shape::data<mark,shape::ptr> {
357357
case shape::SHAPE_BOX_FN: {
358358
// Record an irc for the environment box, but don't descend
359359
// into it since it will be walked via the box's allocation
360-
shape::data<mark,shape::ptr>::walk_fn_contents1(dp);
360+
shape::data<mark,shape::ptr>::walk_fn_contents1(dp, false);
361361
break;
362362
}
363363
case shape::SHAPE_BARE_FN: // Does not close over data.
@@ -552,15 +552,14 @@ class sweep : public shape::data<sweep,shape::ptr> {
552552
fn_env_pair pair = *(fn_env_pair*)dp;
553553

554554
// free closed over data:
555-
//
556-
// FIXME--this is a bit sketchy, since there is an
557-
// embedded tydesc that we will be using to walk the
558-
// data, but it will be freed as we walk. In the
559-
// generated code we pull this desc out and free it
560-
// later. We may well want to do the same. However,
561-
// since all we use from the descr. is the "shape", I
562-
// think we're ok.
563-
shape::data<sweep,shape::ptr>::walk_fn_contents1(dp);
555+
shape::data<sweep,shape::ptr>::walk_fn_contents1(dp, true);
556+
557+
// now free the embedded type descr:
558+
//
559+
// see comment in walk_fn_contents1() concerning null_td
560+
// to understand why this does not occur during the normal
561+
// walk.
562+
upcall_s_free_shared_type_desc((type_desc*)pair.env->td);
564563

565564
// now free the ptr:
566565
task->kernel->free(pair.env);

src/rt/rust_shape.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,7 @@ type_param::make(const type_desc **tydescs, unsigned n_tydescs,
4444
return ptrs;
4545
}
4646

47-
// Constructs type parameters from a function shape. This is a bit messy,
48-
// because it requires that the function shape have a specific format.
49-
type_param *
50-
type_param::from_fn_shape(rust_opaque_closure *env, arena &arena) {
51-
unsigned n_tydescs = env->td->n_obj_params & 0x7fffffff;
52-
return make(env->captured_tds, n_tydescs, arena);
53-
}
54-
55-
// Constructs type parameters from an object shape. This is also a bit messy,
47+
// Constructs type parameters from an object shape. This is a bit messy,
5648
// because it requires that the object shape have a specific format.
5749
type_param *
5850
type_param::from_obj_shape(const uint8_t *sp, ptr dp, arena &arena) {
@@ -354,6 +346,10 @@ class cmp : public data<cmp,ptr_pair> {
354346
data<cmp,ptr_pair>::walk_box_contents1();
355347
}
356348

349+
void walk_tydesc2(char) {
350+
cmp_pointer();
351+
}
352+
357353
void walk_fn2(char) { return cmp_two_pointers(); }
358354
void walk_obj2() { return cmp_two_pointers(); }
359355

src/rt/rust_shape.h

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,6 @@ class type_param {
306306
const rust_shape_tables *tables;
307307
const type_param *params; // subparameters
308308

309-
// Constructs type parameters from a function shape.
310-
static type_param *from_fn_shape(rust_opaque_closure *env, arena &arena);
311309
// Creates type parameters from an object shape description.
312310
static type_param *from_obj_shape(const uint8_t *sp, ptr dp,
313311
arena &arena);
@@ -326,8 +324,8 @@ class type_param {
326324
// have to actually have the data pointer, since we don't statically
327325
// know from the type of an object or function which type parameters
328326
// it closes over.
329-
assert(!tydesc->n_obj_params && "Type-parametric objects and "
330-
"functions must go through from_tydesc_and_data() instead!");
327+
assert(!tydesc->n_obj_params && "Type-parametric objects "
328+
"must go through from_tydesc_and_data() instead!");
331329

332330
return make(tydesc->first_param, tydesc->n_params, arena);
333331
}
@@ -337,20 +335,11 @@ class type_param {
337335
if (tydesc->n_obj_params) {
338336
uintptr_t n_obj_params = tydesc->n_obj_params;
339337
const type_desc **first_param;
340-
if (n_obj_params & 0x80000000) {
341-
// Function closure.
342-
DPRINT("n_obj_params FN %lu, tydesc %p, starting at %p\n",
343-
(unsigned long)n_obj_params, tydesc,
344-
dp + sizeof(uintptr_t) + tydesc->size);
345-
n_obj_params &= 0x7fffffff;
346-
first_param = (const type_desc **)(dp + sizeof(uintptr_t));
347-
} else {
348-
// Object closure.
349-
DPRINT("n_obj_params OBJ %lu, tydesc %p, starting at %p\n",
350-
(unsigned long)n_obj_params, tydesc,
351-
dp + sizeof(uintptr_t) * 2);
352-
first_param = (const type_desc **)(dp + sizeof(uintptr_t) * 2);
353-
}
338+
// Object closure.
339+
DPRINT("n_obj_params OBJ %lu, tydesc %p, starting at %p\n",
340+
(unsigned long)n_obj_params, tydesc,
341+
dp + sizeof(uintptr_t) * 2);
342+
first_param = (const type_desc **)(dp + sizeof(uintptr_t) * 2);
354343
return make(first_param, n_obj_params, arena);
355344
}
356345

@@ -852,7 +841,7 @@ class data : public ctxt< data<T,U> > {
852841

853842
void walk_box_contents1();
854843
void walk_uniq_contents1();
855-
void walk_fn_contents1(ptr &dp);
844+
void walk_fn_contents1(ptr &dp, bool null_td);
856845
void walk_obj_contents1(ptr &dp);
857846
void walk_iface_contents1(ptr &dp);
858847
void walk_variant1(tag_info &tinfo, tag_variant_t variant);
@@ -1008,20 +997,40 @@ data<T,U>::walk_tag1(tag_info &tinfo) {
1008997

1009998
template<typename T,typename U>
1010999
void
1011-
data<T,U>::walk_fn_contents1(ptr &dp) {
1000+
data<T,U>::walk_fn_contents1(ptr &dp, bool null_td) {
10121001
fn_env_pair pair = bump_dp<fn_env_pair>(dp);
10131002
if (!pair.env)
10141003
return;
10151004

10161005
arena arena;
1017-
type_param *params =
1018-
type_param::from_fn_shape(pair.env, arena);
10191006
const type_desc *closure_td = pair.env->td;
1007+
type_param *params =
1008+
type_param::from_tydesc(closure_td, arena);
10201009
ptr closure_dp((uintptr_t)pair.env);
10211010
T sub(*static_cast<T *>(this), closure_td->shape, params,
10221011
closure_td->shape_tables, closure_dp);
10231012
sub.align = true;
1013+
1014+
if (null_td) {
1015+
// if null_td flag is true, null out the type descr from
1016+
// the data structure while we walk. This is used in cycle
1017+
// collector when we are sweeping up data. The idea is that
1018+
// we are using the information in the embedded type desc to
1019+
// walk the contents, so we do not want to free it during that
1020+
// walk. This is not *strictly* necessary today because
1021+
// type_param::from_tydesc() actually pulls out the "shape"
1022+
// string and other information and copies it into a new
1023+
// location that is unaffected by the free. But it seems
1024+
// safer, particularly as this pulling out of information will
1025+
// not cope with nested, derived type descriptors.
1026+
pair.env->td = NULL;
1027+
}
1028+
10241029
sub.walk();
1030+
1031+
if (null_td) {
1032+
pair.env->td = closure_td;
1033+
}
10251034
}
10261035

10271036
template<typename T,typename U>
@@ -1138,7 +1147,7 @@ class log : public data<log,ptr> {
11381147
void walk_fn2(char kind) {
11391148
out << prefix << "fn";
11401149
prefix = "";
1141-
data<log,ptr>::walk_fn_contents1(dp);
1150+
data<log,ptr>::walk_fn_contents1(dp, false);
11421151
}
11431152

11441153
void walk_obj2() {

src/rt/rust_upcall.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,14 @@ void upcall_s_free_shared_type_desc(type_desc *td)
283283
rust_task *task = rust_scheduler::get_task();
284284
LOG_UPCALL_ENTRY(task);
285285

286-
// Recursively free any referenced descriptors:
287-
for (unsigned i = 0; i < td->n_params; i++) {
288-
upcall_s_free_shared_type_desc((type_desc*) td->first_param[i]);
289-
}
286+
if (td) {
287+
// Recursively free any referenced descriptors:
288+
for (unsigned i = 0; i < td->n_params; i++) {
289+
upcall_s_free_shared_type_desc((type_desc*) td->first_param[i]);
290+
}
290291

291-
task->kernel->free(td);
292+
task->kernel->free(td);
293+
}
292294
}
293295

294296
extern "C" CDECL void

src/test/run-pass/uniq-cc-generic.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
tag maybe_pointy {
2+
none;
3+
p(@pointy);
4+
}
5+
6+
type pointy = {
7+
mutable a : maybe_pointy,
8+
d : sendfn() -> uint,
9+
};
10+
11+
fn make_uniq_closure<A:send>(a: A) -> sendfn() -> uint {
12+
sendfn() -> uint { ptr::addr_of(a) as uint }
13+
}
14+
15+
fn empty_pointy() -> @pointy {
16+
ret @{
17+
mutable a : none,
18+
d : make_uniq_closure("hi")
19+
}
20+
}
21+
22+
fn main()
23+
{
24+
let v = empty_pointy();
25+
v.a = p(v);
26+
}

src/test/run-pass/uniq-cc.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
tag maybe_pointy {
2+
none;
3+
p(@pointy);
4+
}
5+
6+
type pointy = {
7+
mutable a : maybe_pointy,
8+
c : ~int,
9+
d : sendfn()->(),
10+
};
11+
12+
fn empty_pointy() -> @pointy {
13+
ret @{
14+
mutable a : none,
15+
c : ~22,
16+
d : sendfn()->(){},
17+
}
18+
}
19+
20+
fn main()
21+
{
22+
let v = empty_pointy();
23+
v.a = p(v);
24+
}

src/test/run-pass/uniq-fn-leak.rs

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)