[m-rev.] diff: refactor mercury_accurate_gc.c
Fergus Henderson
fjh at cs.mu.OZ.AU
Thu Nov 13 00:56:18 AEDT 2003
Estimated hours taken: 4
Branches: main
Refactor the accurate garbage collector code.
No algorithm changes (except some minor modifications to debugging messages).
runtime/mercury_accurate_gc.c:
- Simplify the code and reduce code duplication,
by moving most of the code in the long garbage collection
functions (one for MLDS, one for LLDS) into subroutines.
- Move the definition of init_forwarding_pointer_bitmap() from the
start of the file to the end, so that the code is in top-down
ordering.
- Rename garbage_collect_roots() as traverse_extra_roots(),
for consistency with the names used for traversing the other roots.
- Delete some unused variable declarations.
- Improve the layout in a few places.
- Add some comments.
Workspace: /home/jupiter/fjh/ws-jupiter/mercury
Index: runtime/mercury_accurate_gc.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_accurate_gc.c,v
retrieving revision 1.29
diff -u -d -r1.29 mercury_accurate_gc.c
--- runtime/mercury_accurate_gc.c 11 Nov 2003 09:12:26 -0000 1.29
+++ runtime/mercury_accurate_gc.c 12 Nov 2003 13:51:24 -0000
@@ -15,7 +15,7 @@
** For the LLDS back-end, we detect heap overflow
** using the virtual memory system; the page fault
** handler will set the return address to call the
-** garbage collector.
+** garbage collector. See also compiler/notes/gc_and_c_code.html.
**
** XXX this may cause problems for tight loops that
** allocate memory and don't have any procedure
@@ -27,6 +27,9 @@
** of overwriting the return address, so instead we
** just explicitly call MR_GC_check() to check for
** heap overflow before each heap allocation.
+**
+** For documentation on accurate collection in the MLDS back-end,
+** see compiler/ml_elim_nested.m.
*/
#include "mercury_imp.h"
@@ -37,33 +40,51 @@
#include "mercury_layout_util.h"
#include "mercury_agc_debug.h"
+/*---------------------------------------------------------------------------*/
/*
** Function prototypes.
*/
#ifdef MR_HIGHLEVEL_CODE
-void MR_garbage_collect(void);
-static void traverse_stack(struct MR_StackChain *top);
+ void MR_garbage_collect(void);
+ static void traverse_stack(struct MR_StackChain *top);
#else /* !MR_HIGHLEVEL_CODE */
-MR_define_extern_entry(mercury__garbage_collect_0_0);
+ MR_define_extern_entry(mercury__garbage_collect_0_0);
-static void garbage_collect(MR_Code *saved_success,
+ static void MR_LLDS_garbage_collect(MR_Code *saved_success,
MR_Word *stack_pointer,
MR_Word *max_frame, MR_Word *current_frame);
-static void copy_long_value(MR_Long_Lval locn, MR_TypeInfo type_info,
+ static void traverse_call_stack(MR_Code *success_ip, MR_Internal *label,
+ const MR_Label_Layout *label_layout,
+ MR_Word **ptr_to_stack_pointer,
+ MR_Word **ptr_to_current_frame);
+ static void traverse_nondet_stack(MR_Word *stack_pointer,
+ MR_Word *max_frame, MR_Word *current_frame);
+ static void resize_and_reset_redzone(MR_MemoryZone *old_heap,
+ MR_MemoryZone *new_heap);
+ static void copy_long_value(MR_Long_Lval locn, MR_TypeInfo type_info,
MR_bool copy_regs, MR_Word *stack_pointer,
MR_Word *current_frame);
-static void copy_short_value(MR_Short_Lval locn, MR_TypeInfo type_info,
+ static void copy_short_value(MR_Short_Lval locn, MR_TypeInfo type_info,
MR_bool copy_regs, MR_Word *stack_pointer,
MR_Word *current_frame);
#endif
-static void garbage_collect_roots(void);
+static void notify_gc_start(const MR_MemoryZone *old_heap,
+ const MR_MemoryZone *new_heap);
+static void notify_gc_end(const MR_MemoryZone *old_heap,
+ const MR_MemoryZone *new_heap, const MR_Word *old_hp);
+static void init_forwarding_pointer_bitmap(const MR_MemoryZone *old_heap,
+ MR_Word *old_hp);
+static void swap_heaps(void);
+static void traverse_extra_roots(void);
+static void maybe_clear_old_heap(MR_MemoryZone *old_heap, MR_Word *old_hp);
+/*---------------------------------------------------------------------------*/
/*
** Global variables (only used in this module, however).
*/
@@ -81,30 +102,10 @@
/* The last root on the list */
static MR_RootList last_root = NULL;
+/*---------------------------------------------------------------------------*/
/*
-** Initialize the forwarding pointer bitmap (MR_has_forwarding_pointer[])
-** with all bits unset (zero).
+** The MLDS version of the collector.
*/
-static void
-init_forwarding_pointer_bitmap(const MR_MemoryZone *old_heap, MR_Word *old_hp)
-{
- size_t heap_size_in_words;
- size_t num_words_for_bitmap;
- size_t num_bytes_for_bitmap;
- static size_t prev_num_bytes_for_bitmap;
-
- heap_size_in_words = old_hp - old_heap->min;
- num_words_for_bitmap = (heap_size_in_words + MR_WORDBITS - 1) / MR_WORDBITS;
- num_bytes_for_bitmap = num_words_for_bitmap * sizeof(MR_Word);
- if (MR_has_forwarding_pointer == NULL
- || num_bytes_for_bitmap > prev_num_bytes_for_bitmap)
- {
- MR_has_forwarding_pointer =
- MR_realloc(MR_has_forwarding_pointer, num_bytes_for_bitmap);
- prev_num_bytes_for_bitmap = num_bytes_for_bitmap;
- }
- memset(MR_has_forwarding_pointer, 0, num_bytes_for_bitmap);
-}
#ifdef MR_HIGHLEVEL_CODE
@@ -121,31 +122,16 @@
MR_garbage_collect(void)
{
MR_MemoryZone *old_heap, *new_heap;
- MR_Word *old_hp, *new_hp;
+ MR_Word *old_hp;
old_heap = MR_ENGINE(MR_eng_heap_zone);
new_heap = MR_ENGINE(MR_eng_heap_zone2);
-
- /*
- ** Print some debugging messages.
- */
- if (MR_agc_debug) {
- fprintf(stderr, "\ngarbage_collect() called.\n");
-
- fprintf(stderr, "old_heap->min: %lx \t old_heap->hardmax: %lx\n",
- (long) old_heap->min, (long) old_heap->hardmax);
- fprintf(stderr, "new_heap->min: %lx \t new_heap->hardmax: %lx\n",
- (long) new_heap->min, (long) new_heap->hardmax);
-
- fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
- }
-
old_hp = MR_virtual_hp;
/*
- ** The new heap pointer starts at the bottom of the new heap.
+ ** Print some debugging messages.
*/
- MR_virtual_hp = new_heap->min;
+ notify_gc_start(old_heap, new_heap);
/*
** Initialize the forwarding pointer bitmap.
@@ -154,19 +140,10 @@
/*
** Swap the two heaps.
+ ** The new heap pointer starts at the bottom of the new heap.
*/
- {
- MR_MemoryZone *tmp;
-
- tmp = MR_ENGINE(MR_eng_heap_zone2);
- MR_ENGINE(MR_eng_heap_zone2) = MR_ENGINE(MR_eng_heap_zone);
- MR_ENGINE(MR_eng_heap_zone) = tmp;
- }
-
- if (MR_agc_debug) {
- fprintf(stderr, "Swapped heaps\n");
- fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
- }
+ swap_heaps();
+ MR_virtual_hp = new_heap->min;
/*
** Copy any roots on the stack
@@ -176,44 +153,20 @@
/*
** Copy any roots that are not on the stack.
*/
- garbage_collect_roots();
+ traverse_extra_roots();
+
+ /*
+ ** Clear out the old heap.
+ */
+ maybe_clear_old_heap(old_heap, old_hp);
/*
** Print some more debugging messages,
- ** and clear out the old heap.
*/
if (MR_agc_debug) {
- fprintf(stderr, "Clearing old heap:\n");
-
- {
- MR_Word *tmp_hp;
-
- for (tmp_hp = old_heap->min; tmp_hp <= old_hp; tmp_hp++) {
- *tmp_hp = 0xDEADBEAF;
- }
- }
-
fprintf(stderr, "AFTER:\n");
-
- /* XXX save this, it appears to get clobbered */
- new_hp = MR_virtual_hp;
-
- MR_agc_dump_roots(root_list);
-
- /* XXX restore this, it appears to get clobbered */
- fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
- MR_virtual_hp = new_hp;
- fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
-
- fprintf(stderr, "old heap: %ld bytes, new heap: %ld bytes\n",
- (long) ((char *) old_hp - (char *) old_heap->min),
- (long) ((char *) MR_virtual_hp - (char *) new_heap->min));
- fprintf(stderr, "%ld bytes recovered\n",
- (long) ((char *) old_hp - (char *) old_heap->min) -
- ((char *) MR_virtual_hp - (char *) new_heap->min));
-
- fprintf(stderr, "garbage_collect() done.\n\n");
}
+ notify_gc_end(old_heap, new_heap, old_hp);
}
static void
@@ -229,6 +182,11 @@
}
}
+/*---------------------------------------------------------------------------*/
+/*
+** The LLDS version of the collector.
+*/
+
#else /* !MR_HIGHLEVEL_CODE */
/*
@@ -256,14 +214,12 @@
MR_schedule_agc(MR_Code *pc_at_signal, MR_Word *sp_at_signal,
MR_Word *curfr_at_signal)
{
- MR_Label_Layout *layout;
- const MR_Proc_Layout *proc_layout;
- MR_Long_Lval_Type type;
- MR_Long_Lval location;
- const char *reason;
- MR_Entry *entry_label = NULL;
- int number;
- MR_Determinism determinism;
+ const MR_Proc_Layout *proc_layout;
+ MR_Long_Lval_Type type;
+ MR_Long_Lval location;
+ MR_Entry *entry_label = NULL;
+ int number;
+ MR_Determinism determinism;
if (gc_running) {
/*
@@ -415,7 +371,7 @@
gc_running = MR_TRUE;
MR_save_registers();
- garbage_collect(saved_success, MR_sp, MR_maxfr, MR_curfr);
+ MR_LLDS_garbage_collect(saved_success, MR_sp, MR_maxfr, MR_curfr);
MR_restore_registers();
gc_scheduled = MR_FALSE;
gc_running = MR_FALSE;
@@ -426,56 +382,37 @@
MR_END_MODULE
-/*---------------------------------------------------------------------------*/
-
/*
-** garbage_collect:
+** MR_LLDS_garbage_collect:
**
** The main garbage collection routine.
**
** This is the version for the LLDS back-end. Beware that there is some
** code duplication with the version for the MLDS back-end, which is above.
-**
-** (We use 4 space tabs here because of the depth of indentation).
*/
static void
-garbage_collect(MR_Code *success_ip, MR_Word *stack_pointer,
+MR_LLDS_garbage_collect(MR_Code *success_ip, MR_Word *stack_pointer,
MR_Word *max_frame, MR_Word *current_frame)
{
- MR_Internal *label, *first_label;
- int i, count;
- const MR_Label_Layout *label_layout;
MR_MemoryZone *old_heap, *new_heap;
- MR_TypeInfoParams type_params;
- MR_bool succeeded;
- MR_bool top_frame = MR_TRUE;
- MR_MemoryList allocated_memory_cells = NULL;
- MR_Word *old_hp, *new_hp;
- const MR_Proc_Layout *proc_layout;
+ MR_Word *old_hp;
+
+ MR_Internal *label;
+ const MR_Label_Layout *label_layout;
+
+ MR_Internal *first_label;
MR_Word *first_stack_pointer;
- MR_Word *first_current_frame;
MR_Word *first_max_frame;
+ MR_Word *first_current_frame;
old_heap = MR_ENGINE(MR_eng_heap_zone);
new_heap = MR_ENGINE(MR_eng_heap_zone2);
-
- if (MR_agc_debug) {
- fprintf(stderr, "\ngarbage_collect() called.\n");
-
- fprintf(stderr, "old_heap->min: %lx \t old_heap->hardmax: %lx\n",
- (long) old_heap->min, (long) old_heap->hardmax);
- fprintf(stderr, "new_heap->min: %lx \t new_heap->hardmax: %lx\n",
- (long) new_heap->min, (long) new_heap->hardmax);
-
- fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
- }
-
old_hp = MR_virtual_hp;
/*
- ** The new heap pointer starts at the bottom of the new heap.
+ ** Print some debugging messages
*/
- MR_virtual_hp = new_heap->min;
+ notify_gc_start(old_heap, new_heap);
/*
** Initialize the forwarding pointer bitmap.
@@ -484,19 +421,10 @@
/*
** Swap the two heaps.
+ ** The new heap pointer starts at the bottom of the new heap.
*/
- {
- MR_MemoryZone *tmp;
-
- tmp = MR_ENGINE(MR_eng_heap_zone2);
- MR_ENGINE(MR_eng_heap_zone2) = MR_ENGINE(MR_eng_heap_zone);
- MR_ENGINE(MR_eng_heap_zone) = tmp;
- }
-
- if (MR_agc_debug) {
- fprintf(stderr, "Swapped heaps\n");
- fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
- }
+ swap_heaps();
+ MR_virtual_hp = new_heap->min;
label = MR_lookup_internal_by_addr(success_ip);
label_layout = label->i_layout;
@@ -506,7 +434,9 @@
first_stack_pointer = stack_pointer;
first_current_frame = current_frame;
first_max_frame = max_frame;
+
fprintf(stderr, "BEFORE:\n");
+
MR_agc_dump_stack_frames(first_label, old_heap, first_stack_pointer,
first_current_frame);
MR_agc_dump_nondet_stack_frames(first_label, old_heap,
@@ -530,14 +460,78 @@
** way to do that without traversing the success continuation frames of
** the nondet stack too.)
*/
+ traverse_call_stack(success_ip, label, label_layout,
+ &stack_pointer, ¤t_frame);
+
+ /*
+ ** Next, traverse the whole of the nondet stack.
+ */
+ traverse_nondet_stack(stack_pointer, max_frame, current_frame);
+
+ /*
+ ** Copy any roots that are not on the stack.
+ */
+ traverse_extra_roots();
+
+ /*
+ ** Clear out the old heap. This needs to be
+ ** done _before_ we reset the redzone.
+ */
+ maybe_clear_old_heap(old_heap, old_hp);
+
+ /*
+ ** Compute the new size at which to GC,
+ ** and reset the redzone on the new heap.
+ */
+ resize_and_reset_redzone(old_heap, new_heap);
+
+ /*
+ ** Print some more debugging messages
+ */
+ if (MR_agc_debug) {
+ MR_Word *new_hp;
+
+ fprintf(stderr, "AFTER:\n");
+
+ /* XXX save this, it appears to get clobbered */
+ new_hp = MR_virtual_hp;
+
+ MR_agc_dump_stack_frames(first_label, new_heap, first_stack_pointer,
+ first_current_frame);
+ MR_agc_dump_nondet_stack_frames(first_label, new_heap,
+ first_stack_pointer, first_current_frame, first_max_frame);
+
+ /* XXX restore this, it appears to get clobbered */
+ MR_virtual_hp = new_hp;
+ }
+
+ notify_gc_end(old_heap, new_heap, old_hp);
+}
+
+/*
+** Traverse the call stack. This includes all of the det stack
+** and the success continuation frames on the nondet stack. It does not
+** include the failure continuation frames on the nondet stack.
+** (We really only need to traverse the det stack here, but there's no
+** way to do that without traversing the success continuation frames of
+** the nondet stack too.)
+*/
+static void
+traverse_call_stack(MR_Code *success_ip, MR_Internal *label,
+ const MR_Label_Layout *label_layout,
+ MR_Word **ptr_to_stack_pointer, MR_Word **ptr_to_current_frame)
+{
+ MR_bool top_frame = MR_TRUE;
/*
** For each stack frame ...
*/
do {
- MR_Stack_Walk_Step_Result result;
- const char *problem;
const MR_Label_Layout *return_label_layout;
int short_var_count, long_var_count;
+ int i;
+ MR_MemoryList allocated_memory_cells = NULL;
+ MR_TypeInfoParams type_params;
+ const MR_Proc_Layout *proc_layout;
if (MR_agc_debug) {
MR_printlabel(stderr, (MR_Code *) (MR_Word) label->i_addr);
@@ -557,7 +551,7 @@
** XXX except for the topmost frame!
*/
type_params = MR_materialize_type_params_base(label_layout,
- NULL, stack_pointer, current_frame);
+ NULL, *ptr_to_stack_pointer, *ptr_to_current_frame);
/* Copy each live variable */
@@ -572,7 +566,7 @@
type_info = MR_make_type_info(type_params, pseudo_type_info,
&allocated_memory_cells);
copy_long_value(locn, type_info, top_frame,
- stack_pointer, current_frame);
+ *ptr_to_stack_pointer, *ptr_to_current_frame);
MR_deallocate(allocated_memory_cells);
allocated_memory_cells = NULL;
}
@@ -588,7 +582,7 @@
type_info = MR_make_type_info(type_params, pseudo_type_info,
&allocated_memory_cells);
copy_short_value(locn, type_info, top_frame,
- stack_pointer, current_frame);
+ *ptr_to_stack_pointer, *ptr_to_current_frame);
MR_deallocate(allocated_memory_cells);
allocated_memory_cells = NULL;
}
@@ -610,8 +604,8 @@
MR_fatal_error("can only handle stackvars");
}
success_ip = (MR_Code *)
- MR_based_stackvar(stack_pointer, number);
- stack_pointer = stack_pointer -
+ MR_based_stackvar(*ptr_to_stack_pointer, number);
+ *ptr_to_stack_pointer = *ptr_to_stack_pointer -
proc_layout->MR_sle_stack_slots;
} else {
/*
@@ -624,8 +618,8 @@
*/
/* succip is saved in succip_slot */
assert(location == -1);
- success_ip = MR_succip_slot(current_frame);
- current_frame = MR_succfr_slot(current_frame);
+ success_ip = MR_succip_slot(*ptr_to_current_frame);
+ *ptr_to_current_frame = MR_succfr_slot(*ptr_to_current_frame);
}
label = MR_lookup_internal_by_addr(success_ip);
}
@@ -635,7 +629,7 @@
a redesign of the code around here.
result = MR_stack_walk_step(proc_layout, &label_layout,
- (MR_Word **) &stack_pointer, ¤t_frame, &problem);
+ ptr_to_stack_pointer, ptr_to_current_frame, &problem);
if (result == MR_STEP_ERROR_BEFORE || result == MR_STEP_ERROR_AFTER) {
MR_fatal_error(problem);
@@ -649,19 +643,27 @@
label_layout = return_label_layout;
top_frame = MR_FALSE;
} while (label_layout != NULL); /* end for each stack frame... */
+}
+
+/*
+** Traverse the whole of the nondet stack.
+**
+** XXX The code below is broken. We should use
+** MR_traverse_nondet_stack_from_layout() instead.
+**
+** XXX Will we need correct value of stack_pointer (the pointer
+** to the det stack)?
+** Hopefully not, since I think that for nondet code, all values
+** should be saved on the nondet stack, not the det stack?
+*/
+static void
+traverse_nondet_stack(MR_Word *stack_pointer,
+ MR_Word *max_frame, MR_Word *current_frame)
+{
+ MR_bool top_frame = MR_FALSE; /* XXX always false... is this wrong? */
- /*
- ** Next, traverse the whole of the nondet stack.
- ** XXX The code below is broken. We should use
- ** MR_traverse_nondet_stack_from_layout() instead.
- **
- ** XXX Will we need correct value of stack_pointer (the pointer
- ** to the det stack)?
- ** Hopefully not, since I think that for nondet code, all values
- ** should be saved on the nondet stack, not the det stack?
- */
-
while (max_frame > MR_nondet_stack_trace_bottom) {
+ MR_Internal *label;
#if 0
MR_bool registers_valid;
int frame_size;
@@ -691,7 +693,11 @@
stack_pointer = NULL; /* XXX ??? */
if (label != NULL) {
- int short_var_count, long_var_count;
+ const MR_Label_Layout *label_layout;
+ int short_var_count, long_var_count;
+ int i;
+ MR_MemoryList allocated_memory_cells = NULL;
+ MR_TypeInfoParams type_params;
label_layout = label->i_layout;
short_var_count = MR_short_desc_var_count(label_layout);
@@ -747,76 +753,6 @@
}
max_frame = MR_prevfr_slot(max_frame);
}
-
- /*
- ** Copy any roots that are not on the stack.
- */
- garbage_collect_roots();
-
- if (MR_agc_debug) {
- fprintf(stderr, "Clearing old heap:\n");
-
- {
- MR_Word *tmp_hp;
-
- for (tmp_hp = old_heap->min; tmp_hp <= old_hp; tmp_hp++) {
- *tmp_hp = 0xDEADBEAF;
- }
- }
-
- fprintf(stderr, "AFTER:\n");
-
- /* XXX save this, it appears to get clobbered */
- new_hp = MR_virtual_hp;
-
- MR_agc_dump_stack_frames(first_label, new_heap, first_stack_pointer,
- first_current_frame);
- MR_agc_dump_roots(root_list);
- MR_agc_dump_nondet_stack_frames(first_label, new_heap,
- first_stack_pointer, first_current_frame, first_max_frame);
-
- /* XXX restore this, it appears to get clobbered */
- fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
- MR_virtual_hp = new_hp;
- fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
-
- fprintf(stderr, "old heap: %ld bytes, new heap: %ld bytes\n",
- (long) ((char *) old_hp - (char *) old_heap->min),
- (long) ((char *) MR_virtual_hp - (char *) new_heap->min));
- fprintf(stderr, "%ld bytes recovered\n",
- (long) ((char *) old_hp - (char *) old_heap->min) -
- ((char *) MR_virtual_hp - (char *) new_heap->min));
- }
-
- /* Reset the redzone on the new heap */
- {
- /* These counts include some wasted space between ->min and ->bottom. */
- size_t old_heap_space =
- (char *) old_heap->redzone_base - (char *) old_heap->bottom;
- size_t new_heap_usage =
- (char *) MR_virtual_hp - (char *) new_heap->bottom;
- size_t gc_heap_size;
-
- /*
- ** Set the size at which to GC to be MR_heap_expansion_factor
- ** (which defaults to two) times the current usage,
- ** or the size at which we GC'd last time, whichever is larger.
- */
- gc_heap_size = MR_round_up(
- (size_t) (MR_heap_expansion_factor * new_heap_usage),
- MR_unit);
- if (gc_heap_size < old_heap_space) {
- gc_heap_size = old_heap_space;
- }
- old_heap->redzone_base = (MR_Word *)
- ((char *) old_heap->bottom + gc_heap_size);
- MR_reset_redzone(old_heap);
- }
-
- if (MR_agc_debug) {
- fprintf(stderr, "garbage_collect() done.\n\n");
- }
-
}
/*
@@ -940,17 +876,148 @@
break;
}
}
+
+/*
+** Compute the new size at which to GC,
+** and reset the redzone on the new heap.
+*/
+static void
+resize_and_reset_redzone(MR_MemoryZone *old_heap, MR_MemoryZone *new_heap)
+{
+ /* Reset the redzone on the new heap */
+ {
+ /* These counts include some wasted space between ->min and ->bottom. */
+ size_t old_heap_space =
+ (char *) old_heap->redzone_base - (char *) old_heap->bottom;
+ size_t new_heap_usage =
+ (char *) MR_virtual_hp - (char *) new_heap->bottom;
+ size_t gc_heap_size;
+
+ /*
+ ** Set the size at which to GC to be MR_heap_expansion_factor
+ ** (which defaults to two) times the current usage,
+ ** or the size at which we GC'd last time, whichever is larger.
+ */
+ gc_heap_size = MR_round_up(
+ (size_t) (MR_heap_expansion_factor * new_heap_usage),
+ MR_unit);
+ if (gc_heap_size < old_heap_space) {
+ gc_heap_size = old_heap_space;
+ }
+ old_heap->redzone_base = (MR_Word *)
+ ((char *) old_heap->bottom + gc_heap_size);
+ MR_reset_redzone(old_heap);
+ }
+}
+
#endif /* !MR_HIGHLEVEL_CODE */
+/*---------------------------------------------------------------------------*/
/*
-** garbage_collect_roots:
+** Subroutines shared between both the LLDS and MLDS versions of the collector.
+*/
+
+/*
+** Print debugging messages at the start of a collection.
+*/
+static void
+notify_gc_start(const MR_MemoryZone *old_heap, const MR_MemoryZone *new_heap)
+{
+ if (MR_agc_debug) {
+ fprintf(stderr, "\nGarbage collection started.\n");
+
+ fprintf(stderr, "old_heap->min: %lx \t old_heap->hardmax: %lx\n",
+ (long) old_heap->min, (long) old_heap->hardmax);
+ fprintf(stderr, "new_heap->min: %lx \t new_heap->hardmax: %lx\n",
+ (long) new_heap->min, (long) new_heap->hardmax);
+
+ fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
+ }
+}
+
+/*
+** Print debugging messages at the end of a collection.
+*/
+static void
+notify_gc_end(const MR_MemoryZone *old_heap, const MR_MemoryZone *new_heap,
+ const MR_Word *old_hp)
+{
+ if (MR_agc_debug) {
+ MR_Word *new_hp;
+
+ /* XXX save this, it appears to get clobbered */
+ new_hp = MR_virtual_hp;
+
+ MR_agc_dump_roots(root_list);
+
+ /* XXX restore this, it appears to get clobbered */
+ fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
+ MR_virtual_hp = new_hp;
+ fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
+
+ fprintf(stderr, "old heap: %ld bytes, new heap: %ld bytes\n",
+ (long) ((char *) old_hp - (char *) old_heap->min),
+ (long) ((char *) MR_virtual_hp - (char *) new_heap->min));
+ fprintf(stderr, "%ld bytes recovered\n",
+ (long) ((char *) old_hp - (char *) old_heap->min) -
+ ((char *) MR_virtual_hp - (char *) new_heap->min));
+
+ fprintf(stderr, "Garbage collection done.\n\n");
+ }
+}
+
+/*
+** Initialize the forwarding pointer bitmap (MR_has_forwarding_pointer[])
+** with all bits unset (zero).
+*/
+static void
+init_forwarding_pointer_bitmap(const MR_MemoryZone *old_heap, MR_Word *old_hp)
+{
+ size_t heap_size_in_words;
+ size_t num_words_for_bitmap;
+ size_t num_bytes_for_bitmap;
+ static size_t prev_num_bytes_for_bitmap;
+
+ heap_size_in_words = old_hp - old_heap->min;
+ num_words_for_bitmap = (heap_size_in_words + MR_WORDBITS - 1) / MR_WORDBITS;
+ num_bytes_for_bitmap = num_words_for_bitmap * sizeof(MR_Word);
+ if (MR_has_forwarding_pointer == NULL
+ || num_bytes_for_bitmap > prev_num_bytes_for_bitmap)
+ {
+ MR_has_forwarding_pointer =
+ MR_realloc(MR_has_forwarding_pointer, num_bytes_for_bitmap);
+ prev_num_bytes_for_bitmap = num_bytes_for_bitmap;
+ }
+ memset(MR_has_forwarding_pointer, 0, num_bytes_for_bitmap);
+}
+
+/*
+** Swap the two heaps.
+*/
+static void
+swap_heaps(void)
+{
+ MR_MemoryZone *tmp;
+
+ tmp = MR_ENGINE(MR_eng_heap_zone2);
+ MR_ENGINE(MR_eng_heap_zone2) = MR_ENGINE(MR_eng_heap_zone);
+ MR_ENGINE(MR_eng_heap_zone) = tmp;
+
+ if (MR_agc_debug) {
+ fprintf(stderr, "Swapped heaps\n");
+ fprintf(stderr, "MR_virtual_hp: %lx\n", (long) MR_virtual_hp);
+ }
+}
+
+/*
+** traverse_extra_roots:
**
** Copies the extra roots. The roots are overwritten
** with the new data.
*/
static void
-garbage_collect_roots(void)
+traverse_extra_roots(void)
{
MR_RootList current = root_list;
@@ -964,9 +1031,29 @@
}
/*
-** MR_agc_add_root_internal:
+** If we're debugging, wipe out the contents of the old heap.
+** This helps ensure that any bugs in the collector show up sooner.
+*/
+static void
+maybe_clear_old_heap(MR_MemoryZone *old_heap, MR_Word *old_hp)
+{
+ if (MR_agc_debug) {
+ fprintf(stderr, "Clearing old heap:\n");
+
+ {
+ MR_Word *tmp_hp;
+
+ for (tmp_hp = old_heap->min; tmp_hp <= old_hp; tmp_hp++) {
+ *tmp_hp = 0xDEADBEAF;
+ }
+ }
+ }
+}
+
+/*
+** MR_agc_add_root:
**
-** Adds a new root to the extra roots.
+** Adds a new root to the set of extra roots.
*/
void
@@ -987,4 +1074,5 @@
last_root = node;
}
}
+
#endif /* MR_NATIVE_GC */
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list