Files
mercury/runtime/mercury_engine.h
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

319 lines
9.1 KiB
C

/*
** Copyright (C) 1994-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.
*/
/*
** mercury_engine.h - definitions for the Mercury runtime engine.
**
** For documentation, see also the comments in mercury_engine.c.
*/
#ifndef MERCURY_ENGINE_H
#define MERCURY_ENGINE_H
/*
** include mercury_regs.h first so that we don't have
** any function prototypes before the global register
** declarations.
*/
#include "mercury_regs.h" /* for NUM_REAL_REGS */
#include <setjmp.h>
#include "mercury_std.h" /* for `bool' */
#include "mercury_types.h" /* for `Code *' */
#include "mercury_goto.h" /* for `Define_entry()' */
#include "mercury_thread.h" /* for pthread types */
#include "mercury_context.h" /* for MR_Context, MR_IF_USE_TRAIL */
/*---------------------------------------------------------------------------*/
/*
** Global flags that control the behaviour of the Mercury engine(s)
*/
extern bool debugflag[];
#define PROGFLAG 0
#define GOTOFLAG 1
#define CALLFLAG 2
#define HEAPFLAG 3
#define DETSTACKFLAG 4
#define NONDSTACKFLAG 5
#define FINALFLAG 6
#define MEMFLAG 7
#define SREGFLAG 8
#define TRACEFLAG 9
#define DETAILFLAG 10
#define MAXFLAG 11
/* DETAILFLAG should be the last real flag */
#define progdebug debugflag[PROGFLAG]
#define gotodebug debugflag[GOTOFLAG]
#define calldebug debugflag[CALLFLAG]
#define heapdebug debugflag[HEAPFLAG]
#define detstackdebug debugflag[DETSTACKFLAG]
#define nondstackdebug debugflag[NONDSTACKFLAG]
#define finaldebug debugflag[FINALFLAG]
#define memdebug debugflag[MEMFLAG]
#define sregdebug debugflag[SREGFLAG]
#define tracedebug debugflag[TRACEFLAG]
#define detaildebug debugflag[DETAILFLAG]
/*
** MR_setjmp and MR_longjmp are wrappers around setjmp and longjmp
** to ensure that
** call C -> setjmp -> call Mercury -> call C -> longjmp
** works correctly. This is used by the exception handling code for
** the ODBC interface, and probably shouldn't be used for anything
** else.
*/
typedef struct {
jmp_buf *mercury_env; /*
** used to save MR_ENGINE(e_jmp_buf )
*/
jmp_buf env; /*
** used by calls to setjmp and longjmp
*/
Word *saved_succip;
Word *saved_sp;
Word *saved_curfr;
Word *saved_maxfr;
MR_IF_USE_TRAIL(Word *saved_trail_ptr;)
MR_IF_USE_TRAIL(Word *saved_ticket_counter;)
#if NUM_REAL_REGS > 0
Word regs[NUM_REAL_REGS];
#endif /* NUM_REAL_REGS > 0 */
} MR_jmp_buf;
/*---------------------------------------------------------------------------*/
/*
** Replacements for setjmp() and longjmp() that work
** across calls to Mercury code.
*/
/*
** MR_setjmp(MR_jmp_buf *env, longjmp_label)
**
** Save MR_ENGINE(e_jmp_buf), save the Mercury state, call setjmp(env),
** then fall through.
**
** When setjmp returns via a call to longjmp, control will pass to
** longjmp_label.
**
** Notes:
** - The Mercury registers must be valid before the call to MR_setjmp.
** - The general-purpose registers r1, r2... are not restored and must
** be saved by the caller.
** - In grades without conservative garbage collection, the caller
** must save and restore hp, sol_hp, heap_zone
** and solutions_heap_zone.
*/
#define MR_setjmp(setjmp_env, longjmp_label) \
do { \
(setjmp_env)->mercury_env = MR_ENGINE(e_jmp_buf); \
save_regs_to_mem((setjmp_env)->regs); \
(setjmp_env)->saved_succip = MR_succip; \
(setjmp_env)->saved_sp = MR_sp; \
(setjmp_env)->saved_curfr = MR_curfr; \
(setjmp_env)->saved_maxfr = MR_maxfr; \
MR_IF_USE_TRAIL((setjmp_env)->saved_trail_ptr = \
MR_trail_ptr); \
MR_IF_USE_TRAIL((setjmp_env)->saved_ticket_counter = \
MR_ticket_counter); \
if (setjmp((setjmp_env)->env)) { \
MR_ENGINE(e_jmp_buf) = (setjmp_env)->mercury_env; \
restore_regs_from_mem((setjmp_env)->regs); \
MR_succip = (setjmp_env)->saved_succip; \
MR_sp = (setjmp_env)->saved_sp; \
MR_curfr = (setjmp_env)->saved_curfr; \
MR_maxfr = (setjmp_env)->saved_maxfr; \
MR_IF_USE_TRAIL(MR_trail_ptr = \
(setjmp_env)->saved_trail_ptr); \
MR_IF_USE_TRAIL(MR_ticket_counter = \
(setjmp_env)->saved_ticket_counter); \
goto longjmp_label; \
} \
} while (0)
/*
** MR_longjmp(MR_jmp_buf *env)
**
** Call longjmp(), MR_setjmp() will handle the rest.
*/
#define MR_longjmp(setjmp_env) longjmp((setjmp_env)->env, 1)
/*---------------------------------------------------------------------------*/
/*
** The Mercury engine structure.
** Normally there is one of these for each Posix thread.
*/
typedef struct MR_mercury_engine_struct {
Word fake_reg[MAX_FAKE_REG];
/* The fake reg vector for this engine. */
#ifndef CONSERVATIVE_GC
Word *e_hp;
/* The heap pointer for this engine */
Word *e_sol_hp;
/* The solutions heap pointer for this engine */
Word *e_global_hp;
/* The global heap pointer for this engine */
#endif
MR_Context *this_context;
/*
** this_context points to the context currently
** executing in this engine.
*/
MR_Context context;
/*
** context stores all the context information
** for the context executing in this engine.
*/
#ifdef MR_THREAD_SAFE
MercuryThread owner_thread;
unsigned c_depth;
/*
** These two fields are used to ensure that when a
** thread executing C code calls the Mercury engine
** associated with that thread, the Mercury code
** will finish in the same engine and return appropriately.
** Each time C calls Mercury in a thread, the c_depth
** is incremented, and the owner_thread field of the current
** context is set to the id of the thread. While the
** owner_thread is set, the context will not be scheduled
** for execution by any other thread. When the call to
** the Mercury engine finishes, c_depth is decremented and
** the owner_thread field of the current context is restored
** to its previous value.
*/
#endif
jmp_buf *e_jmp_buf;
#ifndef CONSERVATIVE_GC
MemoryZone *heap_zone;
MemoryZone *solutions_heap_zone;
MemoryZone *global_heap_zone;
#endif
#ifdef NATIVE_GC
MemoryZone *heap_zone2;
#ifdef MR_DEBUG_AGC_PRINT_VARS
MemoryZone *debug_heap_zone;
#endif
#endif
#ifndef SPEED
MemoryZone *dumpstack_zone;
int dumpindex;
#endif
} MercuryEngine;
/*
** MR_engine_base refers to the engine in which execution is taking place.
** In the non-thread-safe situation, it is just a global variable.
** In the thread-safe situation, MR_engine_base is either a global
** register (if one is available), or a macro that accesses thread-local
** storage. We provide two macros, MR_ENGINE(x) and MR_CONTEXT(x),
** that can be used in both kinds of situations to refer to fields
** of the engine structure, and to fields of the engine's current context.
*/
#ifdef MR_THREAD_SAFE
extern MercuryThreadKey MR_engine_base_key;
#define MR_thread_engine_base \
((MercuryEngine *) MR_GETSPECIFIC(MR_engine_base_key))
#if NUM_REAL_REGS > 0
#define MR_ENGINE_BASE_REGISTER
/*
** MR_engine_base is defined in machdeps/{arch}.h
*/
#else
#define MR_engine_base MR_thread_engine_base
#endif
#define MR_ENGINE(x) (((MercuryEngine *)MR_engine_base)->x)
#define MR_get_engine() MR_thread_engine_base
#else /* !MR_THREAD_SAFE */
extern MercuryEngine MR_engine_base;
#define MR_ENGINE(x) (MR_engine_base.x)
#define MR_get_engine() (&MR_engine_base)
#endif /* !MR_THREAD_SAFE */
#define MR_CONTEXT(x) (MR_ENGINE(context).x)
#ifndef CONSERVATIVE_GC
#define IF_NOT_CONSERVATIVE_GC(x) x
#else
#define IF_NOT_CONSERVATIVE_GC(x)
#endif
#define load_engine_regs(eng) \
do { \
IF_NOT_CONSERVATIVE_GC(MR_hp = (eng)->e_hp;) \
IF_NOT_CONSERVATIVE_GC(MR_sol_hp = (eng)->e_sol_hp;) \
IF_NOT_CONSERVATIVE_GC(MR_global_hp = (eng)->e_global_hp;) \
} while (0)
#define save_engine_regs(eng) \
do { \
IF_NOT_CONSERVATIVE_GC((eng)->e_hp = MR_hp;) \
IF_NOT_CONSERVATIVE_GC((eng)->e_sol_hp = MR_sol_hp;) \
IF_NOT_CONSERVATIVE_GC((eng)->e_global_hp = MR_global_hp;) \
} while (0)
/*
** Macros for easy access to heap zones
*/
#ifndef CONSERVATIVE_GC
#define MR_heap_zone MR_ENGINE(heap_zone)
#define MR_solutions_heap_zone MR_ENGINE(solutions_heap_zone)
#define MR_global_heap_zone MR_ENGINE(global_heap_zone)
#endif
/*
** Functions for creating/destroying a MercuryEngine.
*/
extern MercuryEngine *create_engine(void);
extern void destroy_engine(MercuryEngine *engine);
/*
** Functions for initializing/finalizing a MercuryEngine.
** These are like create/destroy except that they don't allocate/deallocate
** the MercuryEngine structure.
*/
extern void init_engine(MercuryEngine *engine);
extern void finalize_engine(MercuryEngine *engine);
/*
** Functions that act on the current Mercury engine.
*/
extern void call_engine(Code *entry_point);
extern void terminate_engine(void);
extern void dump_prev_locations(void);
/*---------------------------------------------------------------------------*/
/*
** Builtin labels that point to commonly used code fragments
*/
Declare_entry(do_redo);
Declare_entry(do_fail);
Declare_entry(do_reset_hp_fail);
Declare_entry(do_reset_framevar0_fail);
Declare_entry(do_succeed);
Declare_entry(do_not_reached);
#endif /* not MERCURY_ENGINE_H */