From e55aa6e5ef60369710d8b2e6f512b2ef84a8c548 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 11 Jan 2012 21:31:36 -0800 Subject: free uniq data we encounter on the sweep, walk thru them otherwise --- src/rt/rust_cc.cpp | 225 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 159 insertions(+), 66 deletions(-) (limited to 'src/rt/rust_cc.cpp') diff --git a/src/rt/rust_cc.cpp b/src/rt/rust_cc.cpp index 06a66366f78..1f99fe98f71 100644 --- a/src/rt/rust_cc.cpp +++ b/src/rt/rust_cc.cpp @@ -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 { 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(dp) == NULL) return; // There can't be any outbound pointers from this. @@ -86,47 +89,63 @@ class irc : public shape::data { } } - void walk_tag(shape::tag_info &tinfo, uint32_t tag_variant) { - shape::data::walk_variant(tinfo, tag_variant); + void walk_tag2(shape::tag_info &tinfo, uint32_t tag_variant) { + shape::data::walk_variant1(tinfo, tag_variant); } - void walk_box() { - shape::data::walk_box_contents(); + void walk_box2() { + shape::data::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(dp); - shape::ptr ref_count_dp(box_ptr); - maybe_record_irc(ref_count_dp); + void walk_uniq2() { + shape::data::walk_uniq_contents1(); + } + + 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(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_obj() { + void walk_obj2() { dp += sizeof(void *); // skip vtable uint8_t *box_ptr = shape::bump_dp(dp); shape::ptr ref_count_dp(box_ptr); maybe_record_irc(ref_count_dp); } - void walk_iface() { - //shape::data::walk_iface_contents(dp); - shape::data::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 { } } - 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 variant_ptr_and_end); template - 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 - variant_ptr_and_end) { +irc::walk_variant2(shape::tag_info &tinfo, uint32_t variant_id, + const std::pair + 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 { 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(dp) == NULL) return; // There can't be any outbound pointers from this. @@ -321,23 +340,39 @@ class mark : public shape::data { } } - void walk_tag(shape::tag_info &tinfo, uint32_t tag_variant) { - shape::data::walk_variant(tinfo, tag_variant); + void walk_tag2(shape::tag_info &tinfo, uint32_t tag_variant) { + shape::data::walk_variant1(tinfo, tag_variant); } - void walk_box() { - shape::data::walk_box_contents(); + void walk_box2() { + shape::data::walk_box_contents1(); } - void walk_fn() { - shape::data::walk_fn_contents(dp); + void walk_uniq2() { + shape::data::walk_uniq_contents1(); } - void walk_obj() { - shape::data::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::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::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 { } } - void walk_subcontext(mark &sub) { sub.walk(); } + void walk_iface2() { + walk_box2(); + } + + void walk_tydesc2(char) { + } - void walk_box_contents(mark &sub, shape::ptr &ref_count_dp) { + 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 { 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 variant_ptr_and_end); template - inline void walk_number() { /* no-op */ } + inline void walk_number2() { /* no-op */ } public: static void do_mark(rust_task *task, const std::vector &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 variant_ptr_and_end) { mark sub(*this, variant_ptr_and_end.first, tinfo.params); @@ -470,13 +514,13 @@ class sweep : public shape::data { : shape::data(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(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 &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 { } } - void walk_tag(shape::tag_info &tinfo, uint32_t tag_variant) { - shape::data::walk_variant(tinfo, tag_variant); - } - - void walk_box() { - shape::data::walk_box_contents(); + void walk_tag2(shape::tag_info &tinfo, uint32_t tag_variant) { + shape::data::walk_variant1(tinfo, tag_variant); + } + + void walk_uniq2() { + void *x = *((void **)dp); + // free contents first: + shape::data::walk_uniq_contents1(); + // now free the ptr: + task->kernel->free(x); + } + + void walk_box2() { + shape::data::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::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(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_fn() { + void walk_obj2() { return; } - void walk_obj() { - return; + void walk_iface2() { + walk_box2(); } - void walk_iface() { - //shape::data::walk_iface_contents(dp); - shape::data::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_uniq_contents2(sweep &sub) { sub.walk(); } - void walk_box_contents(sweep &sub, shape::ptr &ref_count_dp) { + 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 variant_ptr_and_end) { sweep sub(*this, variant_ptr_and_end.first, tinfo.params); @@ -542,7 +635,7 @@ class sweep : public shape::data { } template - inline void walk_number() { /* no-op */ } + inline void walk_number2() { /* no-op */ } public: static void do_sweep(rust_task *task, const std::set &marked); -- cgit 1.4.1-3-g733a5