[svn:parrot] r41167 - in branches/gc-refactor: . config/gen/makefiles include/parrot src/gc

jrtayloriv at svn.parrot.org jrtayloriv at svn.parrot.org
Tue Sep 8 23:18:48 UTC 2009


Author: jrtayloriv
Date: Tue Sep  8 23:18:43 2009
New Revision: 41167
URL: https://trac.parrot.org/parrot/changeset/41167

Log:
Removed everything related to GMS/IMS ... bye bye

Deleted:
   branches/gc-refactor/src/gc/generational_ms.c
   branches/gc-refactor/src/gc/generational_ms.h
   branches/gc-refactor/src/gc/incremental_ms.c
Modified:
   branches/gc-refactor/MANIFEST
   branches/gc-refactor/config/gen/makefiles/root.in
   branches/gc-refactor/include/parrot/settings.h
   branches/gc-refactor/src/gc/alloc_resources.c
   branches/gc-refactor/src/gc/api.c
   branches/gc-refactor/src/gc/gc_private.h

Modified: branches/gc-refactor/MANIFEST
==============================================================================
--- branches/gc-refactor/MANIFEST	Tue Sep  8 22:19:55 2009	(r41166)
+++ branches/gc-refactor/MANIFEST	Tue Sep  8 23:18:43 2009	(r41167)
@@ -1,7 +1,7 @@
 # ex: set ro:
 # $Id$
 #
-# generated by tools/dev/mk_manifest_and_skip.pl Mon Sep  7 21:02:37 2009 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Tue Sep  8 22:16:59 2009 UT
 #
 # See below for documentation on the format of this file.
 #
@@ -1284,8 +1284,6 @@
 src/gc/gc_malloc.c                                          []
 src/gc/gc_ms.c                                              []
 src/gc/gc_private.h                                         []
-src/gc/generational_ms.c                                    []
-src/gc/incremental_ms.c                                     []
 src/gc/malloc.c                                             []
 src/gc/malloc_trace.c                                       []
 src/gc/mark_sweep.c                                         []

Modified: branches/gc-refactor/config/gen/makefiles/root.in
==============================================================================
--- branches/gc-refactor/config/gen/makefiles/root.in	Tue Sep  8 22:19:55 2009	(r41166)
+++ branches/gc-refactor/config/gen/makefiles/root.in	Tue Sep  8 23:18:43 2009	(r41167)
@@ -426,8 +426,6 @@
     $(SRC_DIR)/extend_vtable$(O) \
     $(SRC_DIR)/gc/alloc_memory$(O) \
     $(SRC_DIR)/gc/api$(O) \
-    $(SRC_DIR)/gc/generational_ms$(O) \
-    $(SRC_DIR)/gc/incremental_ms$(O) \
     $(SRC_DIR)/gc/gc_ms$(O) \
     $(SRC_DIR)/gc/gc_inf$(O) \
     $(SRC_DIR)/gc/mark_sweep$(O) \
@@ -1100,10 +1098,6 @@
 
 $(SRC_DIR)/gc/api$(O) : $(GENERAL_H_FILES) $(SRC_DIR)/gc/gc_private.h
 
-$(SRC_DIR)/gc/generational_ms$(O) : $(GENERAL_H_FILES)
-
-$(SRC_DIR)/gc/incremental_ms$(O) : $(GENERAL_H_FILES)
-
 $(SRC_DIR)/gc/alloc_resources$(O) : $(GENERAL_H_FILES)
 
 $(SRC_DIR)/gc/res_lea$(O) : $(GENERAL_H_FILES)

Modified: branches/gc-refactor/include/parrot/settings.h
==============================================================================
--- branches/gc-refactor/include/parrot/settings.h	Tue Sep  8 22:19:55 2009	(r41166)
+++ branches/gc-refactor/include/parrot/settings.h	Tue Sep  8 23:18:43 2009	(r41167)
@@ -35,42 +35,11 @@
 #endif /* DISABLE_GC_DEBUG */
 
 /*
- * GC_SUBSYSTEM selection
- * 0 ... MS  stop-the-world mark & sweep
- * 1 ... IMS incremental mark & sweep
- * 2 ... GMS generational mark & sweep
- * 3 ... INF infinite memory "collector"
- *
- * Please note that only 0 and 3 currently work (and INF doesn't really
- * "work").
+ * GC_DEFAULT_TYPE selection
+ * MS  -- stop-the-world mark & sweep
+ * INF -- infinite memory "collector"
  */
 #define PARROT_GC_DEFAULT_TYPE MS
-#define PARROT_GC_SUBSYSTEM 0
-
-#if PARROT_GC_SUBSYSTEM == 0
-#  define PARROT_GC_MS      1
-#  define PARROT_GC_IMS     0
-#  define PARROT_GC_GMS     0
-#  define PARROT_GC_INF     0
-#endif
-#if PARROT_GC_SUBSYSTEM == 1
-#  define PARROT_GC_MS      0
-#  define PARROT_GC_IMS     1
-#  define PARROT_GC_GMS     0
-#  define PARROT_GC_INF     0
-#endif
-#if PARROT_GC_SUBSYSTEM == 2
-#  define PARROT_GC_MS      0
-#  define PARROT_GC_IMS     0
-#  define PARROT_GC_GMS     1
-#  define PARROT_GC_INF     0
-#endif
-#if PARROT_GC_SUBSYSTEM == 3
-#  define PARROT_GC_MS      0
-#  define PARROT_GC_IMS     0
-#  define PARROT_GC_GMS     0
-#  define PARROT_GC_INF     1
-#endif
 
 /*
  * JIT/i386 can use the CGP run core for external functions instead

Modified: branches/gc-refactor/src/gc/alloc_resources.c
==============================================================================
--- branches/gc-refactor/src/gc/alloc_resources.c	Tue Sep  8 22:19:55 2009	(r41166)
+++ branches/gc-refactor/src/gc/alloc_resources.c	Tue Sep  8 23:18:43 2009	(r41167)
@@ -217,8 +217,7 @@
         &&   interp->mem_pools->mem_allocs_since_last_collect) {
             Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG);
 
-            if ((interp->gc_sys->sys_type != IMS) &&
-                (interp->gc_sys->sys_type != INF)) {
+            if (interp->gc_sys->sys_type != INF) {
                 /* Compact the pool if allowed and worthwhile */
                 if (pool->compact) {
                     /* don't bother reclaiming if it's only a small amount */

Modified: branches/gc-refactor/src/gc/api.c
==============================================================================
--- branches/gc-refactor/src/gc/api.c	Tue Sep  8 22:19:55 2009	(r41166)
+++ branches/gc-refactor/src/gc/api.c	Tue Sep  8 23:18:43 2009	(r41167)
@@ -275,12 +275,6 @@
       case MS:
         Parrot_gc_ms_init(interp);
         break;
-      case IMS:
-        Parrot_gc_ims_init(interp);
-        break;
-      case GMS:
-        Parrot_gc_gms_init(interp);
-        break;
       case INF:
         Parrot_gc_inf_init(interp);
         break;

Modified: branches/gc-refactor/src/gc/gc_private.h
==============================================================================
--- branches/gc-refactor/src/gc/gc_private.h	Tue Sep  8 22:19:55 2009	(r41166)
+++ branches/gc-refactor/src/gc/gc_private.h	Tue Sep  8 23:18:43 2009	(r41167)
@@ -17,8 +17,6 @@
 #define PARROT_GC_PRIVATE_H_GUARD
 
 #include "parrot/settings.h"
-#include "generational_ms.h"
-
 
 #if ! DISABLE_GC_DEBUG
 /* Set when walking the system stack. Defined in src/gc/system.c */
@@ -96,17 +94,13 @@
 
 typedef enum _gc_sys_type_enum {
     MS,  /*mark and sweep*/
-    IMS, /*incremental mark and sweep*/
-    GMS, /*generational mark and sweep*/
     INF /*infinite memory core*/
 } gc_sys_type_enum;
 
 typedef struct GC_Subsystem {
-    gc_sys_type_enum sys_type;  /* Which GC subsystem are we using? */
-
-    union {                     /* Holds system-specific data structures*/
-        struct gc_gms_sys_data gms_data;
-    } gc_sys_data;
+    /* Which GC subsystem are we using? See PARROT_GC_DEFAULT_TYPE in
+     * include/parrot/settings.h for possible values */
+    gc_sys_type_enum sys_type;
 
     /** Function hooks that each subsystem MUST provide */
     void (*do_gc_mark)(PARROT_INTERP, UINTVAL flags);
@@ -117,6 +111,11 @@
      *These will be called via the GC API functions Parrot_gc_func_name
      *e.g. read barrier && write barrier hooks can go here later ...*/
 
+    /* Holds system-specific data structures
+     * unused right now, but this is where it should go if we need them ...
+      union {
+      } gc_private;
+     */
 } GC_Subsystem;
 
 typedef struct Memory_Block {
@@ -174,7 +173,7 @@
 
     struct Variable_Size_Pool *mem_pool;
    /* Size in bytes of an individual pool item. This size may include
-    * a GC-system specific GC header. (e.g. GMS headers) */
+    * a GC-system specific GC header. */
     size_t object_size;
 
     size_t start_arena_memory;
@@ -201,10 +200,11 @@
     alloc_objects_fn_type       more_objects;
     gc_object_fn_type           gc_object;
 
-    /*Contains GC system-specific data structures*/
+    /* Contains GC system-specific data structures ... unused at the moment,
+     * but this is where it should go when we need it ...
     union {
-        struct gc_gms_smallobjpool_data *gms; /*generational mark and sweep*/
-    } gc_sys_priv_data;
+    } gc_private;
+    */
 
 #if GC_USE_LAZY_ALLOCATOR
     void *newfree;

