diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-02-01 18:52:08 -0800 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-02-01 18:52:08 -0800 |
| commit | 196d69beb2c91b29013d44d7a3855561fef600ab (patch) | |
| tree | 01c3878cd9fea6364d8659da36fae42c2b69cfc8 /src/rt/rust_cc.cpp | |
| parent | 31166438063236e6d2ad021cf2169fce2b3839b4 (diff) | |
| download | rust-196d69beb2c91b29013d44d7a3855561fef600ab.tar.gz rust-196d69beb2c91b29013d44d7a3855561fef600ab.zip | |
make boxes self-describing (fixes #1493)" (take 2)
this will be used to generate a new snapshot.
Diffstat (limited to 'src/rt/rust_cc.cpp')
| -rw-r--r-- | src/rt/rust_cc.cpp | 202 |
1 files changed, 86 insertions, 116 deletions
diff --git a/src/rt/rust_cc.cpp b/src/rt/rust_cc.cpp index 78138434d73..60b0b8d2fd0 100644 --- a/src/rt/rust_cc.cpp +++ b/src/rt/rust_cc.cpp @@ -25,7 +25,7 @@ namespace cc { // Internal reference count computation -typedef std::map<void *,uintptr_t> irc_map; +typedef std::map<rust_opaque_box*,uintptr_t> irc_map; class irc : public shape::data<irc,shape::ptr> { friend class shape::data<irc,shape::ptr>; @@ -118,13 +118,6 @@ class irc : public shape::data<irc,shape::ptr> { } } - 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_iface2() { walk_box2(); } @@ -145,30 +138,32 @@ class irc : public shape::data<irc,shape::ptr> { 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); + void walk_box_contents2(irc &sub, shape::ptr &box_dp) { + maybe_record_irc(box_dp); // Do not traverse the contents of this box; it's in the allocation // somewhere, so we're guaranteed to come back to it (if we haven't // traversed it already). } - void maybe_record_irc(shape::ptr &ref_count_dp) { - if (!ref_count_dp) + void maybe_record_irc(shape::ptr &box_dp) { + if (!box_dp) return; + rust_opaque_box *box_ptr = (rust_opaque_box *) box_dp; + // Bump the internal reference count of the box. - if (ircs.find((void *)ref_count_dp) == ircs.end()) { + if (ircs.find(box_ptr) == ircs.end()) { LOG(task, gc, "setting internal reference count for %p to 1", - (void *)ref_count_dp); - ircs[(void *)ref_count_dp] = 1; + box_ptr); + ircs[box_ptr] = 1; } else { - uintptr_t newcount = ircs[(void *)ref_count_dp] + 1; + uintptr_t newcount = ircs[box_ptr] + 1; LOG(task, gc, "bumping internal reference count for %p to %lu", - (void *)ref_count_dp, newcount); - ircs[(void *)ref_count_dp] = newcount; + box_ptr, newcount); + ircs[box_ptr] = newcount; } } @@ -207,36 +202,25 @@ irc::walk_variant2(shape::tag_info &tinfo, uint32_t variant_id, void irc::compute_ircs(rust_task *task, irc_map &ircs) { - std::map<void *,const type_desc *>::iterator - begin(task->local_allocs.begin()), end(task->local_allocs.end()); - while (begin != end) { - uint8_t *p = reinterpret_cast<uint8_t *>(begin->first); - - const type_desc *tydesc = begin->second; - - LOG(task, gc, "determining internal ref counts: %p, tydesc=%p", p, - tydesc); - + boxed_region *boxed = &task->boxed; + for (rust_opaque_box *box = boxed->first_live_alloc(); + box != NULL; + box = box->next) { + type_desc *tydesc = box->td; + uint8_t *body = (uint8_t*) box_body(box); + + LOG(task, gc, + "determining internal ref counts: " + "box=%p tydesc=%p body=%p", + box, tydesc, body); + shape::arena arena; shape::type_param *params = - shape::type_param::from_tydesc_and_data(tydesc, p, arena); - -#if 0 - shape::print print(task, true, tydesc->shape, params, - tydesc->shape_tables); - print.walk(); - - shape::log log(task, true, tydesc->shape, params, - tydesc->shape_tables, p + sizeof(uintptr_t), - std::cerr); - log.walk(); -#endif + shape::type_param::from_tydesc_and_data(tydesc, body, arena); irc irc(task, true, tydesc->shape, params, tydesc->shape_tables, - p + sizeof(uintptr_t), ircs); + body, ircs); irc.walk(); - - ++begin; } } @@ -244,17 +228,17 @@ irc::compute_ircs(rust_task *task, irc_map &ircs) { // Root finding void -find_roots(rust_task *task, irc_map &ircs, std::vector<void *> &roots) { - std::map<void *,const type_desc *>::iterator - begin(task->local_allocs.begin()), end(task->local_allocs.end()); - while (begin != end) { - void *alloc = begin->first; - uintptr_t *ref_count_ptr = reinterpret_cast<uintptr_t *>(alloc); - uintptr_t ref_count = *ref_count_ptr; +find_roots(rust_task *task, irc_map &ircs, + std::vector<rust_opaque_box *> &roots) { + boxed_region *boxed = &task->boxed; + for (rust_opaque_box *box = boxed->first_live_alloc(); + box != NULL; + box = box->next) { + uintptr_t ref_count = box->ref_count; uintptr_t irc; - if (ircs.find(alloc) != ircs.end()) - irc = ircs[alloc]; + if (ircs.find(box) != ircs.end()) + irc = ircs[box]; else irc = 0; @@ -262,16 +246,14 @@ find_roots(rust_task *task, irc_map &ircs, std::vector<void *> &roots) { // This allocation must be a root, because the internal reference // count is smaller than the total reference count. LOG(task, gc,"root found: %p, irc %lu, ref count %lu", - alloc, irc, ref_count); - roots.push_back(alloc); + box, irc, ref_count); + roots.push_back(box); } else { LOG(task, gc, "nonroot found: %p, irc %lu, ref count %lu", - alloc, irc, ref_count); + box, irc, ref_count); assert(irc == ref_count && "Internal reference count must be " "less than or equal to the total reference count!"); } - - ++begin; } } @@ -281,7 +263,7 @@ find_roots(rust_task *task, irc_map &ircs, std::vector<void *> &roots) { class mark : public shape::data<mark,shape::ptr> { friend class shape::data<mark,shape::ptr>; - std::set<void *> &marked; + std::set<rust_opaque_box *> &marked; mark(const mark &other, const shape::ptr &in_dp) : shape::data<mark,shape::ptr>(other.task, other.align, other.sp, @@ -319,7 +301,7 @@ class mark : public shape::data<mark,shape::ptr> { const shape::type_param *in_params, const rust_shape_tables *in_tables, uint8_t *in_data, - std::set<void *> &in_marked) + std::set<rust_opaque_box*> &in_marked) : shape::data<mark,shape::ptr>(in_task, in_align, in_sp, in_params, in_tables, in_data), marked(in_marked) {} @@ -357,7 +339,7 @@ class mark : public shape::data<mark,shape::ptr> { 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, false); + shape::data<mark,shape::ptr>::walk_fn_contents1(); break; } case shape::SHAPE_BARE_FN: // Does not close over data. @@ -368,10 +350,6 @@ class mark : public shape::data<mark,shape::ptr> { } } - 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) { @@ -392,14 +370,16 @@ class mark : public shape::data<mark,shape::ptr> { void walk_uniq_contents2(mark &sub) { sub.walk(); } - void walk_box_contents2(mark &sub, shape::ptr &ref_count_dp) { - if (!ref_count_dp) + void walk_box_contents2(mark &sub, shape::ptr &box_dp) { + if (!box_dp) return; - if (marked.find((void *)ref_count_dp) != marked.end()) + rust_opaque_box *box_ptr = (rust_opaque_box *) box_dp; + + if (marked.find(box_ptr) != marked.end()) return; // Skip to avoid chasing cycles. - marked.insert((void *)ref_count_dp); + marked.insert(box_ptr); sub.walk(); } @@ -418,8 +398,9 @@ class mark : public shape::data<mark,shape::ptr> { inline void walk_number2() { /* no-op */ } public: - static void do_mark(rust_task *task, const std::vector<void *> &roots, - std::set<void *> &marked); + static void do_mark(rust_task *task, + const std::vector<rust_opaque_box *> &roots, + std::set<rust_opaque_box*> &marked); }; void @@ -438,35 +419,28 @@ mark::walk_variant2(shape::tag_info &tinfo, uint32_t variant_id, } void -mark::do_mark(rust_task *task, const std::vector<void *> &roots, - std::set<void *> &marked) { - std::vector<void *>::const_iterator begin(roots.begin()), - end(roots.end()); +mark::do_mark(rust_task *task, + const std::vector<rust_opaque_box *> &roots, + std::set<rust_opaque_box *> &marked) { + std::vector<rust_opaque_box *>::const_iterator + begin(roots.begin()), + end(roots.end()); while (begin != end) { - void *alloc = *begin; - if (marked.find(alloc) == marked.end()) { - marked.insert(alloc); + rust_opaque_box *box = *begin; + if (marked.find(box) == marked.end()) { + marked.insert(box); - const type_desc *tydesc = task->local_allocs[alloc]; + const type_desc *tydesc = box->td; - LOG(task, gc, "marking: %p, tydesc=%p", alloc, tydesc); + LOG(task, gc, "marking: %p, tydesc=%p", box, tydesc); - uint8_t *p = reinterpret_cast<uint8_t *>(alloc); + uint8_t *p = (uint8_t*) box_body(box); shape::arena arena; shape::type_param *params = shape::type_param::from_tydesc_and_data(tydesc, p, arena); -#if 0 - // We skip over the reference count here. - shape::log log(task, true, tydesc->shape, params, - tydesc->shape_tables, p + sizeof(uintptr_t), - std::cerr); - log.walk(); -#endif - - // We skip over the reference count here. mark mark(task, true, tydesc->shape, params, tydesc->shape_tables, - p + sizeof(uintptr_t), marked); + p, marked); mark.walk(); } @@ -552,13 +526,9 @@ class sweep : public shape::data<sweep,shape::ptr> { fn_env_pair pair = *(fn_env_pair*)dp; // free closed over data: - shape::data<sweep,shape::ptr>::walk_fn_contents1(dp, true); + shape::data<sweep,shape::ptr>::walk_fn_contents1(); // now free the embedded type descr: - // - // see comment in walk_fn_contents1() concerning null_td - // to understand why this does not occur during the normal - // walk. upcall_s_free_shared_type_desc((type_desc*)pair.env->td); // now free the ptr: @@ -610,7 +580,7 @@ class sweep : public shape::data<sweep,shape::ptr> { void walk_uniq_contents2(sweep &sub) { sub.walk(); } - void walk_box_contents2(sweep &sub, shape::ptr &ref_count_dp) { + void walk_box_contents2(sweep &sub, shape::ptr &box_dp) { return; } @@ -637,50 +607,50 @@ class sweep : public shape::data<sweep,shape::ptr> { inline void walk_number2() { /* no-op */ } public: - static void do_sweep(rust_task *task, const std::set<void *> &marked); + static void do_sweep(rust_task *task, + const std::set<rust_opaque_box*> &marked); }; void -sweep::do_sweep(rust_task *task, const std::set<void *> &marked) { - std::map<void *,const type_desc *>::iterator - begin(task->local_allocs.begin()), end(task->local_allocs.end()); - while (begin != end) { - void *alloc = begin->first; - - if (marked.find(alloc) == marked.end()) { - LOG(task, gc, "object is part of a cycle: %p", alloc); - - const type_desc *tydesc = begin->second; - uint8_t *p = reinterpret_cast<uint8_t *>(alloc); +sweep::do_sweep(rust_task *task, + const std::set<rust_opaque_box*> &marked) { + boxed_region *boxed = &task->boxed; + rust_opaque_box *box = boxed->first_live_alloc(); + while (box != NULL) { + // save next ptr as we may be freeing box + rust_opaque_box *box_next = box->next; + if (marked.find(box) == marked.end()) { + LOG(task, gc, "object is part of a cycle: %p", box); + + const type_desc *tydesc = box->td; + uint8_t *p = (uint8_t*) box_body(box); shape::arena arena; shape::type_param *params = shape::type_param::from_tydesc_and_data(tydesc, p, arena); sweep sweep(task, true, tydesc->shape, params, tydesc->shape_tables, - p + sizeof(uintptr_t)); + p); sweep.walk(); - // FIXME: Run the destructor, *if* it's a resource. - task->free(alloc); + boxed->free(box); } - ++begin; + box = box_next; } } void do_cc(rust_task *task) { - LOG(task, gc, "cc; n allocs = %lu", - (long unsigned int)task->local_allocs.size()); + LOG(task, gc, "cc"); irc_map ircs; irc::compute_ircs(task, ircs); - std::vector<void *> roots; + std::vector<rust_opaque_box*> roots; find_roots(task, ircs, roots); - std::set<void *> marked; + std::set<rust_opaque_box*> marked; mark::do_mark(task, roots, marked); sweep::do_sweep(task, marked); |
