[m-dev.] diff: minimal model tabling, part 1

Zoltan Somogyi zs at cs.mu.OZ.AU
Tue Apr 20 15:23:00 AEST 1999


> > Most of this diff has already been reviewed by Fergus. He requested
> > the introduction of a new grade component, which I have done. He should
> > review the relevant parts of this diff.
> 
> Could you please post a relative diff, showing the changes made
> between this diff and the previous one that you posted?

Here it is. It does not include any changes to private_builtin.m, since
I could not recreate the earlier version of that file, but I think the only
change to that file was the introduction of calls to abort execution
if you executed minimal model tabling code in a grade which did not allow
minimal tabling.

Zoltan.

diff --recursive -u ./compiler/code_info.m /mnt/munkora/home/staff/zs/mer/ws4/compiler/code_info.m
--- ./compiler/code_info.m	Tue Apr 20 15:58:47 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/compiler/code_info.m	Sat Apr 17 20:55:19 1999
@@ -1700,10 +1700,23 @@
 		{ HijackInfo = commit_temp_frame(MaxfrSlot, UseMinimalModel) },
 		{
 			UseMinimalModel = yes,
+			% If the code we are committing across starts but
+			% does not complete the evaluation of a tabled subgoal,
+			% the cut will remove the generator's choice point,
+			% so that the evaluation of the subgoal will never
+			% be completed. We handle such "dangling" generators
+			% by removing them from the subgoal trie of the
+			% tabled procedure. This requires knowing what
+			% tabled subgoals are started inside commits,
+			% which is why we wrap the goal being committed across
+			% inside MR_commit_{mark,cut}.
 			Components = [
-				pragma_c_raw_code("\tsave_transient_registers();\n"),
-				pragma_c_raw_code("\tMR_commit_mark();\n"),
-				pragma_c_raw_code("\trestore_transient_registers();\n")
+				pragma_c_raw_code(
+					"\tsave_transient_registers();\n"),
+				pragma_c_raw_code(
+					"\tMR_commit_mark();\n"),
+				pragma_c_raw_code(
+					"\trestore_transient_registers();\n")
 			],
 			MarkCode = node([
 				pragma_c([], Components, will_not_call_mercury,
@@ -1778,6 +1791,7 @@
 		]) },
 		{
 			UseMinimalModel = yes,
+			% See the comment in prepare_for_semi_commit above.
 			Components = [
 				pragma_c_raw_code("\tMR_commit_cut();\n")
 			],
diff --recursive -u ./compiler/handle_options.m /mnt/munkora/home/staff/zs/mer/ws4/compiler/handle_options.m
--- ./compiler/handle_options.m	Tue Apr 20 15:58:48 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/compiler/handle_options.m	Sun Apr 11 18:56:26 1999
@@ -164,8 +164,8 @@
                                 ->
                                     postprocess_options_2(OptionTable,
                                         GC_Method, TagsMethod, ArgsMethod,
-                                        PrologDialect, TermNorm, TraceLevel),
-                                    { Error = no }
+                                        PrologDialect, TermNorm, TraceLevel,
+					Error)
                                 ;
                                     { DumpAliasOption = string(DumpAlias) },
                                     { convert_dump_alias(DumpAlias,
@@ -175,8 +175,8 @@
                                         string(DumpOptions), NewOptionTable) },
                                     postprocess_options_2(NewOptionTable,
                                         GC_Method, TagsMethod, ArgsMethod,
-                                        PrologDialect, TermNorm, TraceLevel),
-                                    { Error = no }
+                                        PrologDialect, TermNorm, TraceLevel,
+					Error)
                                 ;
                                     { Error = yes("Invalid argument to option `--hlds-dump-alias'.") }
                                 )
