Files
mercury/runtime/mercury_agc_debug.c
Tyson Dowd 376f2c69af An initial implementation of the accurate garbage collector.
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.
1998-07-22 07:55:19 +00:00

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);
}
}
}