free uniq data we encounter on the sweep, walk thru them otherwise

This commit is contained in:
Niko Matsakis 2012-01-11 21:31:36 -08:00
parent f4a3a3b878
commit e55aa6e5ef
6 changed files with 431 additions and 260 deletions

View File

@ -46,13 +46,18 @@ const shape_vec: u8 = 11u8;
const shape_tag: u8 = 12u8;
const shape_box: u8 = 13u8;
const shape_struct: u8 = 17u8;
const shape_fn: u8 = 18u8;
const shape_box_fn: u8 = 18u8;
const shape_obj: u8 = 19u8;
const shape_res: u8 = 20u8;
const shape_var: u8 = 21u8;
const shape_uniq: u8 = 22u8;
const shape_opaque_closure_ptr: u8 = 23u8; // the closure itself.
const shape_iface: u8 = 24u8;
const shape_uniq_fn: u8 = 25u8;
const shape_stack_fn: u8 = 26u8;
const shape_bare_fn: u8 = 27u8;
const shape_tydesc: u8 = 28u8;
const shape_send_tydesc: u8 = 29u8;
// FIXME: This is a bad API in trans_common.
fn C_u8(n: u8) -> ValueRef { ret trans_common::C_u8(n as uint); }
@ -267,6 +272,14 @@ fn s_variant_tag_t(tcx: ty_ctxt) -> u8 {
ret s_int(tcx);
}
fn s_tydesc(_tcx: ty_ctxt) -> u8 {
ret shape_tydesc;
}
fn s_send_tydesc(_tcx: ty_ctxt) -> u8 {
ret shape_send_tydesc;
}
fn mk_ctxt(llmod: ModuleRef) -> ctxt {
let llshapetablesty = trans_common::T_named_struct("shapes");
let llshapetables =
@ -305,8 +318,10 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint],
ty::ty_bot. { s += [shape_u8]; }
ty::ty_int(ast::ty_i.) { s += [s_int(ccx.tcx)]; }
ty::ty_float(ast::ty_f.) { s += [s_float(ccx.tcx)]; }
ty::ty_uint(ast::ty_u.) | ty::ty_ptr(_) | ty::ty_type. |
ty::ty_send_type. | ty::ty_native(_) { s += [s_uint(ccx.tcx)]; }
ty::ty_uint(ast::ty_u.) | ty::ty_ptr(_) |
ty::ty_native(_) { s += [s_uint(ccx.tcx)]; }
ty::ty_type. { s += [s_tydesc(ccx.tcx)]; }
ty::ty_send_type. { s += [s_send_tydesc(ccx.tcx)]; }
ty::ty_int(ast::ty_i8.) { s += [shape_i8]; }
ty::ty_uint(ast::ty_u16.) { s += [shape_u16]; }
ty::ty_int(ast::ty_i16.) { s += [shape_i16]; }
@ -418,8 +433,17 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint],
}
}
}
ty::ty_fn(_) {
s += [shape_fn];
ty::ty_fn({proto: ast::proto_box., _}) {
s += [shape_box_fn];
}
ty::ty_fn({proto: ast::proto_uniq., _}) {
s += [shape_uniq_fn];
}
ty::ty_fn({proto: ast::proto_block., _}) {
s += [shape_stack_fn];
}
ty::ty_fn({proto: ast::proto_bare., _}) {
s += [shape_bare_fn];
}
ty::ty_opaque_closure_ptr(_) {
s += [shape_opaque_closure_ptr];

View File

@ -18,6 +18,9 @@
// collection.
#define RUST_CC_FREQUENCY 5000
// defined in rust_upcall.cpp:
void upcall_s_free_shared_type_desc(type_desc *td);
namespace cc {
// Internal reference count computation
@ -70,7 +73,7 @@ class irc : public shape::data<irc,shape::ptr> {
in_tables, in_data),
ircs(in_ircs) {}
void walk_vec(bool is_pod, uint16_t sp_size) {
void walk_vec2(bool is_pod, uint16_t sp_size) {
if (is_pod || shape::get_dp<void *>(dp) == NULL)
return; // There can't be any outbound pointers from this.
@ -86,47 +89,63 @@ class irc : public shape::data<irc,shape::ptr> {
}
}
void walk_tag(shape::tag_info &tinfo, uint32_t tag_variant) {
shape::data<irc,shape::ptr>::walk_variant(tinfo, tag_variant);
void walk_tag2(shape::tag_info &tinfo, uint32_t tag_variant) {
shape::data<irc,shape::ptr>::walk_variant1(tinfo, tag_variant);
}
void walk_box() {
shape::data<irc,shape::ptr>::walk_box_contents();
void walk_box2() {
shape::data<irc,shape::ptr>::walk_box_contents1();
}
void walk_fn() {
// Record an irc for the environment box, but don't descend
// into it since it will be walked via the box's allocation
dp += sizeof(void *); // skip code pointer
uint8_t * box_ptr = shape::bump_dp<uint8_t *>(dp);
shape::ptr ref_count_dp(box_ptr);
maybe_record_irc(ref_count_dp);
void walk_uniq2() {
shape::data<irc,shape::ptr>::walk_uniq_contents1();
}
void walk_obj() {
void walk_fn2(char code) {
switch (code) {
case shape::SHAPE_BOX_FN: {
// Record an irc for the environment box, but don't descend
// into it since it will be walked via the box's allocation
shape::bump_dp<void*>(dp); // skip over the code ptr
walk_box2(); // walk over the environment ptr
break;
}
case shape::SHAPE_BARE_FN: // Does not close over data.
case shape::SHAPE_STACK_FN: // Not reachable from heap.
case shape::SHAPE_UNIQ_FN: break; /* Can only close over sendable
* (and hence acyclic) data */
default: abort();
}
}
void walk_obj2() {
dp += sizeof(void *); // skip vtable
uint8_t *box_ptr = shape::bump_dp<uint8_t *>(dp);
shape::ptr ref_count_dp(box_ptr);
maybe_record_irc(ref_count_dp);
}
void walk_iface() {
//shape::data<irc,shape::ptr>::walk_iface_contents(dp);
shape::data<irc,shape::ptr>::walk_box_contents();
void walk_iface2() {
walk_box2();
}
void walk_res(const shape::rust_fn *dtor, unsigned n_params,
const shape::type_param *params, const uint8_t *end_sp,
bool live) {
void walk_tydesc2(char) {
}
void walk_res2(const shape::rust_fn *dtor, unsigned n_params,
const shape::type_param *params, const uint8_t *end_sp,
bool live) {
while (this->sp != end_sp) {
this->walk();
align = true;
}
}
void walk_subcontext(irc &sub) { sub.walk(); }
void walk_subcontext2(irc &sub) { sub.walk(); }
void walk_box_contents(irc &sub, shape::ptr &ref_count_dp) {
void walk_uniq_contents2(irc &sub) { sub.walk(); }
void walk_box_contents2(irc &sub, shape::ptr &ref_count_dp) {
maybe_record_irc(ref_count_dp);
// Do not traverse the contents of this box; it's in the allocation
@ -153,28 +172,28 @@ class irc : public shape::data<irc,shape::ptr> {
}
}
void walk_struct(const uint8_t *end_sp) {
void walk_struct2(const uint8_t *end_sp) {
while (this->sp != end_sp) {
this->walk();
align = true;
}
}
void walk_variant(shape::tag_info &tinfo, uint32_t variant_id,
void walk_variant2(shape::tag_info &tinfo, uint32_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end);
template<typename T>
inline void walk_number() { /* no-op */ }
inline void walk_number2() { /* no-op */ }
public:
static void compute_ircs(rust_task *task, irc_map &ircs);
};
void
irc::walk_variant(shape::tag_info &tinfo, uint32_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
irc::walk_variant2(shape::tag_info &tinfo, uint32_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
irc sub(*this, variant_ptr_and_end.first, tinfo.params);
assert(variant_id < 256); // FIXME: Temporary sanity check.
@ -305,7 +324,7 @@ class mark : public shape::data<mark,shape::ptr> {
in_tables, in_data),
marked(in_marked) {}
void walk_vec(bool is_pod, uint16_t sp_size) {
void walk_vec2(bool is_pod, uint16_t sp_size) {
if (is_pod || shape::get_dp<void *>(dp) == NULL)
return; // There can't be any outbound pointers from this.
@ -321,23 +340,39 @@ class mark : public shape::data<mark,shape::ptr> {
}
}
void walk_tag(shape::tag_info &tinfo, uint32_t tag_variant) {
shape::data<mark,shape::ptr>::walk_variant(tinfo, tag_variant);
void walk_tag2(shape::tag_info &tinfo, uint32_t tag_variant) {
shape::data<mark,shape::ptr>::walk_variant1(tinfo, tag_variant);
}
void walk_box() {
shape::data<mark,shape::ptr>::walk_box_contents();
void walk_box2() {
shape::data<mark,shape::ptr>::walk_box_contents1();
}
void walk_fn() {
shape::data<mark,shape::ptr>::walk_fn_contents(dp);
void walk_uniq2() {
shape::data<mark,shape::ptr>::walk_uniq_contents1();
}
void walk_obj() {
shape::data<mark,shape::ptr>::walk_obj_contents(dp);
void walk_fn2(char code) {
switch (code) {
case shape::SHAPE_BOX_FN: {
// Record an irc for the environment box, but don't descend
// into it since it will be walked via the box's allocation
shape::data<mark,shape::ptr>::walk_fn_contents1(dp);
break;
}
case shape::SHAPE_BARE_FN: // Does not close over data.
case shape::SHAPE_STACK_FN: // Not reachable from heap.
case shape::SHAPE_UNIQ_FN: break; /* Can only close over sendable
* (and hence acyclic) data */
default: abort();
}
}
void walk_res(const shape::rust_fn *dtor, unsigned n_params,
void walk_obj2() {
shape::data<mark,shape::ptr>::walk_obj_contents1(dp);
}
void walk_res2(const shape::rust_fn *dtor, unsigned n_params,
const shape::type_param *params, const uint8_t *end_sp,
bool live) {
while (this->sp != end_sp) {
@ -346,9 +381,18 @@ class mark : public shape::data<mark,shape::ptr> {
}
}
void walk_subcontext(mark &sub) { sub.walk(); }
void walk_iface2() {
walk_box2();
}
void walk_box_contents(mark &sub, shape::ptr &ref_count_dp) {
void walk_tydesc2(char) {
}
void walk_subcontext2(mark &sub) { sub.walk(); }
void walk_uniq_contents2(mark &sub) { sub.walk(); }
void walk_box_contents2(mark &sub, shape::ptr &ref_count_dp) {
if (!ref_count_dp)
return;
@ -359,19 +403,19 @@ class mark : public shape::data<mark,shape::ptr> {
sub.walk();
}
void walk_struct(const uint8_t *end_sp) {
void walk_struct2(const uint8_t *end_sp) {
while (this->sp != end_sp) {
this->walk();
align = true;
}
}
void walk_variant(shape::tag_info &tinfo, uint32_t variant_id,
void walk_variant2(shape::tag_info &tinfo, uint32_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end);
template<typename T>
inline void walk_number() { /* no-op */ }
inline void walk_number2() { /* no-op */ }
public:
static void do_mark(rust_task *task, const std::vector<void *> &roots,
@ -379,7 +423,7 @@ public:
};
void
mark::walk_variant(shape::tag_info &tinfo, uint32_t variant_id,
mark::walk_variant2(shape::tag_info &tinfo, uint32_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
mark sub(*this, variant_ptr_and_end.first, tinfo.params);
@ -470,13 +514,13 @@ class sweep : public shape::data<sweep,shape::ptr> {
: shape::data<sweep,shape::ptr>(in_task, in_align, in_sp,
in_params, in_tables, in_data) {}
void walk_vec(bool is_pod, uint16_t sp_size) {
void walk_vec2(bool is_pod, uint16_t sp_size) {
void *vec = shape::get_dp<void *>(dp);
walk_vec(is_pod, get_vec_data_range(dp));
walk_vec2(is_pod, get_vec_data_range(dp));
task->kernel->free(vec);
}
void walk_vec(bool is_pod,
void walk_vec2(bool is_pod,
const std::pair<shape::ptr,shape::ptr> &data_range) {
sweep sub(*this, data_range.first);
shape::ptr data_end = sub.end_dp = data_range.second;
@ -486,50 +530,99 @@ class sweep : public shape::data<sweep,shape::ptr> {
}
}
void walk_tag(shape::tag_info &tinfo, uint32_t tag_variant) {
shape::data<sweep,shape::ptr>::walk_variant(tinfo, tag_variant);
void walk_tag2(shape::tag_info &tinfo, uint32_t tag_variant) {
shape::data<sweep,shape::ptr>::walk_variant1(tinfo, tag_variant);
}
void walk_box() {
shape::data<sweep,shape::ptr>::walk_box_contents();
void walk_uniq2() {
void *x = *((void **)dp);
// free contents first:
shape::data<sweep,shape::ptr>::walk_uniq_contents1();
// now free the ptr:
task->kernel->free(x);
}
void walk_fn() {
void walk_box2() {
shape::data<sweep,shape::ptr>::walk_box_contents1();
}
void walk_fn2(char code) {
switch (code) {
case shape::SHAPE_UNIQ_FN: {
fn_env_pair pair = *(fn_env_pair*)dp;
// free closed over data:
//
// FIXME--this is a bit sketchy, since there is an
// embedded tydesc that we will be using to walk the
// data, but it will be freed as we walk. In the
// generated code we pull this desc out and free it
// later. We may well want to do the same. However,
// since all we use from the descr. is the "shape", I
// think we're ok.
shape::data<sweep,shape::ptr>::walk_fn_contents1(dp);
// now free the ptr:
task->kernel->free(pair.env);
break;
}
case shape::SHAPE_BOX_FN: {
// the box will be visited separately:
shape::bump_dp<void*>(dp); // skip over the code ptr
walk_box2(); // walk over the environment ptr
break;
}
case shape::SHAPE_BARE_FN: // Does not close over data.
case shape::SHAPE_STACK_FN: break; // Not reachable from heap.
default: abort();
}
}
void walk_obj2() {
return;
}
void walk_obj() {
return;
void walk_iface2() {
walk_box2();
}
void walk_iface() {
//shape::data<sweep,shape::ptr>::walk_iface_contents(dp);
shape::data<sweep,shape::ptr>::walk_box_contents();
void walk_tydesc2(char kind) {
type_desc *td = *(type_desc **)dp;
switch(kind) {
case shape::SHAPE_TYDESC:
break;
case shape::SHAPE_SEND_TYDESC:
upcall_s_free_shared_type_desc(td);
break;
default: abort();
}
}
void walk_res(const shape::rust_fn *dtor, unsigned n_params,
const shape::type_param *params, const uint8_t *end_sp,
bool live) {
void walk_res2(const shape::rust_fn *dtor, unsigned n_params,
const shape::type_param *params, const uint8_t *end_sp,
bool live) {
while (this->sp != end_sp) {
this->walk();
align = true;
}
}
void walk_subcontext(sweep &sub) { sub.walk(); }
void walk_subcontext2(sweep &sub) { sub.walk(); }
void walk_box_contents(sweep &sub, shape::ptr &ref_count_dp) {
void walk_uniq_contents2(sweep &sub) { sub.walk(); }
void walk_box_contents2(sweep &sub, shape::ptr &ref_count_dp) {
return;
}
void walk_struct(const uint8_t *end_sp) {
void walk_struct2(const uint8_t *end_sp) {
while (this->sp != end_sp) {
this->walk();
align = true;
}
}
void walk_variant(shape::tag_info &tinfo, uint32_t variant_id,
void walk_variant2(shape::tag_info &tinfo, uint32_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
sweep sub(*this, variant_ptr_and_end.first, tinfo.params);
@ -542,7 +635,7 @@ class sweep : public shape::data<sweep,shape::ptr> {
}
template<typename T>
inline void walk_number() { /* no-op */ }
inline void walk_number2() { /* no-op */ }
public:
static void do_sweep(rust_task *task, const std::set<void *> &marked);

View File

@ -73,7 +73,7 @@ type_param::from_obj_shape(const uint8_t *sp, ptr dp, arena &arena) {
// A shape printer, useful for debugging
void
print::walk_tag(tag_info &tinfo) {
print::walk_tag1(tag_info &tinfo) {
DPRINT("tag%u", tinfo.tag_id);
if (!tinfo.n_params)
return;
@ -94,7 +94,7 @@ print::walk_tag(tag_info &tinfo) {
}
void
print::walk_struct(const uint8_t *end_sp) {
print::walk_struct1(const uint8_t *end_sp) {
DPRINT("(");
bool first = true;
@ -110,8 +110,8 @@ print::walk_struct(const uint8_t *end_sp) {
}
void
print::walk_res(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp) {
print::walk_res1(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp) {
DPRINT("res@%p", dtor);
// Print type parameters.
@ -151,7 +151,7 @@ print::walk_res(const rust_fn *dtor, unsigned n_params,
}
void
print::walk_var(uint8_t param_index) {
print::walk_var1(uint8_t param_index) {
DPRINT("%c=", 'T' + param_index);
const type_param *param = &params[param_index];
@ -160,25 +160,25 @@ print::walk_var(uint8_t param_index) {
}
template<>
void print::walk_number<uint8_t>() { DPRINT("u8"); }
void print::walk_number1<uint8_t>() { DPRINT("u8"); }
template<>
void print::walk_number<uint16_t>() { DPRINT("u16"); }
void print::walk_number1<uint16_t>() { DPRINT("u16"); }
template<>
void print::walk_number<uint32_t>() { DPRINT("u32"); }
void print::walk_number1<uint32_t>() { DPRINT("u32"); }
template<>
void print::walk_number<uint64_t>() { DPRINT("u64"); }
void print::walk_number1<uint64_t>() { DPRINT("u64"); }
template<>
void print::walk_number<int8_t>() { DPRINT("i8"); }
void print::walk_number1<int8_t>() { DPRINT("i8"); }
template<>
void print::walk_number<int16_t>() { DPRINT("i16"); }
void print::walk_number1<int16_t>() { DPRINT("i16"); }
template<>
void print::walk_number<int32_t>() { DPRINT("i32"); }
void print::walk_number1<int32_t>() { DPRINT("i32"); }
template<>
void print::walk_number<int64_t>() { DPRINT("i64"); }
void print::walk_number1<int64_t>() { DPRINT("i64"); }
template<>
void print::walk_number<float>() { DPRINT("f32"); }
void print::walk_number1<float>() { DPRINT("f32"); }
template<>
void print::walk_number<double>() { DPRINT("f64"); }
void print::walk_number1<double>() { DPRINT("f64"); }
void
@ -225,13 +225,13 @@ size_of::compute_tag_size(tag_info &tinfo) {
}
void
size_of::walk_tag(tag_info &tinfo) {
size_of::walk_tag1(tag_info &tinfo) {
compute_tag_size(*this, tinfo);
sa = tinfo.tag_sa;
}
void
size_of::walk_struct(const uint8_t *end_sp) {
size_of::walk_struct1(const uint8_t *end_sp) {
size_align struct_sa(0, 1);
bool first = true;
@ -264,21 +264,21 @@ class cmp : public data<cmp,ptr_pair> {
friend class data<cmp,ptr_pair>;
private:
void walk_vec(bool is_pod,
const std::pair<ptr_pair,ptr_pair> &data_range);
void walk_vec2(bool is_pod,
const std::pair<ptr_pair,ptr_pair> &data_range);
inline void walk_subcontext(cmp &sub) {
inline void walk_subcontext2(cmp &sub) {
sub.walk();
result = sub.result;
}
inline void walk_box_contents(cmp &sub, ptr_pair &ref_count_dp) {
inline void walk_box_contents2(cmp &sub, ptr_pair &ref_count_dp) {
sub.align = true;
sub.walk();
result = sub.result;
}
inline void walk_uniq_contents(cmp &sub) {
inline void walk_uniq_contents2(cmp &sub) {
sub.align = true;
sub.walk();
result = sub.result;
@ -338,32 +338,36 @@ public:
in_dp),
result(0) {}
void walk_vec(bool is_pod, uint16_t sp_size) {
walk_vec(is_pod, get_vec_data_range(dp));
void walk_vec2(bool is_pod, uint16_t sp_size) {
walk_vec2(is_pod, get_vec_data_range(dp));
}
void walk_box() {
data<cmp,ptr_pair>::walk_box_contents();
void walk_box2() {
data<cmp,ptr_pair>::walk_box_contents1();
}
void walk_uniq() {
data<cmp,ptr_pair>::walk_uniq_contents();
void walk_uniq2() {
data<cmp,ptr_pair>::walk_uniq_contents1();
}
void walk_fn() { return cmp_two_pointers(); }
void walk_obj() { return cmp_two_pointers(); }
void walk_iface2() {
data<cmp,ptr_pair>::walk_box_contents1();
}
void walk_tag(tag_info &tinfo, const data_pair<tag_variant_t> &tag_variants);
void walk_struct(const uint8_t *end_sp);
void walk_res(const rust_fn *dtor, uint16_t n_ty_params,
const type_param *ty_params_sp, const uint8_t *end_sp,
const data_pair<uintptr_t> &live);
void walk_variant(tag_info &tinfo, tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end);
void walk_fn2(char) { return cmp_two_pointers(); }
void walk_obj2() { return cmp_two_pointers(); }
void walk_tag2(tag_info &tinfo, const data_pair<tag_variant_t> &tag_variants);
void walk_struct2(const uint8_t *end_sp);
void walk_res2(const rust_fn *dtor, uint16_t n_ty_params,
const type_param *ty_params_sp, const uint8_t *end_sp,
const data_pair<uintptr_t> &live);
void walk_variant2(tag_info &tinfo, tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end);
template<typename T>
void walk_number() { cmp_number(get_dp<T>(dp)); }
void walk_number2() { cmp_number(get_dp<T>(dp)); }
};
template<>
@ -372,7 +376,7 @@ void cmp::cmp_number<int32_t>(const data_pair<int32_t> &nums) {
}
void
cmp::walk_vec(bool is_pod, const std::pair<ptr_pair,ptr_pair> &data_range) {
cmp::walk_vec2(bool is_pod, const std::pair<ptr_pair,ptr_pair> &data_range) {
cmp sub(*this, data_range.first);
ptr_pair data_end = sub.end_dp = data_range.second;
while (!result && sub.dp < data_end) {
@ -390,15 +394,15 @@ cmp::walk_vec(bool is_pod, const std::pair<ptr_pair,ptr_pair> &data_range) {
}
void
cmp::walk_tag(tag_info &tinfo, const data_pair<tag_variant_t> &tag_variants) {
cmp::walk_tag2(tag_info &tinfo, const data_pair<tag_variant_t> &tag_variants) {
cmp_number(tag_variants);
if (result != 0)
return;
data<cmp,ptr_pair>::walk_variant(tinfo, tag_variants.fst);
data<cmp,ptr_pair>::walk_variant1(tinfo, tag_variants.fst);
}
void
cmp::walk_struct(const uint8_t *end_sp) {
cmp::walk_struct2(const uint8_t *end_sp) {
while (!result && this->sp != end_sp) {
this->walk();
align = true;
@ -406,16 +410,16 @@ cmp::walk_struct(const uint8_t *end_sp) {
}
void
cmp::walk_res(const rust_fn *dtor, uint16_t n_ty_params,
cmp::walk_res2(const rust_fn *dtor, uint16_t n_ty_params,
const type_param *ty_params_sp, const uint8_t *end_sp,
const data_pair<uintptr_t> &live) {
abort(); // TODO
}
void
cmp::walk_variant(tag_info &tinfo, tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
cmp::walk_variant2(tag_info &tinfo, tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
cmp sub(*this, variant_ptr_and_end.first, tinfo.params);
const uint8_t *variant_end = variant_ptr_and_end.second;
@ -430,7 +434,7 @@ cmp::walk_variant(tag_info &tinfo, tag_variant_t variant_id,
// Polymorphic logging, for convenience
void
log::walk_string(const std::pair<ptr,ptr> &data) {
log::walk_string2(const std::pair<ptr,ptr> &data) {
out << prefix << "\"" << std::hex;
ptr subdp = data.first;
@ -447,7 +451,7 @@ log::walk_string(const std::pair<ptr,ptr> &data) {
}
void
log::walk_struct(const uint8_t *end_sp) {
log::walk_struct2(const uint8_t *end_sp) {
out << prefix << "(";
prefix = "";
@ -463,10 +467,10 @@ log::walk_struct(const uint8_t *end_sp) {
}
void
log::walk_vec(bool is_pod, const std::pair<ptr,ptr> &data) {
log::walk_vec2(bool is_pod, const std::pair<ptr,ptr> &data) {
if (peek() == SHAPE_U8) {
sp++; // It's a string. We handle this ourselves.
walk_string(data);
walk_string2(data);
return;
}
@ -485,9 +489,9 @@ log::walk_vec(bool is_pod, const std::pair<ptr,ptr> &data) {
}
void
log::walk_variant(tag_info &tinfo, tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
log::walk_variant2(tag_info &tinfo, tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end) {
log sub(*this, variant_ptr_and_end.first, tinfo.params);
const uint8_t *variant_end = variant_ptr_and_end.second;
@ -503,8 +507,8 @@ log::walk_variant(tag_info &tinfo, tag_variant_t variant_id,
}
void
log::walk_res(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp, bool live) {
log::walk_res2(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp, bool live) {
out << prefix << "res";
if (this->sp == end_sp)

View File

@ -46,12 +46,17 @@ const uint8_t SHAPE_VEC = 11u;
const uint8_t SHAPE_TAG = 12u;
const uint8_t SHAPE_BOX = 13u;
const uint8_t SHAPE_STRUCT = 17u;
const uint8_t SHAPE_FN = 18u;
const uint8_t SHAPE_BOX_FN = 18u;
const uint8_t SHAPE_OBJ = 19u;
const uint8_t SHAPE_RES = 20u;
const uint8_t SHAPE_VAR = 21u;
const uint8_t SHAPE_UNIQ = 22u;
const uint8_t SHAPE_IFACE = 24u;
const uint8_t SHAPE_UNIQ_FN = 25u;
const uint8_t SHAPE_STACK_FN = 26u;
const uint8_t SHAPE_BARE_FN = 27u;
const uint8_t SHAPE_TYDESC = 28u;
const uint8_t SHAPE_SEND_TYDESC = 29u;
#ifdef _LP64
const uint8_t SHAPE_PTR = SHAPE_U64;
@ -247,13 +252,13 @@ protected:
inline size_align get_size_align(const uint8_t *&addr);
private:
void walk_vec();
void walk_tag();
void walk_box();
void walk_uniq();
void walk_struct();
void walk_res();
void walk_var();
void walk_vec0();
void walk_tag0();
void walk_box0();
void walk_uniq0();
void walk_struct0();
void walk_res0();
void walk_var0();
};
@ -357,34 +362,40 @@ public:
// Traversals
#define WALK_NUMBER(c_type) \
static_cast<T *>(this)->template walk_number<c_type>()
static_cast<T *>(this)->template walk_number1<c_type>()
#define WALK_SIMPLE(method) static_cast<T *>(this)->method()
template<typename T>
void
ctxt<T>::walk() {
switch (*sp++) {
case SHAPE_U8: WALK_NUMBER(uint8_t); break;
case SHAPE_U16: WALK_NUMBER(uint16_t); break;
case SHAPE_U32: WALK_NUMBER(uint32_t); break;
case SHAPE_U64: WALK_NUMBER(uint64_t); break;
case SHAPE_I8: WALK_NUMBER(int8_t); break;
case SHAPE_I16: WALK_NUMBER(int16_t); break;
case SHAPE_I32: WALK_NUMBER(int32_t); break;
case SHAPE_I64: WALK_NUMBER(int64_t); break;
case SHAPE_F32: WALK_NUMBER(float); break;
case SHAPE_F64: WALK_NUMBER(double); break;
case SHAPE_VEC: walk_vec(); break;
case SHAPE_TAG: walk_tag(); break;
case SHAPE_BOX: walk_box(); break;
case SHAPE_STRUCT: walk_struct(); break;
case SHAPE_FN: WALK_SIMPLE(walk_fn); break;
case SHAPE_OBJ: WALK_SIMPLE(walk_obj); break;
case SHAPE_RES: walk_res(); break;
case SHAPE_VAR: walk_var(); break;
case SHAPE_UNIQ: walk_uniq(); break;
case SHAPE_IFACE: WALK_SIMPLE(walk_iface); break;
default: abort();
char s = *sp++;
switch (s) {
case SHAPE_U8: WALK_NUMBER(uint8_t); break;
case SHAPE_U16: WALK_NUMBER(uint16_t); break;
case SHAPE_U32: WALK_NUMBER(uint32_t); break;
case SHAPE_U64: WALK_NUMBER(uint64_t); break;
case SHAPE_I8: WALK_NUMBER(int8_t); break;
case SHAPE_I16: WALK_NUMBER(int16_t); break;
case SHAPE_I32: WALK_NUMBER(int32_t); break;
case SHAPE_I64: WALK_NUMBER(int64_t); break;
case SHAPE_F32: WALK_NUMBER(float); break;
case SHAPE_F64: WALK_NUMBER(double); break;
case SHAPE_VEC: walk_vec0(); break;
case SHAPE_TAG: walk_tag0(); break;
case SHAPE_BOX: walk_box0(); break;
case SHAPE_STRUCT: walk_struct0(); break;
case SHAPE_OBJ: WALK_SIMPLE(walk_obj1); break;
case SHAPE_RES: walk_res0(); break;
case SHAPE_VAR: walk_var0(); break;
case SHAPE_UNIQ: walk_uniq0(); break;
case SHAPE_IFACE: WALK_SIMPLE(walk_iface1); break;
case SHAPE_BOX_FN:
case SHAPE_UNIQ_FN:
case SHAPE_STACK_FN:
case SHAPE_BARE_FN: static_cast<T*>(this)->walk_fn1(s); break;
case SHAPE_SEND_TYDESC:
case SHAPE_TYDESC: static_cast<T*>(this)->walk_tydesc1(s); break;
default: abort();
}
}
@ -420,20 +431,20 @@ ctxt<T>::get_variant_sp(tag_info &tinfo, tag_variant_t variant_id) {
template<typename T>
void
ctxt<T>::walk_vec() {
ctxt<T>::walk_vec0() {
bool is_pod = *sp++;
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_vec(is_pod, sp_size);
static_cast<T *>(this)->walk_vec1(is_pod, sp_size);
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_tag() {
ctxt<T>::walk_tag0() {
tag_info tinfo;
tinfo.tag_id = get_u16_bump(sp);
@ -465,45 +476,45 @@ ctxt<T>::walk_tag() {
tinfo.params = params;
// Call to the implementation.
static_cast<T *>(this)->walk_tag(tinfo);
static_cast<T *>(this)->walk_tag1(tinfo);
}
template<typename T>
void
ctxt<T>::walk_box() {
ctxt<T>::walk_box0() {
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_box();
static_cast<T *>(this)->walk_box1();
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_uniq() {
ctxt<T>::walk_uniq0() {
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_uniq();
static_cast<T *>(this)->walk_uniq1();
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_struct() {
ctxt<T>::walk_struct0() {
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_struct(end_sp);
static_cast<T *>(this)->walk_struct1(end_sp);
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_res() {
ctxt<T>::walk_res0() {
uint16_t dtor_offset = get_u16_bump(sp);
const rust_fn **resources =
reinterpret_cast<const rust_fn **>(tables->resources);
@ -523,16 +534,16 @@ ctxt<T>::walk_res() {
uint16_t sp_size = get_u16_bump(sp);
const uint8_t *end_sp = sp + sp_size;
static_cast<T *>(this)->walk_res(dtor, n_ty_params, params, end_sp);
static_cast<T *>(this)->walk_res1(dtor, n_ty_params, params, end_sp);
sp = end_sp;
}
template<typename T>
void
ctxt<T>::walk_var() {
ctxt<T>::walk_var0() {
uint8_t param = *sp++;
static_cast<T *>(this)->walk_var(param);
static_cast<T *>(this)->walk_var1(param);
}
// A shape printer, useful for debugging
@ -553,26 +564,44 @@ public:
const rust_shape_tables *in_tables)
: ctxt<print>(in_task, in_align, in_sp, in_params, in_tables) {}
void walk_tag(tag_info &tinfo);
void walk_struct(const uint8_t *end_sp);
void walk_res(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp);
void walk_var(uint8_t param);
void walk_tag1(tag_info &tinfo);
void walk_struct1(const uint8_t *end_sp);
void walk_res1(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp);
void walk_var1(uint8_t param);
void walk_vec(bool is_pod, uint16_t sp_size) {
void walk_vec1(bool is_pod, uint16_t sp_size) {
DPRINT("vec<"); walk(); DPRINT(">");
}
void walk_box() {
DPRINT("box<"); walk(); DPRINT(">");
void walk_uniq1() {
DPRINT("~<"); walk(); DPRINT(">");
}
void walk_box1() {
DPRINT("@<"); walk(); DPRINT(">");
}
void walk_fn() { DPRINT("fn"); }
void walk_obj() { DPRINT("obj"); }
void walk_iface() { DPRINT("iface"); }
void walk_closure();
void walk_fn1(char kind) {
switch(kind) {
case SHAPE_BARE_FN: DPRINT("fn"); break;
case SHAPE_BOX_FN: DPRINT("fn@"); break;
case SHAPE_UNIQ_FN: DPRINT("fn~"); break;
case SHAPE_STACK_FN: DPRINT("fn&"); break;
default: abort();
}
}
void walk_obj1() { DPRINT("obj"); }
void walk_iface1() { DPRINT("iface"); }
void walk_tydesc1(char kind) {
switch(kind) {
case SHAPE_TYDESC: DPRINT("tydesc"); break;
case SHAPE_SEND_TYDESC: DPRINT("send-tydesc"); break;
default: abort();
}
}
template<typename T>
void walk_number() {}
void walk_number1() {}
template<typename T>
static void print_cx(const T *cx) {
@ -608,33 +637,35 @@ public:
const rust_shape_tables *in_tables = NULL)
: ctxt<size_of>(other, in_sp, in_params, in_tables) {}
void walk_tag(tag_info &tinfo);
void walk_struct(const uint8_t *end_sp);
void walk_tag1(tag_info &tinfo);
void walk_struct1(const uint8_t *end_sp);
void walk_box() { sa.set(sizeof(void *), sizeof(void *)); }
void walk_fn() { sa.set(sizeof(void *)*2, sizeof(void *)); }
void walk_obj() { sa.set(sizeof(void *)*2, sizeof(void *)); }
void walk_iface() { sa.set(sizeof(void *), sizeof(void *)); }
void walk_closure();
void walk_uniq1() { sa.set(sizeof(void *), sizeof(void *)); }
void walk_box1() { sa.set(sizeof(void *), sizeof(void *)); }
void walk_fn1(char) { sa.set(sizeof(void *)*2, sizeof(void *)); }
void walk_obj1() { sa.set(sizeof(void *)*2, sizeof(void *)); }
void walk_iface1() { sa.set(sizeof(void *), sizeof(void *)); }
void walk_tydesc1(char) { sa.set(sizeof(void *), sizeof(void *)); }
void walk_closure1();
void walk_vec(bool is_pod, uint16_t sp_size) {
void walk_vec1(bool is_pod, uint16_t sp_size) {
sa.set(sizeof(void *), sizeof(void *));
}
void walk_var(uint8_t param_index) {
void walk_var1(uint8_t param_index) {
const type_param *param = &params[param_index];
size_of sub(*this, param->shape, param->params, param->tables);
sub.walk();
sa = sub.sa;
}
void walk_res(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp) {
void walk_res1(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp) {
abort(); // TODO
}
template<typename T>
void walk_number() { sa.set(sizeof(T), alignof<T>()); }
void walk_number1() { sa.set(sizeof(T), alignof<T>()); }
void compute_tag_size(tag_info &tinfo);
@ -819,12 +850,12 @@ public:
protected:
U end_dp;
void walk_box_contents();
void walk_uniq_contents();
void walk_fn_contents(ptr &dp);
void walk_obj_contents(ptr &dp);
void walk_iface_contents(ptr &dp);
void walk_variant(tag_info &tinfo, tag_variant_t variant);
void walk_box_contents1();
void walk_uniq_contents1();
void walk_fn_contents1(ptr &dp);
void walk_obj_contents1(ptr &dp);
void walk_iface_contents1(ptr &dp);
void walk_variant1(tag_info &tinfo, tag_variant_t variant);
static std::pair<uint8_t *,uint8_t *> get_vec_data_range(ptr dp);
static std::pair<ptr_pair,ptr_pair> get_vec_data_range(ptr_pair &dp);
@ -840,87 +871,100 @@ public:
dp(in_dp),
end_dp() {}
void walk_tag(tag_info &tinfo);
void walk_tag1(tag_info &tinfo);
void walk_struct(const uint8_t *end_sp) {
static_cast<T *>(this)->walk_struct(end_sp);
void walk_struct1(const uint8_t *end_sp) {
static_cast<T *>(this)->walk_struct2(end_sp);
}
void walk_vec(bool is_pod, uint16_t sp_size) {
DATA_SIMPLE(void *, walk_vec(is_pod, sp_size));
void walk_vec1(bool is_pod, uint16_t sp_size) {
DATA_SIMPLE(void *, walk_vec2(is_pod, sp_size));
}
void walk_box() { DATA_SIMPLE(void *, walk_box()); }
void walk_box1() { DATA_SIMPLE(void *, walk_box2()); }
void walk_uniq() { DATA_SIMPLE(void *, walk_uniq()); }
void walk_uniq1() { DATA_SIMPLE(void *, walk_uniq2()); }
void walk_fn() {
void walk_fn1(char code) {
ALIGN_TO(alignof<void *>());
U next_dp = dp + sizeof(void *) * 2;
static_cast<T *>(this)->walk_fn();
static_cast<T *>(this)->walk_fn2(code);
dp = next_dp;
}
void walk_obj() {
void walk_obj1() {
ALIGN_TO(alignof<void *>());
U next_dp = dp + sizeof(void *) * 2;
static_cast<T *>(this)->walk_obj();
static_cast<T *>(this)->walk_obj2();
dp = next_dp;
}
void walk_iface() {
void walk_iface1() {
ALIGN_TO(alignof<void *>());
U next_dp = dp + sizeof(void *);
static_cast<T *>(this)->walk_iface();
static_cast<T *>(this)->walk_iface2();
dp = next_dp;
}
void walk_res(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp) {
void walk_tydesc1(char kind) {
ALIGN_TO(alignof<void *>());
U next_dp = dp + sizeof(void *);
static_cast<T *>(this)->walk_tydesc2(kind);
dp = next_dp;
}
void walk_res1(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp) {
typename U::template data<uintptr_t>::t live = bump_dp<uintptr_t>(dp);
// Delegate to the implementation.
static_cast<T *>(this)->walk_res(dtor, n_params, params, end_sp,
static_cast<T *>(this)->walk_res2(dtor, n_params, params, end_sp,
live);
}
void walk_var(uint8_t param_index) {
void walk_var1(uint8_t param_index) {
const type_param *param = &this->params[param_index];
T sub(*static_cast<T *>(this), param->shape, param->params,
param->tables);
static_cast<T *>(this)->walk_subcontext(sub);
static_cast<T *>(this)->walk_subcontext2(sub);
dp = sub.dp;
}
template<typename W>
void walk_number() { DATA_SIMPLE(W, walk_number<W>()); }
template<typename WN>
void walk_number1() {
//DATA_SIMPLE(W, walk_number2<W>());
ALIGN_TO(alignof<WN>());
U end_dp = dp + sizeof(WN);
T* t = static_cast<T *>(this);
t->template walk_number2<WN>();
dp = end_dp;
}
};
template<typename T,typename U>
void
data<T,U>::walk_box_contents() {
data<T,U>::walk_box_contents1() {
typename U::template data<uint8_t *>::t box_ptr = bump_dp<uint8_t *>(dp);
U ref_count_dp(box_ptr);
T sub(*static_cast<T *>(this), ref_count_dp + sizeof(ref_cnt_t));
static_cast<T *>(this)->walk_box_contents(sub, ref_count_dp);
static_cast<T *>(this)->walk_box_contents2(sub, ref_count_dp);
}
template<typename T,typename U>
void
data<T,U>::walk_uniq_contents() {
data<T,U>::walk_uniq_contents1() {
typename U::template data<uint8_t *>::t box_ptr = bump_dp<uint8_t *>(dp);
U data_ptr(box_ptr);
T sub(*static_cast<T *>(this), data_ptr);
static_cast<T *>(this)->walk_uniq_contents(sub);
static_cast<T *>(this)->walk_uniq_contents2(sub);
}
template<typename T,typename U>
void
data<T,U>::walk_variant(tag_info &tinfo, tag_variant_t variant_id) {
data<T,U>::walk_variant1(tag_info &tinfo, tag_variant_t variant_id) {
std::pair<const uint8_t *,const uint8_t *> variant_ptr_and_end =
this->get_variant_sp(tinfo, variant_id);
static_cast<T *>(this)->walk_variant(tinfo, variant_id,
variant_ptr_and_end);
static_cast<T *>(this)->walk_variant2(tinfo, variant_id,
variant_ptr_and_end);
}
template<typename T,typename U>
@ -943,7 +987,7 @@ data<T,U>::get_vec_data_range(ptr_pair &dp) {
template<typename T,typename U>
void
data<T,U>::walk_tag(tag_info &tinfo) {
data<T,U>::walk_tag1(tag_info &tinfo) {
size_of::compute_tag_size(*this, tinfo);
if (tinfo.variant_count > 1)
@ -957,14 +1001,14 @@ data<T,U>::walk_tag(tag_info &tinfo) {
else
tag_variant = 0;
static_cast<T *>(this)->walk_tag(tinfo, tag_variant);
static_cast<T *>(this)->walk_tag2(tinfo, tag_variant);
dp = end_dp;
}
template<typename T,typename U>
void
data<T,U>::walk_fn_contents(ptr &dp) {
data<T,U>::walk_fn_contents1(ptr &dp) {
fn_env_pair pair = bump_dp<fn_env_pair>(dp);
if (!pair.env)
return;
@ -982,7 +1026,7 @@ data<T,U>::walk_fn_contents(ptr &dp) {
template<typename T,typename U>
void
data<T,U>::walk_obj_contents(ptr &dp) {
data<T,U>::walk_obj_contents1(ptr &dp) {
dp += sizeof(void *); // Skip over the vtable.
uint8_t *box_ptr = bump_dp<uint8_t *>(dp);
@ -1003,7 +1047,7 @@ data<T,U>::walk_obj_contents(ptr &dp) {
template<typename T,typename U>
void
data<T,U>::walk_iface_contents(ptr &dp) {
data<T,U>::walk_iface_contents1(ptr &dp) {
uint8_t *box_ptr = bump_dp<uint8_t *>(dp);
if (!box_ptr) return;
U ref_count_dp(box_ptr);
@ -1017,7 +1061,7 @@ data<T,U>::walk_iface_contents(ptr &dp) {
T sub(*static_cast<T *>(this), valtydesc->shape + 5, NULL, NULL,
value_dp);
sub.align = true;
static_cast<T *>(this)->walk_box_contents(sub, ref_count_dp);
static_cast<T *>(this)->walk_box_contents2(sub, ref_count_dp);
}
// Polymorphic logging, for convenience
@ -1067,52 +1111,56 @@ private:
out(other.out),
prefix("") {}
void walk_vec(bool is_pod, uint16_t sp_size) {
void walk_vec2(bool is_pod, uint16_t sp_size) {
if (!get_dp<void *>(dp))
out << prefix << "(null)";
else
walk_vec(is_pod, get_vec_data_range(dp));
walk_vec2(is_pod, get_vec_data_range(dp));
}
void walk_tag(tag_info &tinfo, tag_variant_t tag_variant) {
void walk_tag2(tag_info &tinfo, tag_variant_t tag_variant) {
out << prefix << "tag" << tag_variant;
data<log,ptr>::walk_variant(tinfo, tag_variant);
data<log,ptr>::walk_variant1(tinfo, tag_variant);
}
void walk_box() {
void walk_box2() {
out << prefix << "@";
prefix = "";
data<log,ptr>::walk_box_contents();
data<log,ptr>::walk_box_contents1();
}
void walk_uniq() {
void walk_uniq2() {
out << prefix << "~";
prefix = "";
data<log,ptr>::walk_uniq_contents();
data<log,ptr>::walk_uniq_contents1();
}
void walk_fn() {
void walk_fn2(char kind) {
out << prefix << "fn";
prefix = "";
data<log,ptr>::walk_fn_contents(dp);
data<log,ptr>::walk_fn_contents1(dp);
}
void walk_obj() {
void walk_obj2() {
out << prefix << "obj";
prefix = "";
data<log,ptr>::walk_obj_contents(dp);
data<log,ptr>::walk_obj_contents1(dp);
}
void walk_iface() {
void walk_iface2() {
out << prefix << "iface(";
prefix = "";
data<log,ptr>::walk_iface_contents(dp);
data<log,ptr>::walk_iface_contents1(dp);
out << prefix << ")";
}
void walk_subcontext(log &sub) { sub.walk(); }
void walk_tydesc2(char kind) {
out << prefix << "tydesc";
}
void walk_box_contents(log &sub, ptr &ref_count_dp) {
void walk_subcontext2(log &sub) { sub.walk(); }
void walk_box_contents2(log &sub, ptr &ref_count_dp) {
out << prefix;
if (!ref_count_dp) {
out << "(null)";
@ -1122,23 +1170,23 @@ private:
}
}
void walk_uniq_contents(log &sub) {
void walk_uniq_contents2(log &sub) {
out << prefix;
sub.align = true;
sub.walk();
}
void walk_struct(const uint8_t *end_sp);
void walk_vec(bool is_pod, const std::pair<ptr,ptr> &data);
void walk_variant(tag_info &tinfo, tag_variant_t variant_id,
void walk_struct2(const uint8_t *end_sp);
void walk_vec2(bool is_pod, const std::pair<ptr,ptr> &data);
void walk_variant2(tag_info &tinfo, tag_variant_t variant_id,
const std::pair<const uint8_t *,const uint8_t *>
variant_ptr_and_end);
void walk_string(const std::pair<ptr,ptr> &data);
void walk_res(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp, bool live);
void walk_string2(const std::pair<ptr,ptr> &data);
void walk_res2(const rust_fn *dtor, unsigned n_params,
const type_param *params, const uint8_t *end_sp, bool live);
template<typename T>
inline void walk_number() {
inline void walk_number2() {
out << prefix;
fmt_number(out, get_dp<T>(dp));
}

View File

@ -279,7 +279,7 @@ upcall_create_shared_type_desc(type_desc *td) {
*/
void upcall_s_free_shared_type_desc(type_desc *td)
{
{ // n.b.: invoked from rust_cc.cpp as well as generated code
rust_task *task = rust_scheduler::get_task();
LOG_UPCALL_ENTRY(task);

View File

@ -6,12 +6,14 @@
type pointy = {
mutable a : maybe_pointy,
c : ~int,
d : sendfn()->(),
};
fn empty_pointy() -> @pointy {
ret @{
mutable a : none,
c : ~22,
d : sendfn()->(){},
}
}