@@ -204,11 +204,11 @@
 
 :- pred postprocess_options_2(option_table, gc_method, tags_method,
 	args_method, prolog_dialect, termination_norm, trace_level,
-	io__state, io__state).
-:- mode postprocess_options_2(in, in, in, in, in, in, in, di, uo) is det.
+	maybe(string), io__state, io__state).
+:- mode postprocess_options_2(in, in, in, in, in, in, in, out, di, uo) is det.
 
 postprocess_options_2(OptionTable, GC_Method, TagsMethod, ArgsMethod,
-		PrologDialect, TermNorm, TraceLevel) -->
+		PrologDialect, TermNorm, TraceLevel, Error) -->
 	% work around for NU-Prolog problems
 	( { map__search(OptionTable, heap_space, int(HeapSpace)) } ->
 		io__preallocate_heap_space(HeapSpace)
@@ -285,8 +285,20 @@
 	% --split-c-files implies --procs-per-c-function 1
 	option_implies(split_c_files, procs_per_c_function, int(1)),
 
+	% Minimal model tabling is not compatible with trailing;
+	% see the comment in runtime/mercury_tabling.c.
+
+	globals__io_lookup_bool_option(use_trail, UseTrail),
+	globals__io_lookup_bool_option(use_minimal_model, UseMinimalModel),
+	{ UseTrail = yes, UseMinimalModel = yes ->
+		Error = yes("trailing and minimal model tabling are not compatible")
+	;
+		Error = no
+	},
+
 	% The `.debug' grade (i.e. --stack-trace plus --require-tracing)
-	% implies --use-trail.
+	% implies --use-trail, except with --use-minimal-model, which is
+	% not compatible with --use-trail.
 	%
 	% The reason for this is to avoid unnecessary proliferation in
 	% the number of different grades.  If you're using --debug,
@@ -296,7 +308,7 @@
 
 	globals__io_lookup_bool_option(stack_trace, StackTrace),
 	globals__io_lookup_bool_option(require_tracing, RequireTracing),
-	( { StackTrace = yes, RequireTracing = yes } ->
+	( { StackTrace = yes, RequireTracing = yes, UseMinimalModel = no } ->
 		globals__io_set_option(use_trail, bool(yes))
 	;
 		[]
@@ -562,6 +574,7 @@
 	;	gc		% the kind of GC to use
 	;	prof		% what profiling options to use
 	;	trail		% whether or not to use trailing
+	;	minimal_model	% whether we set up for minimal model tabling
 	;	args		% argument passing convention
 	;	trace		% tracing/debugging options
 	;	par		% parallelism / multithreading
@@ -695,6 +708,10 @@
 	% Trailing components
 grade_component_table("tr", trail, [use_trail - bool(yes)]).
 
+	% Mimimal model tabling components
+grade_component_table("mm", minimal_model,
+	[use_minimal_model - bool(yes)]).
+
 :- pred reset_grade_options(option_table, option_table).
 :- mode reset_grade_options(in, out) is det.
 
@@ -721,6 +738,7 @@
 grade_start_values(stack_trace - bool(no)).
 grade_start_values(require_tracing - bool(no)).
 grade_start_values(use_trail - bool(no)).
+grade_start_values(use_minimal_model - bool(no)).
 
 :- pred split_grade_string(string, list(string)).
 :- mode split_grade_string(in, out) is semidet.
diff --recursive -u ./compiler/options.m /mnt/munkora/home/staff/zs/mer/ws4/compiler/options.m
--- ./compiler/options.m	Tue Apr 20 15:58:48 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/compiler/options.m	Sat Apr 17 20:55:33 1999
@@ -1785,6 +1785,8 @@
 		"\tEnable the use of minimal model tabling.",
 		"\tYou must compile the entire program with this option",
 		"\tif any part of the program uses `:- pragma minimal_model'.",
+		"\tAll the C code also needs to be compiled with the flag",
+		"\t`-DMR_USE_MINIMAL_MODEL'.",
 
 		"--unboxed-float",
 		"(This option is not for general use.)",
diff --recursive -u ./compiler/table_gen.m /mnt/munkora/home/staff/zs/mer/ws4/compiler/table_gen.m
--- ./compiler/table_gen.m	Tue Apr 20 15:58:49 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/compiler/table_gen.m	Wed Mar 17 18:57:42 1999
@@ -325,7 +325,7 @@
 
 	( EvalMethod = eval_loop_check ->
 		SaveAnsGoal = MarkAsInactiveGoal
-	;	EvalMethod = eval_memo ->
+	; EvalMethod = eval_memo ->
 		SaveAnsGoal = SaveAnsGoal0
 	;
 		error(
diff --recursive -u ./runtime/mercury_conf_param.h /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_conf_param.h
--- ./runtime/mercury_conf_param.h	Tue Apr 20 12:50:16 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_conf_param.h	Tue Apr 20 12:27:43 1999
@@ -48,6 +48,7 @@
 ** NO_TYPE_LAYOUT
 ** BOXED_FLOAT
 ** MR_USE_TRAIL
+** MR_USE_MINIMAL_MODEL
 **	See the documentation for
 **		--gcc-global-registers
 **		--gcc-non-local-gotos
@@ -58,6 +59,7 @@
 **		--no-type-layout
 **		--unboxed-float
 **		--use-trail
+**		--use-minimal-model
 **	(respectively) in the mmc help message or the Mercury User's Guide.
 **
 ** USE_SINGLE_PREC_FLOAT:
diff --recursive -u ./runtime/mercury_context.c /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_context.c
--- ./runtime/mercury_context.c	Tue Apr 20 15:59:03 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_context.c	Sun Mar 21 20:38:36 1999
@@ -3,7 +3,7 @@
 ENDINIT
 */
 /*
-** Copyright (C) 1995-1998 The University of Melbourne.
+** Copyright (C) 1995-1999 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.
 */
@@ -117,6 +117,7 @@
 	MR_succip_slot(c->context_curfr) = ENTRY(do_not_reached);
 	MR_succfr_slot(c->context_curfr) = NULL;
 
+#ifdef	MR_USE_MINIMAL_MODEL
 	if (c->generatorstack_zone != NULL) {
 		reset_redzone(c->generatorstack_zone);
 	} else {
@@ -124,7 +125,7 @@
 			generatorstack_size, next_offset(),
 			generatorstack_zone_size, default_handler);
 	}
-	c->context_gen_sp = 0;
+	c->context_gen_next = 0;
 
 	if (c->cutstack_zone != NULL) {
 		reset_redzone(c->cutstack_zone);
@@ -133,7 +134,8 @@
 			cutstack_size, next_offset(),
 			cutstack_zone_size, default_handler);
 	}
-	c->context_cut_sp = 0;
+	c->context_cut_next = 0;
+#endif
 
 #ifdef MR_USE_TRAIL
 	if (c->trail_zone != NULL) {
diff --recursive -u ./runtime/mercury_context.h /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_context.h
--- ./runtime/mercury_context.h	Tue Apr 20 15:59:03 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_context.h	Sun Mar 21 21:24:01 1999
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1997-1998 The University of Melbourne.
+** Copyright (C) 1997-1999 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.
 */
@@ -106,16 +106,18 @@
 		/* saved maxfr pointer for this context */
 	Word		*context_curfr;
 		/* saved curfr pointer for this context */
+#ifdef	MR_USE_MINIMAL_MODEL
 	MemoryZone	*generatorstack_zone;
 		/* pointer to the generatorstack_zone for this context */
-	Integer		context_gen_sp;
-		/* saved generator stack pointer for this context */
+	Integer		context_gen_next;
+		/* saved generator stack index for this context */
 	MemoryZone	*cutstack_zone;
 		/* pointer to the cutstack_zone for this context */
-	Integer		context_cut_sp;
-		/* saved cut stack pointer for this context */
+	Integer		context_cut_next;
+		/* saved cut stack index for this context */
+#endif
 
-#ifdef MR_USE_TRAIL
+#ifdef	MR_USE_TRAIL
 	MemoryZone	*trail_zone;
 		/* pointer to the MR_trail_zone for this context */
 	MR_TrailEntry	*context_trail_ptr;
@@ -324,6 +326,12 @@
   #define MR_IF_USE_TRAIL(x)
 #endif
 
+#ifdef MR_USE_MINIMAL_MODEL
+  #define MR_IF_USE_MINIMAL_MODEL(x) x
+#else
+  #define MR_IF_USE_MINIMAL_MODEL(x)
+#endif
+
 #define load_context(cptr)						\
 	do {								\
 		MR_Context	*load_context_c;			\
@@ -332,8 +340,10 @@
 		MR_sp		= load_context_c->context_sp;		\
 		MR_maxfr	= load_context_c->context_maxfr; 	\
 		MR_curfr	= load_context_c->context_curfr;	\
-		MR_gen_sp	= load_context_c->context_gen_sp;	\
-		MR_cut_sp	= load_context_c->context_cut_sp;	\
+		MR_IF_USE_MINIMAL_MODEL(				\
+		    MR_gen_next = load_context_c->context_gen_next;	\
+		    MR_cut_next = load_context_c->context_cut_next;	\
+		)							\
 	        MR_IF_USE_TRAIL(					\
 		    MR_trail_zone = load_context_c->trail_zone;		\
 		    MR_trail_ptr = load_context_c->context_trail_ptr;	\
@@ -344,14 +354,16 @@
 				load_context_c->detstack_zone;		\
 		MR_ENGINE(context).nondetstack_zone =			\
 				load_context_c->nondetstack_zone;	\
-		MR_ENGINE(context).generatorstack_zone =		\
+		MR_IF_USE_MINIMAL_MODEL(				\
+		    MR_ENGINE(context).generatorstack_zone =		\
 				load_context_c->generatorstack_zone;	\
-		MR_ENGINE(context).cutstack_zone =			\
+		    MR_ENGINE(context).cutstack_zone =			\
 				load_context_c->cutstack_zone;		\
-		MR_gen_stack	= (MR_GeneratorStackFrame *)		\
-					MR_ENGINE(context).generatorstack_zone;\
-		MR_cut_stack	= (MR_CutStackFrame *)			\
-					MR_ENGINE(context).cutstack_zone;\
+		    MR_gen_stack = (MR_GeneratorStackFrame *)		\
+				MR_ENGINE(context).generatorstack_zone;	\
+		    MR_cut_stack = (MR_CutStackFrame *)			\
+				MR_ENGINE(context).cutstack_zone;	\
+	    	)							\
 		set_min_heap_reclamation_point(load_context_c);		\
 	} while (0)
 
@@ -360,11 +372,13 @@
 		MR_Context	*save_context_c;			\
 		save_context_c = (cptr);				\
 		save_context_c->context_succip	= MR_succip;		\
-		save_context_c->context_sp	 = MR_sp;		\
-		save_context_c->context_maxfr	= MR_maxfr;		\
-		save_context_c->context_curfr	= MR_curfr;		\
-		save_context_c->context_gen_sp	= MR_gen_sp;		\
-		save_context_c->context_cut_sp	= MR_cut_sp;		\
+		save_context_c->context_sp	= MR_sp;		\
+		save_context_c->context_maxfr   = MR_maxfr;		\
+		save_context_c->context_curfr   = MR_curfr;		\
+		MR_IF_USE_MINIMAL_MODEL(				\
+		    save_context_c->context_gen_next = MR_gen_next;	\
+		    save_context_c->context_cut_next = MR_cut_next;	\
+		)							\
 		MR_IF_USE_TRAIL(					\
 		    save_context_c->trail_zone = MR_trail_zone;		\
 		    save_context_c->context_trail_ptr = MR_trail_ptr;	\
@@ -375,14 +389,16 @@
 				MR_ENGINE(context).detstack_zone;	\
 		save_context_c->nondetstack_zone =			\
 				MR_ENGINE(context).nondetstack_zone;	\
-		save_context_c->generatorstack_zone =			\
+		MR_IF_USE_MINIMAL_MODEL(				\
+		    save_context_c->generatorstack_zone =		\
 				MR_ENGINE(context).generatorstack_zone;	\
-		save_context_c->cutstack_zone =				\
+		    save_context_c->cutstack_zone =			\
 				MR_ENGINE(context).cutstack_zone;	\
-		assert(MR_gen_stack == (MR_GeneratorStackFrame *)	\
+		    assert(MR_gen_stack == (MR_GeneratorStackFrame *)	\
 				MR_ENGINE(context).generatorstack_zone);\
-		assert(MR_cut_stack == (MR_CutStackFrame *)		\
+		    assert(MR_cut_stack == (MR_CutStackFrame *)		\
 				MR_ENGINE(context).cutstack_zone);	\
+		)							\
 		save_hp_in_context(save_context_c);			\
 	} while (0)
 
diff --recursive -u ./runtime/mercury_grade.h /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_grade.h
--- ./runtime/mercury_grade.h	Mon Mar 29 16:15:07 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_grade.h	Fri Apr  9 16:26:09 1999
@@ -129,13 +129,23 @@
   #define MR_GRADE_PART_6	MR_GRADE_PART_5
 #endif
 
+#ifdef MR_USE_MINIMAL_MODEL
+  #define MR_GRADE_PART_6A	MR_PASTE2(MR_GRADE_PART_6, _mm)
+#else
+  #define MR_GRADE_PART_6A	MR_GRADE_PART_6
+#endif
+
+#if defined(MR_USE_TRAIL) && defined(MR_USE_MINIMAL_MODEL)
+  #error "trailing and minimal model tabling are not compatible"
+#endif
+
 #if TAGBITS == 0
-  #define MR_GRADE_PART_7	MR_PASTE2(MR_GRADE_PART_6, _notags)
+  #define MR_GRADE_PART_7	MR_PASTE2(MR_GRADE_PART_6A, _notags)
 #elif defined(HIGHTAGS)
-  #define MR_GRADE_PART_7	MR_PASTE2(MR_GRADE_PART_6, \
+  #define MR_GRADE_PART_7	MR_PASTE2(MR_GRADE_PART_6A, \
   					MR_PASTE2(_hightags, TAGBITS))
 #else
-  #define MR_GRADE_PART_7	MR_PASTE2(MR_GRADE_PART_6, \
+  #define MR_GRADE_PART_7	MR_PASTE2(MR_GRADE_PART_6A, \
   					MR_PASTE2(_tags, TAGBITS))
 #endif
 
@@ -275,6 +285,12 @@
   #define MR_GRADE_OPT_PART_6	MR_GRADE_OPT_PART_5
 #endif
 
+#ifdef MR_USE_MINIMAL_MODEL
+  #define MR_GRADE_OPT_PART_6A	MR_GRADE_OPT_PART_6 ".mm"
+#else
+  #define MR_GRADE_OPT_PART_6A	MR_GRADE_OPT_PART_6
+#endif
+
 /*
 ** Parts 7-10 above (i.e. tag bits, compact args, and (un)boxed float)
 ** are documented as "not for general use", and can't be set via the
@@ -282,9 +298,9 @@
 */
 
 #if defined(PIC_REG) && defined(USE_GCC_GLOBAL_REGISTERS) && defined(__i386__)
-  #define MR_GRADE_OPT_PART_11	MR_GRADE_OPT_PART_6 ".picreg"
+  #define MR_GRADE_OPT_PART_11	MR_GRADE_OPT_PART_6A ".picreg"
 #else
-  #define MR_GRADE_OPT_PART_11	MR_GRADE_OPT_PART_6
+  #define MR_GRADE_OPT_PART_11	MR_GRADE_OPT_PART_6A
 #endif
 
 /*
diff --recursive -u ./runtime/mercury_init.h /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_init.h
--- ./runtime/mercury_init.h	Tue Apr 20 15:59:04 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_init.h	Sat Apr 17 20:56:25 1999
@@ -76,10 +76,10 @@
 ** by C programs that wish to interface to Mercury.
 */
 
-#include "mercury_regs.h"	/* must be before prototypes */
-#include "mercury_goto.h"		/* for Declare_entry */
+#include "mercury_regs.h"	/* must come before system headers */
+#include "mercury_goto.h"	/* for Declare_entry */
 #include "mercury_types.h"	/* for `Word' */
-#include "mercury_wrapper.h"		/* for do_init_modules,
+#include "mercury_wrapper.h"	/* for do_init_modules,
 				   mercury_runtime_init(),
 				   mercury_runtime_main(),
 				   mercury_runtime_terminate(),
diff --recursive -u ./runtime/mercury_memory.c /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_memory.c
--- ./runtime/mercury_memory.c	Tue Apr 20 15:59:04 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_memory.c	Sun Mar 21 20:38:54 1999
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1994-1998 The University of Melbourne.
+** Copyright (C) 1994-1999 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.
 */
@@ -109,8 +109,10 @@
   MemoryZone *heap_zone;
   MemoryZone *solutions_heap_zone;
 #endif
-MemoryZone *generatorstack_zone;
-MemoryZone *cutstack_zone;
+#ifdef	MR_USE_MINIMAL_MODEL
+  MemoryZone *generatorstack_zone;
+  MemoryZone *cutstack_zone;
+#endif
 
 #ifdef	MR_LOWLEVEL_DEBUG
   MemoryZone *dumpstack_zone;
@@ -138,41 +140,43 @@
 	unit = max(page_size, pcache_size);
 
 #ifdef CONSERVATIVE_GC
-	heap_size	    = 0;
+	heap_size		 = 0;
 	heap_zone_size		 = 0;
-	solutions_heap_size = 0;
+	solutions_heap_size	 = 0;
 	solutions_heap_zone_size = 0;
-	global_heap_size    = 0;
+	global_heap_size	 = 0;
 	global_heap_zone_size	 = 0;
-	debug_heap_size = 0;
+	debug_heap_size		 = 0;
 	debug_heap_zone_size	 = 0;
 #else
-	heap_size           = round_up(heap_size * 1024, unit);
+	heap_size		 = round_up(heap_size * 1024, unit);
 	heap_zone_size		 = round_up(heap_zone_size * 1024, unit);
 	solutions_heap_size	 = round_up(solutions_heap_size * 1024, unit);
 	solutions_heap_zone_size = round_up(solutions_heap_zone_size * 1024, 
-		unit);
-	global_heap_size    = round_up(global_heap_size * 1024, unit);
+					unit);
+	global_heap_size	 = round_up(global_heap_size * 1024, unit);
 	global_heap_zone_size	 = round_up(global_heap_zone_size * 1024, unit);
-	debug_heap_size    = round_up(debug_heap_size * 1024, unit);
+	debug_heap_size		 = round_up(debug_heap_size * 1024, unit);
 	debug_heap_zone_size	 = round_up(debug_heap_zone_size * 1024, unit);
 #endif
-	detstack_size       = round_up(detstack_size * 1024, unit);
-	detstack_zone_size  = round_up(detstack_zone_size * 1024, unit);
-	nondstack_size      = round_up(nondstack_size * 1024, unit);
-	nondstack_zone_size = round_up(nondstack_zone_size * 1024, unit);
+	detstack_size		 = round_up(detstack_size * 1024, unit);
+	detstack_zone_size	 = round_up(detstack_zone_size * 1024, unit);
+	nondstack_size		 = round_up(nondstack_size * 1024, unit);
+	nondstack_zone_size	 = round_up(nondstack_zone_size * 1024, unit);
+#ifdef	MR_USE_MINIMAL_MODEL
 	generatorstack_size	 = round_up(generatorstack_size * 1024, unit);
 	generatorstack_zone_size = round_up(generatorstack_zone_size * 1024,
 					unit);
 	cutstack_size		 = round_up(cutstack_size * 1024, unit);
 	cutstack_zone_size	 = round_up(cutstack_zone_size * 1024, unit);
+#endif
 
-#ifdef MR_USE_TRAIL
-	trail_size       = round_up(trail_size * 1024, unit);
-	trail_zone_size  = round_up(trail_zone_size * 1024, unit);
+#ifdef	MR_USE_TRAIL
+	trail_size		 = round_up(trail_size * 1024, unit);
+	trail_zone_size		 = round_up(trail_zone_size * 1024, unit);
 #else
-	trail_size	    = 0;
-	trail_zone_size	    = 0;
+	trail_size		 = 0;
+	trail_zone_size		 = 0;
 #endif
 
 	/*
diff --recursive -u ./runtime/mercury_regorder.h /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_regorder.h
--- ./runtime/mercury_regorder.h	Tue Nov 10 01:35:36 1998
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_regorder.h	Fri Mar 26 21:17:26 1999
@@ -101,6 +101,14 @@
 			count_usage(MR_MIN_HP_REC, mr(40)))
 #define MR_global_hp	LVALUE_CAST(Word *,	\
 			count_usage(MR_GLOBAL_HP_RN, mr(41)))
+#define MR_gen_next	LVALUE_CAST(Integer,	\
+			count_usage(MR_GEN_NEXT_RN, mr(42)))
+#define MR_gen_stack	LVALUE_CAST(struct MR_GeneratorStackFrameStruct *, \
+			count_usage(MR_GEN_STACK_RN, mr(43)))
+#define MR_cut_next	LVALUE_CAST(Integer,	\
+			count_usage(MR_CUT_NEXT_RN, mr(44)))
+#define MR_cut_stack	LVALUE_CAST(struct MR_CutStackFrameStruct *, \
+			count_usage(MR_CUT_STACK_RN, mr(45)))
 
 #define MR_trail_ptr	count_usage(MR_TRAIL_PTR_RN, MR_trail_ptr_var)
 #define MR_ticket_counter	 \
@@ -114,10 +122,10 @@
 #define MR_NUM_VERY_SPECIAL_REG	6
 
 /* the number of special-purpose Mercury registers */
-#define MR_NUM_SPECIAL_REG	12
+#define MR_NUM_SPECIAL_REG	16
 
 /* the maximum mrN number of special registers */
-#define	MR_MAX_SPECIAL_REG_MR	41
+#define	MR_MAX_SPECIAL_REG_MR	45
 
 /*
 ** The MR_saved_foo macros are like MR_foo except that
@@ -134,6 +142,14 @@
 #define MR_saved_min_hp_rec(save_area)	LVALUE_CAST(Word *, save_area[39])
 #define MR_saved_min_sol_hp_rec(save_area) LVALUE_CAST(Word *, save_area[40])
 #define MR_saved_global_hp(save_area)	LVALUE_CAST(Word *, save_area[41])
+#define MR_saved_gen_stack(save_area)	LVALUE_CAST(Integer, save_area[42])
+#define MR_saved_gen_next(save_area)	LVALUE_CAST(			      \
+					struct MR_GeneratorStackFrameStruct *,\
+					save_area[43])
+#define MR_saved_cut_stack(save_area)	LVALUE_CAST(Integer, save_area[44])
+#define MR_saved_cut_next(save_area)	LVALUE_CAST(			      \
+					struct MR_CutStackFrameStruct *,      \
+					save_area[45])
 
 #define VIRTUAL_REG_MAP_BODY	{ \
 	3, \
@@ -243,6 +259,14 @@
 #define MR_trail_ptr	count_usage(MR_TRAIL_PTR_RN, MR_trail_ptr_var)
 #define MR_ticket_counter	 \
 		count_usage(MR_TICKET_COUNTER_RN, MR_ticket_counter_var)
+#define MR_gen_next	LVALUE_CAST(Integer,	\
+			count_usage(MR_GEN_NEXT_RN, mr(41)))
+#define MR_gen_stack	LVALUE_CAST(struct MR_GeneratorStackFrameStruct *, \
+			count_usage(MR_GEN_STACK_RN, mr(42)))
+#define MR_cut_next	LVALUE_CAST(Integer,	\
+			count_usage(MR_CUT_NEXT_RN, mr(43)))
+#define MR_cut_stack	LVALUE_CAST(struct MR_CutStackFrameStruct *, \
+			count_usage(MR_CUT_STACK_RN, mr(44)))
 
 /*
 ** the number of "very special" registers, i.e. special registers that can
@@ -252,10 +276,10 @@
 #define MR_NUM_VERY_SPECIAL_REG	5
 
 /* the number of special registers */
-#define MR_NUM_SPECIAL_REG	11
+#define MR_NUM_SPECIAL_REG	15
 
 /* the maximum mrN number of special, non rN registers */
-#define	MR_MAX_SPECIAL_REG_MR	40
+#define	MR_MAX_SPECIAL_REG_MR	44
 
 /*
 ** The MR_saved_foo macros are like MR_foo except that
@@ -272,6 +296,14 @@
 #define MR_saved_min_hp_rec(save_area)	LVALUE_CAST(Word *, save_area[38])
 #define MR_saved_min_sol_hp_rec(save_area) LVALUE_CAST(Word *, save_area[39])
 #define MR_saved_global_hp(save_area)	LVALUE_CAST(Word *, save_area[40])
+#define MR_saved_gen_stack(save_area)	LVALUE_CAST(Integer, save_area[41])
+#define MR_saved_gen_next(save_area)	LVALUE_CAST(			      \
+					struct MR_GeneratorStackFrameStruct *,\
+					save_area[42])
+#define MR_saved_cut_stack(save_area)	LVALUE_CAST(Integer, save_area[43])
+#define MR_saved_cut_next(save_area)	LVALUE_CAST(			      \
+					struct MR_CutStackFrameStruct *,      \
+					save_area[44])
 
 #define VIRTUAL_REG_MAP_BODY	{ \
 	2, \
diff --recursive -u ./runtime/mercury_regs.h /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_regs.h
--- ./runtime/mercury_regs.h	Thu Mar 11 09:05:24 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_regs.h	Fri Mar 26 21:09:03 1999
@@ -260,6 +260,10 @@
 #define	MR_MIN_HP_REC		(MR_ORD_RN + 8)
 #define	MR_MIN_SOL_HP_REC	(MR_ORD_RN + 9)
 #define	MR_GLOBAL_HP_RN		(MR_ORD_RN + 10)
-#define	MAX_RN			(MR_ORD_RN + 11)
+#define	MR_GEN_STACK_RN		(MR_ORD_RN + 11)
+#define	MR_GEN_NEXT_RN		(MR_ORD_RN + 12)
+#define	MR_CUT_STACK_RN		(MR_ORD_RN + 13)
+#define	MR_CUT_NEXT_RN		(MR_ORD_RN + 14)
+#define	MAX_RN			(MR_ORD_RN + 15)
 
 #endif /* not MERCURY_REGS_H */
diff --recursive -u ./runtime/mercury_stacks.h /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_stacks.h
--- ./runtime/mercury_stacks.h	Tue Apr 20 15:59:04 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_stacks.h	Fri Mar 26 21:12:38 1999
@@ -1,5 +1,5 @@
 /*
-** Copyright (C) 1995-1998 The University of Melbourne.
+** Copyright (C) 1995-1999 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.
 */
@@ -234,9 +234,11 @@
 				GOTO(MR_redoip_slot(MR_maxfr));		\
 			} while (0)
 
+#ifdef	MR_USE_MINIMAL_MODEL
+
 /* DEFINITIONS FOR GENERATOR STACK FRAMES */
 
-typedef struct {
+typedef struct MR_GeneratorStackFrameStruct {
 	Word			*generator_frame;
 	MR_Subgoal		*generator_table;
 } MR_GeneratorStackFrame;
@@ -255,9 +257,9 @@
 	MR_CutGeneratorList	next_generator;
 };
 
-typedef struct {
+typedef struct MR_CutStackFrameStruct {
 	Word			*frame;
-	Integer			gen_sp;
+	Integer			gen_next;
 	MR_CutGeneratorList	generators;
 } MR_CutStackFrame;
 
@@ -266,4 +268,6 @@
 
 extern	void			MR_register_generator_ptr(MR_Subgoal **);
 
-#endif /* not MERCURY_STACKS_H */
+#endif	/* MR_USE_MINIMAL_MODEL */
+
+#endif	/* not MERCURY_STACKS_H */
diff --recursive -u ./runtime/mercury_tabling.c /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_tabling.c
--- ./runtime/mercury_tabling.c	Tue Apr 20 16:01:15 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_tabling.c	Fri Apr  9 16:34:19 1999
@@ -14,21 +14,21 @@
 /*
 ** this part defines the functions
 **	MR_int_hash_lookup_or_add(),
-**	MR_float_hash_lookup_or_add(), and 
+**	MR_float_hash_lookup_or_add(), and
 ** 	MR_string_hash_lookup_or_add().
 */
 
 /* Initial size of a new table */
-#define TABLE_START_SIZE primes[0] 
+#define TABLE_START_SIZE primes[0]
 
-/* 
-** Maximum ratio of used to unused buckets in the table. Must be less than 
-** 0.9 if you want even poor lookup times. 
+/*
+** Maximum ratio of used to unused buckets in the table. Must be less than
+** 0.9 if you want even poor lookup times.
 */
 #define MAX_EL_SIZE_RATIO 0.65
 
 /* Extract info from a table */
-#define SIZE(table)		(((TableRoot *) table)->size) 
+#define SIZE(table)		(((TableRoot *) table)->size)
 #define ELEMENTS(table)	 	(((TableRoot *) table)->used_elements)
 #define BUCKET(table, Bucket) 	((TableNode **) &(((TableRoot *) table)-> \
 					elements))[(Bucket)]
