Files
mercury/runtime/mercury_debug.h
Zoltan Somogyi ecf1ee3117 Add a mechanism for growing the stacks on demand by adding new segments
Estimated hours taken: 20
Branches: main

Add a mechanism for growing the stacks on demand by adding new segments
to them. You can ask for the new mechanism via a new grade component, stseg
(short for "stack segments").

The mechanism works by adding a test to each increment of a stack pointer (sp
or maxfr). If the test indicates that we are about to run out of stack, we
allocate a new stack segment, allocate a placeholder frame on the new segment,
and then allocate the frame we wanted in the first place on top of the
placeholder. We also override succip to make it point code that will (1)
release the new segment when the newly created stack frame returns, and then
(2) go to the place indicated by the original, overridden succip.

For leaf procedures on the det stack, we optimize away the check of the stack
pointer. We can do this because we reserve some space on each stack for the
use of such stack frames.

My intention is that doc/user_guide.texi and NEWS will be updated once we have
used the feature ourselves for a while and it seems to be stable.

runtime/mercury_grade.h:
	Add the new grade component.

runtime/mercury_conf_param.h:
	Document the new grade component, and the option used to debug stack
	segments.

runtime/mercury_context.[ch]:
	Add new fields to contexts to hold the list of previous segments of the
	det and nondet stacks.

runtime/mercury_memory_zones.[ch]:
	Include a threshold in all zones, for use in stack segments.
	Set it when a zone is allocated.

	Restore the previous #ifdef'd out function MR_unget_zone, for use
	when freeing stack segments execution has fallen out of.

runtime/mercury_debug.[ch]:
	When printing the offsets of pointers into the det and nondet stacks,
	print the number of the segment the pointer points into (unless it is
	the first, in which case we suppress this in the interest of brevity
	and simplicity).

	Make all the functions in this module take a FILE * as an input
	argument; don't print to stdout by default.

runtime/mercury_stacks.[ch]:
	Modify the macros that allocate stack frames to invoke the code for
	adding new stack segments when we are about to run out of stack.

	Standardize on "nondet" over "nond" as the abbreviation referring to
	the nondet stack.

	Conform to the changes in mercury_debug.c.

runtime/mercury_stack_trace.c:
	When traversing the stack, step over the placeholder stack frames
	at the bottoms of stack segments.

	Conform to the changes in mercury_debug.c.

runtime/mercury_wrapper.[ch]:
	Make the default stack size small in grades that support stack
	segments.

	Standardize on "nondet" over "nond" as the abbreviation referring to
	the nondet stack.

	Conform to the changes in mercury_debug.c.

runtime/mercury_memory.c:
	Standardize on "nondet" over "nond" as the abbreviation referring to
	the nondet stack.

runtime/mercury_engine.[ch]:
runtime/mercury_overflow.h:
	Standardize on "nondet" over "nond" as the abbreviation referring to
	the nondet stack.

	Convert these files to four-space indentation.

runtime/mercury_minimal_model.c:
trace/mercury_trace.c:
trace/mercury_trace_util.c:
	Conform to the changes in mercury_debug.c.

compiler/options.m:
	Add the new grade option for stack segments.

compiler/compile_target_code.m:
compiler/handle_options.m:
	Add the new grade component, and handle its exclusions with other grade
	components and optimizations.

compiler/llds.m:
	Extend the incr_sp instruction to record whether the stack frame
	is for a leaf procedure.

compiler/llds_out.m:
	Output the extended incr_sp instruction.

compiler/proc_gen.m:
	Fill in the extra slot in incr_sp instructions.

compiler/goal_util.m:
	Provide a predicate for testing whether a procedure body is a leaf.

compiler/delay_slot.m:
compiler/dupelim.m:
compiler/dupproc.m:
compiler/exprn_aux.m:
compiler/frameopt.m:
compiler/global_data.m:
compiler/jumpopt.m:
compiler/middle_rec.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/peephole.m:
compiler/reassign.m:
compiler/use_local_vars.m:
	Conform to the change in llds.m.

