From 263f4c58a0c9409f257d45ae03d4b19700ef232b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 12 Jan 2012 09:28:29 -0800 Subject: add tydescs into shape, rewrite walk_fn_contents() --- src/rt/rust_cc.cpp | 19 +++++++++-------- src/rt/rust_shape.cpp | 14 +++++-------- src/rt/rust_shape.h | 55 +++++++++++++++++++++++++++++--------------------- src/rt/rust_upcall.cpp | 12 ++++++----- 4 files changed, 53 insertions(+), 47 deletions(-) (limited to 'src/rt') diff --git a/src/rt/rust_cc.cpp b/src/rt/rust_cc.cpp index 1f99fe98f71..78138434d73 100644 --- a/src/rt/rust_cc.cpp +++ b/src/rt/rust_cc.cpp @@ -357,7 +357,7 @@ class mark : public shape::data { 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); + shape::data::walk_fn_contents1(dp, false); break; } case shape::SHAPE_BARE_FN: // Does not close over data. @@ -552,15 +552,14 @@ class sweep : public shape::data { 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); + shape::data::walk_fn_contents1(dp, true); + + // 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: task->kernel->free(pair.env); diff --git a/src/rt/rust_shape.cpp b/src/rt/rust_shape.cpp index b7ab591ce04..961cfe7bc46 100644 --- a/src/rt/rust_shape.cpp +++ b/src/rt/rust_shape.cpp @@ -44,15 +44,7 @@ type_param::make(const type_desc **tydescs, unsigned n_tydescs, return ptrs; } -// Constructs type parameters from a function shape. This is a bit messy, -// because it requires that the function shape have a specific format. -type_param * -type_param::from_fn_shape(rust_opaque_closure *env, arena &arena) { - unsigned n_tydescs = env->td->n_obj_params & 0x7fffffff; - return make(env->captured_tds, n_tydescs, arena); -} - -// Constructs type parameters from an object shape. This is also a bit messy, +// Constructs type parameters from an object shape. This is a bit messy, // because it requires that the object shape have a specific format. type_param * type_param::from_obj_shape(const uint8_t *sp, ptr dp, arena &arena) { @@ -354,6 +346,10 @@ public: data::walk_box_contents1(); } + void walk_tydesc2(char) { + cmp_pointer(); + } + void walk_fn2(char) { return cmp_two_pointers(); } void walk_obj2() { return cmp_two_pointers(); } diff --git a/src/rt/rust_shape.h b/src/rt/rust_shape.h index b4efae9e704..41cc9c11fb3 100644 --- a/src/rt/rust_shape.h +++ b/src/rt/rust_shape.h @@ -306,8 +306,6 @@ public: const rust_shape_tables *tables; const type_param *params; // subparameters - // Constructs type parameters from a function shape. - static type_param *from_fn_shape(rust_opaque_closure *env, arena &arena); // Creates type parameters from an object shape description. static type_param *from_obj_shape(const uint8_t *sp, ptr dp, arena &arena); @@ -326,8 +324,8 @@ public: // have to actually have the data pointer, since we don't statically // know from the type of an object or function which type parameters // it closes over. - assert(!tydesc->n_obj_params && "Type-parametric objects and " - "functions must go through from_tydesc_and_data() instead!"); + assert(!tydesc->n_obj_params && "Type-parametric objects " + "must go through from_tydesc_and_data() instead!"); return make(tydesc->first_param, tydesc->n_params, arena); } @@ -337,20 +335,11 @@ public: if (tydesc->n_obj_params) { uintptr_t n_obj_params = tydesc->n_obj_params; const type_desc **first_param; - if (n_obj_params & 0x80000000) { - // Function closure. - DPRINT("n_obj_params FN %lu, tydesc %p, starting at %p\n", - (unsigned long)n_obj_params, tydesc, - dp + sizeof(uintptr_t) + tydesc->size); - n_obj_params &= 0x7fffffff; - first_param = (const type_desc **)(dp + sizeof(uintptr_t)); - } else { - // Object closure. - DPRINT("n_obj_params OBJ %lu, tydesc %p, starting at %p\n", - (unsigned long)n_obj_params, tydesc, - dp + sizeof(uintptr_t) * 2); - first_param = (const type_desc **)(dp + sizeof(uintptr_t) * 2); - } + // Object closure. + DPRINT("n_obj_params OBJ %lu, tydesc %p, starting at %p\n", + (unsigned long)n_obj_params, tydesc, + dp + sizeof(uintptr_t) * 2); + first_param = (const type_desc **)(dp + sizeof(uintptr_t) * 2); return make(first_param, n_obj_params, arena); } @@ -852,7 +841,7 @@ protected: void walk_box_contents1(); void walk_uniq_contents1(); - void walk_fn_contents1(ptr &dp); + void walk_fn_contents1(ptr &dp, bool null_td); void walk_obj_contents1(ptr &dp); void walk_iface_contents1(ptr &dp); void walk_variant1(tag_info &tinfo, tag_variant_t variant); @@ -1008,20 +997,40 @@ data::walk_tag1(tag_info &tinfo) { template void -data::walk_fn_contents1(ptr &dp) { +data::walk_fn_contents1(ptr &dp, bool null_td) { fn_env_pair pair = bump_dp(dp); if (!pair.env) return; arena arena; - type_param *params = - type_param::from_fn_shape(pair.env, arena); const type_desc *closure_td = pair.env->td; + type_param *params = + type_param::from_tydesc(closure_td, arena); ptr closure_dp((uintptr_t)pair.env); T sub(*static_cast(this), closure_td->shape, params, closure_td->shape_tables, closure_dp); sub.align = true; + + if (null_td) { + // if null_td flag is true, null out the type descr from + // the data structure while we walk. This is used in cycle + // collector when we are sweeping up data. The idea is that + // we are using the information in the embedded type desc to + // walk the contents, so we do not want to free it during that + // walk. This is not *strictly* necessary today because + // type_param::from_tydesc() actually pulls out the "shape" + // string and other information and copies it into a new + // location that is unaffected by the free. But it seems + // safer, particularly as this pulling out of information will + // not cope with nested, derived type descriptors. + pair.env->td = NULL; + } + sub.walk(); + + if (null_td) { + pair.env->td = closure_td; + } } template @@ -1138,7 +1147,7 @@ private: void walk_fn2(char kind) { out << prefix << "fn"; prefix = ""; - data::walk_fn_contents1(dp); + data::walk_fn_contents1(dp, false); } void walk_obj2() { diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 12ef28065bd..65299a7d244 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -283,12 +283,14 @@ void upcall_s_free_shared_type_desc(type_desc *td) rust_task *task = rust_scheduler::get_task(); LOG_UPCALL_ENTRY(task); - // Recursively free any referenced descriptors: - for (unsigned i = 0; i < td->n_params; i++) { - upcall_s_free_shared_type_desc((type_desc*) td->first_param[i]); - } + if (td) { + // Recursively free any referenced descriptors: + for (unsigned i = 0; i < td->n_params; i++) { + upcall_s_free_shared_type_desc((type_desc*) td->first_param[i]); + } - task->kernel->free(td); + task->kernel->free(td); + } } extern "C" CDECL void -- cgit 1.4.1-3-g733a5