[svn:parrot] r49356 - branches/generational_gc/src/gc

bacek at svn.parrot.org bacek at svn.parrot.org
Mon Sep 27 11:25:59 UTC 2010


Author: bacek
Date: Mon Sep 27 11:25:59 2010
New Revision: 49356
URL: https://trac.parrot.org/parrot/changeset/49356

Log:
First real generational GC attempt.

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	Mon Sep 27 11:19:46 2010	(r49355)
+++ branches/generational_gc/src/gc/gc_ms2.c	Mon Sep 27 11:25:59 2010	(r49356)
@@ -42,12 +42,19 @@
 #define PObj_to_generation(pobj)                    \
     (                                               \
         (pobj)->flags & PObj_GC_generation_0_FLAG   \
-        ? (pobj->flags) & PObj_GC_generation_1_FLAG \
+        ? 1                                         \
+        : (pobj->flags) & PObj_GC_generation_1_FLAG \
             ? 2                                     \
-            : 1                                     \
-        : 0                                         \
+            : 0                                     \
     )
 
+#define generation_to_flags(gen)                    \
+    (gen) == 1                                      \
+        ? PObj_GC_generation_0_FLAG                 \
+        : (gen) == 2                                \
+            ? PObj_GC_generation_1_FLAG             \
+            : 0
+
 /* Private information */
 typedef struct MarkSweep_GC {
     /* Allocator for PMC headers */
@@ -250,6 +257,14 @@
         __attribute__nonnull__(2)
         FUNC_MODIFIES(*pmc);
 
+static void gc_ms2_propagate_to_older_generation(PARROT_INTERP,
+    size_t current_gen,
+    ARGIN(Linked_List *from),
+    ARGIN(Linked_List *to))
+        __attribute__nonnull__(1)
+        __attribute__nonnull__(3)
+        __attribute__nonnull__(4);
+
 static void gc_ms2_reallocate_buffer_storage(PARROT_INTERP,
     ARGIN(Buffer *str),
     size_t size)
@@ -391,6 +406,11 @@
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(pmc))
+#define ASSERT_ARGS_gc_ms2_propagate_to_older_generation \
+     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+       PARROT_ASSERT_ARG(interp) \
+    , PARROT_ASSERT_ARG(from) \
+    , PARROT_ASSERT_ARG(to))
 #define ASSERT_ARGS_gc_ms2_reallocate_buffer_storage \
      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
@@ -847,6 +867,7 @@
     ASSERT_ARGS(gc_ms2_sweep_pmc_cb)
     PMC *pmc = (PMC *)obj;
     Parrot_pmc_destroy(interp, pmc);
+    gc_ms2_free_pmc_header(interp, pmc);
 }
 
 /*
@@ -1124,7 +1145,7 @@
     MarkSweep_GC      *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
     List_Item_Header *tmp;
     Linked_List      *list;
-    size_t            counter;
+    size_t            gen;
     UNUSED(flags);
 
     /* GC is blocked */
@@ -1148,11 +1169,11 @@
     /* TODO Use less naive approach. E.g. count amount of allocated memory in
      * older generations */
     if (0 && interp->gc_sys->stats.gc_mark_runs % 100 == 0)
-        self->current_generation = 2;
+        gen = self->current_generation = 2;
     else if (interp->gc_sys->stats.gc_mark_runs % 10 == 0)
-        self->current_generation = 1;
+        gen = self->current_generation = 1;
     else
-        self->current_generation = 0;
+        gen = self->current_generation = 0;
 
     /* Trace "roots" */
     gc_ms2_mark_pmc_header(interp, PMCNULL);
@@ -1177,6 +1198,8 @@
         if (PMC_metadata(pmc))
             Parrot_gc_mark_PMC_alive(interp, PMC_metadata(pmc));
 
+        PObj_live_SET(pmc);
+
         tmp = tmp->next;
     }
 
@@ -1186,14 +1209,18 @@
     /* 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);
 
-    /* TODO Depends on current collected generation */
+    /* Depends on current collected generation */
     gc_ms2_sweep_pool(interp, self->pmc_allocator, self->objects[0], gc_ms2_sweep_pmc_cb);
-    gc_ms2_sweep_pool(interp, self->pmc_allocator, self->objects[1], gc_ms2_sweep_pmc_cb);
-    gc_ms2_sweep_pool(interp, self->pmc_allocator, self->objects[2], 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);
-    gc_ms2_sweep_pool(interp, self->string_allocator, self->strings[1], gc_ms2_sweep_string_cb);
-    gc_ms2_sweep_pool(interp, self->string_allocator, self->strings[2], 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);
 
     /* TODO */
     /* Replace objects with root_objects. Ignoring "constant" one */
@@ -1205,6 +1232,13 @@
     list->count = 0;
     self->root_objects = list;
 
+    /* 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]);
+        gc_ms2_propagate_to_older_generation(interp, gen, self->strings[gen], self->strings[gen+1]);
+    }
+
     interp->gc_sys->stats.header_allocs_since_last_collect = 0;
     interp->gc_sys->stats.mem_used_last_collect            = 0;
     self->gc_mark_block_level--;
@@ -1214,7 +1248,47 @@
     gc_ms2_compact_memory_pool(interp);
 }
 
+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;
+    ++current_gen;
+    while (tmp) {
+        PObj * obj = LLH2Obj_typed(tmp, PObj);
+        next = tmp->next;
 
+        /* 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 (0 && 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);
+            obj->flags |= generation_to_flags(current_gen);
+
+            if (PObj_is_PMC_TEST(obj)) {
+                PMC     *pmc = (PMC *)obj;
+                VTABLE  *t   = pmc->vtable;
+                pmc->vtable = pmc->vtable->wb_variant_vtable;
+                pmc->vtable->wb_variant_vtable = t;
+            }
+        }
+        else {
+            /* First time survival. */
+            obj->flags |= PObj_GC_generation_2_FLAG;
+        }
+
+        tmp = next;
+    }
+}
 
 /*
 =item C<static void gc_ms2_sweep_pool(PARROT_INTERP, Pool_Allocator *pool,


More information about the parrot-commits mailing list