@@ -61,8 +61,8 @@
 ** Return the next prime number greater than the number received.
 ** If no such prime number can be found, compute an approximate one.
 */
-static Word 
-next_prime(Word old_size) 
+static Word
+next_prime(Word old_size)
 {
 	int i;
 
@@ -73,20 +73,20 @@
 
 	if (i < NUM_OF_PRIMES) {
 		return primes[i];
-	} else { 
+	} else {
 		return 2 * old_size - 1;
 	}
 }
 
 /* Create a new empty hash table. */
-static Word * 
+static Word *
 create_hash_table(Word table_size)
 {
    	Word i;
 	TableRoot * table =
 		table_allocate_bytes(sizeof(Word) * 2 +
 				table_size * sizeof(TableNode *));
-	
+
 	table->size = table_size;
 	table->used_elements = 0;
 
@@ -97,10 +97,10 @@
 	return (Word *) table;
 }
 
-/* 
+/*
 ** Insert key and Data into a new hash table using the given hash.
-** this function does not have to do compares as the given key 
-** is definitely not in the table. 
+** this function does not have to do compares as the given key
+** is definitely not in the table.
 */
 static void
 re_hash(Word * table, Word hash, TableNode * node)
@@ -116,21 +116,21 @@
 
 	BUCKET(table, bucket) = node;
 	++ELEMENTS(table);
