/* Processes the work items, until we've none left. */ static void process_collectable(MVMThreadContext *tc, MVMHeapSnapshotState *ss, MVMHeapSnapshotCollectable *col, MVMCollectable *c) { MVMuint32 sc_idx = MVM_sc_get_idx_of_sc(c); if (sc_idx > 0) add_reference_const_cstr(tc, ss, "<SC>", get_collectable_idx(tc, ss, (MVMCollectable *)tc->instance->all_scs[sc_idx]->sc)); col->collectable_size = c->size; }
/* Marks a collectable item (object, type object, STable). */ void MVM_gc_mark_collectable(MVMThreadContext *tc, MVMGCWorklist *worklist, MVMCollectable *new_addr) { MVMuint16 i; MVMuint32 sc_idx; assert(!(new_addr->flags & MVM_CF_FORWARDER_VALID)); /*assert(REPR(new_addr));*/ sc_idx = MVM_sc_get_idx_of_sc(new_addr); if (sc_idx > 0) { #if MVM_GC_DEBUG if (sc_idx >= tc->instance->all_scs_next_idx) MVM_panic(1, "SC index out of range"); #endif MVM_gc_worklist_add(tc, worklist, &(tc->instance->all_scs[sc_idx]->sc)); } if (new_addr->flags & MVM_CF_TYPE_OBJECT) { /* Add the STable to the worklist. */ MVM_gc_worklist_add(tc, worklist, &((MVMObject *)new_addr)->st); } else if (new_addr->flags & MVM_CF_STABLE) { /* Add all references in the STable to the work list. */ MVMSTable *new_addr_st = (MVMSTable *)new_addr; MVM_gc_worklist_add(tc, worklist, &new_addr_st->method_cache); for (i = 0; i < new_addr_st->type_check_cache_length; i++) MVM_gc_worklist_add(tc, worklist, &new_addr_st->type_check_cache[i]); if (new_addr_st->container_spec) if (new_addr_st->container_spec->gc_mark_data) new_addr_st->container_spec->gc_mark_data(tc, new_addr_st, worklist); if (new_addr_st->boolification_spec) MVM_gc_worklist_add(tc, worklist, &new_addr_st->boolification_spec->method); if (new_addr_st->invocation_spec) { MVM_gc_worklist_add(tc, worklist, &new_addr_st->invocation_spec->class_handle); MVM_gc_worklist_add(tc, worklist, &new_addr_st->invocation_spec->attr_name); MVM_gc_worklist_add(tc, worklist, &new_addr_st->invocation_spec->invocation_handler); MVM_gc_worklist_add(tc, worklist, &new_addr_st->invocation_spec->md_class_handle); MVM_gc_worklist_add(tc, worklist, &new_addr_st->invocation_spec->md_cache_attr_name); MVM_gc_worklist_add(tc, worklist, &new_addr_st->invocation_spec->md_valid_attr_name); } MVM_gc_worklist_add(tc, worklist, &new_addr_st->WHO); MVM_gc_worklist_add(tc, worklist, &new_addr_st->WHAT); MVM_gc_worklist_add(tc, worklist, &new_addr_st->HOW); MVM_gc_worklist_add(tc, worklist, &new_addr_st->HOW_sc); MVM_gc_worklist_add(tc, worklist, &new_addr_st->method_cache_sc); if (new_addr_st->mode_flags & MVM_PARAMETRIC_TYPE) { MVM_gc_worklist_add(tc, worklist, &new_addr_st->paramet.ric.parameterizer); MVM_gc_worklist_add(tc, worklist, &new_addr_st->paramet.ric.lookup); } else if (new_addr_st->mode_flags & MVM_PARAMETERIZED_TYPE) { MVM_gc_worklist_add(tc, worklist, &new_addr_st->paramet.erized.parametric_type); MVM_gc_worklist_add(tc, worklist, &new_addr_st->paramet.erized.parameters); } /* If it needs to have its REPR data marked, do that. */ if (new_addr_st->REPR->gc_mark_repr_data) new_addr_st->REPR->gc_mark_repr_data(tc, new_addr_st, worklist); } else if (new_addr->flags & MVM_CF_FRAME) { MVM_gc_root_add_frame_roots_to_worklist(tc, worklist, (MVMFrame *)new_addr); } else { /* Need to view it as an object in here. */ MVMObject *new_addr_obj = (MVMObject *)new_addr; /* Add the STable to the worklist. */ MVM_gc_worklist_add(tc, worklist, &new_addr_obj->st); /* If needed, mark it. This will add addresses to the worklist * that will need updating. Note that we are passing the address * of the object *after* copying it since those are the addresses * we care about updating; the old chunk of memory is now dead! */ if (MVM_GC_DEBUG_ENABLED(MVM_GC_DEBUG_COLLECT) && !STABLE(new_addr_obj)) MVM_panic(MVM_exitcode_gcnursery, "Found an outdated reference to address %p", new_addr); if (REPR(new_addr_obj)->gc_mark) REPR(new_addr_obj)->gc_mark(tc, STABLE(new_addr_obj), OBJECT_BODY(new_addr_obj), worklist); } }