mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-15 22:03:26 +00:00
Estimated hours taken: 90 An initial implementation of the accurate garbage collector. WORK_IN_PROGRESS: Add an entry for the accurate garbage collector. library/builtin.m: library/mercury_builtin.m: library/std_util.m: runtime/mercury_tabling.h: Deep copy terms using the address of the value instead of just the value. library/io.m: Initialize the garbage collector's rootset with the globals. runtime/Mmakefile: Add new files to the Mmakefile. runtime/mercury_accurate_gc.h: runtime/mercury_accurate_gc.c: The new garbage collector. runtime/mercury_agc_debug.c: runtime/mercury_agc_debug.h: Debugging utilities for the new garbage collector. runtime/mercury_deep_copy.c: runtime/mercury_deep_copy.h: runtime/mercury_deep_copy_body.h: Put the deep copy code in mercury_deep_copy_body.h, and #include it with appropriate #defines in order to get a variant for deep_copy(), and one for agc_deep_copy(). agc_deep_copy() forwards pointers as it copies. Also, deep_copy (all variants) have been modified to take a pointer to the data to be copied, because some variants need to be able to modify it. runtime/mercury_engine.c: runtime/mercury_engine.h: Add a second heap_zone which is the to-space of the copying collector. Add a debug_heap_zone, which is used as a scratch heap for debugging. runtime/mercury_label.c: Instead of realloc(entry_table, ....) do entry_table = realloc(entry_table, ....) to avoid horrible bugs. Also, make sure the tables get initialized before looking up an entry label. runtime/mercury_imp.h: Include mercury_debug.h before most of the modules. (mercury_engine.h adds a new MemoryZone only if we are debugging accurate GC). runtime/mercury_memory.c: Setup the debug_memory_zone sizes. Remove an unnecessary prototype. runtime/mercury_memory_handlers.c: Add code to get the program counter and the stack pointer from the signal context. Call MR_schedule_agc() from default_handler() if doing accurate gc. runtime/mercury_memory_zones.c: Setup the hardzone regardless of whether redzones are used. Add some more debugging information. runtime/mercury_regorder.h: runtime/machdeps/alpha_regs.h: runtime/machdeps/i386_regs.h: Add definitions to make the real machine registers name/number for MR_sp available. runtime/mercury_trace_internal.c: runtime/mercury_trace_util.c: runtime/mercury_trace_util.h: Add MR_trace_write_variable(), which writes terms given their value and type_info. runtime/mercury_wrapper.c: runtime/mercury_wrapper.h: Change the size of the heap redzone when doing accurate GC. Use a small heap when debugging agc. runtime/mercury_debug.h: runtime/mercury_conf_param.h: Add new debugging macros and document them. runtime/mercury_type_info.c: Add const to the pointer arguments of MR_make_type_info.
244 lines
5.5 KiB
C
244 lines
5.5 KiB
C
/*
|
|
** Copyright (C) 1998 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
/*
|
|
** Debugging support for the accurate garbage collector.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include "mercury_trace_util.h"
|
|
#include "mercury_deep_copy.h"
|
|
#include "mercury_agc_debug.h"
|
|
|
|
/*
|
|
** Function prototypes.
|
|
*/
|
|
static void dump_live_value(MR_Live_Lval locn, MemoryZone *heap_zone,
|
|
Word * stack_pointer, Word *current_frame,
|
|
bool do_regs);
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
void
|
|
MR_agc_dump_roots(MR_RootList roots)
|
|
{
|
|
fflush(NULL);
|
|
fprintf(stderr, "Dumping roots\n");
|
|
|
|
#ifdef MR_DEBUG_AGC_PRINT_VARS
|
|
while (roots != NULL) {
|
|
|
|
|
|
/*
|
|
** Restore the registers, because we need to save them
|
|
** to a more permanent backing store (we are going to
|
|
** call Mercury soon, and we don't want it messing with
|
|
** the saved registers).
|
|
*/
|
|
restore_registers();
|
|
MR_copy_regs_to_saved_regs(MAX_REAL_REG + NUM_SPECIAL_REG);
|
|
|
|
MR_hp = MR_ENGINE(debug_heap_zone->min);
|
|
MR_virtual_hp = MR_ENGINE(debug_heap_zone->min);
|
|
|
|
fflush(NULL);
|
|
MR_trace_write_variable((Word) roots->type_info, *roots->root);
|
|
fflush(NULL);
|
|
fprintf(stderr, "\n");
|
|
|
|
MR_copy_saved_regs_to_regs(MAX_REAL_REG + NUM_SPECIAL_REG);
|
|
save_registers();
|
|
roots = roots->next;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void
|
|
MR_agc_dump_stack_frames(MR_Internal *label, MemoryZone *heap_zone,
|
|
Word *stack_pointer, Word *current_frame)
|
|
{
|
|
int i, var_count;
|
|
const MR_Stack_Layout_Vars *vars;
|
|
Word *type_params, type_info, value;
|
|
MR_Stack_Layout_Entry *entry_layout;
|
|
const MR_Stack_Layout_Label *layout;
|
|
Code *success_ip;
|
|
bool top_frame = TRUE;
|
|
|
|
layout = label->i_layout;
|
|
entry_layout = layout->MR_sll_entry;
|
|
|
|
/*
|
|
** For each stack frame...
|
|
*/
|
|
|
|
while (MR_DETISM_DET_STACK(entry_layout->MR_sle_detism)) {
|
|
fprintf(stderr, " label: %s\n", label->i_name);
|
|
|
|
if (success_ip == MR_stack_trace_bottom) {
|
|
break;
|
|
}
|
|
|
|
var_count = layout->MR_sll_var_count;
|
|
vars = &(layout->MR_sll_var_info);
|
|
|
|
type_params = MR_trace_materialize_typeinfos_base(vars,
|
|
top_frame, stack_pointer, current_frame);
|
|
|
|
for (i = 0; i < var_count; i++) {
|
|
MR_Stack_Layout_Var sl_var;
|
|
MR_Live_Type sl_type;
|
|
|
|
|
|
fprintf(stderr, "%-12s\t", vars->MR_slvs_names[i]);
|
|
|
|
sl_var = vars->MR_slvs_pairs[i];
|
|
|
|
dump_live_value(sl_var.MR_slv_locn, heap_zone,
|
|
stack_pointer, current_frame, top_frame);
|
|
fprintf(stderr, "\n");
|
|
fflush(NULL);
|
|
|
|
#ifdef MR_DEBUG_AGC_PRINT_VARS
|
|
/*
|
|
** Restore the registers, because we need to
|
|
** save them to a more permanent backing store
|
|
** (we are going to call Mercury soon, and we
|
|
** don't want it messing with the saved
|
|
** registers).
|
|
*/
|
|
restore_registers();
|
|
MR_copy_regs_to_saved_regs(MAX_REAL_REG +
|
|
NUM_SPECIAL_REG);
|
|
|
|
MR_hp = MR_ENGINE(debug_heap_zone->min);
|
|
MR_virtual_hp = MR_ENGINE(debug_heap_zone->min);
|
|
|
|
if (MR_trace_get_type_and_value_base(&sl_var,
|
|
top_frame, stack_pointer,
|
|
current_frame, type_params,
|
|
&type_info, &value)) {
|
|
printf("\t");
|
|
MR_trace_write_variable(type_info, value);
|
|
printf("\n");
|
|
}
|
|
|
|
MR_copy_saved_regs_to_regs(MAX_REAL_REG +
|
|
NUM_SPECIAL_REG);
|
|
save_registers();
|
|
#endif /* MR_DEBUG_AGC_PRINT_VARS */
|
|
|
|
fflush(NULL);
|
|
|
|
}
|
|
free(type_params);
|
|
|
|
/*
|
|
** Move to the next stack frame.
|
|
*/
|
|
{
|
|
MR_Live_Lval location;
|
|
MR_Lval_Type type;
|
|
int number;
|
|
|
|
location = entry_layout->MR_sle_succip_locn;
|
|
type = MR_LIVE_LVAL_TYPE(location);
|
|
number = MR_LIVE_LVAL_NUMBER(location);
|
|
if (type != MR_LVAL_TYPE_STACKVAR) {
|
|
fatal_error("can only handle stackvars");
|
|
}
|
|
|
|
success_ip = (Code *)
|
|
based_detstackvar(stack_pointer, number);
|
|
stack_pointer = stack_pointer -
|
|
entry_layout->MR_sle_stack_slots;
|
|
label = MR_lookup_internal_by_addr(success_ip);
|
|
}
|
|
|
|
top_frame = FALSE;
|
|
|
|
layout = label->i_layout;
|
|
entry_layout = layout->MR_sll_entry;
|
|
}
|
|
}
|
|
|
|
static void
|
|
dump_live_value(MR_Live_Lval locn, MemoryZone *heap_zone, Word *stack_pointer,
|
|
Word *current_frame, bool do_regs)
|
|
{
|
|
int locn_num;
|
|
Word value = 0;
|
|
int difference;
|
|
bool have_value = FALSE;
|
|
|
|
locn_num = (int) MR_LIVE_LVAL_NUMBER(locn);
|
|
switch (MR_LIVE_LVAL_TYPE(locn)) {
|
|
case MR_LVAL_TYPE_R:
|
|
if (do_regs) {
|
|
value = virtual_reg(locn_num);
|
|
have_value = TRUE;
|
|
fprintf(stderr, "r%d\t", locn_num);
|
|
}
|
|
break;
|
|
|
|
case MR_LVAL_TYPE_F:
|
|
fprintf(stderr, "f%d\t", locn_num);
|
|
break;
|
|
|
|
case MR_LVAL_TYPE_STACKVAR:
|
|
value = based_detstackvar(stack_pointer, locn_num);
|
|
have_value = TRUE;
|
|
fprintf(stderr, "stackvar%d", locn_num);
|
|
break;
|
|
|
|
case MR_LVAL_TYPE_FRAMEVAR:
|
|
value = bt_var(current_frame, locn_num);
|
|
have_value = TRUE;
|
|
fprintf(stderr, "framevar%d", locn_num);
|
|
break;
|
|
|
|
case MR_LVAL_TYPE_SUCCIP:
|
|
fprintf(stderr, "succip");
|
|
break;
|
|
|
|
case MR_LVAL_TYPE_MAXFR:
|
|
fprintf(stderr, "maxfr");
|
|
break;
|
|
|
|
case MR_LVAL_TYPE_CURFR:
|
|
fprintf(stderr, "curfr");
|
|
break;
|
|
|
|
case MR_LVAL_TYPE_HP:
|
|
fprintf(stderr, "hp");
|
|
break;
|
|
|
|
case MR_LVAL_TYPE_SP:
|
|
fprintf(stderr, "sp");
|
|
break;
|
|
|
|
case MR_LVAL_TYPE_UNKNOWN:
|
|
fprintf(stderr, "unknown");
|
|
break;
|
|
|
|
default:
|
|
fprintf(stderr, "DEFAULT");
|
|
break;
|
|
}
|
|
if (have_value) {
|
|
if (value >= (Word) heap_zone->min &&
|
|
value < (Word) heap_zone->hardmax) {
|
|
difference = (Word *) value - (Word *) heap_zone->min;
|
|
fprintf(stderr, "\thp[%d]\t(%lx)", difference,
|
|
(long) value);
|
|
} else {
|
|
fprintf(stderr, "\t \t(%lx)", (long) value);
|
|
}
|
|
}
|
|
}
|
|
|