[svn:parrot] r49479 - branches/generational_gc/src/gc
bacek at svn.parrot.org
bacek at svn.parrot.org
Fri Oct 8 10:59:21 UTC 2010
Author: bacek
Date: Fri Oct 8 10:59:21 2010
New Revision: 49479
URL: https://trac.parrot.org/parrot/changeset/49479
Log:
Rewrite generational MS algorithm. Does compile. Doesn't work
Modified:
branches/generational_gc/src/gc/gc_ms2.c
Modified: branches/generational_gc/src/gc/gc_ms2.c
==============================================================================
--- branches/generational_gc/src/gc/gc_ms2.c Fri Oct 8 10:59:00 2010 (r49478)
+++ branches/generational_gc/src/gc/gc_ms2.c Fri Oct 8 10:59:21 2010 (r49479)
@@ -597,7 +597,17 @@
MarkSweep_GC *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
List_Item_Header *tmp;
Linked_List *list;
- size_t gen;
+ int i, gen;
+
+ /*
+ * Remember current postions of objects.
+ * We will use later for properly moving objects between generations.
+ */
+ List_Item_Header *old_object_tails[] = {
+ self->objects[0]->last,
+ self->objects[1]->last,
+ self->objects[2]->last
+ };
UNUSED(flags);
/* GC is blocked */
@@ -627,7 +637,7 @@
else
gen = self->current_generation = 0;
- /* Trace "roots" */
+ /* Trace roots */
gc_ms2_mark_pmc_header(interp, PMCNULL);
Parrot_gc_trace_root(interp, NULL, GC_TRACE_FULL);
if (interp->pdb && interp->pdb->debugger) {
@@ -655,53 +665,129 @@
tmp = tmp->next;
}
- /* At this point of time root_objects contains only live PMCs */
- /* objects contains "dead" or "constant" PMCs */
- /* sweep of root_objects will repaint them white */
- /* sweep of objects will destroy dead objects leaving only "constant" */
- gc_ms2_sweep_pool(interp, self->pmc_allocator, self->root_objects, gc_ms2_sweep_pmc_cb);
-
- /* Depends on current collected generation */
- gc_ms2_sweep_pool(interp, self->pmc_allocator, self->objects[0], gc_ms2_sweep_pmc_cb);
- if (gen >= 1)
- gc_ms2_sweep_pool(interp, self->pmc_allocator, self->objects[1], gc_ms2_sweep_pmc_cb);
- if (gen >= 2)
- gc_ms2_sweep_pool(interp, self->pmc_allocator, self->objects[2], gc_ms2_sweep_pmc_cb);
-
- gc_ms2_sweep_pool(interp, self->string_allocator, self->strings[0], gc_ms2_sweep_string_cb);
- if (gen >= 1)
- gc_ms2_sweep_pool(interp, self->string_allocator, self->strings[1], gc_ms2_sweep_string_cb);
- if (gen >= 2)
- gc_ms2_sweep_pool(interp, self->string_allocator, self->strings[2], gc_ms2_sweep_string_cb);
+ /*
+ * At this point of time root_objects contains live objects from different
+ * generations.
+ *
+ * Iterate over them and move into proper list. Do not repaint them white yet.
+ *
+ * Remember postions of last item in lists. We will need it to pull more
+ * objects into those generations.
+ */
+ old_object_tails[0] = self->objects[0]->last;
+ old_object_tails[1] = self->objects[1]->last;
+ old_object_tails[2] = self->objects[2]->last;
- /* Root objects can contains PMCs from older generations. Put them into proper list */
tmp = self->root_objects->first;
while (tmp) {
List_Item_Header *next = tmp->next;
- PMC *pmc = LLH2Obj_typed(tmp, PMC);
- if (PObj_to_generation(pmc)) {
- LIST_REMOVE(self->root_objects, tmp);
- LIST_APPEND(self->objects[PObj_to_generation(pmc)], tmp);
- }
+ LIST_REMOVE(self->root_objects, tmp);
+ LIST_APPEND(self->objects[PObj_to_generation(LLH2Obj_typed(tmp, PMC))], tmp);
tmp = next;
}
- /* TODO Handle oldest generation */
- /* Propagate survived objects into older generation */
- if (gen != 2) {
- gc_ms2_propagate_to_older_generation(interp, gen, self->objects[gen], self->objects[gen+1]);
+ /*
+ * Now. self->objects[N] contains properly marked objects.
+ * (For current or younger generations).
+ * 1. Propagate survived objects into older generation.
+ * 2. Paint them white.
+ * 3. Destroy everything else.
+ */
+ for (i = gen; gen >= 0; i--) {
+ tmp = self->objects[i]->first;
+ while (tmp) {
+ PMC *pmc = LLH2Obj_typed(tmp, PMC);
+ List_Item_Header *next = tmp->next;
+
+ /* We are moving previousely remembered tail. Update it */
+ if (!next) {
+ old_object_tails[i] = tmp->prev;
+ }
+
+ if (PObj_live_TEST(pmc)) {
+ if (!PObj_constant_TEST(pmc)) {
+ /* "Seal" object with write barrier */
+ VTABLE *t = pmc->vtable;
+
+ PARROT_ASSERT(pmc->vtable);
+ PARROT_ASSERT(pmc->vtable->wb_variant_vtable);
- while (self->root_objects->first)
- gc_ms2_propagate_to_older_generation(interp, gen, self->root_objects, self->objects[gen+1]);
+ pmc->vtable = pmc->vtable->wb_variant_vtable;
+ pmc->vtable->wb_variant_vtable = t;
+
+ PARROT_ASSERT(pmc->vtable != pmc->vtable->wb_variant_vtable);
+ PARROT_ASSERT(pmc->vtable != pmc->vtable->ro_variant_vtable);
+
+ /* Move to older generation */
+ LIST_REMOVE(self->objects[i], tmp);
+ LIST_APPEND(self->objects[i+1], tmp);
+
+ pmc->flags &= ~(PObj_GC_generation_0_FLAG
+ | PObj_GC_generation_1_FLAG
+ | PObj_GC_generation_2_FLAG);
+ pmc->flags |= generation_to_flags(i+1);
+ }
+
+ /* Paint white for next cycle */
+ PObj_live_CLEAR(pmc);
+ }
+ else {
+ /* Object is dead. Bury it */
+ PObj_on_free_list_SET(pmc);
+ LIST_REMOVE(self->objects[i], tmp);
+
+ Parrot_pmc_destroy(interp, pmc);
+ gc_ms2_free_pmc_header(interp, pmc);
+
+ Parrot_gc_pool_free(interp, self->pmc_allocator, tmp);
+ }
- gc_ms2_propagate_to_older_generation(interp, gen, self->strings[gen], self->strings[gen+1]);
+ tmp = next;
+ }
+ }
+
+
+ /*
+ * Last step. old_object_tails contains pointer to previous end of generation.
+ * We have to move old-to-young referenced objects into same generation.
+ *
+ * Use special version of VTABLE_mark for it.
+ */
+ interp->gc_sys->mark_pmc_header = gc_ms2_vtable_mark_propagate;
+ interp->gc_sys->mark_str_header = gc_ms2_string_mark_propagate;
+
+ for (i = 2; i > 0; i--) {
+ /* We are "marking" this generation */
+ self->current_generation = i;
+
+ /* It can be our first move to this generation */
+ tmp = old_object_tails[i]
+ ? old_object_tails[i]
+ : self->objects[i]->first;
+
+ while (tmp) {
+ PMC *pmc = LLH2Obj_typed(tmp, PMC);
+
+ /* mark can append more objects to this list */
+ if (PObj_custom_mark_TEST(pmc))
+ VTABLE_mark(interp, pmc);
+
+ tmp = tmp->next;
+ }
}
+
+ interp->gc_sys->mark_str_header = gc_ms2_mark_string_header;
+ interp->gc_sys->mark_pmc_header = gc_ms2_mark_pmc_header;
+
+
+ /* Update some stats */
interp->gc_sys->stats.header_allocs_since_last_collect = 0;
interp->gc_sys->stats.mem_used_last_collect = 0;
self->gc_mark_block_level--;
+
/* We swept all dead objects */
self->num_early_gc_PMCs = 0;
@@ -1253,99 +1339,6 @@
}
}
-/*
-
-=item C<static void gc_ms2_propagate_to_older_generation(PARROT_INTERP, size_t
-current_gen, Linked_List *from, Linked_List *to)>
-
-Move to Older Generation
-
-=cut
-
-*/
-
-static void
-gc_ms2_propagate_to_older_generation(PARROT_INTERP,
- size_t current_gen,
- ARGIN(Linked_List *from),
- ARGIN(Linked_List *to))
-{
- ASSERT_ARGS(gc_ms2_propagate_to_older_generation)
- List_Item_Header *next, *tmp = from->first;
- List_Item_Header *previous_last = to->last;
-
- ++current_gen;
- while (tmp) {
- PObj * obj = LLH2Obj_typed(tmp, PObj);
- next = tmp->next;
-
- if (!PObj_constant_TEST(obj)) {
-
- /* We can't do such a naive check for "survived" objects */
- /* If PMC "A" survived first collection */
- /* Then PMC "B" was added to it */
- /* We'll move "A" into older generation */
- /* But keep "B" in younger */
- /* Kaboom. "B" collected prematurely on next run */
- if (1 || obj->flags & PObj_GC_generation_2_FLAG) {
- /* Move into older generation */
- LIST_REMOVE(from, tmp);
- LIST_APPEND(to, tmp);
- obj->flags &= ~(PObj_GC_generation_0_FLAG | PObj_GC_generation_1_FLAG | PObj_GC_generation_2_FLAG);
- obj->flags |= generation_to_flags(current_gen);
-
- if (PObj_is_PMC_TEST(obj)) {
- PMC *pmc = (PMC *)obj;
- VTABLE *t = pmc->vtable;
-
- PARROT_ASSERT(pmc->vtable);
- PARROT_ASSERT(pmc->vtable->wb_variant_vtable);
-
- pmc->vtable = pmc->vtable->wb_variant_vtable;
- pmc->vtable->wb_variant_vtable = t;
-
- PARROT_ASSERT(pmc->vtable != pmc->vtable->wb_variant_vtable);
- PARROT_ASSERT(pmc->vtable != pmc->vtable->ro_variant_vtable);
-
- }
- }
- else {
- /* First time survival. */
- obj->flags |= PObj_GC_generation_2_FLAG;
- }
- }
-
- tmp = next;
- }
-
- /* Ugly, awful, terrible hack. I'm not even trying to find excuse for doing it */
- /* When we propagating object to older generation we have to propagate all his
- * dependant objects. To do it I just override mark_pmc_header function with
- * special version which copy this objects into C<root_objects>. After first
- * pass I just propagate all gathered objects into older generation */
- if (to->first && PObj_is_PMC_TEST(LLH2Obj_typed(to->first, PObj))) {
- size_t count = 0;
- interp->gc_sys->mark_pmc_header = gc_ms2_vtable_mark_propagate;
- interp->gc_sys->mark_str_header = gc_ms2_string_mark_propagate;
-
- tmp = previous_last
- ? previous_last->next
- : to->first;
- while (tmp) {
- PMC *pmc = LLH2Obj_typed(tmp, PMC);
- next = tmp->next;
- if (PObj_custom_mark_TEST(pmc))
- VTABLE_mark(interp, pmc);
- ++count;
- tmp = next;
- }
-
- //fprintf(stderr, "count: %d\n", count);
- interp->gc_sys->mark_str_header = gc_ms2_mark_string_header;
- interp->gc_sys->mark_pmc_header = gc_ms2_mark_pmc_header;
- }
-
-}
static void
gc_ms2_vtable_mark_propagate(PARROT_INTERP, ARGIN(PMC *pmc))
@@ -1362,12 +1355,10 @@
if (pmc->flags & PObj_constant_FLAG)
return;
- if (pmc->flags & PObj_GC_generation_2_FLAG)
- return;
-
LIST_REMOVE(self->objects[gen], item);
- LIST_APPEND(self->root_objects, item);
- pmc->flags |= PObj_GC_generation_2_FLAG;
+ LIST_APPEND(self->objects[self->current_generation], item);
+ pmc->flags &= ~generation_to_flags(gen);
+ pmc->flags |= generation_to_flags(self->current_generation);
}
static void
@@ -1387,12 +1378,10 @@
if (s->flags & PObj_constant_FLAG)
return;
- if (s->flags & PObj_GC_generation_2_FLAG)
- return;
-
LIST_REMOVE(self->strings[gen], item);
LIST_REMOVE(self->strings[self->current_generation], item);
- s->flags |= generation_to_flags(self->current_generation) | PObj_GC_generation_2_FLAG;
+ s->flags &= ~generation_to_flags(gen);
+ s->flags |= generation_to_flags(self->current_generation);
}
/*
=item C<static void gc_ms2_sweep_pool(PARROT_INTERP, Pool_Allocator *pool,
More information about the parrot-commits
mailing list