scripts/canonicate_grade.sh-subr:
scripts/init_grade_options.sh-subr:
scripts/parse_grade_options.sh-subr:
scripts/final_grade_options.sh-subr:
scripts/mgnuc.in:
	Handle the new grade component.

	Convert parse_grade_options.sh-subr to four-space indentation.

Mmake.workspace:
	Fix an old bug that prevented bootcheck from working in the new grade:
	when computing the gc grade, use the workspace's version of ml (which
	in this case understands the new grade components), rather than the
	installed ml (which does not).

	(This was a devil to track down, because neither make --debug nor
	strace on make revealed how the installed ml was being invoked,
	and there was no explicit invocation in the Makefile either; the error
	message appeared to come out of thin air just before the completion
	of the stage 2 library. It turned out the invocation happened
	implicitly, as a result of expanding a make variable.)
2006-11-01 02:31:19 +00:00

263 lines
7.9 KiB
C

/*
** Copyright (C) 1995-2003, 2006 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.
*/
/* mercury_debug.h - definitions for debugging messages */
#ifndef MERCURY_DEBUG_H
#define MERCURY_DEBUG_H
#include "mercury_types.h" /* for MR_Word and MR_Code */
#include "mercury_type_info.h" /* for MR_TypeInfo */
#include <stdio.h> /* for FILE */
/*---------------------------------------------------------------------------*/
#ifdef MR_DEBUG_ON
#define MR_DEBUG(X) X
#else
#define MR_DEBUG(X)
#endif
#if !defined(MR_DEBUG_GOTOS)
#define MR_debuggoto(label) ((void)0)
#define MR_debugsreg() ((void)0)
#else
#define MR_debuggoto(label) \
MR_IF (MR_gotodebug, \
(MR_save_transient_registers(), MR_goto_msg(stdout, label)))
#define MR_debugsreg() \
MR_IF (MR_sregdebug, \
(MR_save_transient_registers(), MR_reg_msg(stdout)))
#endif
#ifndef MR_DEBUG_HEAP_ALLOC
#define MR_debug_unravel_univ(univ, typeinfo, value) ((void) 0)
#define MR_debug_new_univ_on_hp(univ, typeinfo, value) ((void) 0)
#define MR_debug_tag_offset_incr_hp_base(ptr, tag, offset, count, is_atomic) \
((void) 0)
#else
#define MR_debug_unravel_univ(univ, typeinfo, value) \
MR_unravel_univ_msg((univ), (typeinfo), (value))
#define MR_debug_new_univ_on_hp(univ, typeinfo, value) \
MR_new_univ_on_hp_msg((univ), (typeinfo), (value))
#define MR_debug_tag_offset_incr_hp_base(ptr, tag, offset, count, is_atomic) \
MR_debug_tag_offset_incr_hp_base_msg((ptr), (tag), \
(offset), (count), (is_atomic))
#endif
#ifndef MR_LOWLEVEL_DEBUG
#define MR_debugcr1(hp) ((void) 0)
#define MR_debugcr2(hp) ((void) 0)
#define MR_debugcr3(hp) ((void) 0)
#define MR_debugincrhp(val, hp) ((void) 0)
#define MR_debugincrsp(val, sp) ((void) 0)
#define MR_debugdecrsp(val, sp) ((void) 0)
#define MR_debugregs(msg) ((void) 0)
#define MR_debugframe(msg) ((void) 0)
#define MR_debugmkframe(predname) ((void) 0)
#define MR_debugmktempframe() ((void) 0)
#define MR_debugmkdettempframe() ((void) 0)
#define MR_debugsucceed() ((void) 0)
#define MR_debugsucceeddiscard() ((void) 0)
#define MR_debugfail() ((void) 0)
#define MR_debugredo() ((void) 0)
#define MR_debugcall(proc, succ_cont) ((void) 0)
#define MR_debugtailcall(proc) ((void) 0)
#define MR_debugproceed() ((void) 0)
#define MR_debugmsg0(msg) ((void) 0)
#define MR_debugmsg1(msg, arg1) ((void) 0)
#define MR_debugmsg2(msg, arg1, arg2) ((void) 0)
#define MR_debugmsg3(msg, arg1, arg2, arg3) ((void) 0)
#else
#define MR_debugcr1(hp) \
MR_IF (MR_heapdebug, \
(MR_save_transient_registers(), \
MR_cr1_msg(stdout, hp)))
#define MR_debugcr2(hp) \
MR_IF (MR_heapdebug, \
(MR_save_transient_registers(), \
MR_cr2_msg(stdout, hp)))
#define MR_debugcr3(hp) \
MR_IF (MR_heapdebug, \
(MR_save_transient_registers(), \
MR_cr3_msg(stdout, hp)))
#define MR_debugincrhp(val, hp) \
MR_IF (MR_heapdebug, \
(MR_save_transient_registers(), \
MR_incr_hp_debug_msg(stdout, (val), (hp))))
#define MR_debugincrsp(val, sp) \
MR_IF (MR_detstackdebug, \
(MR_save_transient_registers(), \
MR_incr_sp_msg(stdout, (val), (sp))))
#define MR_debugdecrsp(val, sp) \
MR_IF (MR_detstackdebug, \
(MR_save_transient_registers(), \
MR_decr_sp_msg(stdout, (val), (sp))))
#define MR_debugregs(msg) \
MR_IF (MR_progdebug, \
(MR_save_transient_registers(), \
MR_printregs(stdout, msg)))
#define MR_debugframe(msg) \
MR_IF (MR_progdebug, \
(MR_save_transient_registers(), \
MR_printframe(stdout, msg)))
#define MR_debugmkframe(predname) \
MR_IF (MR_nondetstackdebug, \
(MR_save_transient_registers(), \
MR_mkframe_msg(stdout, predname)))
#define MR_debugmktempframe() \
MR_IF (MR_nondetstackdebug, \
(MR_save_transient_registers(), \
MR_mktempframe_msg(stdout)))
#define MR_debugmkdettempframe() \
MR_IF (MR_nondetstackdebug, \
(MR_save_transient_registers(), \
MR_mkdettempframe_msg(stdout)))
#define MR_debugsucceed() \
MR_IF (MR_calldebug, \
(MR_save_transient_registers(), \
MR_succeed_msg(stdout)))
#define MR_debugsucceeddiscard() \
MR_IF (MR_calldebug, \
(MR_save_transient_registers(), \
MR_succeeddiscard_msg(stdout)))
#define MR_debugfail() \
MR_IF (MR_calldebug, \
(MR_save_transient_registers(), \
MR_fail_msg(stdout)))
#define MR_debugredo() \
MR_IF (MR_calldebug, \
(MR_save_transient_registers(), \
MR_redo_msg(stdout)))
#define MR_debugcall(proc, succ_cont) \
MR_IF (MR_calldebug, \
(MR_save_transient_registers(), \
MR_call_msg(stdout, proc, succ_cont)))
#define MR_debugtailcall(proc) \
MR_IF (MR_calldebug, \
(MR_save_transient_registers(), \
MR_tailcall_msg(stdout, proc)))
#define MR_debugproceed() \
MR_IF (MR_calldebug, \
(MR_save_transient_registers(), \
MR_proceed_msg(stdout)))
#define MR_debugmsg0(msg) \
MR_IF (MR_progdebug, (fprintf(stdout, msg)))
#define MR_debugmsg1(msg, arg1) \
MR_IF (MR_progdebug, (fprintf(stdout, msg, arg1)))
#define MR_debugmsg2(msg, arg1, arg2) \
MR_IF (MR_progdebug, (fprintf(stdout, msg, arg1, arg2)))
#define MR_debugmsg3(msg, arg1, arg2, arg3) \
MR_IF (MR_progdebug, (fprintf(stdout, msg, arg1, arg2, arg3)))
#endif /* MR_LOWLEVEL_DEBUG */
#define MR_print_deep_prof_vars(fp, msg) \
do { \
fprintf(fp, "%s\n", msg); \
MR_print_deep_prof_var(fp, "curcsd", \
MR_current_call_site_dynamic); \
MR_print_deep_prof_var(fp, "nextcsd", \
MR_next_call_site_dynamic); \
} while (0)
/*---------------------------------------------------------------------------*/
#ifdef MR_DEBUG_HEAP_ALLOC
extern void MR_unravel_univ_msg(FILE *fp, MR_Word univ,
MR_TypeInfo type_info, MR_Word value);
extern void MR_new_univ_on_hp_msg(FILE *fp, MR_Word univ,
MR_TypeInfo type_info, MR_Word value);
extern void MR_debug_tag_offset_incr_hp_base_msg(FILE *fp, MR_Word ptr,
int tag, int offset, int count, int is_atomic);
#endif
#ifdef MR_LOWLEVEL_DEBUG
extern void MR_mkframe_msg(FILE *fp, const char *);
extern void MR_mktempframe_msg(FILE *fp);
extern void MR_mkdettempframe_msg(FILE *fp);
extern void MR_succeed_msg(FILE *fp);
extern void MR_succeeddiscard_msg(FILE *fp);
extern void MR_fail_msg(FILE *fp);
extern void MR_redo_msg(FILE *fp);
extern void MR_call_msg(FILE *fp, const MR_Code *proc,
const MR_Code *succ_cont);
extern void MR_tailcall_msg(FILE *fp, const MR_Code *proc);
extern void MR_proceed_msg(FILE *fp);
extern void MR_cr1_msg(FILE *fp, const MR_Word *addr);
extern void MR_cr2_msg(FILE *fp, const MR_Word *addr);
extern void MR_cr3_msg(FILE *fp, const MR_Word *addr);
extern void MR_incr_hp_debug_msg(FILE *fp, MR_Word val,
const MR_Word *addr);
extern void MR_incr_sp_msg(FILE *fp, MR_Word val, const MR_Word *addr);
extern void MR_decr_sp_msg(FILE *fp, MR_Word val, const MR_Word *addr);
#endif
#ifdef MR_DEBUG_GOTOS
extern void MR_goto_msg(FILE *fp, const MR_Code *addr);
extern void MR_reg_msg(FILE *fp);
#endif
#ifdef MR_LOWLEVEL_DEBUG
extern void MR_printint(FILE *fp, MR_Word n);
extern void MR_printstring(FILE *fp, const char *s);
extern void MR_printheap(FILE *fp, const MR_Word *h);
extern void MR_dumpframe(FILE *fp, const MR_Word *);
extern void MR_dumpnondetstack(FILE *fp);
extern void MR_printlist(FILE *fp, MR_Word p);
extern void MR_printframe(FILE *fp, const char *);
extern void MR_printregs(FILE *fp, const char *msg);
#endif
extern void MR_printdetstack(FILE *fp, const MR_Word *s);
extern void MR_print_detstackptr(FILE *fp, const MR_Word *s);
extern void MR_printnondetstack(FILE *fp, const MR_Word *s);
extern void MR_print_nondetstackptr(FILE *fp, const MR_Word *s);
extern void MR_print_heapptr(FILE *fp, const MR_Word *s);
extern void MR_print_label(FILE *fp, const MR_Code *w);
extern void MR_printlabel(FILE *fp, const MR_Code *w);
extern void MR_print_deep_prof_var(FILE *fp, const char *name,
MR_CallSiteDynamic *csd);
/*---------------------------------------------------------------------------*/
#endif /* not MERCURY_DEBUG_H */