-}			
+}
 
-/* 
+/*
 ** Look to see if the given integer key is in the given table. If it
 ** is return the address of the data pointer associated with the key.
 ** If it is not; create a new element for the key in the table and
 ** return the address of its data pointer.
 */
-MR_TrieNode 
+MR_TrieNode
 MR_int_hash_lookup_or_add(MR_TrieNode t, Integer key)
 {
 	TableNode * p, * q;
 	Word * table = *t;	/* Deref the table pointer */
 	Word bucket;
-	
+
 	/* Has the the table been built? */
 	if (table == NULL) {
 		table = create_hash_table(TABLE_START_SIZE);
@@ -148,7 +148,7 @@
 
 		if (bucket == SIZE(table))
 			bucket = 0;
-		
+
 		p = BUCKET(table, bucket);
 	}
 
@@ -157,27 +157,27 @@
 	p->data = NULL;
 
 	/* Rehash the table if it has grown to full */
-	if ((float) ELEMENTS(table) / (float) SIZE(table) > 
-	   		MAX_EL_SIZE_RATIO) 
+	if ((float) ELEMENTS(table) / (float) SIZE(table) >
+	   		MAX_EL_SIZE_RATIO)
 	{
 		int old_size = SIZE(table);
 		int new_size = next_prime(old_size);
 		Word * new_table = create_hash_table(new_size);
 		int i;
-		
+
 		for (i = 0; i < old_size; i++) {
 			q = BUCKET(table, i);
 			if (q) {
 				re_hash(new_table, q->key, q);
 			}
 		}
-		
+
 		/* Free the old table */
 		table_free(table);
 
 		/* Point to the new table */
 		*t = new_table;
-		
+
 		/* Add a new element */
 		re_hash(new_table, key, p);
 	} else {
@@ -188,13 +188,13 @@
 	return &p->data;
 }
 
-/* 
+/*
 ** Look to see if the given float key is in the given table. If it
 ** is return the address of the data pointer associated with the key.
 ** If it is not create a new element for the key in the table and
 ** return the address of its data pointer.
 */
-MR_TrieNode 
+MR_TrieNode
 MR_float_hash_lookup_or_add(MR_TrieNode t, Float key)
 {
 	TableNode * p, * q;
@@ -219,20 +219,20 @@
 			return &p->data;
 		}
 		++bucket;
-		
+
 		if (bucket == SIZE(table))
 			bucket = 0;
-		
+
 		p = BUCKET(table, bucket);
 	}
 
 	p = table_allocate_bytes(sizeof(TableNode));
 	p->key = float_to_word(key);
 	p->data = NULL;