Deleted: branches/gc-refactor/src/gc/generational_ms.c
==============================================================================
--- branches/gc-refactor/src/gc/generational_ms.c	Tue Sep  8 23:18:43 2009	(r41166)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,1974 +0,0 @@
-/*
-Copyright (C) 2001-2009, Parrot Foundation.
-$Id$
-
-=head1 NAME
-
-src/gc/generational_ms.c - Generational mark and sweep garbage collection
-
-=head1 OVERVIEW
-
-The following comments describe a generational garbage collection
-scheme for Parrot.
-
-Keywords:
-
- - non-copying, mark & sweep
- - generational
- - implicit reclamation, treadmill
-
-=head1 DESCRIPTION
-
-A plain mark & sweep collector performs work depending on the amount
-of all allocated objects. The advantage of a generational GC is
-achieved by not processing all objects. This is based on the weak
-generational hypothesis, which states that young objects are likely to
-die early. Old objects, which have survived a few GC cycles tend to be
-long-lived.
-
-The terms young and old objects imply that there is some ordering in
-object creation time and the ordering is also followed by object
-references.
-
-Specifically object references have to follow the marking direction.
-In pure functional programming languages this can be a very simple
-scheme:
-
-        +------------+    object references
-        v            |
-   old   .... young .... youngest
-                            |
-                   <--------  scan direction
-
-If (simplified) the only reference-like operation of the interpreter
-is:
-
-   cons = (car, cdr)
-
-and the object references "car" and "cdr" are created prior to the
-"aggregate" "cons", all object references point always to older
-objects.  By scanning from the youngest to the oldest objects, all
-non-marked objects can be reclaimed immediately. And the scan can be
-aborted at any time after some processing, creating a generational GC
-in a trivial way.
-
-But the programming languages we are serving are working basically the
-other direction, when it comes to object history:
-
-  @a[$i] = $n
-
-A reference operation like this needs first an aggregate and then the
-contents of it. So the scan direction is from old objects to younger
-ones.  In such a scheme it's a bit more complicated to skip parts of
-the objects.
-
-To take advantage of not processing all the objects, these are divided
-into generations, e.g.:
-
-   old               young := nursery
-   generation 0      generation 1
-
-A mark phase now processes the root set and only objects from the
-young generation. When all objects are either referenced by the root
-set or only by the young generation, the algorithm is correct and
-complete.
-
-But there is of course the possibilty that a young object is
-stored into an aggregate of an older generation. This case is tracked
-by the write barrier, which remembers all such operations in the IGP
-(inter generational pointer) list. When now generation 1 is marked,
-the IGP list can be considered as an extension to the root set, so
-that again all live objects of the young generation are detected.
-
-
-=head2 Structures
-
-=over 4
-
-=item C<typedef struct _gc_gms_gen Gc_gms_gen>
-
-Describes the state of one generation for one pool.
-
-=item C<typedef struct _gc_gms_hdr Gc_gms_hdr>
-
-This header is in front of all Parrot objects. It forms a doubly-linked
-list of all objects in one pool and points to its generation.
-
-=item PObj_to_GMSH(o)
-
-=item GMSH_to_PObj(p)
-
-These two macros convert from and to headers and objects.
-
-=item C<typedef struct _gc_gms_hdr_list Gc_gms_hdr_list>
-
-A chained list of headers used e.g. for the IGP list.
-
-=back
-
-=cut
-
-*/
-
-#include "parrot/parrot.h"
-#include "parrot/gc_api.h"
-
-#if PARROT_GC_GMS
-
-typedef struct Gc_gms_private {
-    UINTVAL current_gen_no;             /* the nursery generation number */
-} Gc_gms_private;
-
-/* HEADERIZER HFILE: src/gc/gc_private.h */
-
-/* HEADERIZER BEGIN: static */
-/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
-
-static int end_cycle_cb(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    int flag,
-    SHIM(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static void gc_gms_add_free_object(PARROT_INTERP,
-    SHIM(Fixed_Size_Pool *pool),
-    SHIM(PObj *to_add))
-        __attribute__nonnull__(1);
-
-static void gc_gms_alloc_objects(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static void gc_gms_chain_objects(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    ARGIN(Fixed_Size_Arena *new_arena),
-    size_t real_size)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
-        FUNC_MODIFIES(*pool);
-
-static void gc_gms_clear_hdr_list(PARROT_INTERP, ARGMOD(Gc_gms_hdr_list *l))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*l);
-
-static void gc_gms_clear_igp(PARROT_INTERP, ARGIN(Gc_gms_gen *gen))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-PARROT_MALLOC
-PARROT_CANNOT_RETURN_NULL
-static Gc_gms_gen * gc_gms_create_gen(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    size_t gen_no)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static void gc_gms_end_cycle(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static Gc_gms_gen * gc_gms_find_gen(PARROT_INTERP,
-    ARGIN(const Gc_gms_hdr *h),
-    UINTVAL gen_no)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static PObj * gc_gms_get_free_object(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static void gc_gms_init_gen(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static void gc_gms_init_mark(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static void gc_gms_merge_gen(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    int flag,
-    SHIM(Gc_gms_plan *plan))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static void gc_gms_more_objects(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static void gc_gms_pool_init(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static void gc_gms_promote(PARROT_INTERP,
-    ARGIN(Gc_gms_hdr *h),
-    UINTVAL gen_no)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-static void gc_gms_set_gen(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static void gc_gms_setto_black(PARROT_INTERP,
-    ARGMOD(Gc_gms_hdr *h),
-    int priority)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*h);
-
-static void gc_gms_setto_gray(PARROT_INTERP,
-    ARGIN(Gc_gms_hdr *h),
-    int priority)
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-static void gc_gms_store_hdr_list(PARROT_INTERP,
-    ARGMOD(Gc_gms_hdr_list *l),
-    ARGIN(Gc_gms_hdr *h))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
-        FUNC_MODIFIES(*l);
-
-static void gc_gms_store_igp(PARROT_INTERP, ARGIN(Gc_gms_hdr *h))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-static void gc_gms_sweep(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static int gc_gms_trace_children(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static int gc_gms_trace_root(PARROT_INTERP, int trace_stack)
-        __attribute__nonnull__(1);
-
-static void gc_gms_use_gen(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    int flag,
-    ARGIN(const Gc_gms_plan *plan))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(4)
-        FUNC_MODIFIES(*pool);
-
-static void gms_debug_verify(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    ARGIN(const char *action))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
-        FUNC_MODIFIES(*pool);
-
-static int init_mark_cb(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    int flag,
-    ARGIN(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(4)
-        FUNC_MODIFIES(*pool);
-
-static void parrot_gc_gms_deinit(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static void parrot_gc_gms_run(PARROT_INTERP, UINTVAL flags)
-        __attribute__nonnull__(1);
-
-PARROT_WARN_UNUSED_RESULT
-static int set_gen_cb(PARROT_INTERP,
-    ARGIN(Fixed_Size_Pool *pool),
-    int flag,
-    ARGIN(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(4);
-
-static int sweep_cb_buf(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    int flag,
-    SHIM(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static int sweep_cb_pmc(PARROT_INTERP,
-    ARGIN(Fixed_Size_Pool *pool),
-    int flag,
-    SHIM(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-static int trace_children_cb(PARROT_INTERP,
-    ARGIN(Fixed_Size_Pool *pool),
-    int flag,
-    SHIM(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-static int trace_igp_cb(PARROT_INTERP,
-    ARGIN(Fixed_Size_Pool *pool),
-    int flag,
-    SHIM(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2);
-
-#define ASSERT_ARGS_end_cycle_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_gms_add_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_gc_gms_alloc_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_gms_chain_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool) \
-    || PARROT_ASSERT_ARG(new_arena)
-#define ASSERT_ARGS_gc_gms_clear_hdr_list __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(l)
-#define ASSERT_ARGS_gc_gms_clear_igp __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(gen)
-#define ASSERT_ARGS_gc_gms_create_gen __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_gms_end_cycle __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_gc_gms_find_gen __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(h)
-#define ASSERT_ARGS_gc_gms_get_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_gms_init_gen __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_gms_init_mark __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_gc_gms_merge_gen __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_gms_more_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_gms_pool_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_gms_promote __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(h)
-#define ASSERT_ARGS_gc_gms_set_gen __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_gc_gms_setto_black __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(h)
-#define ASSERT_ARGS_gc_gms_setto_gray __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(h)
-#define ASSERT_ARGS_gc_gms_store_hdr_list __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(l) \
-    || PARROT_ASSERT_ARG(h)
-#define ASSERT_ARGS_gc_gms_store_igp __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(h)
-#define ASSERT_ARGS_gc_gms_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_gc_gms_trace_children __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_gc_gms_trace_root __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_gc_gms_use_gen __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool) \
-    || PARROT_ASSERT_ARG(plan)
-#define ASSERT_ARGS_gms_debug_verify __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool) \
-    || PARROT_ASSERT_ARG(action)
-#define ASSERT_ARGS_init_mark_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool) \
-    || PARROT_ASSERT_ARG(arg)
-#define ASSERT_ARGS_parrot_gc_gms_deinit __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_parrot_gc_gms_run __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_set_gen_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool) \
-    || PARROT_ASSERT_ARG(arg)
-#define ASSERT_ARGS_sweep_cb_buf __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_sweep_cb_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_trace_children_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_trace_igp_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
-/* HEADERIZER END: static */
-
-
-/*
-
-=pod
-
- * XXX
-
-Main problem TODO 1):
-
- [ PCont ]       ... continuation object in old generation
-    |
-    v
- [ Stack chunk ] --> [ e.g. P register frame ]  ... new generation
-
-By pushing a new stack chunk onto the (old) existing stack frame,
-we'd need a WRITE_BARRIER that promotes the stack chunk to the old
-generation of the continuation.
-This would also need an IGP entry for the stack chunk buffer. But -
-as buffers aren't really containers in Parrot - this isn't possible.
-
-To get that right, the code needs better support by the running
-interpreter.
- - never promote continuations (and stacks) in the current stack frame
-   to an old generation
- - create scope_enter / scope_exit opcodes
-
-A scope_enter happens on a subroutine call *and' with new_pad /
-push_pad opcodes. Each lexical scope must have its distinct register
-frame, else timely destruction can't work.
-If the frame needs active destruction, the old frame should be
-converted to the (new-1) generation, the inner frame is the nursery.
-On scope exit the newest (nursery) generation is collected and the
-current generation number is reset back to (new-1).
-
-If the scope_enter doesn't indicate timely destruction, generation
-promoting should be done only, if object statistics indicate the
-presence of a fair amount of live objects.
-
-TODO 2) in lazy sweep
-If timely destruction didn't find (all) eager objects, go back to
-older generations, until all these objects have been seen.
-
-TODO 3) interpreter startup
-After all internal structures are created, promote interpreter state
-into initial first old generation by running one GC cycle before
-program execution begins (or just treat all objects as being alive).
-
-=cut
-
-*/
-
-/*
- * call code to verify chain of pointers after each change
- * this is very expensive, but should be used during development
- */
-#  define GC_GMS_DEBUG 0
-
-#  define UNITS_PER_ALLOC_GROWTH_FACTOR 1.75
-#  define POOL_MAX_BYTES 65536*128
-
-/*
-
-=head2 Initialization functions
-
-=over 4
-
-=item C<static void parrot_gc_gms_deinit(PARROT_INTERP)>
-
-Free used resources.
-
-=cut
-
-*/
-
-static void
-parrot_gc_gms_deinit(PARROT_INTERP)
-{
-    ASSERT_ARGS(parrot_gc_gms_deinit)
-    Memory_Pools * const mem_pools = interp->mem_pools;
-
-    /*
-     * TODO free generations
-     */
-    mem_sys_free(mem_pools->gc_private);
-    mem_pools->gc_private = NULL;
-}
-
-/*
-
-=item C<static void gc_gms_pool_init(PARROT_INTERP, Fixed_Size_Pool *pool)>
-
-Initialize pool variables. This function must set the pool function pointers
-for C<add_free_object>, C<get_free_object>, C<alloc_objects>, and
-C<more_objects>.
-
-=cut
-
-*/
-
-static void
-gc_gms_pool_init(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-{
-    ASSERT_ARGS(gc_gms_pool_init)
-    pool->add_free_object = gc_gms_add_free_object;
-    pool->get_free_object = gc_gms_get_free_object;
-    pool->alloc_objects   = gc_gms_alloc_objects;
-    pool->more_objects    = gc_gms_more_objects;
-
-    /* initialize generations */
-    gc_gms_init_gen(interp, pool);
-    pool->white = pool->white_fin = pool->free_list = &pool->marker;
-
-    pool->object_size += sizeof (Gc_gms_hdr);
-}
-
-/*
-
-=item C<void Parrot_gc_gms_init(PARROT_INTERP)>
-
-Initialize the state structures of the gc system. Called immediately before
-creation of memory pools.
-
-=cut
-
-*/
-
-PARROT_EXPORT
-void
-Parrot_gc_gms_init(PARROT_INTERP)
-{
-    ASSERT_ARGS(Parrot_gc_gms_init)
-    Memory_Pools * const mem_pools = interp->mem_pools;
-
-    mem_pools->gc_private = mem_sys_allocate_zeroed(sizeof (Gc_gms_private));
-
-    /*
-     * set function hooks according to pdd09
-     */
-    interp->gc_sys->do_gc_mark         = parrot_gc_gms_run;
-    interp->gc_sys->finalize_gc_system = parrot_gc_gms_deinit;
-    interp->gc_sys->init_pool          = gc_gms_pool_init;
-
-}
-
-/*
-
-=back
-
-=head2 Interface functions
-
-=over 4
-
-=item C<static void gc_gms_add_free_object(PARROT_INTERP, Fixed_Size_Pool
-*pool, PObj *to_add)>
-
-Unused. White (dead) objects are added in a bunch to the free_list.
-
-=cut
-
-*/
-
-static void
-gc_gms_add_free_object(PARROT_INTERP, SHIM(Fixed_Size_Pool *pool),
-        SHIM(PObj *to_add))
-{
-    ASSERT_ARGS(gc_gms_add_free_object)
-    Parrot_ex_throw_from_c_args(interp, NULL, 1, "gms abuse");
-}
-
-
-/*
-
-=item C<static void gc_gms_chain_objects(PARROT_INTERP, Fixed_Size_Pool *pool,
-Fixed_Size_Arena *new_arena, size_t real_size)>
-
-TODO: interfere custom_destroy and put these items into a
-separate white area, so that a sweep has just to run through these
-objects
-
-Header chain layout:
-- all objects are chained together forming a circular list
-- pool->marker is the "anchor" of the circle (shown twice below)
-
- 1) object allocation
-
- 1a) one bunch of allocated objects was consumed: the free ptr did
-     hit the marker
-
- +===+---+---+---+---+---+===+
- I M I w | w | w | w | w I M I
- +   +---+---+---+---+---+   +
-       ^                   ^
-       |                   |
-       white               free == marker
-
- All these pointer ranges include the first element, but not the last one.
-
-  [white ... free_list)   is the list of all whites
-
- 1b) after allocating another bunch of objects
-
- +===+---+---+---+---+---+---+---+---+---+---+===+
- I M I w | w | w | w | w | f | f | f | f | f I M I
- +   +---+---+---+---+---+---+---+---+---+---+   +
-       ^                   ^                   ^
-       |                   |                   |
-       white               free                marker
-
-=cut
-
-*/
-
-static void
-gc_gms_chain_objects(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool),
-        ARGIN(Fixed_Size_Arena *new_arena), size_t real_size)
-{
-    ASSERT_ARGS(gc_gms_chain_objects)
-    Gc_gms_hdr *next, *prev;
-    size_t i, n;
-
-    Gc_gms_hdr *p = new_arena->start_objects;
-    Gc_gms_hdr * const marker = &pool->marker;
-
-    PARROT_ASSERT(pool->free_list == marker);
-
-    /* update pool statistics */
-    n = new_arena->total_objects;
-    pool->total_objects += n;
-    pool->num_free_objects += n;
-    new_arena->used = n;
-    /* initially all is pointing to marker */
-    if (pool->white == marker) {
-        /* set origin of first allocation */
-        marker->next = p;
-        p->prev = marker;
-        pool->white = pool->white_fin = p;
-        prev = marker;
-    }
-    else
-        prev = marker->prev;
-    /* chain objects together by inserting to the left of marker */
-
-    /* point to end of last object */
-    p = (void*) ((char*) p + real_size * n);
-    next = marker;
-    for (i = 0; i < n; ++i) {
-        p = (void*) ((char *)p - real_size);
-        p->next = next;
-        next->prev = p;
-#  ifndef NDEBUG
-        p->gen = (void *)0xdeadbeef;
-#  endif
-        next = p;
-    }
-    PARROT_ASSERT(p == new_arena->start_objects);
-    p->prev = prev;
-    prev->next = p;
-    pool->free_list = p;
-    PARROT_ASSERT(p != marker);
-}
-
-/*
-
-=item C<static void gc_gms_alloc_objects(PARROT_INTERP, Fixed_Size_Pool
-*pool)>
-
-Allocate new objects for the given pool.
-
-=cut
-
-*/
-
-static void
-gc_gms_alloc_objects(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-{
-    ASSERT_ARGS(gc_gms_alloc_objects)
-    const size_t real_size = pool->object_size;
-    Fixed_Size_Arena * const new_arena = mem_internal_allocate(sizeof (Fixed_Size_Arena));
-    const size_t size = real_size * pool->objects_per_alloc;
-
-    new_arena->start_objects = mem_internal_allocate(size);
-    /* insert arena in list */
-    Parrot_append_arena_in_pool(interp, pool, new_arena, size);
-    /* create chain of objects, set free pointer */
-    gc_gms_chain_objects(interp, pool, new_arena, real_size);
-
-    /* allocate more next time */
-    pool->objects_per_alloc = (UINTVAL) pool->objects_per_alloc *
-        UNITS_PER_ALLOC_GROWTH_FACTOR;
-    size = real_size * pool->objects_per_alloc;
-    if (size > POOL_MAX_BYTES) {
-        pool->objects_per_alloc = POOL_MAX_BYTES / real_size;
-    }
-}
-
-/*
-
-=item C<static void gc_gms_more_objects(PARROT_INTERP, Fixed_Size_Pool *pool)>
-
-Run a GC cycle or allocate new objects for the given pool.
-
-=cut
-
-*/
-
-static void
-gc_gms_more_objects(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-{
-    ASSERT_ARGS(gc_gms_more_objects)
-    if (pool->skip)
-        pool->skip = 0;
-    else if (pool->last_Arena) {
-        Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG);
-        if (pool->num_free_objects <= pool->replenish_level)
-            pool->skip = 1;
-    }
-
-    if (pool->free_list == &pool->marker) {
-        (*pool->alloc_objects) (interp, pool);
-    }
-}
-
-/*
-
-=item C<static PObj * gc_gms_get_free_object(PARROT_INTERP, Fixed_Size_Pool
-*pool)>
-
-Get a new object off the free_list in the given pool.
-
-2) object consumption
-   the free ptr moves towards the marker
-
-=cut
-
-*/
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static PObj *
-gc_gms_get_free_object(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-{
-    ASSERT_ARGS(gc_gms_get_free_object)
-    PObj *ptr;
-    Gc_gms_hdr *hdr;
-
-    hdr = pool->free_list;
-    if (hdr == &pool->marker)
-        (pool->more_objects)(interp, pool);
-
-    hdr = pool->free_list;
-    pool->free_list = hdr->next;
-    hdr->gen = pool->last_gen;
-    ptr = GMSH_to_PObj(hdr);
-    PObj_flags_SETTO((PObj*) ptr, 0);
-    return ptr;
-}
-
-/*
-
-=back
-
-=head2 Generation handling functions
-
-overall header chain layout
-
-           gen 0         gen 1      ...    gen N
-  marker [first last) [first last)  ...   [first last)  marker
-
-The last (youngest) generation N holds these (pool) pointers:
-
-  [ black ... gray )          during marking
-  [ gray ... white )          during marking
-  [ white ... free_list )     allocated items
-  [ free_list ... marker )    free items
-
-The black, white, and generation ranges have additionally (TODO)
-*fin variants, which refer to PMCs that need destruction/finalization.
-These are always in front of the ranges to be processed first.
-
-=over 4
-
-=item C<static Gc_gms_gen * gc_gms_create_gen(PARROT_INTERP, Fixed_Size_Pool
-*pool, size_t gen_no)>
-
-Create a generation structure for the given generation number.
-
-=cut
-
-*/
-
-PARROT_MALLOC
-PARROT_CANNOT_RETURN_NULL
-static Gc_gms_gen *
-gc_gms_create_gen(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool), size_t gen_no)
-{
-    ASSERT_ARGS(gc_gms_create_gen)
-    Gc_gms_gen * const gen = mem_sys_allocate(sizeof (*gen));
-
-    gen->gen_no = gen_no;
-    gen->pool = pool;
-    gen->timely_destruct_obj_sofar = 0;
-    gen->black_color = b_PObj_live_FLAG;
-    gen->prev = NULL;
-    gen->next = NULL;
-    gen->first = gen->last = gen->fin = &pool->marker;
-    gen->igp.first = NULL;
-    gen->igp.last = NULL;
-
-    return gen;
-}
-
-/*
-
-=item C<static void gc_gms_init_gen(PARROT_INTERP, Fixed_Size_Pool *pool)>
-
-Initalize the generation system by creating the first two generations.
-
-=cut
-
-*/
-
-static void
-gc_gms_init_gen(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-{
-    ASSERT_ARGS(gc_gms_init_gen)
-    Gc_gms_private *gmsp;
-    /*
-     * Generations are numbered beginning at zero
-     * 0 ... oldest
-     * 1 ... next oldest
-     *
-     * If a constant hash PMC refers to non-constant header buffers or
-     * items, these items can be placed in the constant generation 0
-     * XXX: OTOH this would work only for this GC subsystem.
-     */
-    pool->first_gen = gc_gms_create_gen(interp, pool, 0);
-    pool->last_gen = pool->first_gen;
-    gmsp = interp->mem_pools->gc_private;
-    gmsp->current_gen_no = 0;
-}
-
-/*
-
-=item C<static Gc_gms_gen * gc_gms_find_gen(PARROT_INTERP, const Gc_gms_hdr *h,
-UINTVAL gen_no)>
-
-Finds the generation associated with the given header and generation number.
-
-=cut
-
-*/
-
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-static Gc_gms_gen *
-gc_gms_find_gen(PARROT_INTERP, ARGIN(const Gc_gms_hdr *h), UINTVAL gen_no)
-{
-    ASSERT_ARGS(gc_gms_find_gen)
-    Gc_gms_gen *gen;
-    const Fixed_Size_Pool * const pool = h->gen->pool;
-
-    PARROT_ASSERT(pool);
-
-    for (gen = pool->first_gen; gen; gen = gen->next) {
-        if (gen_no == gen->gen_no)
-            return gen;
-        if (gen->gen_no > gen_no) {
-            gen = NULL;
-            break;
-        }
-    }
-    /* we could create generations lazily - not all object sizes
-     * might exist in every generation
-     *
-     * TODO insert generation
-     */
-    Parrot_ex_throw_from_c_args(interp, NULL, 1,
-        "generation %d not found for hdr %p", gen_no, h);
-}
-
-/*
-
-=item C<static void gc_gms_promote(PARROT_INTERP, Gc_gms_hdr *h, UINTVAL
-gen_no)>
-
-Promote the header to the specified generation.
-
-=cut
-
-*/
-
-static void
-gc_gms_promote(PARROT_INTERP, ARGIN(Gc_gms_hdr *h), UINTVAL gen_no)
-{
-    ASSERT_ARGS(gc_gms_promote)
-    Gc_gms_gen *gen;
-    Gc_gms_hdr *prev, *next;
-    Fixed_Size_Pool * const pool = h->gen->pool;
-
-    /* unsnap from current generation */
-    prev = h->prev;
-    next = h->next;
-    if (h == pool->white) {
-        pool->white = next;
-    }
-    prev->next = next;
-    next->prev = prev;
-
-    /* locate generation pointer */
-    gen = gc_gms_find_gen(interp, h, gen_no);
-    PARROT_ASSERT(gen->last);
-    PARROT_ASSERT(gen->first);
-
-    /* TODO if it needs destroy put it in front */
-    next = gen->last;
-    if (h == next)
-        next = gen->last = h->next;
-    prev = next->prev;
-    if (gen->first == &pool->marker)
-        gen->first = h;
-    h->prev = prev;
-    h->next = next;
-    prev->next = h;
-    next->prev = h;
-#  if GC_GMS_DEBUG
-    gms_debug_verify(interp, pool, "promote");
-#  endif
-}
-
-/*
-
-=item C<static void gc_gms_store_hdr_list(PARROT_INTERP, Gc_gms_hdr_list *l,
-Gc_gms_hdr *h)>
-
-Store the header into the header list.
-
-=cut
-
-*/
-
-static void
-gc_gms_store_hdr_list(PARROT_INTERP, ARGMOD(Gc_gms_hdr_list *l), ARGIN(Gc_gms_hdr *h))
-{
-    ASSERT_ARGS(gc_gms_store_hdr_list)
-    Gc_gms_hdr_store * const s = l->last;
-
-    /* if it's not created or if it's full allocate new store */
-    if (!s || s->ptr == &s->store[GC_GMS_STORE_SIZE]) {
-        s = mem_sys_allocate(sizeof (Gc_gms_hdr_store));
-        s->ptr = &s->store[0];
-        s->next = NULL;
-        /* chain new store to old one */
-        if (l->first) {
-            PARROT_ASSERT(l->last);
-            l->last->next = s;
-        }
-        else {
-            l->first = s;
-        }
-        l->last = s;
-    }
-    *(s->ptr)++ = h;
-}
-
-/*
-
-=item C<static void gc_gms_clear_hdr_list(PARROT_INTERP, Gc_gms_hdr_list *l)>
-
-Clear the header list and free it's memory to the OS.
-
-=cut
-
-*/
-
-static void
-gc_gms_clear_hdr_list(PARROT_INTERP, ARGMOD(Gc_gms_hdr_list *l))
-{
-    ASSERT_ARGS(gc_gms_clear_hdr_list)
-    Gc_gms_hdr_store *s, *next;
-
-    for (s = l->first; s; s = next) {
-        next = s->next;
-        mem_sys_free(s);
-    }
-    l->first = l->last = NULL;
-}
-
-/*
-
-=item C<static void gc_gms_store_igp(PARROT_INTERP, Gc_gms_hdr *h)>
-
-Add the header to the inter-generational pointer list of it's generation.
-
-=cut
-
-*/
-
-static void
-gc_gms_store_igp(PARROT_INTERP, ARGIN(Gc_gms_hdr *h))
-{
-    ASSERT_ARGS(gc_gms_store_igp)
-    Gc_gms_gen * const gen = h->gen;
-    Gc_gms_hdr_list * const igp = &gen->igp;
-
-    gc_gms_store_hdr_list(interp, igp, h);
-}
-
-/*
-
-=item C<static void gc_gms_clear_igp(PARROT_INTERP, Gc_gms_gen *gen)>
-
-Clear the inter-generational pointer list of the given generation.
-
-=cut
-
-*/
-
-static void
-gc_gms_clear_igp(PARROT_INTERP, ARGIN(Gc_gms_gen *gen))
-{
-    ASSERT_ARGS(gc_gms_clear_igp)
-    Gc_gms_hdr_list * const igp = &gen->igp;
-
-    gc_gms_clear_hdr_list(interp, igp);
-}
-
-/*
-
-=item C<void parrot_gc_gms_wb(PARROT_INTERP, PMC *agg, void *old, void *_new)>
-
-Called by the write barrier. The aggregate belongs to an older generation
-then the I<new> value written into it. Put the header of the new value
-onto the IGP list for the current generation, if it contains pointers
-to other items, and promote it to the old generation.
-
-=cut
-
-*/
-
-void
-parrot_gc_gms_wb(PARROT_INTERP, ARGIN(PMC *agg), ARGIN(void *old),
-    ARGIN(void *_new))
-{
-    ASSERT_ARGS(parrot_gc_gms_wb)
-    Gc_gms_hdr * const nh = PObj_to_GMSH(_new);
-    Gc_gms_hdr * const ah = PObj_to_GMSH(agg);
-
-    /* if this may be an aggregate store it in IGP list, thus making
-     * it a possible root for this generation
-     */
-    if (PObj_is_PMC_TEST((PObj *)_new))
-        gc_gms_store_igp(interp, nh);
-
-    /* promote RHS to old generation of aggregate */
-    gc_gms_promote(interp, nh, ah->gen->gen_no);
-
-    /*
-     * TODO check old - its overwritten, increment overwrite count,
-     * if it's an aggregate all contents *may* be dead now, so
-     * increment overwrite count by elements
-     */
-}
-
-/*
-
-=item C<void parrot_gc_gms_wb_key(PARROT_INTERP, PMC *agg, void *old, void
-*old_key, void *_new, void *new_key)>
-
-=cut
-
-*/
-
-void
-parrot_gc_gms_wb_key(PARROT_INTERP, ARGIN(PMC *agg), ARGIN(void *old),
-    ARGIN(void *old_key), ARGIN(void *_new), ARGIN(void *new_key))
-{
-    ASSERT_ARGS(parrot_gc_gms_wb_key)
-    Gc_gms_hdr *nh, *ah;
-
-    /* handle hash values */
-    parrot_gc_gms_wb(interp, agg, old, _new);
-
-    /* if hash keys are PObj* then promote new key too */
-
-    /* TODO: check if key is a PObj */
-
-    nh = PObj_to_GMSH(new_key);
-    ah = PObj_to_GMSH(agg);
-
-    /* promote new key to old generation of aggregate */
-    gc_gms_promote(interp, nh, ah->gen->gen_no);
-}
-
-typedef struct Gc_gms_plan {
-    int merge_gen;
-    int gen_no;
-} Gc_gms_plan;
-
-/*
-
-=item C<static void gc_gms_merge_gen(PARROT_INTERP, Fixed_Size_Pool *pool, int
-flag, Gc_gms_plan *plan)>
-
-Merge black pointers to the previous generation, and update the free list.
-
-=cut
-
-*/
-
-static void
-gc_gms_merge_gen(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool),
-        int flag, SHIM(Gc_gms_plan *plan))
-{
-    ASSERT_ARGS(gc_gms_merge_gen)
-    Gc_gms_hdr *h;
-
-    /* run through the blacks and set their generation pointer
-     * to the previous generation
-     */
-    Gc_gms_gen * const gen = pool->last_gen;
-    Gc_gms_gen * const prev = gen->prev;
-
-    for (h = pool->black; h != pool->free_list; h = h->next) {
-        h->gen = prev;
-        /* TODO update statistics */
-        /* TODO merge hdrs that need finalization */
-    }
-    prev->last = pool->free_list;
-    /*
-     * clear IGP for gen
-     */
-    gc_gms_clear_igp(interp, gen);
-}
-
-/*
-
-=item C<static void gc_gms_use_gen(PARROT_INTERP, Fixed_Size_Pool *pool, int
-flag, const Gc_gms_plan *plan)>
-
-Specify what generation to use by default.
-
-=cut
-
-*/
-
-static void
-gc_gms_use_gen(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool),
-        int flag, ARGIN(const Gc_gms_plan *plan))
-{
-    ASSERT_ARGS(gc_gms_use_gen)
-    Gc_gms_gen *gen, *prev;
-    UINTVAL next_gen;
-
-    /* set hdr pointers in last generation */
-    gen        = pool->last_gen;
-    gen->first = pool->black;
-    gen->fin   = pool->black_fin;
-    gen->last  = pool->free_list;
-
-    /* create and append a new generation */
-    next_gen       = plan->gen_no + 1;
-    gen            = gc_gms_create_gen(interp, pool, next_gen);
-    prev           = pool->last_gen;
-    pool->last_gen = gen;
-    prev->next     = gen;
-    gen->prev      = prev;
-
-    /* set generation in interpreter */
-    interp->gc_generation = next_gen;
-}
-
-/*
-
-=item C<static int set_gen_cb(PARROT_INTERP, Fixed_Size_Pool *pool, int flag,
-void *arg)>
-
-Set the generation to use, merging if necessary.
-
-=cut
-
-*/
-
-PARROT_WARN_UNUSED_RESULT
-static int
-set_gen_cb(PARROT_INTERP, ARGIN(Fixed_Size_Pool *pool), int flag, ARGIN(void *arg))
-{
-    ASSERT_ARGS(set_gen_cb)
-    Gc_gms_plan * const plan = (Gc_gms_plan *)arg;
-
-    if (plan->merge_gen)
-        gc_gms_merge_gen(interp, pool, flag, plan);
-    else
-        gc_gms_use_gen(interp, pool, flag, plan);
-    return 0;
-}
-
-/*
-
-=item C<static void gc_gms_set_gen(PARROT_INTERP)>
-
-Setup the generations, deciding what to do based on the plan and moving
-headers around as necessary.
-
-=cut
-
-*/
-
-static void
-gc_gms_set_gen(PARROT_INTERP)
-{
-    ASSERT_ARGS(gc_gms_set_gen)
-    Gc_gms_plan plan;
-    Gc_gms_private *gmsp;
-    /*
-     * there are these basic plans
-     * 1) Use the black as the next old generation
-     * 2) Merge the blacks to the existing older generation
-     *    The plan to use depends on the interpreter, specifically, if
-     *    we are doing a lazy run, entering a new scope, or what not.
-     * 3) If we are leaving a scope (denoted by a lazy GC run
-     *    and we had created one or more generations in this scope
-     *    go back by resetting the generation number to the outer
-     *    scope's generation
-     * 4) Check the overwrite count of older generations. If there is
-     *    a significant percentage of possibly dead objects, scan
-     *    older generations too.
-     *
-     * TODO only 1 and 2 done for now
-     *      3) and 4) need to reset live flags of the previous generation(s)
-     *      or better use the per-generation black_color for marking
-     */
-    gmsp = interp->mem_pools->gc_private;
-    plan.merge_gen = 0;
-    plan.gen_no = gmsp->current_gen_no;
-    if (gmsp->current_gen_no > 0)
-        plan.merge_gen = 1;
-    else
-        gmsp->current_gen_no = 1;
-    header_pools_iterate_callback(interp, POOL_ALL, &plan, set_gen_cb);
-}
-
-/*
-
-=back
-
-=head2 Marking functions
-
-Header chain layout
-
-Init: gray := black := white
-
- 3) marking the root set
-
- 3a) the white 'h' is to be set to gray to be scanned for children
-
- +---+---+---+---+---+---+->      +---+->
- | b | b | g | g | g | w          | h |
- +---+---+---+---+---+---+      <-+---+
-   ^       ^           ^
-   |       |           |
-   black   gray        white
-
- 3b) DFS if 'h' needs timely destruction
-
- +---+---+---+---+---+---+---+->
- | b | b | h | g | g | g | w
- +---+---+---+---+---+---+---+
-   ^       ^               ^
-   |       |               |
-   black   gray            white
-
-
- 3c) BFS in the normal case
-
- +---+---+---+---+---+---+---+->
- | b | b | g | g | g | h | w
- +---+---+---+---+---+---+---+
-   ^       ^               ^
-   |       |               |
-   black   gray            white
-
- 3d) the white is a scalar and immediately blackened
-
-
- +---+---+---+---+---+---+---+->
- | b | b | h | g | g | g | w
- +---+---+---+---+---+---+---+
-   ^           ^           ^
-   |           |           |
-   black       gray        white
-
- 3e) blacken the gray 'h' during trace_children
-
- +---+---+---+---+---+---+---+->
- | b | b | h | g | g | g | w
- +---+---+---+---+---+---+---+
-   ^       ^               ^
-   |       |               |
-   black   gray            white
-
-
- +---+---+---+---+---+---+---+->
- | b | b | h | g | g | g | w
- +---+---+---+---+---+---+---+
-   ^           ^           ^
-   |           |           |
-   black       gray        white
-
-=over 4
-
-=cut
-
-*/
-
-/*
-
-=item C<static void gc_gms_setto_gray(PARROT_INTERP, Gc_gms_hdr *h, int
-priority)>
-
-Set the white header C<h> to gray.
-
-=cut
-
-*/
-
-static void
-gc_gms_setto_gray(PARROT_INTERP, ARGIN(Gc_gms_hdr *h), int priority)
-{
-    ASSERT_ARGS(gc_gms_setto_gray)
-    Fixed_Size_Pool * const pool = h->gen->pool;
-    /*
-     * TODO high_priority like in src/gc/api.c
-     */
-    /*
-     * if the white is adjacent to gray, move pointer
-     */
-    if (pool->white == h && (!priority || pool->white == pool->gray))
-        pool->white = h->next;
-    else {
-        Gc_gms_hdr *next, *prev;
-
-        prev = h->prev;
-        next = h->next;
-        if (h == pool->white)
-            pool->white = next;
-        prev->next = next;
-        next->prev = prev;
-
-        if (priority) {
-            /* insert at gray */
-            next = pool->gray;       /* DFS */
-            pool->gray = h;
-        }
-        else {
-            /* insert before white */
-            next = pool->white;                  /* BFS */
-        }
-        prev = next->prev;
-        h->next = next;
-        h->prev = prev;
-        next->prev = h;
-        prev->next = h;
-
-        /* if there wasn't any gray or black before */
-        if (pool->gray == pool->white) {
-            pool->gray = h;
-            if (pool->black == pool->white) {
-                pool->black = h;
-            }
-        }
-    }
-    PARROT_ASSERT(h != pool->white);
-    /* verify all these pointer moves */
-#  if GC_GMS_DEBUG
-    gms_debug_verify(interp, pool, "to_gray");
-#  endif
-}
-
-/*
-
-=item C<static void gc_gms_setto_black(PARROT_INTERP, Gc_gms_hdr *h, int
-priority)>
-
-Set the white header C<h> to black.
-
-=cut
-
-*/
-
-static void
-gc_gms_setto_black(PARROT_INTERP, ARGMOD(Gc_gms_hdr *h), int priority)
-{
-    ASSERT_ARGS(gc_gms_setto_black)
-    Fixed_Size_Pool * const pool = h->gen->pool;
-
-    /*
-     * TODO high_priority like src/gc/api.c
-     * TODO if h needs destructions insert in front of chain
-     */
-    /*
-     * if the white is adjacent to black, move pointer
-     */
-    if (pool->black == h) {
-        PARROT_ASSERT(pool->gray == h);
-        PARROT_ASSERT(pool->white == h);
-        pool->white = h->next;
-        pool->gray = h->next;
-    }
-    else {
-        Gc_gms_hdr *next, *prev;
-
-        prev = h->prev;
-        next = h->next;
-        if (h == pool->white) {
-            pool->white = next;
-            if (h == pool->gray)
-                pool->gray = next;
-        }
-        prev->next = next;
-        next->prev = prev;
-
-        /* insert before gray */
-        next = pool->gray;
-        prev = next->prev;
-        h->next = next;
-        h->prev = prev;
-        next->prev = h;
-        prev->next = h;
-        if (pool->black == pool->gray) {
-            pool->black = h;
-        }
-    }
-    PARROT_ASSERT(h != pool->white);
-    PARROT_ASSERT(h != pool->gray);
-#  if GC_GMS_DEBUG
-    gms_debug_verify(interp, pool, "to_black");
-#  endif
-}
-
-/*
-
-=item C<void parrot_gc_gms_Parrot_gc_mark_PObj_alive(PARROT_INTERP, PObj *obj)>
-
-Set the object live - called by the Parrot_gc_mark_PObj_alive macro
-
-=cut
-
-*/
-
-PARROT_EXPORT
-void
-parrot_gc_gms_Parrot_gc_mark_PObj_alive(PARROT_INTERP, ARGMOD(PObj *obj))
-{
-    ASSERT_ARGS(parrot_gc_gms_Parrot_gc_mark_PObj_alive)
-    Gc_gms_hdr *h;
-    int priority;
-
-    PObj_live_SET(obj);
-    priority =  PObj_needs_early_gc_TEST(obj);
-    if (priority)
-        ++interp->mem_pools->num_early_PMCs_seen;
-    h = PObj_to_GMSH(obj);
-    /* unsnap it from white, put it into gray or black */
-    if (PObj_is_PMC_TEST(obj))
-        gc_gms_setto_gray(interp, h, priority);
-    else
-        gc_gms_setto_black(interp, h, priority);
-}
-
-/*
-
-=item C<static int init_mark_cb(PARROT_INTERP, Fixed_Size_Pool *pool, int
-flag, void *arg)>
-
-Initialization callback, initialize all the pointers.
-
-=cut
-
-*/
-
-static int
-init_mark_cb(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool), int flag, ARGIN(void *arg))
-{
-    ASSERT_ARGS(init_mark_cb)
-    pool->gray = pool->black = pool->black_fin = pool->white;
-#  if GC_GMS_DEBUG
-    gms_debug_verify(interp, pool, "init_mark");
-#  endif
-    return 0;
-}
-
-/*
-
-=item C<static void gc_gms_init_mark(PARROT_INTERP)>
-
-Initialize the mark phase of GC.
-
-=cut
-
-*/
-
-static void
-gc_gms_init_mark(PARROT_INTERP)
-{
-    ASSERT_ARGS(gc_gms_init_mark)
-    Memory_Pools * const mem_pools = interp->mem_pools;
-
-    mem_pools->gc_trace_ptr        = NULL;
-    mem_pools->gc_mark_start       = NULL;
-    mem_pools->num_early_PMCs_seen = 0;
-    mem_pools->num_extended_PMCs   = 0;
-
-    header_pools_iterate_callback(interp, POOL_ALL, 0, init_mark_cb);
-}
-
-/*
-
-=item C<static int trace_igp_cb(PARROT_INTERP, Fixed_Size_Pool *pool, int
-flag, void *arg)>
-
-Trace through the IGP of the pool to find alive items that are pointing
-to items in other generations.
-
-=cut
-
-*/
-
-static int
-trace_igp_cb(PARROT_INTERP, ARGIN(Fixed_Size_Pool *pool), int flag, SHIM(void *arg))
-{
-    ASSERT_ARGS(trace_igp_cb)
-    Gc_gms_hdr_store *s;
-    Gc_gms_gen * const gen = pool->last_gen;
-    Gc_gms_hdr_list * const igp = &gen->igp;
-
-    for (s = igp->first; s; s = s->next) {
-        const Gc_gms_hdr **p;
-        for (p = s->store; p < s->ptr; ++p) {
-            Gc_gms_hdr * const h = *p;
-            Parrot_gc_mark_PObj_alive(interp, GMSH_to_PObj(h));
-        }
-    }
-    return 0;
-}
-
-/*
-
-=item C<static int gc_gms_trace_root(PARROT_INTERP, int trace_stack)>
-
-Trace the root set. If C<trace_stack> is true, trace system areas.
-
-=cut
-
-*/
-
-static int
-gc_gms_trace_root(PARROT_INTERP, int trace_stack)
-{
-    ASSERT_ARGS(gc_gms_trace_root)
-    const int ret = Parrot_gc_trace_root(interp, trace_stack);
-
-    if (ret == 0)
-        return 0;
-    header_pools_iterate_callback(interp, POOL_ALL, 0, trace_igp_cb);
-    return ret;
-}
-
-/*
-
-=item C<static int trace_children_cb(PARROT_INTERP, Fixed_Size_Pool *pool, int
-flag, void *arg)>
-
-Trace through child objects
-
-=cut
-
-*/
-
-static int
-trace_children_cb(PARROT_INTERP, ARGIN(Fixed_Size_Pool *pool), int flag, SHIM(void *arg))
-{
-    ASSERT_ARGS(trace_children_cb)
-    Memory_Pools * const mem_pools = interp->mem_pools;
-    const int lazy_gc = mem_pools->lazy_gc;
-    Gc_gms_hdr *h;
-
-    for (h = pool->gray; h != pool->white;) {
-        PMC * const current = (PMC*)GMSH_to_PObj(h);
-        UINTVAL bits;
-
-        if (lazy_gc && mem_pools->num_early_PMCs_seen >=
-                mem_pools->num_early_gc_PMCs) {
-            return 1;
-        }
-        /* TODO propagate flag in Parrot_gc_mark_PObj_alive */
-        mem_pools->gc_trace_ptr = current;
-        if (!PObj_needs_early_gc_TEST(current))
-            PObj_high_priority_gc_CLEAR(current);
-
-        /* mark children */
-        if (PObj_custom_mark_TEST(current)) {
-            VTABLE_mark(interp, current);
-        }
-        if (h != pool->gray) {
-            /* if a gray was inserted DFS, it is next */
-            h = pool->gray;
-        }
-        else {
-            h = h->next;
-            pool->gray = h;
-        }
-    }
-    return 0;
-}
-
-/*
-
-=item C<static int gc_gms_trace_children(PARROT_INTERP)>
-
-Traverse gray objects: mark and blacken. Returns 0 if the trace was aborted
-lazily.
-
-=cut
-
-*/
-
-static int
-gc_gms_trace_children(PARROT_INTERP)
-{
-    ASSERT_ARGS(gc_gms_trace_children)
-    return !header_pools_iterate_callback(interp, POOL_PMC, 0,
-            trace_children_cb);
-}
-
-/*
-
-=item C<static int sweep_cb_pmc(PARROT_INTERP, Fixed_Size_Pool *pool, int
-flag, void *arg)>
-
-move everything from white up to the free_list to the free_list
-scan for active destroy objects
-TODO put these in front of the pool at pool->white_fin
-
-=cut
-
-*/
-
-static int
-sweep_cb_pmc(PARROT_INTERP, ARGIN(Fixed_Size_Pool *pool), int flag, SHIM(void *arg))
-{
-    ASSERT_ARGS(sweep_cb_pmc)
-    Gc_gms_hdr *h;
-    Memory_Pools * const mem_pools = interp->mem_pools;
-
-    /* TODO object stats */
-
-    for (h = pool->white; h != pool->free_list; h = h->next) {
-        PMC * const obj = (PMC*)GMSH_to_PObj(h);
-        if (PObj_needs_early_gc_TEST(obj))
-            --mem_pools->num_early_gc_PMCs;
-        if (PObj_custom_destroy_TEST(obj))
-            VTABLE_destroy(interp, (PMC *)obj);
-    }
-    pool->free_list = pool->white;
-    return 0;
-}
-
-/*
-
-=item C<static int sweep_cb_buf(PARROT_INTERP, Fixed_Size_Pool *pool, int
-flag, void *arg)>
-
-Sweep the buffer pool, freeing things that are dead.
-
-=cut
-
-*/
-
-static int
-sweep_cb_buf(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool), int flag, SHIM(void *arg))
-{
-    ASSERT_ARGS(sweep_cb_buf)
-    Gc_gms_hdr *h;
-
-    /* TODO object stats */
-
-    for (h = pool->white; h != pool->free_list; h = h->next) {
-        PObj * const obj = GMSH_to_PObj(h);
-        /*
-         * this is ugly, we still have to sweep all buffers
-         */
-        if (PObj_sysmem_TEST(obj) && PObj_bufstart(obj)) {
-            /* has sysmem allocated, e.g. Parrot_str_pin */
-            mem_sys_free(PObj_bufstart(obj));
-            PObj_bufstart(obj) = NULL;
-            PObj_buflen(obj) = 0;
-        }
-        else {
-#  ifdef GC_IS_MALLOC
-            /* free allocated space at (int*)bufstart - 1,
-             * but not if it is used COW or external
-             */
-            if (PObj_bufstart(obj) &&
-                    !PObj_is_external_or_free_TESTALL(obj)) {
-                if (PObj_COW_TEST(obj)) {
-                    INTVAL *refcount = PObj_bufrefcountptr(obj);
-
-                    if (!--(*refcount))
-                        free(refcount); /* the actual bufstart */
-                }
-                else
-                    free(PObj_bufrefcountptr(obj));
-            }
-#  else
-            /*
-             * XXX Jarkko did report that on irix pool->mem_pool
-             *     was NULL, which really shouldn't happen
-             */
-            if (pool->mem_pool) {
-                if (!PObj_COW_TEST(obj)) {
-                    ((Variable_Size_Pool *)
-                     pool->mem_pool)->guaranteed_reclaimable +=
-                        PObj_buflen(obj);
-                }
-                ((Variable_Size_Pool *)
-                 pool->mem_pool)->possibly_reclaimable +=
-                    PObj_buflen(obj);
-            }
-#  endif
-            PObj_buflen(obj) = 0;
-        }
-    }
-    pool->free_list = pool->white;
-    return 0;
-}
-
-/*
-
-=item C<static void gc_gms_sweep(PARROT_INTERP)>
-
-Free unused resources, put white objects onto free_list.
-
-=cut
-
-*/
-
-static void
-gc_gms_sweep(PARROT_INTERP)
-{
-    ASSERT_ARGS(gc_gms_sweep)
-    header_pools_iterate_callback(interp, POOL_PMC, 0, sweep_cb_pmc);
-    header_pools_iterate_callback(interp, POOL_BUFFER, 0, sweep_cb_buf);
-}
-
-/*
-
-=item C<static int end_cycle_cb(PARROT_INTERP, Fixed_Size_Pool *pool, int
-flag, void *arg)>
-
-Reset the pointers in the pool at the end of the cycle.
-
-=cut
-
-*/
-
-static int
-end_cycle_cb(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool), int flag, SHIM(void *arg))
-{
-    ASSERT_ARGS(end_cycle_cb)
-    Gc_gms_hdr *h;
-    /*
-     * clear live flags
-     * TODO just swap black and white
-     */
-    if (!pool->black || pool->black == &pool->marker)
-        return 0;
-    for (h = pool->black; h != pool->white; h = h->next)
-        PObj_live_CLEAR(GMSH_to_PObj(h));
-    pool->black = pool->black_fin = pool->gray = pool->white;
-    return 0;
-}
-
-/*
-
-=item C<static void gc_gms_end_cycle(PARROT_INTERP)>
-
-End the cycle, resetting pointers in all pools.
-
-=cut
-
-*/
-
-static void
-gc_gms_end_cycle(PARROT_INTERP)
-{
-    ASSERT_ARGS(gc_gms_end_cycle)
-    header_pools_iterate_callback(interp, POOL_ALL, 0, end_cycle_cb);
-}
-
-/*
-
-=back
-
-=head2 Interface function main entry
-
-=over 4
-
-=item C<static void parrot_gc_gms_run(PARROT_INTERP, UINTVAL flags)>
-
-Interface to C<Parrot_gc_mark_and_sweep>. C<flags> is one of:
-
-  GC_lazy_FLAG   ... timely destruction
-  GC_finish_FLAG ... run a final sweep to destruct objects at
-                      interpreter shutdown
-
-=cut
-
-*/
-
-static void
-parrot_gc_gms_run(PARROT_INTERP, UINTVAL flags)
-{
-    ASSERT_ARGS(parrot_gc_gms_run)
-    Memory_Pools * const mem_pools = interp->mem_pools;
-    Gc_gms_private *g_gms;
-
-    if (mem_pools->gc_mark_block_level) {
-        return;
-    }
-    ++mem_pools->gc_mark_block_level;
-    g_gms = mem_pools->gc_private;
-    if (flags & GC_finish_FLAG) {
-        Fixed_Size_Pool * const pool = mem_pools->pmc_pool;
-
-        pool->white = pool->marker.next;
-        /* XXX need to sweep over objects that have finalizers only */
-        header_pools_iterate_callback(interp, POOL_PMC, 0, sweep_cb_pmc);
-        gc_gms_end_cycle(interp);
-        --mem_pools->gc_mark_block_level;
-        return;
-    }
-
-    /* normal or lazy mark run */
-    mem_pools->gc_mark_runs++;
-    mem_pools->lazy_gc = (flags & GC_lazy_FLAG);
-    gc_gms_init_mark(interp);
-    if (gc_gms_trace_root(interp, !mem_pools->lazy_gc) &&
-            gc_gms_trace_children(interp)) {
-        gc_gms_sweep(interp);
-        gc_gms_set_gen(interp);
-    }
-    else {
-        /*
-         * successful lazy mark run
-         */
-        ++mem_pools->gc_lazy_mark_runs;
-    }
-    gc_gms_end_cycle(interp);
-    --mem_pools->gc_mark_block_level;
-}
-
-/*
-
-=item C<static void gms_debug_verify(PARROT_INTERP, Fixed_Size_Pool *pool,
-const char *action)>
-
-Debug function, check that everything is right.
-
-=cut
-
-*/
-
-#  if GC_GMS_DEBUG
-static void
-gms_debug_verify(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool), ARGIN(const char *action))
-{
-    ASSERT_ARGS(gms_debug_verify)
-    Gc_gms_hdr *h;
-    int bf, gf, wf, ff;
-    size_t i;
-
-    const size_t n = pool->total_objects;
-
-    bf = gf = wf = ff = 0;
-
-
-    for (i = 0, h = &pool->marker; i <= n + 10; ++i) {
-        if (i && h == &pool->marker)
-            break;
-        if (h == pool->black)
-            bf++;
-        if (h == pool->gray)
-            gf++;
-        if (h == pool->white)
-            wf++;
-        if (h == pool->free_list)
-            ff++;
-        h = h->next;
-    }
-    if (i != n + 1)
-        fprintf(stderr, "gms_verify %s: chain corrupt %u objs %u total\n",
-                action, i, n);
-    if (bf != 1)
-        fprintf(stderr, "gms_verify %s: found %u blacks\n", action, bf);
-    if (gf != 1)
-        fprintf(stderr, "gms_verify %s: found %u grays\n", action, gf);
-    if (wf != 1)
-        fprintf(stderr, "gms_verify %s: found %u whites\n", action, wf);
-    if (ff != 1)
-        fprintf(stderr, "gms_verify %s: found %u frees\n", action, ff);
-}
-
-
-#  endif  /* GC_GMS_DEBUG */
-
-#endif  /* PARROT_GC_GMS */
-
-/*
-
-=back
-
-=head1 SEE ALSO
-
-F<src/gc/api.c>, F<include/parrot/gc_api.h>, F<include/parrot/pobj.h>,
-F<src/gc/incremental_ms.c>
-
-=head1 HISTORY
-
-Initial version by leo (2005.01.12 - 2005.01.30)
-
-=cut
-
-*/
-
-
-/*
- * Local variables:
- *   c-file-style: "parrot"
- * End:
- * vim: expandtab shiftwidth=4:
- */

Deleted: branches/gc-refactor/src/gc/generational_ms.h
==============================================================================
--- branches/gc-refactor/src/gc/generational_ms.h	Tue Sep  8 23:18:43 2009	(r41166)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,82 +0,0 @@
-#ifndef PARROT_GC_GMS_H_GUARD
-#define PARROT_GC_GMS_H_GUARD
-
-/*
- * all objects have this header in front of the actual
- * object pointer. The prev/next pointers chain all existing
- * objects for one pool (sizeclass) together.
- *
- * XXX this could lead to unaligned FLOATVALs in the adjacent PMC
- *     if that's true either insert a dummy or reorder PMC members
- *     ??? How is that possible?
- */
-typedef struct _gc_gms_hdr {
-    struct _gc_gms_hdr *prev;
-    struct _gc_gms_hdr *next;
-    struct _gc_gms_gen *gen;
-    void *gc_dummy_align;       /* see above */
-} Gc_gms_hdr;
-
-#  define PObj_to_GMSH(o) (((Gc_gms_hdr*)(o))-1)
-#  define GMSH_to_PObj(p) ((PObj*) ((p)+1))
-
-/* the structure uses 2 ptrs itself */
-#  define GC_GMS_STORE_SIZE (64-2)
-
-typedef struct _gc_gms_hdr_store {
-    struct _gc_gms_hdr_store *next;
-    Gc_gms_hdr **ptr;                           /* insert location */
-    Gc_gms_hdr * (store[GC_GMS_STORE_SIZE]);    /* array of hdr pointers */
-} Gc_gms_hdr_store;
-
-typedef struct _gc_gms_hdr_list {
-    Gc_gms_hdr_store *first;
-    Gc_gms_hdr_store *last;
-} Gc_gms_hdr_list;
-
-
-/*
- * all objects belong to one generation
- */
-typedef struct _gc_gms_gen {
-    UINTVAL gen_no;                     /* generation number */
-    UINTVAL timely_destruct_obj_sofar;  /* sum up to this generation */
-    UINTVAL black_color;                /* live color of this generation */
-    struct _gc_gms_hdr *first;          /* first header in this generation */
-    struct _gc_gms_hdr *last;           /* last header in this generation */
-    struct _gc_gms_hdr *fin;            /* need destruction/finalization */
-    struct Fixed_Size_Pool *pool;     /* where this generation belongs to */
-    Gc_gms_hdr_list igp;                /* IGPs for this generation */
-    UINTVAL n_possibly_dead;            /* overwritten count */
-    UINTVAL n_objects;                  /* live objects count */
-    struct _gc_gms_gen *prev;
-    struct _gc_gms_gen *next;
-} Gc_gms_gen;
-
-/* System-specific data for the Fixed_Size_Pool struct's gc_sys_private_data field. */
-struct gc_gms_smallobjpool_data {
-    Gc_gms_hdr marker;          /* limit of list ... also the anchor of the "header chain"
-				   -- see gc_gms_chain_objects() */
-    Gc_gms_hdr *black;          /* alive */
-    Gc_gms_hdr *black_fin;      /* alive, needs destruction */
-    Gc_gms_hdr *gray;           /* to be scanned */
-    Gc_gms_hdr *white;          /* unprocessed */
-    Gc_gms_hdr *white_fin;      /* unprocesse, needs destruction */
-
-    Gc_gms_gen *first_gen;      /* linked list of generations */
-    Gc_gms_gen *last_gen;
-};
-
-
-/*For arenas->gc_private*/
-typedef struct Gc_gms_private {
-    UINTVAL current_gen_no;             /* the nursery generation number */
-} Gc_gms_private;
-
-
-/*For gc_sys_priv_data in interp*/
-struct gc_gms_sys_data {
-  UINTVAL gc_generation;        /* GC generation number */
-} gc_gms_sys_data;
-
-#endif /*PARROT_GC_GMS_H_GUARD*/

Deleted: branches/gc-refactor/src/gc/incremental_ms.c
==============================================================================
--- branches/gc-refactor/src/gc/incremental_ms.c	Tue Sep  8 23:18:43 2009	(r41166)
+++ /dev/null	00:00:00 1970	(deleted)
@@ -1,1152 +0,0 @@
-/*
-Copyright (C) 2001-2009, Parrot Foundation.
-$Id$
-
-=head1 NAME
-
-src/gc/incremental_ms.c - Incremental mark and sweep garbage collection
-
-=head1 DESCRIPTION
-
-The following comments describe a new garbage collection scheme for
-Parrot.
-
-The scheme of this algorithm is described in the literature with these
-keywords:
-
- - non-copying, mark & sweep
- - incremental
- - realtime
- - incremental update with write barrier
-
-Further we might try this optimization
-
- - treadmill optimization or
- - implict reclamation
-
-=head1 Drawbacks of the current mark and sweep collector.
-
- * can take arbitrary time to complete (1s for 1 Meg objects)
- * can't be used in multi-threaded Parrot
- * works fast for plain (non-aggregate) objects but suffers badly
-   for nested aggregates or HLL objects
- * the sweep phase takes time proportional to the allocated storage
-
-=head1 INCREMENTAL GARBAGE COLLECTION
-
-=head2 Terms
-
-=over 4
-
-=item object
-
-An item like a buffer header or a PMC which is managed by Parrot's
-dynamic memory system.
-
-=item aggregate
-
-An object that possibly holds references to other objects. For example
-an array, hash, or reference PMC.
-
-=item tri-color marking
-
-All objects have one of three colors: white, grey, or black.
-
-At the beginning of a GC mark run all objects are white (not yet visited).
-During marking objects are greyed (visited - found alive), but their
-contents isn't yet scanned. A fully scanned grey object gets finally
-colored black. It will not again be rescanned in this run.
-
-Only aggregates can be grey, non-containers are blackened immediately.
-
-Objects on the free-list are sometimes denoted having the color off-white
-or ecru.
-
-=item GC
-
-In Parrot tree the copying garbage collector that recycles string and
-buffer memory. Configure.pl has a switch to use a malloc library instead,
-which makes string and buffer memory non-moving.
-
-=item collector
-
-The reclamation system.
-
-=item mutator
-
-The normal operation of the program which may or may not change the
-collectors view of objects.
-
-=item incremental
-
-Garbage collection and normal program operation is interleaved. This
-guarantees short and bounded pause times. Garbage collection doesn't
-significantly interrupt program execution, collector and mutator are
-running pseudo-parallel.
-
-=item root set
-
-All structures in the interpreter that might point to objects. E.g.
-stacks, globals, and of course the registers. All objects the
-interpreter works with, are directly or indirectly reachable starting
-from the root set.
-
-=item the tri-color invariant
-
-At no time a black object may reference a white one directly. Actually
-this is the strong incarnation of the invariant - all paths from black
-objects to white objects lead over at least one grey object.
-
-The weak tri-color invariant is: there is at least one such path to a
-white object, so that it's reachable.
-
-The strong invariant is the basic idea of mark and sweep too. But as the
-mutator isn't running during mark phase, the invariant is never violated.
-
-Due to this invariant, after the root set has been marked and when all
-greyed objects are marked (blackened), the white objects have to be
-dead.
-
-=item paint it black
-
-Or, which color do new objects have?
-
-Actually this should be tunable. Or it depends. If objects are born
-white and die immediately, they get collected in the same GC cycle. OTOH
-when these objects are stored into an existing (black) array, we have to
-do more work to keep the tri-color invariant valid.
-
-Anyway, when allocating new objects white, the collector must run more
-often or must do more work per increment to make the algorithm stop
-somewhen.
-
-=item write barrier
-
-To keep the tri-color invariant valid all pointer stores into black
-objects have to be tracked. If a white object would be stored into a
-black array, and this object isn't refered to by another object it would
-get collected. The write barrier greys the white object, so that it get
-scanned later or alternatively greys the aggregate for a rescan. The latter
-can be better, if a sequence of such stores would happen.
-
-=back
-
-=head2 Data structure overview
-
-The incremental mark and sweep collector has an additional structure in
-the mem_pools that keeps track of the collector's state. Pool and arena
-structures are unchanged. Only the allocation of new arena blocks is done
-much more fine grained in e.g. 8K blocks.
-
-=head2 Implicit reclamation (optional)
-
-=over 4
-
-=item from-space
-
-The graph of all objects found live during the last collection.
-
-=item to-space
-
-The work area of the collector. During marking live objects are "moved"
-from the from-space into the to-space. This is the same as the text_for_GC
-list used in src/gc/api.c. The to-space is initially empty. During marking
-it gets greyed and finally all reachable objects are black.
-
-=item free-list
-
-New objects are allocated from the free-list. The free-list is adjacent
-to the to-space. Allocating a new objects thus means, moving the free
-pointer one word forward and paint the new object black.
-
-=back
-
-All objects get two additional pointers (forward, backward) and are
-arranged like in this scheme:
-
-
-    <-- allocation direction         marking -->
-            |                          |
-  [w] <--> [w] <--> [b] <--> [b] <--> [g] <--> [g] <--> [w] <-> [w]
-
-            ^        ^                 ^                 ^
-            |        |                 |                 |
-   free-list-ptr     to-space          scan-pointer      from-space
-
-Objects get "moved" during collection by rearranging the doubly-linked
-object pointers. At the end of a mark run (when the last grey object is
-blackened), the from-space and the free-list are merged serving
-as the new free-list of the next GC cycle. This operation is just a few
-pointer manipulations that replaces the sweep phase of a mark and sweep
-collector.
-
-=head2 Phases of operation
-
-=over 4
-
-=item a) initialization
-
-After interpreter creation the GC system is initialized by marking
-parts of the root set (globals, internal structures).
-
-=item b) program operation
-
-For each bunch of allocated objects (A) the collector does k.A work, for
-some constant k > 1. As new objects are allocated black the number of
-whites is reduced steadily. This means that the throttle factor k could
-be less then one too, but this could highly increase average memory usage.
-
-To keep the memory usage limited k > 1 must hold.
-
-=item c) near the end of a mark phase
-
-The rest of the root set is scanned, i.e. the registers. By deferring
-scanning of registers all temporaries that might have exist somewhen
-just stay unscanned - they will be collected in this mark phase, if
-we allocate new objects white or in the next mark phase.
-
-=item d) finishing a mark phase
-
-The current sweep of the whole arena is done, or with implicit reclamation:
-
-Garbage gets appended to the free-list by merging the unscanned
-from-space with the free-list, these objects are all considered white.
-All other items are in the to-space and are black. These objects
-constitute the from-space of the new collection cycle.
-
-Now he meaning of the black bit is reversed effectively setting the new
-from-space to white.
-
-The next mark phase is initialized in one step a) and the new cycle starts.
-
-Alternatively the mutator could run and allocate objects for some time,
-without starting the collector again, if there are plenty of free objects on
-all free-lists.
-
-=item e) collect buffer memory
-
-Finally, we might trigger a collect run on string and buffer memory if
-there is an impending shortage of resources. While the copying compactor
-is rather independent of the collector that cleans object headers, it's
-more efficient to collect buffer memory when the live information is
-accurate. This avoids copying of dead buffer memory.
-
-=back
-
-=head2 Comparison with our current mark and sweep collector
-
-  MS  ... mark and sweep (stop-the-world)
-  IMS ... incremental mark and sweep
-  IMIR .. incremental mark implicit reclamation
-
-                       MS                 IMS               IMIR
-  ------------------------------------------------------------------------
-  operation            stop-the-world     incremental       incremental
-  time per mark phase  unbounded          bounded           bounded
-  size overhead        1 word             1 word            2 words
-  time overhead        O(2*live + dead)   O(2*live + dead)  O(live)   2)
-
-Notes:
-
-  2) it should be possible to mark containers at once by using the
-     information of the from-space pointers and tracking changes
-     to the aggregate.
-
-=head2 Implementation details and unsorted remarks
-
-=over 4
-
-=item the object graph
-
-The MS and IMS scheme use the next_for_GC pointer for keeping track of
-references. This interferes with the freeze functionality, which can use
-the same pointer to keep track of visited objects.
-
-IMIR has a dedicated pointer pair to build the object graph.
-
-=item Greying objects
-
-Greying objects is done depth-first. This has much better cache locality
-then visiting an object again much later. In the picture above this means
-that grey objects are inserted at the left end of the mark chain immediately
-to the right of the object that gets blackened.
-
-=item big aggregates
-
-Greying has to be done in increments. Big aggregates can't have a mark
-vtable that could run arbitrarily long. This means that the GC system
-must know the layout of arrays, hashes, and objects. This is currently
-true for arrays and objects but not for hashes. But the latter need some
-refactoring of internals anyway.
-
-To avoid visiting all aggregate elements, it could be better to track
-the graph of old aggregates by using a write barrier for all writes into
-the array. This would basically create a generational collector. The old
-generation (the aggregate) isn't scanned. But changes to this "old
-generation" are tracked and reflected in the collectors graph of
-objects.
-
-=item timely destruction
-
-The interpreter arena has a count of currently active objects that need
-timely destruction. When during scope exit an high priority sweep is
-triggered, we have basically two cases:
-
-1) all of these objects were already seen in this mark phase - the scope
-exit can continue.
-
-2) Not all objects were seen - they might be alive or not. This means
-that the mark phase must run to the end to decide, if these objects are
-alive (or again until all are found alive).
-
-To increase performance its likely that we need some additional
-information that keeps track of the location of such objects and just
-try to mark paths to objects that need timely destruction.
-
-=item concurrent or parallel collection
-
-As the described algorithm is already incremental its well-suited for
-parallel collection in a multi-threaded Parrot. The work of greying
-objects can be done in parallel by atomically handling a bunch of
-objects to another thread. After doing some increments of marking, these
-objects then get returned to the shared to-space. The parallel
-collection is finished when the last object is blackened and all threads
-have reached the thread barrier rendezvous point. (Please note the very
-different meaning of barrier here).
-
-But also a single-threaded Parrot can vastly take advantage by running
-increments of the collection during waiting for I/O completion or during
-a sleep opcode.
-
-=back
-
-=head1 FUNCTIONS
-
-=over 4
-
-=cut
-
-*/
-
-#include "parrot/parrot.h"
-#include "parrot/gc_api.h"
-#include "gc_private.h"
-
-/* HEADERIZER HFILE: src/gc/gc_private.h */
-
-/* HEADERIZER BEGIN: static */
-/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
-
-static int collect_cb(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    SHIM(int flag),
-    ARGIN(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(4)
-        FUNC_MODIFIES(*pool);
-
-static void gc_ims_add_free_object(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    ARGOUT(void *to_add))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(3)
-        FUNC_MODIFIES(*pool)
-        FUNC_MODIFIES(*to_add);
-
-static void gc_ims_alloc_objects(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-PARROT_CANNOT_RETURN_NULL
-PARROT_WARN_UNUSED_RESULT
-static void * gc_ims_get_free_object(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static void gc_ims_pool_init(SHIM_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-        __attribute__nonnull__(2)
-        FUNC_MODIFIES(*pool);
-
-static int parrot_gc_ims_collect(PARROT_INTERP, int check_only)
-        __attribute__nonnull__(1);
-
-static void parrot_gc_ims_deinit(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static void parrot_gc_ims_mark(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static void parrot_gc_ims_reinit(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static void parrot_gc_ims_run(PARROT_INTERP, UINTVAL flags)
-        __attribute__nonnull__(1);
-
-static void parrot_gc_ims_run_increment(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static void parrot_gc_ims_sweep(PARROT_INTERP)
-        __attribute__nonnull__(1);
-
-static int sweep_cb(PARROT_INTERP,
-    ARGMOD(Fixed_Size_Pool *pool),
-    int flag,
-    ARGIN(void *arg))
-        __attribute__nonnull__(1)
-        __attribute__nonnull__(2)
-        __attribute__nonnull__(4)
-        FUNC_MODIFIES(*pool);
-
-#define ASSERT_ARGS_collect_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool) \
-    || PARROT_ASSERT_ARG(arg)
-#define ASSERT_ARGS_gc_ims_add_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool) \
-    || PARROT_ASSERT_ARG(to_add)
-#define ASSERT_ARGS_gc_ims_alloc_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_ims_get_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_gc_ims_pool_init __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(pool)
-#define ASSERT_ARGS_parrot_gc_ims_collect __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_parrot_gc_ims_deinit __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_parrot_gc_ims_mark __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_parrot_gc_ims_reinit __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_parrot_gc_ims_run __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_parrot_gc_ims_run_increment __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_parrot_gc_ims_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp)
-#define ASSERT_ARGS_sweep_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = \
-       PARROT_ASSERT_ARG(interp) \
-    || PARROT_ASSERT_ARG(pool) \
-    || PARROT_ASSERT_ARG(arg)
-/* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
-/* HEADERIZER END: static */
-
-
-/* size of one arena */
-#define ALLOCATION_BLOCK_SIZE 8192
-
-/*
- * each ALLOCATIONS_INIT allocations of any object an incremental
- * step is triggered
- */
-#define ALLOCATIONS_INIT      1024*4
-
-/* a mark step does allocations * throttle work */
-#define THROTTLE              1.3
-
-/*
- * if we have at the end total * refill free objects
- * we just do nothing
- */
-#define REFILL_FACTOR         0.5
-
-/*
- * we run the copying collector, if memory pool statistics indicate
- * that this amount of the total size could be freed
- *
- * This factor also depends on the allocation color of buffer headers,
- * which is set to black now. So we are always one mark phase behind
- * and the statistics are rather wrong.
- */
-#define MEM_POOL_RECLAIM      0.2
-
-#if 0
-#  define IMS_DEBUG(x) fprintf (x)
-#else
-#  define IMS_DEBUG(x)
-#endif
-
-typedef enum {          /* these states have to be in execution order */
-    GC_IMS_INITIAL,     /* memory subsystem setup */
-    GC_IMS_STARTING,    /* wait for gc_block_level to clear */
-    GC_IMS_RE_INIT,     /* start of normal operation - mark root */
-    GC_IMS_MARKING,     /* mark children */
-    GC_IMS_START_SWEEP, /* mark finished, start sweep buffers */
-    GC_IMS_SWEEP,       /* sweep buffers */
-    GC_IMS_COLLECT,     /* collect buffer memory */
-    GC_IMS_FINISHED,    /* update statistics */
-    GC_IMS_CONSUMING,   /* when we have plenty of free objects */
-    GC_IMS_DEAD         /* gc is already shutdown */
-
-} gc_ims_state_enum;
-
-typedef struct Gc_ims_private {
-    gc_ims_state_enum   state;
-    size_t      allocations;    /* get_free_object count */
-    size_t      alloc_trigger;  /* after this number of allocations a gc
-                                   increment is triggered */
-    double      throttle;       /* throttle * allocations per increment work */
-    size_t      increments;     /* increment count */
-    int         lazy;           /* timely destruction run */
-    size_t      n_objects;      /* live count of prev run */
-    size_t      n_extended_PMCs;/* PMCs found during mark_special */
-} Gc_ims_private;
-
-
-
-/*
-
-=item C<void Parrot_gc_ims_init(PARROT_INTERP)>
-
-Initialize the state structures of the gc system. Called immediately before
-creation of memory pools. This function must set the function pointers
-for C<add_free_object_fn>, C<get_free_object_fn>, C<alloc_objects_fn>, and
-C<more_objects_fn>.
-
-=cut
-
-*/
-
-void
-Parrot_gc_ims_init(PARROT_INTERP)
-{
-    ASSERT_ARGS(Parrot_gc_ims_init)
-    Memory_Pools * const mem_pools = interp->mem_pools;
-    mem_pools->gc_private    = mem_allocate_zeroed_typed(Gc_ims_private);
-
-    /* set function hooks according to pdd09 */
-
-    interp->gc_sys->do_gc_mark         = parrot_gc_ims_run;
-    interp->gc_sys->finalize_gc_system = parrot_gc_ims_deinit;
-    interp->gc_sys->init_pool          = gc_ims_pool_init;
-
-    /* run init state */
-    parrot_gc_ims_run_increment(interp);
-}
-
-
-/*
-
-=item C<static void gc_ims_pool_init(PARROT_INTERP, Fixed_Size_Pool *pool)>
-
-Initializes a pool by setting the appropriate function pointers to add, get,
-and allocate objects.
-
-=cut
-
-*/
-
-static void
-gc_ims_pool_init(SHIM_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-{
-    ASSERT_ARGS(gc_ims_pool_init)
-    pool->add_free_object = gc_ims_add_free_object;
-    pool->get_free_object = gc_ims_get_free_object;
-    pool->alloc_objects   = gc_ims_alloc_objects;
-    pool->more_objects    = pool->alloc_objects;
-}
-
-
-/*
-
-=item C<static void parrot_gc_ims_deinit(PARROT_INTERP)>
-
-Shuts down this GC system.
-
-=cut
-
-*/
-
-static void
-parrot_gc_ims_deinit(PARROT_INTERP)
-{
-    ASSERT_ARGS(parrot_gc_ims_deinit)
-    Memory_Pools * const mem_pools = interp->mem_pools;
-
-    mem_sys_free(mem_pools->gc_private);
-    mem_pools->gc_private = NULL;
-}
-
-
-
-/*
-
-=item C<static void parrot_gc_ims_reinit(PARROT_INTERP)>
-
-Reinitialize the collector for the next collection cycle.
-
-=cut
-
-*/
-
-static void
-parrot_gc_ims_reinit(PARROT_INTERP)
-{
-    ASSERT_ARGS(parrot_gc_ims_reinit)
-    Gc_ims_private *g_ims;
-    Memory_Pools * const  mem_pools = interp->mem_pools;
-
-    mem_pools->lazy_gc = 0;
-    Parrot_gc_run_init(interp);
-
-    /*
-     * trace root set w/o system areas
-     * TODO also skip volatile roots
-     */
-    Parrot_gc_trace_root(interp, GC_TRACE_ROOT_ONLY);
-
-    g_ims        = (Gc_ims_private *)mem_pools->gc_private;
-    g_ims->state = GC_IMS_MARKING;
-
-}
-
-
-/*
-
-=item C<static void gc_ims_add_free_object(PARROT_INTERP, Fixed_Size_Pool
-*pool, void *to_add)>
-
-Add object C<to_add> to the free_list in the given pool.
-C<pool->num_free_objects> has to be updated by the caller.
-
-=cut
-
-*/
-
-static void
-gc_ims_add_free_object(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool), ARGOUT(void *to_add))
-{
-    ASSERT_ARGS(gc_ims_add_free_object)
-    *(void **)to_add = pool->free_list;
-    pool->free_list  = (GC_MS_PObj_Wrapper*)to_add;
-#if DISABLE_GC_DEBUG
-    UNUSED(interp);
-#else
-    if (GC_DEBUG(interp)  && pool == interp->mem_pools->pmc_pool) {
-        PMC * const p = (PMC *)to_add;
-        p->vtable     = interp->vtables[enum_class_Null];
-    }
-#endif
-}
-
-/*
-
-=item C<static void * gc_ims_get_free_object(PARROT_INTERP, Fixed_Size_Pool
-*pool)>
-
-Get a new object off the free_list in the given pool.
-
-=cut
-
-*/
-
-PARROT_CANNOT_RETURN_NULL
-PARROT_WARN_UNUSED_RESULT
-static void *
-gc_ims_get_free_object(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-{
-    ASSERT_ARGS(gc_ims_get_free_object)
-    PObj *ptr;
-    Memory_Pools * const mem_pools    = interp->mem_pools;
-    Gc_ims_private * const g_ims = (Gc_ims_private *)mem_pools->gc_private;
-
-    if (++g_ims->allocations >= g_ims->alloc_trigger) {
-        g_ims->allocations = 0;
-        parrot_gc_ims_run_increment(interp);
-    }
-
-    /* if we don't have any objects */
-    if (!pool->free_list)
-        (*pool->alloc_objects) (interp, pool);
-
-    ptr             = (PObj *)pool->free_list;
-    pool->free_list = (GC_MS_PObj_Wrapper*)(*(void **)ptr);
-
-    /*
-     * buffers are born black, PMCs not yet?
-     * XXX this does not solve the problem of storing keys in hashes
-     *     in the next mark phase (if the key isn't marked elsewhere ?)
-     */
-    PObj_flags_SETTO(ptr, pool == mem_pools->pmc_pool ? 0 : PObj_live_FLAG);
-    --pool->num_free_objects;
-    return (void *)ptr;
-}
-
-
-/*
-
-=item C<static void gc_ims_alloc_objects(PARROT_INTERP, Fixed_Size_Pool
-*pool)>
-
-Allocate new objects for the given pool.
-
-=cut
-
-*/
-
-static void
-gc_ims_alloc_objects(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool))
-{
-    ASSERT_ARGS(gc_ims_alloc_objects)
-    Fixed_Size_Arena *new_arena;
-    size_t size;
-
-    pool->objects_per_alloc  = ALLOCATION_BLOCK_SIZE / pool->object_size;
-
-    /* Setup memory for the new objects */
-    new_arena                = mem_allocate_typed(Fixed_Size_Arena);
-    size                     = ALLOCATION_BLOCK_SIZE;
-    new_arena->start_objects = mem_sys_allocate(size);
-
-    Parrot_append_arena_in_pool(interp, pool, new_arena, size);
-
-    Parrot_add_to_free_list(interp, pool, new_arena);
-}
-
-
-/*
-
-=item C<static void parrot_gc_ims_mark(PARROT_INTERP)>
-
-Mark a bunch of children.
-
-The work depends on item counts with and without a next_for_GC field.
-The former are marked immediately, only the latter need real work here.
-
-=cut
-
-*/
-
-static void
-parrot_gc_ims_mark(PARROT_INTERP)
-{
-    ASSERT_ARGS(parrot_gc_ims_mark)
-    size_t todo;
-    double work_factor;
-    PMC   *next;
-
-    Memory_Pools * const mem_pools    = (Memory_Pools *)interp->mem_pools;
-    Gc_ims_private * const g_ims = (Gc_ims_private *)mem_pools->gc_private;
-
-    /* use statistics from the previous run */
-    if (g_ims->n_objects)
-        work_factor = (double)g_ims->n_extended_PMCs / g_ims->n_objects;
-    else
-        work_factor = 1.0;
-
-    todo = (size_t)(g_ims->alloc_trigger * g_ims->throttle * work_factor);
-
-    PARROT_ASSERT(mem_pools->lazy_gc == 0);
-    Parrot_gc_trace_children(interp, todo);
-
-    /* check if we are finished with marking -- the end is self-referential */
-    next = mem_pools->gc_mark_start;
-
-    if (next == PMC_next_for_GC(next))
-        g_ims->state = GC_IMS_START_SWEEP;
-}
-
-
-/*
-
-=item C<static int sweep_cb(PARROT_INTERP, Fixed_Size_Pool *pool, int flag,
-void *arg)>
-
-Callback to sweep a header pool (see header_pools_iterate_callback).
-
-=cut
-
-*/
-
-static int
-sweep_cb(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool), int flag, ARGIN(void *arg))
-{
-    ASSERT_ARGS(sweep_cb)
-    int * const n_obj = (int *)arg;
-
-    Parrot_gc_sweep_pool(interp, pool);
-
-    *n_obj += pool->total_objects - pool->num_free_objects;
-
-    return 0;
-}
-
-
-/*
-
-=item C<static void parrot_gc_ims_sweep(PARROT_INTERP)>
-
-Free unused objects in all header pools.
-
-TODO split work per pool.
-
-=cut
-
-*/
-
-static void
-parrot_gc_ims_sweep(PARROT_INTERP)
-{
-    ASSERT_ARGS(parrot_gc_ims_sweep)
-    Memory_Pools * const  mem_pools = interp->mem_pools;
-    Gc_ims_private *g_ims      = (Gc_ims_private *)mem_pools->gc_private;
-    size_t          n_objects;
-    int             ignored;
-
-    IMS_DEBUG((stderr, "\nSWEEP\n"));
-
-    /*
-     * as we are now gonna kill objects, make sure that we
-     * have traced the current stack
-     * except for a lazy run, which is invoked from the run loop
-     */
-
-    /* TODO mark volatile roots */
-    Parrot_gc_trace_root(interp, g_ims->lazy ? GC_TRACE_ROOT_ONLY
-                                             : GC_TRACE_FULL);
-
-    /* mark (again) rest of children */
-    Parrot_gc_trace_children(interp, (size_t) -1);
-
-    /* now sweep all */
-    n_objects = 0;
-    ignored   = header_pools_iterate_callback(interp, POOL_BUFFER | POOL_PMC,
-            (void*)&n_objects, sweep_cb);
-    UNUSED(ignored);
-
-    g_ims->state           = GC_IMS_COLLECT;
-    g_ims->n_objects       = n_objects;
-}
-
-
-/*
-
-=item C<static int collect_cb(PARROT_INTERP, Fixed_Size_Pool *pool, int flag,
-void *arg)>
-
-Callback to collect a header pool (see header_pools_iterate_callback).
-
-=cut
-
-*/
-
-#if !defined(GC_IS_MALLOC) || !GC_IS_MALLOC
-
-static int
-collect_cb(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool), SHIM(int flag), ARGIN(void *arg))
-{
-    ASSERT_ARGS(collect_cb)
-    const int           check_only = (int)(INTVAL)arg;
-    Variable_Size_Pool * const mem_pool   = pool->mem_pool;
-
-    /* check if there is an associated memory pool */
-    if (!mem_pool)
-        return 0;
-
-    /* and if the memory pool supports compaction */
-    if (!mem_pool->compact)
-        return 0;
-
-    /*
-     * several header pools can share one memory pool
-     * if that pool is already compacted, the following is zero
-     */
-    if (!mem_pool->guaranteed_reclaimable)
-        return 0;
-
-    /* check used size */
-    if ((mem_pool->possibly_reclaimable * mem_pool->reclaim_factor +
-                mem_pool->guaranteed_reclaimable) >=
-            mem_pool->total_allocated * MEM_POOL_RECLAIM) {
-        IMS_DEBUG((stderr, "COMPACT\n"));
-        if (check_only)
-            return 1;
-        mem_pool->compact(interp, mem_pool);
-    }
-
-    return 0;
-}
-
-#endif
-
-
-/*
-
-=item C<static int parrot_gc_ims_collect(PARROT_INTERP, int check_only)>
-
-Run the copying collector in memory pools, if it could yield some free memory.
-
-=cut
-
-*/
-
-static int
-parrot_gc_ims_collect(PARROT_INTERP, int check_only)
-{
-    ASSERT_ARGS(parrot_gc_ims_collect)
-#if defined(GC_IS_MALLOC) && GC_IS_MALLOC
-    UNUSED(interp);
-    UNUSED(check_only);
-#else
-    Memory_Pools * const  mem_pools = interp->mem_pools;
-    Gc_ims_private *g_ims;
-    int             ret;
-
-    g_ims = (Gc_ims_private *)mem_pools->gc_private;
-
-    ret   = header_pools_iterate_callback(interp, POOL_BUFFER,
-            (void *)(long)check_only, collect_cb);
-
-    if (ret)
-        return ret;
-
-    if (check_only)
-        return 0;
-
-    g_ims->state = GC_IMS_FINISHED;
-#endif
-    return 0;
-}
-
-
-/*
-
-=item C<static void parrot_gc_ims_run_increment(PARROT_INTERP)>
-
-Run one increment of collection. This function is triggered by object
-allocation.
-
-=cut
-
-*/
-
-static void
-parrot_gc_ims_run_increment(PARROT_INTERP)
-{
-    ASSERT_ARGS(parrot_gc_ims_run_increment)
-    Memory_Pools * const mem_pools    = interp->mem_pools;
-    Gc_ims_private * const g_ims = (Gc_ims_private *)mem_pools->gc_private;
-
-    if (mem_pools->gc_mark_block_level || g_ims->state == GC_IMS_DEAD)
-        return;
-
-    ++g_ims->increments;
-    IMS_DEBUG((stderr, "state = %d => ", g_ims->state));
-
-    switch (g_ims->state) {
-        case GC_IMS_INITIAL:
-            g_ims->state         = GC_IMS_STARTING;
-            g_ims->alloc_trigger = ALLOCATIONS_INIT;
-            g_ims->throttle      = THROTTLE;
-            break;
-        case GC_IMS_STARTING:
-            /*  fall through and start */
-            /* FALLTHRU */
-        case GC_IMS_RE_INIT:
-            parrot_gc_ims_reinit(interp);
-            break;
-
-        case GC_IMS_MARKING:
-            parrot_gc_ims_mark(interp);
-            break;
-
-        case GC_IMS_START_SWEEP:
-            g_ims->state = GC_IMS_SWEEP;
-            /* fall through */
-        case GC_IMS_SWEEP:
-            parrot_gc_ims_sweep(interp);
-            /* fall through */
-        case GC_IMS_COLLECT:
-            (void)parrot_gc_ims_collect(interp, 0);
-            break;
-        case GC_IMS_FINISHED:
-            ++mem_pools->gc_mark_runs;
-            g_ims->state = GC_IMS_CONSUMING;
-            /* fall through */
-        case GC_IMS_CONSUMING:
-            /*
-             * This currently looks only at PMCs and string_headers.
-             * There shouldn't be other pools that could run out of
-             * headers independent of PMCs
-             */
-            if (mem_pools->pmc_pool->num_free_objects <
-                    mem_pools->pmc_pool->total_objects * REFILL_FACTOR) {
-                g_ims->state = GC_IMS_STARTING;
-            }
-            else if (mem_pools->string_header_pool->num_free_objects <
-                    mem_pools->string_header_pool->total_objects *
-                    REFILL_FACTOR) {
-                g_ims->state = GC_IMS_STARTING;
-            }
-            break;
-        default:
-            PANIC(interp, "Unknown state in gc_ims");
-    }
-
-    IMS_DEBUG((stderr, "%d\n", g_ims->state));
-}
-
-
-/*
-
-=item C<static void parrot_gc_ims_run(PARROT_INTERP, UINTVAL flags)>
-
-Interface to C<Parrot_gc_mark_and_sweep>. C<flags> is one of:
-
-  GC_lazy_FLAG   ... timely destruction
-  GC_finish_FLAG ... run until live bits are clear
-
-=cut
-
-*/
-
-static void
-parrot_gc_ims_run(PARROT_INTERP, UINTVAL flags)
-{
-    ASSERT_ARGS(parrot_gc_ims_run)
-    int                    lazy;
-    Memory_Pools * const         mem_pools = interp->mem_pools;
-    Gc_ims_private * const g_ims      = (Gc_ims_private *)mem_pools->gc_private;
-
-    if (mem_pools->gc_mark_block_level || g_ims->state == GC_IMS_DEAD)
-        return;
-
-    if (flags & GC_finish_FLAG) {
-        /*
-         * called from really_destroy. This interpreter is gonna die.
-         * The destruction includes a sweep over PMCs, so that
-         * destructors/finalizers are called.
-         *
-         * Be sure live bits are clear.
-         */
-        if (g_ims->state >= GC_IMS_RE_INIT || g_ims->state < GC_IMS_FINISHED)
-            Parrot_gc_clear_live_bits(interp, mem_pools->pmc_pool);
-
-        Parrot_gc_sweep_pool(interp, interp->mem_pools->pmc_pool);
-        g_ims->state = GC_IMS_DEAD;
-
-        return;
-    }
-
-    /* make the test happy that checks the count ;) */
-    mem_pools->gc_mark_runs++;
-
-    lazy = flags & GC_lazy_FLAG;
-
-    if (!lazy) {
-        /* run a full cycle
-         * TODO if we are called from mem_allocate() in src/resources.c:
-         *   * pass needed size
-         *   * test   examples/benchmarks/gc_header_new.pasm
-         */
-        if (!parrot_gc_ims_collect(interp, 1)) {
-            parrot_gc_ims_run_increment(interp);
-            return;
-        }
-
-        if (g_ims->state >= GC_IMS_FINISHED)
-            g_ims->state = GC_IMS_STARTING;
-
-        while (1) {
-            parrot_gc_ims_run_increment(interp);
-            if (g_ims->state > GC_IMS_COLLECT)
-                break;
-        }
-
-        return;
-    }
-
-    /* lazy GC handling */
-    IMS_DEBUG((stderr, "\nLAZY state = %d\n", g_ims->state));
-    g_ims->lazy = lazy;
-
-    if (g_ims->state >= GC_IMS_COLLECT) {
-        /* we are beyond sweep, timely destruction is done */
-        if (mem_pools->num_early_PMCs_seen >= mem_pools->num_early_gc_PMCs)
-            return;
-
-        /* when not all seen, start a fresh cycle */
-        g_ims->state = GC_IMS_RE_INIT;
-
-        /* run init, which clears lazy seen counter */
-        parrot_gc_ims_run_increment(interp);
-    }
-
-    /*
-     *  run through all steps until we see enough PMCs that need timely
-     *  destruction or we finished sweeping
-     */
-    while (mem_pools->num_early_PMCs_seen < mem_pools->num_early_gc_PMCs) {
-        parrot_gc_ims_run_increment(interp);
-        if (g_ims->state >= GC_IMS_COLLECT)
-            break;
-    }
-
-    /* if we stopped early, the lazy run was successful */
-    if (g_ims->state < GC_IMS_COLLECT)
-        ++mem_pools->gc_lazy_mark_runs;
-
-    g_ims->lazy = 0;
-}
-
-
-/*
-
-=item C<void Parrot_gc_ims_wb(PARROT_INTERP, PMC *agg, PMC *_new)>
-
-Write barrier called by the GC_WRITE_BARRIER macro. Always when storing
-a white object into a black aggregate, either the object must
-be greyed or the aggregate must be rescanned -- so grey it.
-
-=cut
-
-*/
-
-#define GC_IMS_GREY_NEW 1
-
-void
-Parrot_gc_ims_wb(PARROT_INTERP, ARGMOD(PMC *agg), ARGMOD(PMC *_new))
-{
-    ASSERT_ARGS(Parrot_gc_ims_wb)
-#if GC_IMS_GREY_NEW
-    IMS_DEBUG((stderr, "%d agg %p mark %p\n",
-                ((Gc_ims_private *)interp->mem_pools->
-                gc_private)->state, agg, _new));
-    Parrot_gc_mark_PObj_alive(interp, (PObj*)_new);
-#else
-    PObj_get_FLAGS(agg) &= ~ (PObj_live_FLAG|PObj_custom_GC_FLAG);
-    Parrot_gc_mark_PObj_alive(interp, (PObj*)agg);
-#endif
-}
-
-/*
-
-=back
-
-=head1 SEE ALSO
-
-F<src/gc/api.c>, F<include/parrot/gc_api.h>, F<include/parrot/pobj.h>,
-
-=head1 HISTORY
-
-Initial version by leo (2004.08.12 - 2004.08.15)
-
-=cut
-
-*/
-
-/*
- * Local variables:
- *   c-file-style: "parrot"
- * End:
- * vim: expandtab shiftwidth=4:
- */


More information about the parrot-commits mailing list