[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