diff --git a/src/rt/rust_cc.cpp b/src/rt/rust_cc.cpp index 4befb36d819..146c1f514ba 100644 --- a/src/rt/rust_cc.cpp +++ b/src/rt/rust_cc.cpp @@ -169,7 +169,6 @@ irc::compute_ircs(rust_task *task, irc_map &ircs) { begin(task->local_allocs.begin()), end(task->local_allocs.end()); while (begin != end) { uint8_t *p = reinterpret_cast<uint8_t *>(begin->first); - p += sizeof(uintptr_t); // Skip over the reference count. const type_desc *tydesc = begin->second; @@ -178,9 +177,9 @@ irc::compute_ircs(rust_task *task, irc_map &ircs) { shape::arena arena; shape::type_param *params = - shape::type_param::from_tydesc(&tydesc, arena); - irc irc(task, true, tydesc->shape, params, tydesc->shape_tables, p, - ircs); + shape::type_param::from_tydesc_and_data(tydesc, p, arena); + irc irc(task, true, tydesc->shape, params, tydesc->shape_tables, + p + sizeof(uintptr_t), ircs); irc.walk(); #if 0 @@ -374,26 +373,25 @@ mark::do_mark(rust_task *task, const std::vector<void *> &roots, if (marked.find(alloc) == marked.end()) { marked.insert(alloc); - uint8_t *p = reinterpret_cast<uint8_t *>(alloc); - p += sizeof(uintptr_t); // Skip over the reference count. - - const type_desc *tydesc = task->local_allocs[*begin]; + const type_desc *tydesc = task->local_allocs[alloc]; //DPRINT("marking: %p, tydesc=%p\n", p, tydesc); + uint8_t *p = reinterpret_cast<uint8_t *>(alloc); shape::arena arena; shape::type_param *params = - shape::type_param::from_tydesc(&tydesc, arena); + 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, std::cerr); + tydesc->shape_tables, p + sizeof(uintptr_t), + std::cerr); log.walk(); DPRINT("\n"); -#endif + // We skip over the reference count here. mark mark(task, true, tydesc->shape, params, tydesc->shape_tables, - p, marked); + p + sizeof(uintptr_t), marked); mark.walk(); } diff --git a/src/rt/rust_gc.cpp b/src/rt/rust_gc.cpp index ae3c5a01031..26e48857ecb 100644 --- a/src/rt/rust_gc.cpp +++ b/src/rt/rust_gc.cpp @@ -105,7 +105,8 @@ gc::mark(std::vector<root> &roots) { shape::arena arena; shape::type_param *params = - shape::type_param::from_tydesc(&ri->tydesc, arena); + shape::type_param::from_tydesc_and_data(ri->tydesc, ri->data, + arena); shape::log log(task, true, ri->tydesc->shape, params, ri->tydesc->shape_tables, ri->data, std::cerr); log.walk(); diff --git a/src/rt/rust_obstack.cpp b/src/rt/rust_obstack.cpp index 99e72489f5f..e8dbffd74a2 100644 --- a/src/rt/rust_obstack.cpp +++ b/src/rt/rust_obstack.cpp @@ -160,12 +160,13 @@ rust_obstack::dump() const { iterator b = begin(), e = end(); while (b != e) { std::pair<const type_desc *,void *> data = *b; + uint8_t *dp = reinterpret_cast<uint8_t *>(data.second); + shape::arena arena; shape::type_param *params = - shape::type_param::from_tydesc(&data.first, arena); + shape::type_param::from_tydesc_and_data(data.first, dp, arena); shape::log log(task, true, data.first->shape, params, - data.first->shape_tables, - reinterpret_cast<uint8_t *>(data.second), std::cerr); + data.first->shape_tables, dp, std::cerr); log.walk(); std::cerr << "\n"; diff --git a/src/rt/rust_shape.cpp b/src/rt/rust_shape.cpp index d25c340264e..994c4df0fb9 100644 --- a/src/rt/rust_shape.cpp +++ b/src/rt/rust_shape.cpp @@ -37,7 +37,10 @@ type_param::make(const type_desc **tydescs, unsigned n_tydescs, const type_desc *subtydesc = tydescs[i]; ptrs[i].shape = subtydesc->shape; ptrs[i].tables = subtydesc->shape_tables; - ptrs[i].params = from_tydesc(&subtydesc, arena); + + // FIXME: Doesn't handle a type-parametric object closing over a + // type-parametric object type properly. + ptrs[i].params = from_tydesc(subtydesc, arena); } return ptrs; } @@ -531,8 +534,12 @@ upcall_cmp_type(int8_t *result, rust_task *task, const type_desc *tydesc, const type_desc **subtydescs, uint8_t *data_0, uint8_t *data_1, uint8_t cmp_type) { shape::arena arena; + + // FIXME: This may well be broken when comparing two closures or objects + // that close over different sets of type parameters. shape::type_param *params = - shape::type_param::from_tydesc(&tydesc, arena); + shape::type_param::from_tydesc_and_data(tydesc, data_0, arena); + shape::cmp cmp(task, true, tydesc->shape, params, tydesc->shape_tables, data_0, data_1); cmp.walk(); @@ -552,7 +559,7 @@ upcall_log_type(rust_task *task, const type_desc *tydesc, uint8_t *data, shape::arena arena; shape::type_param *params = - shape::type_param::from_tydesc(&tydesc, arena); + shape::type_param::from_tydesc_and_data(tydesc, data, arena); std::stringstream ss; shape::log log(task, true, tydesc->shape, params, tydesc->shape_tables, diff --git a/src/rt/rust_shape.h b/src/rt/rust_shape.h index 64859dbfa35..e71c5c8188f 100644 --- a/src/rt/rust_shape.h +++ b/src/rt/rust_shape.h @@ -310,27 +310,44 @@ public: } // Creates type parameters from a type descriptor. - static inline type_param *from_tydesc(const type_desc **tydesc, + static inline type_param *from_tydesc(const type_desc *tydesc, arena &arena) { - if ((*tydesc)->n_obj_params) { - uintptr_t n_obj_params = (*tydesc)->n_obj_params; + // In order to find the type parameters of objects and functions, we + // 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!"); + + return make(tydesc->first_param, tydesc->n_params, arena); + } + + static type_param *from_tydesc_and_data(const type_desc *tydesc, + uint8_t *dp, arena &arena) { + 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, tydesc + 4); + (unsigned long)n_obj_params, tydesc, + dp + sizeof(uintptr_t) + tydesc->size); n_obj_params &= 0x7fffffff; + // FIXME: Is this right? first_param = (const type_desc **) - ((uint8_t *)(tydesc + 4) + (*tydesc)->size); + (dp + sizeof(uintptr_t) + tydesc->size); } else { // Object closure. DPRINT("n_obj_params OBJ %lu, tydesc %p, starting at %p\n", - (unsigned long)n_obj_params, tydesc, tydesc + 4); - first_param = tydesc + 4; + (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); } - return make((*tydesc)->first_param, (*tydesc)->n_params, arena); + return make(tydesc->first_param, tydesc->n_params, arena); } };