-	
+
 	/* Rehash the table if it has grown to full */
-	if ((float) ELEMENTS(table) / (float) SIZE(table) > 
-	   		MAX_EL_SIZE_RATIO) 
+	if ((float) ELEMENTS(table) / (float) SIZE(table) >
+	   		MAX_EL_SIZE_RATIO)
 	{
 		int old_size = SIZE(table);
 		int new_size = next_prime(old_size);
@@ -242,16 +242,16 @@
 		for (i = 0; i < old_size; i++) {
 			q = BUCKET(table, i);
 			if (q) {
-				re_hash(new_table, hash_float(q->key), q); 
+				re_hash(new_table, hash_float(q->key), q);
 			}
 		}
-		
+
 		/* Free the old table */
 		table_free(table);
 
 		/* Point to the new table */
 		*t = new_table;
-		
+
 		/* Add a new element */
 		re_hash(new_table, hash, p);
 	} else {
@@ -264,13 +264,13 @@
 
 
 
-/* 
+/*
 ** Look to see if the given string key is in the given table. If it
 ** is return the address of the data pointer associated with the key.
 ** If it is not create a new element for the key in the table and
 ** return the address of its data pointer.
 */
-MR_TrieNode 
+MR_TrieNode
 MR_string_hash_lookup_or_add(MR_TrieNode t, String key)
 {
 	TableNode * p, * q;
@@ -292,25 +292,25 @@
 	/* Find if the element is present. */
 	while (p) {
 		int res = strtest((String)p->key, key);
-		
+
 		if (res == 0) {
 			return &p->data;
 		}
 		++bucket;
-		
+
 		if (bucket == SIZE(table))
 			bucket = 0;
-		
+
 		p = BUCKET(table, bucket);
 	}
 
 	p = table_allocate_bytes(sizeof(TableNode));
 	p->key = (Word) key;
 	p->data = NULL;
-	
+
 	/* Rehash the table if it has grown to full */
-	if ((float) ELEMENTS(table) / (float) SIZE(table) > 
-	   		MAX_EL_SIZE_RATIO) 
+	if ((float) ELEMENTS(table) / (float) SIZE(table) >
+	   		MAX_EL_SIZE_RATIO)
 	{
 		int old_size = SIZE(table);
 		int new_size = next_prime(old_size);
@@ -320,19 +320,19 @@
 		for (i = 0; i < old_size; i++) {
 			q = BUCKET(table, i);
 			if (q) {
-				re_hash(new_table, 
-					hash_string((Word) q->key), q); 
+				re_hash(new_table,
+					hash_string((Word) q->key), q);
 			}
 		}
-		
+
 		/* Free the old table */
 		table_free(t);
 
 		/* Point to the new table */
 		*t = new_table;
-		
+
 		/* Add a new element to rehashed table */
-		re_hash(new_table, hash, p); 
+		re_hash(new_table, hash, p);
 	} else {
 		BUCKET(table, bucket) = p;
 		++ELEMENTS(table);
@@ -406,7 +406,7 @@
 
 		return (Word**) &p->value;
 	}
-	
+
 	p = (TreeNode *) *table;
 
 	while (p != NULL) {
@@ -414,10 +414,10 @@
 
 		if (i == COMPARE_EQUAL) {
 			return (Word **) &p->value;
-		} 
-		
+		}
+
 		q = p;
-		
+
 		if (i == COMPARE_LESS) {
 			p = p->left;
 		} else {
@@ -427,7 +427,7 @@
 
 	p = table_allocate_bytes(sizeof(TreeNode));
 	p->key = type_info;
-	p->value = (Word) NULL; 
+	p->value = (Word) NULL;
 	p->left = NULL;
 	p->right = NULL;
 
@@ -436,7 +436,7 @@
 	} else {
 		q ->right = p;
 	}
-	
+
 	return (Word **) &p->value;
 }
 
@@ -651,6 +651,18 @@
 
 /*---------------------------------------------------------------------------*/
 
+#ifdef	MR_USE_MINIMAL_MODEL
+
+/*
+** Save the current state of the Mercury abstract machine, so that the
+** current computation may be suspended for a while, and restored later.
+** The generator_{maxfr,sp} arguments give the points from which we need
+** to copy the nondet and the det stacks. The parts of those stacks below
+** the given points will not change between the suspension and the resumption
+** of this state, or if they do, the stack segments in the saved state
+** will be extended (via extend_consumer_stacks).
+*/
+
 static void
 save_state(MR_SavedState *saved_state,
 	Word *generator_maxfr, Word *generator_sp,
@@ -689,27 +701,45 @@
 		saved_state->det_stack_block = NULL;
 	}
 
-	saved_state->gen_sp = MR_gen_sp;
+	saved_state->gen_next = MR_gen_next;
 	saved_state->generator_stack_block = table_allocate_bytes(
-			MR_gen_sp * sizeof(MR_GeneratorStackFrame));
+			MR_gen_next * sizeof(MR_GeneratorStackFrame));
 	table_copy_bytes(saved_state->generator_stack_block,
 		(char *) MR_gen_stack,
-		MR_gen_sp * sizeof(MR_GeneratorStackFrame));
+		MR_gen_next * sizeof(MR_GeneratorStackFrame));
 
-	saved_state->cut_sp = MR_cut_sp;
+	saved_state->cut_next = MR_cut_next;
 	saved_state->cut_stack_block = table_allocate_bytes(
-			(MR_cut_sp + 1) * sizeof(MR_CutStackFrame));
+			MR_cut_next * sizeof(MR_CutStackFrame));
 	table_copy_bytes(saved_state->cut_stack_block,
 		(char *) MR_cut_stack,
-		(MR_cut_sp + 1) * sizeof(MR_CutStackFrame));
+		MR_cut_next * sizeof(MR_CutStackFrame));
 
 #ifdef MR_USE_TRAIL
 	/*
-	** We ought to save the trail state here --
-	** this is not yet implemented.
+	** Saving the trail state here would not be sufficient to handle
+	** the combination of trailing and minimal model tabling.
+	** Consider the following sequence of events:
+	**
+	**	execution enters a goal being committed across
+	**	a new entry is pushed on the trail
+	**	a tabled goal suspends,
+	**		causing the saving of a trail segment
+	**		and then a failure
+	**	the goal being committed across fails,
+	**		which invokes a failed commit on the trail entry
+	**	...
+	**	the tabled goal is resumed,
+	**		causing the restoring of the saved trail segment
+	**		and then a success
+	**	the goal being committed across now succeeds,
+	**		which invokes a successful commit on the trail entry
+	**
+	** The trail handler will be thoroughly confused by such a sequence.
 	*/
+
 	fatal_error("Sorry, not implemented: "
-		"can't have both tabling and trailing");
+		"can't have both minimal model tabling and trailing");
 #endif
 
 #ifdef	MR_TABLE_DEBUG
@@ -718,7 +748,7 @@
 		printf("%d non, %d det, %d generator, %d cut\n",
 			saved_state->non_stack_block_size,
 			saved_state->det_stack_block_size,
-			MR_gen_sp, MR_cut_sp);
+			MR_gen_next, MR_cut_next);
 
 		printf("non region from ");
 		MR_printnondstackptr(saved_state->non_stack_block_start);
@@ -759,6 +789,10 @@
 	save_transient_registers();
 }
 
+/*
+** Restore the state of the Mercury abstract machine from saved_state.
+*/
+
 static void
 restore_state(MR_SavedState *saved_state, const char *who, const char *what)
 {
@@ -777,15 +811,15 @@
 		saved_state->det_stack_block,
 		saved_state->det_stack_block_size);
 
-	MR_gen_sp = saved_state->gen_sp;
+	MR_gen_next = saved_state->gen_next;
 	table_copy_bytes((char *) MR_gen_stack,
 		saved_state->generator_stack_block,
-		saved_state->gen_sp);
+		saved_state->gen_next * sizeof(MR_GeneratorStackFrame));
 
-	MR_cut_sp = saved_state->cut_sp;
+	MR_cut_next = saved_state->cut_next;
 	table_copy_bytes((char *) MR_cut_stack,
 		(char *) saved_state->cut_stack_block,
-		(saved_state->cut_sp + 1) * sizeof(MR_CutStackFrame));
+		saved_state->cut_next * sizeof(MR_CutStackFrame));
 
 #ifdef	MR_TABLE_DEBUG
 	if (MR_tabledebug) {
@@ -793,7 +827,7 @@
 		printf("%d non, %d det, %d generator, %d cut\n",
 			saved_state->non_stack_block_size,
 			saved_state->det_stack_block_size,
-			saved_state->gen_sp, saved_state->cut_sp);
+			saved_state->gen_next, saved_state->cut_next);
 
 		printf("non region from ");
 		MR_printnondstackptr(saved_state->non_stack_block_start);
@@ -868,6 +902,17 @@
 	printf("\n");
 }
 
+/*
+** The saved state of a consumer for a subgoal (say subgoal A) includes
+** the stack segments between the tops of the stack at the time that
+** A's generator was entered and the time that A's consumer was entered.
+** When A becomes a follower of another subgoal B, the responsibility for
+** scheduling A's consumers passes to B's generator. Since by definition
+** B's nondet stack frame is lower in the stack than A's generator's,
+** we need to extend the stack segments of A's consumers to also include
+** the parts of the stacks between the generator of B and the generator of A.
+*/
+
 Declare_entry(mercury__table_nondet_resume_1_0);
 
 static void
@@ -1015,6 +1060,13 @@
 #endif
 }
 
+/*
+** When we discover that two subgoals depend on each other, neither can be
+** completed alone. We therefore pass responsibility for completing all
+** the subgoals in an SCC to the subgoal whose nondet stack frame is
+** lowest in the nondet stack.
+*/
+
 static void
 make_subgoal_follow_leader(MR_Subgoal *this_follower, MR_Subgoal *leader)
 {
@@ -1050,21 +1102,21 @@
 	save_transient_registers();
 }
 
-/* 
-** The following procedure saves the state of the mercury runtime 
-** so that it may be used in the table_nondet_resume procedure below to return 
-** answers through this saved state. The procedure table_nondet_suspend is 
-** declared as nondet but the code below is obviously of detism failure, 
+/*
+** The following procedure saves the state of the Mercury runtime
+** so that it may be used in the table_nondet_resume procedure below to return
+** answers through this saved state. The procedure table_nondet_suspend is
+** declared as nondet but the code below is obviously of detism failure;
 ** the reason for this is quite simple. Normally when a nondet proc
-** is called it will first return all of its answers and then fail. In the 
-** case of calls to this procedure this is reversed first the call will fail
+** is called it will first return all of its answers and then fail. In the
+** case of calls to this procedure this is reversed: first the call will fail
 ** then later on, when the answers are found, answers will be returned.
-** It is also important to note that the answers are returned not from the 
+** It is also important to note that the answers are returned not from the
 ** procedure that was originally called (table_nondet_suspend) but from the
 ** procedure table_nondet_resume. So essentially what is below is the code
 ** to do the initial fail; the code to return the answers is in
 ** table_nondet_resume.
-*/ 
+*/
 
 Declare_entry(mercury__table_nondet_resume_1_0);
 Declare_entry(MR_do_trace_redo_fail);
@@ -1110,8 +1162,8 @@
 		"suspension", "consumer");
 	restore_transient_registers();
 
-	cur_gen = MR_gen_sp - 1;
-	cur_cut = MR_cut_sp;
+	cur_gen = MR_gen_next - 1;
+	cur_cut = MR_cut_next - 1;
 	stop_addr = consumer->saved_state.non_stack_block_start;
 	for (fr = MR_maxfr; fr > stop_addr; fr = MR_prevfr_slot(fr))
 	{
@@ -1135,19 +1187,21 @@
 				*/
 
 				assert(MR_prevfr_slot(fr) == (stop_addr - 1));
-				*clobber_addr = (Word) ENTRY(mercury__table_nondet_resume_1_0);
+				*clobber_addr = (Word)
+					ENTRY(mercury__table_nondet_resume_1_0);
 #ifdef	MR_TABLE_DEBUG
 				if (MR_tablestackdebug) {
-					printf("completing redoip of frame at ");
+					printf("completing redoip "
+						"of frame at ");
 					MR_printnondstackptr(fr);
 					printf(" (in saved copy)\n");
 				}
 #endif
 
-				consumer->saved_state.gen_sp = cur_gen + 1;
+				consumer->saved_state.gen_next = cur_gen + 1;
 #ifdef	MR_TABLE_DEBUG
 				if (MR_tabledebug) {
-					printf("saved gen_sp set to %d\n",
+					printf("saved gen_next set to %d\n",
 						cur_gen + 1);
 				}
 #endif
@@ -1162,7 +1216,8 @@
 				*clobber_addr = (Word) ENTRY(do_fail);
 #ifdef	MR_TABLE_DEBUG
 				if (MR_tablestackdebug) {
-					printf("clobbering redoip of frame at ");
+					printf("clobbering redoip "
+						"of frame at ");
 					MR_printnondstackptr(fr);
 					printf(" (in saved copy)\n");
 				}
@@ -1225,7 +1280,7 @@
 ** to table_nondet_suspend. By restoring such states and then returning
 ** answers, table_nondet_resume is essentially returning answers out of
 ** the call to table_nondet_suspend, not out of the call to
-** table_nondet_resume. 
+** table_nondet_resume.
 **
 ** The code is arranged as a three level iteration to a fixpoint.
 ** The three levels are: iterating over all subgoals in a connected component,
@@ -1448,7 +1503,7 @@
 	assert((MR_maxfr - MR_prevfr_slot(MR_maxfr)) ==
 		(MR_NONDET_FIXED_SIZE + 1));
 
-	MR_gen_sp = MR_cur_leader->resume_info->leader_state.gen_sp;
+	MR_gen_next = MR_cur_leader->resume_info->leader_state.gen_next;
 	MR_redoip_slot(MR_maxfr) =
 		LABEL(mercury__table_nondet_resume_1_0_RedoPoint);
 	MR_redofr_slot(MR_maxfr) = MR_maxfr;
@@ -1481,7 +1536,7 @@
 		MR_cur_leader->resume_info->cur_consumer_answer_list->
 		next_answer;
 
-	/* 
+	/*
 	** Return the answer. Since we just restored the state of the
 	** computation that existed when suspend was called, the code
 	** that we return to is the code following the call to suspend.
@@ -1512,20 +1567,9 @@
 	}
 #endif
 
-#if 1
 	if (MR_cur_leader->resume_info->cur_consumer_answer_list != NULL) {
 		GOTO_LABEL(mercury__table_nondet_resume_1_0_ReturnAnswer);
 	}
-#else
-	if (*(MR_cur_leader->resume_info->cur_consumer->
-		remaining_answer_list_ptr) != NULL)
-	{
-		MR_cur_leader->resume_info->cur_consumer_answer_list =
-			*(MR_cur_leader->resume_info->cur_consumer->
-				remaining_answer_list_ptr);
-		GOTO_LABEL(mercury__table_nondet_resume_1_0_ReturnAnswer);
-	}
-#endif
 
 #ifdef	MR_TABLE_DEBUG
 	if (MR_tabledebug) {
@@ -1555,12 +1599,12 @@
 			}
 #endif
 
-			table_list->item->status = MR_SUBGOAL_COMPLETE; 
+			table_list->item->status = MR_SUBGOAL_COMPLETE;
 			table_list->item->num_committed_ans = -1;
 		}
 	}
 
-	/* Restore the state we had when table_nondet_resume was called */ 
+	/* Restore the state we had when table_nondet_resume was called */
 	save_transient_registers();
 	restore_state(&(MR_cur_leader->resume_info->leader_state),
 		"resumption", "generator");
@@ -1584,19 +1628,25 @@
 	fail();
 END_MODULE
 
-/* Ensure that the initialization code for the above modules get run. */
+#endif
+
+/* Ensure that the initialization code for the above modules gets to run. */
 /*
 INIT mercury_sys_init_table_modules
 */
 
+#ifdef	MR_USE_MINIMAL_MODEL
 extern ModuleFunc table_nondet_suspend_module;
 extern ModuleFunc table_nondet_resume_module;
 extern ModuleFunc table_nondet_commit_module;
+#endif
 
 void mercury_sys_init_table_modules(void);
 	/* extra declaration to suppress gcc -Wmissing-decl warning */
 void mercury_sys_init_table_modules(void) {
+#ifdef	MR_USE_MINIMAL_MODEL
 	table_nondet_suspend_module();
 	table_nondet_resume_module();
 	table_nondet_commit_module();
+#endif
 }
diff --recursive -u ./runtime/mercury_tabling.h /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_tabling.h
--- ./runtime/mercury_tabling.h	Tue Apr 20 15:59:21 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_tabling.h	Sun Mar 21 20:44:30 1999
@@ -410,7 +410,7 @@
 		printf("pointing to: %p\n",				\
 			*((MR_AnswerBlock) ABlock)))			\
 	:								\
-		0 /* do nothing */					\
+		(void ) 0 /* do nothing */				\
 	),								\
 	(* ((MR_AnswerBlock) ABlock))[Offset])
 
@@ -524,7 +524,7 @@
 ** is used only when the goal has no outputs. This is why
 ** MR_SIMPLETABLE_SUCCEEDED must the last entry in the enum,
 ** and why code looking at an MR_SimpletableStatus must test
-** for success with "x >= MR_SIMPLETABLE_SUCCEEDED".
+** for success with "(Unsigned) x >= MR_SIMPLETABLE_SUCCEEDED".
 */
 
 typedef enum {
@@ -534,6 +534,8 @@
 	MR_SIMPLETABLE_SUCCEEDED
 } MR_SimpletableStatus;
 
+#ifdef	MR_USE_MINIMAL_MODEL
+
 typedef enum {
    	MR_SUBGOAL_INACTIVE,
 	MR_SUBGOAL_ACTIVE,
@@ -580,9 +582,9 @@
 	Word	*det_stack_block_start;
 	Word	det_stack_block_size;
 	Word	*det_stack_block;
-	Integer	gen_sp;
+	Integer	gen_next;
 	char	*generator_stack_block;
-	Integer	cut_sp;
+	Integer	cut_next;
 	char	*cut_stack_block;
 } MR_SavedState;
 
@@ -663,4 +665,6 @@
 
 /*---------------------------------------------------------------------------*/
 
-#endif /* not MERCURY_TABLING_H */
+#endif	/* MR_USE_MINIMAL_MODEL */
+
+#endif	/* not MERCURY_TABLING_H */
diff --recursive -u ./runtime/mercury_wrapper.c /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_wrapper.c
--- ./runtime/mercury_wrapper.c	Tue Apr 20 15:59:21 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_wrapper.c	Sat Apr 17 20:56:31 1999
@@ -47,9 +47,9 @@
 /* size of data areas (including redzones), in kilobytes */
 /* (but we later multiply by 1024 to convert to bytes) */
 #ifdef MR_DEBUG_AGC
-  size_t		heap_size =       128;
+  size_t	heap_size =		  128;
 #else
-  size_t		heap_size =	 4096;
+  size_t	heap_size =		 4096;
 #endif
 size_t		detstack_size =  	 2048;
 size_t		nondstack_size =  	  128;
@@ -63,9 +63,9 @@
 /* size of the redzones at the end of data areas, in kilobytes */
 /* (but we later multiply by 1024 to convert to bytes) */
 #ifdef NATIVE_GC
-  size_t		heap_zone_size =   96;
+  size_t	heap_zone_size =	   96;
 #else
-  size_t		heap_zone_size =   16;
+  size_t	heap_zone_size =	   16;
 #endif
 size_t		detstack_zone_size =	   16;
 size_t		nondstack_zone_size =	   16;
@@ -76,19 +76,13 @@
 size_t		generatorstack_zone_size = 16;
 size_t		cutstack_zone_size =	   16;
 
-/* virtual machine registers that we don't even try to make real ones */
-Integer			MR_gen_sp = 0;
-Integer			MR_cut_sp = 0;
-MR_GeneratorStackFrame	*MR_gen_stack = NULL;
-MR_CutStackFrame	*MR_cut_stack = NULL;
-
 /* primary cache size to optimize for, in bytes */
 size_t		pcache_size =	         8192;
 
 /* file names for mdb's debugger I/O streams */
-const char *MR_mdb_in_filename = NULL;
-const char *MR_mdb_out_filename = NULL;
-const char *MR_mdb_err_filename = NULL;
+const char	*MR_mdb_in_filename = NULL;
+const char	*MR_mdb_out_filename = NULL;
+const char	*MR_mdb_err_filename = NULL;
 
 /* other options */
 
@@ -964,6 +958,18 @@
 				break;
 			case MR_GLOBAL_HP_RN:
 				printf("MR_global_hp");
+				break;
+			case MR_GEN_STACK_RN:
+				printf("MR_gen_stack");
+				break;
+			case MR_GEN_NEXT_RN:
+				printf("MR_gen_next");
+				break;
+			case MR_CUT_STACK_RN:
+				printf("MR_cut_stack");
+				break;
+			case MR_CUT_NEXT_RN:
+				printf("MR_cut_next");
 				break;
 			default:
 				printf("UNKNOWN%d", i);
diff --recursive -u ./runtime/mercury_wrapper.h /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_wrapper.h
--- ./runtime/mercury_wrapper.h	Tue Apr 20 15:59:22 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/runtime/mercury_wrapper.h	Thu Apr 15 12:03:01 1999
@@ -129,16 +129,10 @@
 extern	size_t		generatorstack_zone_size;
 extern	size_t		cutstack_zone_size;
 
-/* virtual machine registers that we don't even try to make real ones */
-extern	Integer			MR_gen_sp;
-extern	Integer			MR_cut_sp;
-extern	MR_GeneratorStackFrame	*MR_gen_stack;
-extern	MR_CutStackFrame	*MR_cut_stack;
-
 /* file names for the mdb debugging streams */
-extern const char *MR_mdb_in_filename;
-extern const char *MR_mdb_out_filename;
-extern const char *MR_mdb_err_filename;
+extern	const char	*MR_mdb_in_filename;
+extern	const char	*MR_mdb_out_filename;
+extern	const char	*MR_mdb_err_filename;
 
 /* size of the primary cache */
 extern	size_t		pcache_size;
diff --recursive -u ./scripts/final_grade_options.sh-subr /mnt/munkora/home/staff/zs/mer/ws4/scripts/final_grade_options.sh-subr
--- ./scripts/final_grade_options.sh-subr	Fri Oct 16 16:19:22 1998
+++ /mnt/munkora/home/staff/zs/mer/ws4/scripts/final_grade_options.sh-subr	Wed Apr 14 09:43:09 1999
@@ -1,5 +1,5 @@
 #---------------------------------------------------------------------------#
-# Copyright (C) 1998 The University of Melbourne.
+# Copyright (C) 1998-1999 The University of Melbourne.
 # This file may only be copied under the terms of the GNU General
 # Public License - see the file COPYING in the Mercury distribution.
 #---------------------------------------------------------------------------#
@@ -14,11 +14,21 @@
 #---------------------------------------------------------------------------#
 
 #
-# .debug grade implies --use-trail
-#	(see comment in compiler/handle_options.m for rationale)
+# .tr grade is not compatible with .mm
+#	(see comment in runtime/mercury_tabling.c for rationale)
 #
-case $stack_trace,$require_tracing in
+case $use_trail,$use_minimal_model in
 	true,true)
+		echo "trailing and minimal model tabling are not compatible"
+		exit 1 ;;
+esac
+
+#
+# .debug grade implies --use-trail in the absence of .mm
+#	(see comment in compiler/handle_options.m for rationale)
+#
+case $stack_trace,$require_tracing,$use_minimal_model in
+	true,true,false)
 		use_trail=true ;;
 esac
 
diff --recursive -u ./scripts/init_grade_options.sh-subr /mnt/munkora/home/staff/zs/mer/ws4/scripts/init_grade_options.sh-subr
--- ./scripts/init_grade_options.sh-subr	Tue Jun  9 12:16:22 1998
+++ /mnt/munkora/home/staff/zs/mer/ws4/scripts/init_grade_options.sh-subr	Wed Apr 14 09:43:17 1999
@@ -1,5 +1,5 @@
 #---------------------------------------------------------------------------#
-# Copyright (C) 1997-1998 The University of Melbourne.
+# Copyright (C) 1997-1999 The University of Melbourne.
 # This file may only be copied under the terms of the GNU General
 # Public License - see the file COPYING in the Mercury distribution.
 #---------------------------------------------------------------------------#
@@ -21,6 +21,7 @@
 profile_calls=false
 profile_memory=false
 use_trail=false
+use_minimal_model=false
 args_method=compact
 stack_trace=false
 require_tracing=false
diff --recursive -u ./scripts/mgnuc.in /mnt/munkora/home/staff/zs/mer/ws4/scripts/mgnuc.in
--- ./scripts/mgnuc.in	Wed Apr  7 03:13:01 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/scripts/mgnuc.in	Wed Apr 14 09:42:55 1999
@@ -267,6 +267,11 @@
 	false)		TRAIL_OPTS="" ;;
 esac
 
+case $use_minimal_model in
+	true)		MINIMAL_MODEL_OPTS="-DMR_USE_MINIMAL_MODEL" ;;
+	false)		MINIMAL_MODEL_OPTS="" ;;
+esac
+
 case $thread_safe in
 	true)
 	case $FULLARCH in
@@ -434,8 +439,8 @@
 		$GRADE_OPTS $GC_OPTS $DEFINE_OPTS \
 		$TRACE_OPTS $STACK_TRACE_OPTS $LLDEBUG_OPTS $C_DEBUG_OPTS \
 		$PROF_TIME_OPTS $PROF_CALLS_OPTS $PROF_MEMORY_OPTS \
-		$INLINE_ALLOC_OPTS $TRAIL_OPTS $SPLIT_OPTS $THREAD_OPTS \
-		$PICREG_OPTS $ARCH_OPTS $ARG_OPTS"
+		$INLINE_ALLOC_OPTS $TRAIL_OPTS $MINIMAL_MODEL_OPTS \
+		$SPLIT_OPTS $THREAD_OPTS $PICREG_OPTS $ARCH_OPTS $ARG_OPTS"
 
 case $verbose in true)
 	echo $CC $ALL_CC_OPTS "$@" $OVERRIDE_OPTS $ALL_LOCAL_C_INCL_DIRS;;
diff --recursive -u ./scripts/parse_grade_options.sh-subr /mnt/munkora/home/staff/zs/mer/ws4/scripts/parse_grade_options.sh-subr
--- ./scripts/parse_grade_options.sh-subr	Wed Sep 23 08:57:11 1998
+++ /mnt/munkora/home/staff/zs/mer/ws4/scripts/parse_grade_options.sh-subr	Wed Apr 14 09:43:35 1999
@@ -96,6 +96,11 @@
 	--no-use-trail)
 		use_trail=false ;;
 
+	--use-minimal-model)
+		use_minimal_model=true ;;
+	--no-use-minimal-model)
+		use_minimal_model=false ;;
+
 	--args)
 		shift
 		case "$1" in
@@ -133,6 +138,7 @@
 	    profile_calls=false
 	    profile_memory=false
 	    use_trail=false
+	    use_minimal_model=false
 	    args_method=compact
 	    stack_trace=false
 	    require_tracing=false
@@ -161,6 +167,8 @@
 				args_method=simple
 				;;
 			tr)	use_trail=true
+				;;
+			mm)	use_minimal_model=true
 				;;
 			memprof)
 				profile_time=false
diff --recursive -u ./trace/mercury_trace_internal.c /mnt/munkora/home/staff/zs/mer/ws4/trace/mercury_trace_internal.c
--- ./trace/mercury_trace_internal.c	Fri Apr 16 12:30:19 1999
+++ /mnt/munkora/home/staff/zs/mer/ws4/trace/mercury_trace_internal.c	Thu Apr 15 12:04:04 1999
@@ -1294,6 +1294,15 @@
 		} else {
 			MR_trace_usage("developer", "nondet_stack");
 		}
+#ifdef	MR_USE_MINIMAL_MODEL
+	} else if (streq(words[0], "gen_stack")) {
+		if (word_count == 1) {
+			do_init_modules();
+			MR_print_gen_stack(MR_mdb_out);
+		} else {
+			MR_trace_usage("developer", "gen_stack");
+		}
+#endif
 	} else if (streq(words[0], "stack_regs")) {
 		if (word_count == 1) {
 			fprintf(MR_mdb_out, "sp = ");
@@ -2489,6 +2498,9 @@
 	{ "exp", "clear_histogram" },
 #endif
 	{ "developer", "nondet_stack" },
+#ifdef	MR_USE_MINIMAL_MODEL
+	{ "developer", "gen_stack" },
+#endif
 	{ "developer", "stack_regs" },
 	{ "misc", "source" },
 	{ "misc", "quit" },
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list