[m-rev.] diff: major improvements to tabling (part 2 of 2)

Zoltan Somogyi zs at cs.mu.OZ.AU
Tue Jul 20 14:44:00 AEST 2004


cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/Mmakefile,v
retrieving revision 1.112
diff -u -b -r1.112 Mmakefile
--- runtime/Mmakefile	7 Jul 2004 07:11:07 -0000	1.112
+++ runtime/Mmakefile	7 Jul 2004 07:57:28 -0000
@@ -29,8 +29,8 @@
 			mercury_builtin_types.h	\
 			mercury_builtin_types_proc_layouts.h	\
 			mercury_calls.h		\
-			mercury_conf.h		\
 			mercury_conf_bootstrap.h \
+			mercury_conf.h		\
 			mercury_conf_param.h	\
 			mercury_construct.h	\
 			mercury_context.h	\
@@ -64,19 +64,22 @@
 			mercury_memory_zones.h	\
 			mercury_minimal_model.h	\
 			mercury_misc.h		\
+			mercury_mm_own_stacks.h	\
 			mercury_overflow.h	\
 			mercury_proc_id.h	\
 			mercury_prof.h		\
+			mercury_profiling_builtin.h	\
 			mercury_prof_mem.h	\
 			mercury_prof_time.h	\
 			mercury_profiling_builtin.h	\
 			mercury_reg_workarounds.h	\
 			mercury_regs.h		\
+			mercury_reg_workarounds.h	\
 			mercury_runtime_util.h	\
 			mercury_signal.h	\
 			mercury_stack_layout.h	\
-			mercury_stack_trace.h	\
 			mercury_stacks.h	\
+			mercury_stack_trace.h	\
 			mercury_std.h		\
 			mercury_string.h	\
 			mercury_tabling.h	\
@@ -88,11 +91,11 @@
 			mercury_timing.h	\
 			mercury_trace_base.h	\
 			mercury_trail.h		\
+			mercury_typeclass_info.h	\
 			mercury_type_desc.h	\
 			mercury_type_info.h	\
-			mercury_type_tables.h	\
-			mercury_typeclass_info.h	\
 			mercury_types.h		\
+			mercury_type_tables.h	\
 			mercury_univ.h		\
 			mercury_wrapper.h
 
@@ -148,8 +151,8 @@
 			mercury_engine.c	\
 			mercury_file.c		\
 			mercury_float.c		\
-			mercury_getopt.c	\
 			mercury_getopt1.c	\
+			mercury_getopt.c	\
 			mercury_grade.c		\
 			mercury_hash_table.c	\
 			mercury_heap_profile.c	\
@@ -161,16 +164,17 @@
 			mercury_memory_zones.c	\
 			mercury_minimal_model.c	\
 			mercury_misc.c		\
+			mercury_mm_own_stacks.c	\
 			mercury_prof.c		\
+			mercury_profiling_builtin.c	\
 			mercury_prof_mem.c	\
 			mercury_prof_time.c	\
-			mercury_profiling_builtin.c	\
-			mercury_reg_workarounds.c	\
 			mercury_regs.c		\
+			mercury_reg_workarounds.c	\
 			mercury_runtime_util.c	\
 			mercury_signal.c	\
-			mercury_stack_trace.c	\
 			mercury_stacks.c	\
+			mercury_stack_trace.c	\
 			mercury_string.c	\
 			mercury_tabling.c	\
 			mercury_term_size.c	\
Index: runtime/mercury_bootstrap.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_bootstrap.h,v
retrieving revision 1.36
diff -u -b -r1.36 mercury_bootstrap.h
--- runtime/mercury_bootstrap.h	7 Jul 2004 07:11:08 -0000	1.36
+++ runtime/mercury_bootstrap.h	18 Jul 2004 01:53:16 -0000
@@ -48,6 +48,11 @@
 typedef MR_UnsignedChar 	UnsignedChar;
 typedef MR_String 		String;
 typedef MR_ConstString 		ConstString;
+
+#ifndef	MR_HIGHLEVEL_CODE
+typedef	MR_Context		Context;
+#endif
+
 /*
 ** MR_Bool is the C representation for the Mercury type bool__bool.
 ** For ordinary booleans, use MR_bool in mercury_std.h.
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.78
diff -u -b -r1.78 mercury_conf_param.h
--- runtime/mercury_conf_param.h	31 May 2004 04:13:04 -0000	1.78
+++ runtime/mercury_conf_param.h	2 Jul 2004 07:31:40 -0000
@@ -53,7 +53,8 @@
 ** MR_BOXED_FLOAT
 ** MR_USE_TRAIL
 ** MR_RESERVE_TAG
-** MR_USE_MINIMAL_MODEL
+** MR_USE_MINIMAL_MODEL_STACK_COPY
+** MR_USE_MINIMAL_MODEL_OWN_STACKS
 ** MR_MINIMAL_MODEL_DEBUG
 ** MR_SPLIT_C_FILES
 ** MR_INLINE_ALLOC
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_context.c,v
retrieving revision 1.37
diff -u -b -r1.37 mercury_context.c
--- runtime/mercury_context.c	7 Jul 2004 07:11:09 -0000	1.37
+++ runtime/mercury_context.c	18 Jul 2004 11:42:54 -0000
@@ -26,6 +26,9 @@
 #include "mercury_engine.h"		/* for `MR_memdebug' */
 #include "mercury_reg_workarounds.h"	/* for `MR_fd*' stuff */
 
+static	void	MR_init_context_maybe_generator(MR_Context *c,
+			MR_Generator *gen);
+
 MR_Context	*MR_runqueue_head;
 MR_Context	*MR_runqueue_tail;
 #ifdef	MR_THREAD_SAFE
@@ -83,8 +86,9 @@
 }
 
 void 
-MR_init_context(MR_Context *c)
+MR_init_context(MR_Context *c, const char *id, MR_Generator *gen)
 {
+	c->MR_ctxt_id = id;
 	c->MR_ctxt_next = NULL;
 	c->MR_ctxt_resume = NULL;
 #ifdef	MR_THREAD_SAFE
@@ -96,18 +100,26 @@
 
 	if (c->MR_ctxt_detstack_zone != NULL) {
 		MR_reset_redzone(c->MR_ctxt_detstack_zone);
+	} else if (gen != NULL) {
+		c->MR_ctxt_detstack_zone = MR_create_zone("gen_detstack",
+			0, MR_gen_detstack_size, MR_next_offset(),
+			MR_gen_detstack_zone_size, MR_default_handler);
 	} else {
-		c->MR_ctxt_detstack_zone = MR_create_zone("detstack", 0,
-			MR_detstack_size, MR_next_offset(),
+		c->MR_ctxt_detstack_zone = MR_create_zone("detstack",
+			0, MR_detstack_size, MR_next_offset(),
 			MR_detstack_zone_size, MR_default_handler);
 	}
 	c->MR_ctxt_sp = c->MR_ctxt_detstack_zone->min;
 
 	if (c->MR_ctxt_nondetstack_zone != NULL) {
 		MR_reset_redzone(c->MR_ctxt_nondetstack_zone);
+	} else if (gen != NULL) {
+		c->MR_ctxt_nondetstack_zone = MR_create_zone("gen_nondetstack",
+			0, MR_gen_nonstack_size, MR_next_offset(),
+			MR_gen_nonstack_zone_size, MR_default_handler);
 	} else {
-		c->MR_ctxt_nondetstack_zone = MR_create_zone("nondetstack", 0,
-			MR_nondstack_size, MR_next_offset(),
+		c->MR_ctxt_nondetstack_zone = MR_create_zone("nondetstack",
+			0, MR_nondstack_size, MR_next_offset(),
 			MR_nondstack_zone_size, MR_default_handler);
 	}
 	/*
@@ -127,7 +139,12 @@
 		MR_ENTRY(MR_do_not_reached);
 	MR_succfr_slot_word(c->MR_ctxt_curfr) = (MR_Word) NULL;
 
-  #ifdef MR_USE_MINIMAL_MODEL
+  #ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
+	if (gen != NULL) {
+		MR_fatal_error("MR_init_context_maybe_generator: "
+			"generator and stack_copy");
+	}
+
 	if (c->MR_ctxt_genstack_zone != NULL) {
 		MR_reset_redzone(c->MR_ctxt_genstack_zone);
 	} else {
@@ -154,10 +171,19 @@
 			MR_pnegstack_zone_size, MR_default_handler);
 	}
 	c->MR_ctxt_pneg_next = 0;
-  #endif /* MR_USE_MINIMAL_MODEL */
+  #endif /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+  #ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
+	c->MR_ctxt_owner_generator = gen;
+  #endif /* MR_USE_MINIMAL_MODEL_OWN_STACKS */
 #endif /* !MR_HIGHLEVEL_CODE */
 
 #ifdef MR_USE_TRAIL
+	if (gen != NULL) {
+		MR_fatal_error("MR_init_context_maybe_generator: "
+			"generator and trail");
+	}
+
 	if (c->MR_ctxt_trail_zone != NULL) {
 		MR_reset_redzone(c->MR_ctxt_trail_zone);
 	} else {
@@ -170,11 +196,19 @@
 	c->MR_ctxt_ticket_high_water = 1;
 #endif
 
+#ifndef	MR_CONSERVATIVE_GC
+	if (is_generator) {
+		MR_fatal_error("MR_init_context_maybe_generator: "
+			"generator and no conservative gc");
+	}
+
 	c->MR_ctxt_hp = NULL;
+	c->MR_ctxt_min_hp_rec = NULL;
+#endif
 }
 
 MR_Context *
-MR_create_context(void)
+MR_create_context(const char *id, MR_Generator *gen)
 {
 	MR_Context *c;
 
@@ -195,7 +229,7 @@
 		MR_UNLOCK(&free_context_list_lock, "create_context ii");
 	}
 
-	MR_init_context(c);
+	MR_init_context(c, id, gen);
 
 	return c;
 }
Index: runtime/mercury_context.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_context.h,v
retrieving revision 1.25
diff -u -b -r1.25 mercury_context.h
--- runtime/mercury_context.h	7 Jul 2004 07:11:09 -0000	1.25
+++ runtime/mercury_context.h	7 Jul 2004 08:02:15 -0000
@@ -47,7 +47,7 @@
 
 #include <stdio.h>
 
-#include "mercury_types.h"		/* for MR_Word */
+#include "mercury_types.h"		/* for MR_Word, MR_Code, etc */
 #include "mercury_trail.h"		/* for MR_TrailEntry */
 #include "mercury_memory.h"		/* for MR_MemoryZone */
 #include "mercury_thread.h"		/* for MercuryLock */
@@ -62,28 +62,31 @@
 
 typedef struct MR_Context_Struct MR_Context;
 struct MR_Context_Struct {
+	const char	*MR_ctxt_id;
+
 	MR_Context	 *MR_ctxt_next;	
 		/*
-		** if this context is in the free-list `next' will point
-		** to the next free context. If this context is suspended
-		** waiting for a variable to become bound, `next' will point to
-		** the next waiting context. If this context is runnable but not
-		** currently running then `next' points to the next runnable
+			** If this context is in the free-list `next' will
+			** point to the next free context. If this context
+			** is suspended waiting for a variable to become bound,
+			** `next' will point to the next waiting context.
+			** If this context is runnable but not currently
+			** running then `next' points to the next runnable
 		** context in the runqueue.
 		*/
 
 	MR_Code		*MR_ctxt_resume;
 		/*
-		** a pointer to the code at which execution should resume when
-		** this context is next scheduled.
+			** A pointer to the code at which execution should
+			** resume when this context is next scheduled.
 		*/
 
 #ifdef	MR_THREAD_SAFE
 	MercuryThread	MR_ctxt_owner_thread;
 		/*
-		** The owner_thread field is used to ensure that when we
-		** enter a mercury engine from C, we return to the same
-		** engine. See the coments in mercury_engine.h
+			** The owner_thread field is used to ensure that when
+			** we enter a mercury engine from C, we return to the
+			** same engine. See the coments in mercury_engine.h
 		*/
 #endif
 
@@ -102,7 +105,7 @@
 		/* saved maxfr pointer for this context */
 	MR_Word		*MR_ctxt_curfr;
 		/* saved curfr pointer for this context */
-  #ifdef MR_USE_MINIMAL_MODEL
+  #ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
 	MR_MemoryZone	*MR_ctxt_genstack_zone;
 		/* pointer to the genstack_zone for this context */
 	MR_Integer	MR_ctxt_gen_next;
@@ -115,7 +118,10 @@
 		/* pointer to the pnegstack_zone for this context */
 	MR_Integer	MR_ctxt_pneg_next;
 		/* saved pneg stack index for this context */
-  #endif /* MR_USE_MINIMAL_MODEL */
+  #endif /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+  #ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
+	MR_Generator	*MR_ctxt_owner_generator;
+  #endif /* MR_USE_MINIMAL_MODEL_OWN_STACKS */
 #endif /* !MR_HIGHLEVEL_CODE */
 
 #ifdef	MR_USE_TRAIL
@@ -129,18 +135,19 @@
 		/* saved MR_ticket_high_water for this context */
 #endif
 
+#ifndef	MR_CONSERVATIVE_GC
 	MR_Word		*MR_ctxt_hp;
 		/* saved hp for this context */
 	MR_Word		*MR_ctxt_min_hp_rec;
 		/*
-		** this pointer marks the minimum value of MR_hp to which we can
-		** truncate the heap on backtracking. See comments before the
-		** set_min_heap_reclamation_point macro (below).
+			** This pointer marks the minimum value of MR_hp to
+			** which we can truncate the heap on backtracking.
+			** See comments before the macro
+			** set_min_heap_reclamation_point (below).
 		*/
+#endif
 };
 
-typedef MR_Context Context;	/* for backwards compatibility */
-
 /*
 ** The runqueue is a linked list of contexts that are runnable.
 */
@@ -187,42 +194,44 @@
 #endif
 
 /*
-** Initializes a context structure.
+** Initializes a context structure, and gives it the given id. If gen is
+** non-NULL, the context is for the given generator.
 */
-extern	void		MR_init_context(MR_Context *context);
+extern	void		MR_init_context(MR_Context *context, const char *id,
+				MR_Generator *gen);
 
 /*
-** create_context() allocates and initializes a new context
-** structure.
+** Allocates and initializes a new context structure, and gives it the given
+** id. If gen is non-NULL, the context is for the given generator.
 */
-extern	MR_Context 	*MR_create_context(void);
+extern	MR_Context 	*MR_create_context(const char *id, MR_Generator *gen);
 
 /*
-** destroy_context(ptr) returns the context structure pointed
+** MR_destroy_context(ptr) returns the context structure pointed
 ** to by ptr to the free list, and releases resources as
 ** necessary.
 */
 extern	void		MR_destroy_context(MR_Context *context);
 
 /*
-** init_thread_stuff() initializes the lock structures for the runqueue.
+** MR_init_thread_stuff() initializes the lock structures for the runqueue.
 */
 extern	void		MR_init_thread_stuff(void);
 
 /*
-** finialize_runqueue() finalizes the lock structures for the runqueue.
+** MR_finialize_runqueue() finalizes the lock structures for the runqueue.
 */
 extern	void		MR_finalize_runqueue(void);
 
 /*
-** flounder() aborts with a runtime error message. It is called if
+** MR_flounder() aborts with a runtime error message. It is called if
 ** the runqueue becomes empty and none of the running processes are
 ** working - ie the computation has floundered.
 */
 extern	void		MR_flounder(void);
 
 /*
-** schedule(MR_Context *cptr):
+** MR_schedule(MR_Context *cptr):
 **	Append a context onto the end of the run queue.
 */
 
@@ -250,16 +259,19 @@
   ** The new context gets put on the runqueue, and the current
   ** context resumes at `parent'.
   */
-  #define MR_fork_new_context(child, parent, numslots) do {		\
+  #define MR_fork_new_context(child, parent, numslots)			\
+	do {								\
 		MR_Context	*f_n_c_context;				\
 		int		fork_new_context_i;			\
+									\
 		f_n_c_context = MR_create_context();			\
 		MR_IF_MR_THREAD_SAFE(					\
 			f_n_c_context->owner_thread = NULL;		\
 		)							\
-		for (fork_new_context_i = (numslots) ;			\
-				fork_new_context_i > 0 ;		\
-				fork_new_context_i--) {			\
+		for (fork_new_context_i = (numslots);			\
+			fork_new_context_i > 0;				\
+			fork_new_context_i--)				\
+		{							\
 			*(f_n_c_context->context_sp) = 			\
 				MR_stackvar(fork_new_context_i);	\
 			f_n_c_context->MR_ctxt_sp++;			\
@@ -303,7 +315,8 @@
   #define MR_set_min_heap_reclamation_point(ctxt)			\
 	do {								\
 		if (MR_hp != (ctxt)->MR_ctxt_hp 			\
-			|| (ctxt)->MR_ctxt_hp == NULL)	{		\
+			|| (ctxt)->MR_ctxt_hp == NULL)			\
+		{							\
 			MR_min_hp_rec = MR_hp;				\
 			(ctxt)->MR_ctxt_min_hp_rec = MR_hp;		\
 		} else {						\
@@ -331,10 +344,10 @@
   #define MR_IF_USE_TRAIL(x)
 #endif
 
-#ifdef MR_USE_MINIMAL_MODEL
-  #define MR_IF_USE_MINIMAL_MODEL(x) x
+#ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
+  #define MR_IF_USE_MINIMAL_MODEL_STACK_COPY(x) x
 #else
-  #define MR_IF_USE_MINIMAL_MODEL(x)
+  #define MR_IF_USE_MINIMAL_MODEL_STACK_COPY(x)
 #endif
 
 #ifndef MR_HIGHLEVEL_CODE
@@ -357,26 +370,26 @@
 				load_context_c->MR_ctxt_maxfr; 		\
 			MR_curfr_word   = (MR_Word)			\
 				load_context_c->MR_ctxt_curfr;		\
-		  MR_IF_USE_MINIMAL_MODEL(				\
+		  MR_IF_USE_MINIMAL_MODEL_STACK_COPY(			\
 			MR_gen_next = load_context_c->MR_ctxt_gen_next;	\
 			MR_cut_next = load_context_c->MR_ctxt_cut_next;	\
-			MR_pneg_next = load_context_c->MR_ctxt_pneg_next;\
+		    MR_pneg_next = load_context_c->MR_ctxt_pneg_next;	\
 		  )							\
 		)							\
 	        MR_IF_USE_TRAIL(					\
-			MR_trail_zone = load_context_c->MR_ctxt_trail_zone;\
-			MR_trail_ptr = load_context_c->MR_ctxt_trail_ptr;\
+		  MR_trail_zone = load_context_c->MR_ctxt_trail_zone;	\
+		  MR_trail_ptr = load_context_c->MR_ctxt_trail_ptr;	\
 		    MR_ticket_counter =					\
 				load_context_c->MR_ctxt_ticket_counter;	\
 		    MR_ticket_high_water =				\
-				 load_context_c->MR_ctxt_ticket_high_water;\
+		    load_context_c->MR_ctxt_ticket_high_water;		\
 	    	)							\
 		MR_IF_NOT_HIGHLEVEL_CODE(				\
 		  MR_ENGINE(MR_eng_context).MR_ctxt_detstack_zone =	\
 				load_context_c->MR_ctxt_detstack_zone;	\
 		  MR_ENGINE(MR_eng_context).MR_ctxt_nondetstack_zone =	\
-				load_context_c->MR_ctxt_nondetstack_zone;\
-		  MR_IF_USE_MINIMAL_MODEL(				\
+		    load_context_c->MR_ctxt_nondetstack_zone;		\
+		  MR_IF_USE_MINIMAL_MODEL_STACK_COPY(			\
 		    MR_ENGINE(MR_eng_context).MR_ctxt_genstack_zone =   \
 				load_context_c->MR_ctxt_genstack_zone;	\
 		    MR_ENGINE(MR_eng_context).MR_ctxt_cutstack_zone =   \
@@ -407,15 +420,15 @@
 			save_context_c->MR_ctxt_sp	= MR_sp;	\
 			save_context_c->MR_ctxt_maxfr   = MR_maxfr;	\
 			save_context_c->MR_ctxt_curfr   = MR_curfr;	\
-		  MR_IF_USE_MINIMAL_MODEL(				\
+		  MR_IF_USE_MINIMAL_MODEL_STACK_COPY(			\
 			save_context_c->MR_ctxt_gen_next = MR_gen_next;	\
 			save_context_c->MR_ctxt_cut_next = MR_cut_next;	\
 			save_context_c->MR_ctxt_pneg_next = MR_pneg_next;\
 		  )							\
 		)							\
 		MR_IF_USE_TRAIL(					\
-			save_context_c->MR_ctxt_trail_zone = MR_trail_zone;\
-			save_context_c->MR_ctxt_trail_ptr = MR_trail_ptr;\
+		  save_context_c->MR_ctxt_trail_zone = MR_trail_zone;	\
+		  save_context_c->MR_ctxt_trail_ptr = MR_trail_ptr;	\
 			save_context_c->MR_ctxt_ticket_counter =	\
 						MR_ticket_counter;	\
 			save_context_c->MR_ctxt_ticket_high_water =	\
@@ -423,30 +436,22 @@
 		)							\
 		MR_IF_NOT_HIGHLEVEL_CODE(				\
 		  save_context_c->MR_ctxt_detstack_zone =		\
-				MR_ENGINE(MR_eng_context).		\
-					MR_ctxt_detstack_zone;		\
+		    MR_ENGINE(MR_eng_context).MR_ctxt_detstack_zone;	\
 		  save_context_c->MR_ctxt_nondetstack_zone =		\
-				MR_ENGINE(MR_eng_context).		\
-					MR_ctxt_nondetstack_zone;	\
-		  MR_IF_USE_MINIMAL_MODEL(				\
+		    MR_ENGINE(MR_eng_context).MR_ctxt_nondetstack_zone;	\
+		  MR_IF_USE_MINIMAL_MODEL_STACK_COPY(			\
 		    save_context_c->MR_ctxt_genstack_zone =		\
-				MR_ENGINE(MR_eng_context).		\
-					MR_ctxt_genstack_zone;		\
+		      MR_ENGINE(MR_eng_context).MR_ctxt_genstack_zone;	\
 		    save_context_c->MR_ctxt_cutstack_zone =		\
-				MR_ENGINE(MR_eng_context).		\
-					MR_ctxt_cutstack_zone;		\
+		      MR_ENGINE(MR_eng_context).MR_ctxt_cutstack_zone;	\
 		    save_context_c->MR_ctxt_pnegstack_zone =		\
-				MR_ENGINE(MR_eng_context).		\
-					MR_ctxt_pnegstack_zone;		\
+		      MR_ENGINE(MR_eng_context).MR_ctxt_pnegstack_zone;	\
 		    assert(MR_gen_stack == (MR_GenStackFrame *)		\
-				MR_ENGINE(MR_eng_context).		\
-					MR_ctxt_genstack_zone->min);	\
+		      MR_ENGINE(MR_eng_context).MR_ctxt_genstack_zone->min); \
 		    assert(MR_cut_stack == (MR_CutStackFrame *)		\
-				MR_ENGINE(MR_eng_context).		\
-					MR_ctxt_cutstack_zone->min);	\
+		      MR_ENGINE(MR_eng_context).MR_ctxt_cutstack_zone->min); \
 		    assert(MR_pneg_stack == (MR_PNegStackFrame *)	\
-				MR_ENGINE(MR_eng_context).		\
-					MR_ctxt_pnegstack_zone->min);	\
+		      MR_ENGINE(MR_eng_context).MR_ctxt_pnegstack_zone->min);\
 		  )							\
 		)							\
 		MR_save_hp_in_context(save_context_c);			\
Index: runtime/mercury_debug.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_debug.c,v
retrieving revision 1.22
diff -u -b -r1.22 mercury_debug.c
--- runtime/mercury_debug.c	23 May 2004 22:16:50 -0000	1.22
+++ runtime/mercury_debug.c	24 Jun 2004 08:20:37 -0000
@@ -14,6 +14,33 @@
 #include	<stdio.h>
 #include	<stdarg.h>
 
+#ifdef	MR_USE_MINIMAL_MODEL_OWN_STACKS
+  #define	MR_in_ctxt_det_zone(ptr, ctxt)			\
+		MR_in_zone(ptr, ctxt->MR_ctxt_detstack_zone)
+  #define	MR_in_ctxt_non_zone(ptr, ctxt)			\
+		MR_in_zone(ptr, ctxt->MR_ctxt_nondetstack_zone)
+
+  extern  const MR_Context	*MR_find_ctxt_for_det_ptr(const MR_Word *ptr);
+  extern  const MR_Context	*MR_find_ctxt_for_non_ptr(const MR_Word *ptr);
+
+  extern  MR_MemoryZone		*MR_find_zone_for_det_ptr(const MR_Word *ptr);
+  extern  MR_MemoryZone		*MR_find_zone_for_non_ptr(const MR_Word *ptr);
+
+  extern  MR_Generator		*MR_find_gen_for_det_ptr(const MR_Word *ptr);
+  extern  MR_Generator		*MR_find_gen_for_non_ptr(const MR_Word *ptr);
+
+  #define MR_det_zone(fr)	(MR_find_zone_for_det_ptr(fr))
+  #define MR_non_zone(fr)	(MR_find_zone_for_non_ptr(fr))
+#else
+  #define MR_det_zone(fr)	(MR_CONTEXT(MR_ctxt_detstack_zone))
+  #define MR_non_zone(fr)	(MR_CONTEXT(MR_ctxt_nondetstack_zone))
+#endif
+
+#define MR_det_stack_min(fr)	(MR_det_zone(fr)->min)
+#define MR_det_stack_offset(fr) (fr - MR_det_stack_min(fr))
+#define MR_non_stack_min(fr)	(MR_non_zone(fr)->min)
+#define MR_non_stack_offset(fr) (fr - MR_non_stack_min(fr))
+
 /*--------------------------------------------------------------------*/
 
 #ifdef	MR_DEEP_PROFILING
@@ -28,7 +55,6 @@
 static void	MR_print_ordinary_regs(void);
 static void	MR_do_watches(void);
 static MR_bool	MR_proc_matches_name(MR_Code *proc, const char *name);
-static void	MR_printdetslot_as_label(const MR_Integer offset);
 
 #ifdef	MR_LOWLEVEL_ADDR_DEBUG
   #define	MR_PRINT_RAW_ADDRS	MR_TRUE
@@ -38,6 +64,104 @@
 
 static	MR_bool	MR_print_raw_addrs = MR_PRINT_RAW_ADDRS;
 
+/* auxiliary routines for the code that prints debugging messages */
+
+#ifdef	MR_USE_MINIMAL_MODEL_OWN_STACKS
+
+const MR_Context *
+MR_find_ctxt_for_det_ptr(const MR_Word *ptr)
+{
+	const MR_Dlist		*item;
+	const MR_Context	*ctxt;
+
+	if (MR_in_ctxt_det_zone(ptr, MR_ENGINE(MR_eng_main_context))) {
+		return MR_ENGINE(MR_eng_main_context);
+	}
+
+	MR_for_dlist(item, MR_ENGINE(MR_eng_gen_contexts)) {
+		ctxt = (MR_Context *) MR_dlist_data(item);
+		if (MR_in_ctxt_det_zone(ptr, ctxt)) {
+			return ctxt;
+		}
+	}
+
+	return NULL;
+}
+
+const MR_Context *
+MR_find_ctxt_for_non_ptr(const MR_Word *ptr)
+{
+	const MR_Dlist		*item;
+	const MR_Context	*ctxt;
+
+	if (MR_in_ctxt_non_zone(ptr, MR_ENGINE(MR_eng_main_context))) {
+		return MR_ENGINE(MR_eng_main_context);
+	}
+
+	MR_for_dlist(item, MR_ENGINE(MR_eng_gen_contexts)) {
+		ctxt = (MR_Context *) MR_dlist_data(item);
+		if (MR_in_ctxt_non_zone(ptr, ctxt)) {
+			return ctxt;
+		}
+	}
+
+	return NULL;
+}
+
+MR_MemoryZone *
+MR_find_zone_for_det_ptr(const MR_Word *ptr)
+{
+	const MR_Context	*ctxt;
+
+	ctxt = MR_find_ctxt_for_det_ptr(ptr);
+	if (ctxt != NULL) {
+		return ctxt->MR_ctxt_detstack_zone;
+	}
+
+	MR_fatal_error("MR_find_zone_for_det_ptr: not in any context");
+}
+
+MR_MemoryZone *
+MR_find_zone_for_non_ptr(const MR_Word *ptr)
+{
+	const MR_Context	*ctxt;
+
+	ctxt = MR_find_ctxt_for_non_ptr(ptr);
+	if (ctxt != NULL) {
+		return ctxt->MR_ctxt_nondetstack_zone;
+	}
+
+	MR_fatal_error("MR_find_zone_for_non_ptr: not in any context");
+}
+
+MR_Generator *
+MR_find_gen_for_det_ptr(const MR_Word *ptr)
+{
+	const MR_Context	*ctxt;
+
+	ctxt = MR_find_ctxt_for_det_ptr(ptr);
+	if (ctxt != NULL) {
+		return ctxt->MR_ctxt_owner_generator;
+	}
+
+	MR_fatal_error("MR_find_gen_for_det_ptr: not in any context");
+}
+
+MR_Generator *
+MR_find_gen_for_non_ptr(const MR_Word *ptr)
+{
+	const MR_Context	*ctxt;
+
+	ctxt = MR_find_ctxt_for_non_ptr(ptr);
+	if (ctxt != NULL) {
+		return ctxt->MR_ctxt_owner_generator;
+	}
+
+	MR_fatal_error("MR_find_gen_for_non_ptr: not in any context");
+}
+
+#endif	/* MR_USE_MINIMAL_MODEL_OWN_STACKS */
+
 /* debugging messages */
 
 #ifdef MR_DEBUG_HEAP_ALLOC
@@ -95,7 +219,7 @@
 	printf("succ ip: "); MR_printlabel(stdout, MR_succip_slot(MR_curfr));
 	printf("redo fr: "); MR_printnondstack(MR_redofr_slot(MR_curfr));
 	printf("redo ip: "); MR_printlabel(stdout, MR_redoip_slot(MR_curfr));
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_OWN_STACKS
 	printf("det fr:  "); MR_printdetstack(MR_table_detfr_slot(MR_curfr));
 #endif
 
@@ -543,8 +667,7 @@
 	}
 
 	printf("offset %3ld words\n",
-		(long) (MR_Integer)
-			(fr - MR_CONTEXT(MR_ctxt_nondetstack_zone)->min));
+		(long) (MR_Integer) MR_non_stack_offset(fr));
 	printf("\t succip    "); MR_printlabel(stdout, MR_succip_slot(fr));
 	printf("\t redoip    "); MR_printlabel(stdout, MR_redoip_slot(fr));
 	printf("\t succfr    "); MR_printnondstack(MR_succfr_slot(fr));
@@ -784,15 +907,6 @@
 
 #ifndef MR_HIGHLEVEL_CODE
 
-static void 
-MR_printdetslot_as_label(const MR_Integer offset)
-{
-	MR_printdetstackptr(&MR_CONTEXT(MR_ctxt_detstack_zone)->min[offset]);
-	printf(" ");
-	MR_printlabel(stdout,
-		(MR_Code *) (MR_CONTEXT(MR_ctxt_detstack_zone)->min[offset]));
-}
-
 void 
 MR_printdetstackptr(const MR_Word *s)
 {
@@ -803,8 +917,7 @@
 MR_print_detstackptr(FILE *fp, const MR_Word *s)
 {
 	fprintf(fp, "det %3ld",
-		(long) (MR_Integer)
-			(s - MR_CONTEXT(MR_ctxt_detstack_zone)->min));
+		(long) (MR_Integer) MR_det_stack_offset(s));
 
 	if (MR_print_raw_addrs) {
 		fprintf(fp, " (%p)", (const void *) s);
@@ -819,8 +932,7 @@
 	}
 
 	printf("offset %3ld words\n",
-		(long) (MR_Integer)
-			(s - MR_CONTEXT(MR_ctxt_detstack_zone)->min));
+		(long) (MR_Integer) MR_det_stack_offset(s));
 }
 
 void 
@@ -833,8 +945,7 @@
 MR_print_nondstackptr(FILE *fp, const MR_Word *s)
 {
 	fprintf(fp, "non %3ld",
-		(long) (MR_Integer)
-			(s - MR_CONTEXT(MR_ctxt_nondetstack_zone)->min));
+		(long) (MR_Integer) MR_non_stack_offset(s));
 
 	if (MR_print_raw_addrs) {
 		fprintf(fp, " (%p)",
@@ -850,8 +961,7 @@
 	}
 
 	printf("offset %3ld words\n",
-		(long) (MR_Integer)
-			(s - MR_CONTEXT(MR_ctxt_nondetstack_zone)->min));
+		(long) (MR_Integer) MR_non_stack_offset(s));
 }
 
 #endif /* !MR_HIGHLEVEL_CODE */
Index: runtime/mercury_dlist.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_dlist.c,v
retrieving revision 1.6
diff -u -b -r1.6 mercury_dlist.c
--- runtime/mercury_dlist.c	10 Jan 2001 10:57:25 -0000	1.6
+++ runtime/mercury_dlist.c	15 Apr 2004 16:46:05 -0000
@@ -60,7 +60,7 @@
 
 	item = MR_GC_NEW(MR_Dlist);
 	MR_dlist_data(item) = data;
-	MR_dlist_length(list)++;
+	MR_dlist_length_field(list)++;
 
 	/* item's pointers	*/
 	MR_dlist_next(item) = MR_dlist_next(list);
@@ -87,7 +87,7 @@
 
 	item = MR_GC_NEW(MR_Dlist);
 	MR_dlist_data(item) = data;
-	MR_dlist_length(list)++;
+	MR_dlist_length_field(list)++;
 
 	/* item's pointers	*/
 	MR_dlist_next(item) = list;
@@ -125,7 +125,7 @@
 			MR_dlist_prev(MR_dlist_next(list1)) = list1;
 			MR_dlist_next(MR_dlist_prev(list1)) = list1;
 		} else {
-			MR_dlist_length(list1) = MR_dlist_length(list1)
+			MR_dlist_length_field(list1) = MR_dlist_length(list1)
 					+ MR_dlist_length(list2);
 			/* end of list 1 to start of list 2	*/
 			MR_dlist_next(MR_dlist_prev(list1)) =
@@ -179,7 +179,7 @@
 
 	item = MR_GC_NEW(MR_Dlist);
 	MR_dlist_data(item) = data;
-	MR_dlist_length(list)++;
+	MR_dlist_length_field(list)++;
 
 	/* item's pointers */
 	MR_dlist_next(item) = where;
@@ -200,7 +200,7 @@
 
 	item = MR_GC_NEW(MR_Dlist);
 	MR_dlist_data(item) = data;
-	MR_dlist_length(list)++;
+	MR_dlist_length_field(list)++;
 
 	/* item's pointers */
 	MR_dlist_next(item) = MR_dlist_next(where);
@@ -246,7 +246,7 @@
 		func(MR_dlist_data(item));
 	}
 
-	MR_dlist_length(list)--;
+	MR_dlist_length_field(list)--;
 	MR_dlist_next(MR_dlist_prev(item)) = MR_dlist_next(item);
 	MR_dlist_prev(MR_dlist_next(item)) = MR_dlist_prev(item);
 
Index: runtime/mercury_dlist.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_dlist.h,v
retrieving revision 1.4
diff -u -b -r1.4 mercury_dlist.h
--- runtime/mercury_dlist.h	20 Jan 2004 02:51:17 -0000	1.4
+++ runtime/mercury_dlist.h	15 Apr 2004 16:45:44 -0000
@@ -31,7 +31,11 @@
 #define	MR_dlist_next(ptr)		(ptr)->MR_dlist_next
 #define	MR_dlist_prev(ptr)		(ptr)->MR_dlist_prev
 #define	MR_dlist_data(ptr)		(ptr)->MR_dlist_union.MR_dlist_data
-#define	MR_dlist_length(list)		((list)->MR_dlist_union.MR_dlist_length)
+#define	MR_dlist_length_field(list)	((list)->MR_dlist_union.\
+						MR_dlist_length)
+#define	MR_dlist_length(list)		((list) != NULL ?		\
+						MR_dlist_length_field(list) \
+						: 0)
 #define	MR_dlist_first_ptr(list)	((list)->MR_dlist_next)
 #define	MR_dlist_last_ptr(list)		((list)->MR_dlist_prev)
 #define	MR_dlist_first(list)		((list)->MR_dlist_next->	\
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.48
diff -u -b -r1.48 mercury_engine.c
--- runtime/mercury_engine.c	7 Jul 2004 07:11:10 -0000	1.48
+++ runtime/mercury_engine.c	7 Jul 2004 07:17:04 -0000
@@ -74,7 +74,7 @@
 /*---------------------------------------------------------------------------*/
 
 /*
-** init_engine() calls init_memory() which sets up all the necessary
+** MR_init_engine() calls MR_init_memory() which sets up all the necessary
 ** stuff for allocating memory-zones and other runtime areas (such as
 ** the zone structures and context structures).
 */
@@ -105,15 +105,15 @@
 	*/
 
 #ifndef	MR_CONSERVATIVE_GC
-	eng->MR_eng_heap_zone = MR_create_zone("heap", 1, MR_heap_size,
-			MR_next_offset(), MR_heap_zone_size,
-			MR_default_handler);
+	eng->MR_eng_heap_zone = MR_create_zone("heap", 1,
+		MR_heap_size, MR_next_offset(),
+		MR_heap_zone_size, MR_default_handler);
 	eng->MR_eng_hp = eng->MR_eng_heap_zone->min;
 
   #ifdef MR_NATIVE_GC
-	eng->MR_eng_heap_zone2 = MR_create_zone("heap2", 1, MR_heap_size,
-			MR_next_offset(), MR_heap_zone_size,
-			MR_default_handler);
+	eng->MR_eng_heap_zone2 = MR_create_zone("heap2", 1,
+		MR_heap_size, MR_next_offset(),
+		MR_heap_zone_size, MR_default_handler);
 
     #ifdef MR_DEBUG_AGC_PRINT_VARS
 	eng->MR_eng_debug_heap_zone = MR_create_zone("debug_heap", 1,
@@ -145,7 +145,7 @@
 	** Finally, allocate an initial context (Mercury thread)
 	** in the engine and initialize the per-context stuff.
 	*/
-	eng->MR_eng_this_context = MR_create_context();
+	eng->MR_eng_this_context = MR_create_context("main", NULL);
 }
 
 /*---------------------------------------------------------------------------*/
Index: runtime/mercury_engine.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_engine.h,v
retrieving revision 1.35
diff -u -b -r1.35 mercury_engine.h
--- runtime/mercury_engine.h	7 Jul 2004 07:11:10 -0000	1.35
+++ runtime/mercury_engine.h	7 Jul 2004 07:17:04 -0000
@@ -297,6 +297,26 @@
 		** MR_eng_context stores all the context information
 		** for the context executing in this engine.
 		*/
+#ifdef	MR_USE_MINIMAL_MODEL_OWN_STACKS
+	MR_Context	*MR_eng_main_context;
+			/*
+			** The context of the main computation. The
+			** owner_generator field of this context must be NULL.
+			*/
+	MR_Dlist	*MR_eng_gen_contexts;	/* elements are MR_Context */
+			/*
+			** The contexts of the active generators. The
+			** owner_generator fields of these contexts will point
+			** to their generators.
+			*/
+	MR_Dlist	*MR_eng_free_contexts;	/* elements are MR_Context */
+			/*
+			** Contexts that used to belong to active generators,
+			** but which are no longer needed. They are cached here
+			** to allow new generators to be created without
+			** redoing the work required to allocate a new context.
+			*/
+#endif
 #ifdef	MR_THREAD_SAFE
 	MercuryThread	MR_eng_owner_thread;
 	unsigned	MR_eng_c_depth;
@@ -305,19 +325,21 @@
 		** These three 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.
-		** The list `saved_owners' is used in call_engine_inner
-		** to store the owner of a context across calls into Mercury.
-		** At the moment this is only used for sanity checking - that
-		** execution never returns into C in the wrong thread.
+			** 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. The list
+			** `saved_owners' is used in call_engine_inner to store
+			** the owner of a context across calls into Mercury.
+			** At the moment this is only used for sanity checking
+			** - that execution never returns into C in the
+			** wrong thread.
 		*/
 #endif
 	jmp_buf		*MR_eng_jmp_buf;
Index: runtime/mercury_grade.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_grade.h,v
retrieving revision 1.54
diff -u -b -r1.54 mercury_grade.h
--- runtime/mercury_grade.h	7 Jul 2004 07:11:11 -0000	1.54
+++ runtime/mercury_grade.h	7 Jul 2004 07:17:04 -0000
@@ -23,6 +23,7 @@
 ** 	scripts/ml.in
 **	compiler/handle_options.m
 **	compiler/compile_target_code.m
+**	configure.in
 */
 
 #ifndef MERCURY_GRADES_H
@@ -207,13 +208,27 @@
   #define MR_GRADE_OPT_PART_7	MR_GRADE_OPT_PART_6
 #endif
 
-#ifdef MR_USE_MINIMAL_MODEL
+#ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
+  #ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
+    #error "Invalid combination of minimal model tabling options"
+  #endif
+#endif
+
+#ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
+  #ifdef MR_MINIMAL_MODEL_DEBUG
+    #define MR_GRADE_PART_8	MR_PASTE2(MR_GRADE_PART_7, _dmmsc)
+    #define MR_GRADE_OPT_PART_8	MR_GRADE_OPT_PART_7 ".dmmsc"
+  #else
+    #define MR_GRADE_PART_8	MR_PASTE2(MR_GRADE_PART_7, _mmsc)
+    #define MR_GRADE_OPT_PART_8	MR_GRADE_OPT_PART_7 ".mmsc"
+  #endif
+#elif MR_USE_MINIMAL_MODEL_OWN_STACKS
   #ifdef MR_MINIMAL_MODEL_DEBUG
-    #define MR_GRADE_PART_8	MR_PASTE2(MR_GRADE_PART_7, _dmm)
-    #define MR_GRADE_OPT_PART_8	MR_GRADE_OPT_PART_7 ".dmm"
+    #define MR_GRADE_PART_8	MR_PASTE2(MR_GRADE_PART_7, _dmmos)
+    #define MR_GRADE_OPT_PART_8	MR_GRADE_OPT_PART_7 ".dmmos"
   #else
-    #define MR_GRADE_PART_8	MR_PASTE2(MR_GRADE_PART_7, _mm)
-    #define MR_GRADE_OPT_PART_8	MR_GRADE_OPT_PART_7 ".mm"
+    #define MR_GRADE_PART_8	MR_PASTE2(MR_GRADE_PART_7, _mmos)
+    #define MR_GRADE_OPT_PART_8	MR_GRADE_OPT_PART_7 ".mmos"
   #endif
 #else
   #define MR_GRADE_PART_8	MR_GRADE_PART_7
@@ -221,13 +236,17 @@
 #endif
 
 /*
-** Minimal model tabling works by saving and restoring segments of the nondet
-** stack. Since in high level code grades we don't have a nondet stack that
-** we can save and restore, minimal model tabling is fundamentally incompatible
+** One implementation of minimal model tabling works by saving and restoring
+** segments of the nondet stack, the other by creating a separate stack for
+** each generator. Since in high level code grades we don't have a nondet
+** stack that we can save and restore and we can't establish extra stacks,
+** both forms of minimal model tabling are fundamentally incompatible
 ** with high level code.
 */
 
-#if  defined(MR_USE_MINIMAL_MODEL) && defined(MR_HIGHLEVEL_CODE)
+#if defined(MR_HIGHLEVEL_CODE) && \
+	(defined(MR_USE_MINIMAL_MODEL_STACK_COPY) || \
+	defined(MR_USE_MINIMAL_MODEL_OWN_STACKS))
   #error "high level code and minimal model tabling are not compatible"
 #endif
 
@@ -253,17 +272,20 @@
 ** The trail handler will be thoroughly confused by such a sequence.
 **
 ** Until we can figure out (and implement) a fix for this problem,
-** minimal model tabling and trailing cannot be used together.
+** minimal model tabling (either form) and trailing cannot be used together.
 */
 
-#if defined(MR_USE_TRAIL) && defined(MR_USE_MINIMAL_MODEL)
+#if defined(MR_USE_TRAIL) && \
+	(defined(MR_USE_MINIMAL_MODEL_STACK_COPY) || \
+	defined(MR_USE_MINIMAL_MODEL_OWN_STACKS))
   #error "trailing and minimal model tabling are not compatible"
 #endif
 
 /*
 ** Native gc needs to be able to redirect pointers to the heap. Minimal model
 ** tabling takes snapshots of stack segments that may contain pointers to the
-** heap, but there is currently no mechanism implemented to trace and redirect
+** heap, or creates extra stacks that may contain pointers to the heap,
+** but there is currently no mechanism implemented to trace and redirect
 ** such pointers.
 **
 ** Minimal model tabling has no problems with conservative gc or with no gc,
@@ -272,7 +294,9 @@
 ** space.
 */
 
-#if defined(MR_USE_MINIMAL_MODEL) && defined(MR_NATIVE_GC)
+#if defined(MR_NATIVE_GC) && \
+	(defined(MR_USE_MINIMAL_MODEL_STACK_COPY) || \
+	defined(MR_USE_MINIMAL_MODEL_OWN_STACKS))
     #error "minimal model tabling and native gc are not compatible"
 #endif
 
Index: runtime/mercury_imp.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_imp.h,v
retrieving revision 1.22
diff -u -b -r1.22 mercury_imp.h
--- runtime/mercury_imp.h	23 Oct 2003 02:02:31 -0000	1.22
+++ runtime/mercury_imp.h	21 Mar 2004 08:25:11 -0000
@@ -81,8 +81,11 @@
 #include	"mercury_misc.h"
 
 #include	"mercury_tabling.h"
-#ifdef MR_USE_MINIMAL_MODEL
+#ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
 #include	"mercury_minimal_model.h"
+#endif
+#ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
+#include	"mercury_mm_own_stacks.h"
 #endif
 
 #include	"mercury_univ.h"
Index: runtime/mercury_memory.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_memory.c,v
retrieving revision 1.34
diff -u -b -r1.34 mercury_memory.c
--- runtime/mercury_memory.c	30 Dec 2003 13:17:13 -0000	1.34
+++ runtime/mercury_memory.c	15 Apr 2004 16:55:00 -0000
@@ -102,7 +102,7 @@
 ** XXX All the zones should be in mercury_engine.h
 */
 
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
   MR_MemoryZone *MR_genstack_zone;
   MR_MemoryZone *MR_cutstack_zone;
   MR_MemoryZone *MR_pnegstack_zone;
@@ -168,7 +168,7 @@
 					MR_unit);
 	MR_nondstack_zone_size	 = MR_round_up(MR_nondstack_zone_size * 1024,
 					MR_unit);
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 	MR_genstack_size	 = MR_round_up(MR_genstack_size * 1024,
 					MR_unit);
 	MR_genstack_zone_size = MR_round_up(
@@ -182,6 +182,31 @@
 					MR_unit);
 	MR_pnegstack_zone_size	 = MR_round_up(MR_pnegstack_zone_size * 1024,
 					MR_unit);
+#else
+	MR_genstack_size	 = 0;
+	MR_genstack_zone_size	 = 0;
+	MR_cutstack_size	 = 0;
+	MR_cutstack_zone_size	 = 0;
+	MR_pnegstack_size	 = 0;
+	MR_pnegstack_zone_size	 = 0;
+#endif
+
+#ifdef	MR_USE_MINIMAL_MODEL_OWN_STACKS
+	MR_gen_detstack_size	 = MR_round_up(MR_gen_detstack_size * 1024,
+					MR_unit);
+	MR_gen_nonstack_size	 = MR_round_up(MR_gen_nonstack_size * 1024,
+					MR_unit);
+	MR_gen_detstack_zone_size = MR_round_up(
+					MR_gen_detstack_zone_size * 1024,
+					MR_unit);
+	MR_gen_nonstack_zone_size = MR_round_up(
+					MR_gen_nonstack_zone_size * 1024,
+					MR_unit);
+#else
+	MR_gen_detstack_size	 = 0;
+	MR_gen_nonstack_size	 = 0;
+	MR_gen_detstack_zone_size = 0;
+	MR_gen_nonstack_zone_size = 0;
 #endif
 
 #ifdef	MR_USE_TRAIL
Index: runtime/mercury_memory_zones.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_memory_zones.c,v
retrieving revision 1.24
diff -u -b -r1.24 mercury_memory_zones.c
--- runtime/mercury_memory_zones.c	7 Jul 2004 07:11:13 -0000	1.24
+++ runtime/mercury_memory_zones.c	7 Jul 2004 07:17:05 -0000
@@ -466,6 +466,12 @@
 	return used_memory_zones;
 }
 
+MR_bool
+MR_in_zone(const MR_Word *ptr, const MR_MemoryZone *zone)
+{
+	return (zone->bottom <= ptr && ptr < zone->top);
+}
+
 void
 MR_debug_memory(void)
 {
Index: runtime/mercury_memory_zones.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_memory_zones.h,v
retrieving revision 1.15
diff -u -b -r1.15 mercury_memory_zones.h
--- runtime/mercury_memory_zones.h	7 Jul 2004 07:11:13 -0000	1.15
+++ runtime/mercury_memory_zones.h	7 Jul 2004 07:17:05 -0000
@@ -176,7 +176,7 @@
 
 /*
 ** MR_construct_zone(Name, Id, Base, Size, Offset, RedZoneSize, FaultHandler)
-** has the same behaviour as MR_create_zone, except instread of allocating
+** has the same behaviour as MR_create_zone, except instead of allocating
 ** the memory, it takes a pointer to a region of memory that must be at
 ** least Size + unit[*] bytes, or if MR_PROTECTPAGE is defined, then it
 ** must be at least Size + 2 * unit[*] bytes.
@@ -206,6 +206,13 @@
 */
 
 extern	MR_MemoryZone	*MR_get_used_memory_zones(void);
+
+/*
+** Returns true iff ptr is the given zone.
+*/
+
+extern	MR_bool		MR_in_zone(const MR_Word *ptr,
+				const MR_MemoryZone *zone);
 
 /*
 ** MR_debug_memory() prints out debugging information about the current
Index: runtime/mercury_minimal_model.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_minimal_model.c,v
retrieving revision 1.15
diff -u -b -r1.15 mercury_minimal_model.c
--- runtime/mercury_minimal_model.c	7 Jul 2004 07:11:13 -0000	1.15
+++ runtime/mercury_minimal_model.c	19 Jul 2004 02:10:09 -0000
@@ -8,8 +8,8 @@
 */
 
 /*
-** This module contains the functions related specifically to minimal model
-** tabling.
+** This module contains the functions related specifically to the stack copy
+** style of minimal model tabling.
 */
 
 #include "mercury_imp.h"
@@ -32,7 +32,7 @@
   #define   MR_TABLE_DEBUG
 #endif
 
-#ifdef  MR_USE_MINIMAL_MODEL
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
 
 #ifdef  MR_TABLE_DEBUG
 static  MR_Word *saved_to_real_nondet_stack(MR_SavedState *saved_state,
@@ -396,6 +396,7 @@
     MR_ConsumerList consumer;
     MR_AnswerList   answer_list;
     MR_Word         *answer;
+    int             answer_num;
 
     if (subgoal == NULL) {
         fprintf(fp, "NULL subgoal\n");
@@ -444,16 +445,13 @@
 
     if (proc != NULL) {
         answer_list = subgoal->MR_sg_answer_list;
+        answer_num = 1;
         while (answer_list != NULL) {
-#ifdef  MR_MINIMAL_MODEL_DEBUG
-            fprintf(fp, "answer #%d: <", answer_list->MR_aln_answer_num);
-#else
-            fprintf(fp, "answer: <");
-#endif
-            MR_print_answerblock(fp, proc,
-                answer_list->MR_aln_answer_data.MR_answerblock);
+            fprintf(fp, "answer #%d: <", answer_num);
+            MR_print_answerblock(fp, proc, answer_list->MR_aln_answer_block);
             fprintf(fp, ">\n");
             answer_list = answer_list->MR_aln_next_answer;
+            answer_num++;
         }
     }
 }
@@ -504,11 +502,12 @@
     ** In that case, we want to forget all about the old generator.
     */
 
+    MR_restore_transient_registers();
+
 #ifdef  MR_TABLE_STATISTICS
     MR_minmodel_stats_cnt_setup++;
 #endif
 
-    MR_restore_transient_registers();
     if (trie_node->MR_subgoal == NULL) {
         MR_Subgoal  *subgoal;
 
@@ -576,8 +575,8 @@
         trie_node->MR_subgoal = subgoal;
     }
 
-    return trie_node->MR_subgoal;
     MR_save_transient_registers();
+    return trie_node->MR_subgoal;
 }
 
 /*---------------------------------------------------------------------------*/
@@ -747,13 +746,13 @@
 */
 
 #define SUSPEND_LABEL(name)                                             \
-    MR_label_name(MR_SUSPEND_ENTRY, name)
+    MR_label_name(MR_MMSC_SUSPEND_ENTRY, name)
 #define COMPLETION_LABEL(name)                                          \
-    MR_label_name(MR_COMPLETION_ENTRY, name)
+    MR_label_name(MR_MMSC_COMPLETION_ENTRY, name)
 #define RET_ALL_MULTI_LABEL(name)                                       \
-    MR_label_name(MR_RET_ALL_MULTI_ENTRY, name)
+    MR_label_name(MR_MMSC_RET_ALL_MULTI_ENTRY, name)
 #define RET_ALL_NONDET_LABEL(name)                                      \
-    MR_label_name(MR_RET_ALL_NONDET_ENTRY, name)
+    MR_label_name(MR_MMSC_RET_ALL_NONDET_ENTRY, name)
 
 /*
 ** With debugging of tabling code enabled, define function versions
@@ -1407,7 +1406,7 @@
 #endif  /* MR_TABLE_DEBUG */
 
             *MR_redoip_addr(saved_fr) =
-                (MR_Word) MR_ENTRY(MR_COMPLETION_ENTRY);
+                (MR_Word) MR_ENTRY(MR_MMSC_COMPLETION_ENTRY);
         } else if (!generator_is_at_bottom &&
             real_fr == MR_gen_stack[cur_gen].MR_gen_frame)
         {
@@ -1431,7 +1430,7 @@
 #endif  /* MR_TABLE_DEBUG */
 
                 *MR_redoip_addr(saved_fr) =
-                    (MR_Word) MR_ENTRY(MR_COMPLETION_ENTRY);
+                    (MR_Word) MR_ENTRY(MR_MMSC_COMPLETION_ENTRY);
             } else {
                 /*
                 ** This is the nondet stack frame of some other generator.
@@ -1650,7 +1649,7 @@
     }
 }
 
-#endif  /* MR_USE_MINIMAL_MODEL */
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 /*---------------------------------------------------------------------------*/
 
@@ -1659,9 +1658,9 @@
 ** of derivations.
 **
 ** We need to define stubs for the predicates which are marked as `:- external'
-** in table_builtin.m, even if MR_USE_MINIMAL_MODEL is not enabled, because
-** in profiling grades the code generated for table_builtin.m will take their
-** address to store in the label table.
+** in table_builtin.m, even if MR_USE_MINIMAL_MODEL_STACK_COPY is not enabled,
+** because in profiling grades the code generated for table_builtin.m will
+** take their address to store in the label table.
 **
 ** We provide three definitions for these procedures: one for high level
 ** code (which is incompatible with minimal model tabling), and two for low
@@ -1671,19 +1670,6 @@
 
 #ifdef MR_HIGHLEVEL_CODE
 
-/* Declare them first, to avoid warnings from gcc -Wmissing-decls */
-void MR_CALL mercury__table_builtin__table_mm_completion_1_p_0(
-    MR_C_Pointer subgoal_table_node, MR_C_Pointer *answer_block,
-    MR_Cont cont, void *cont_env_ptr);
-void MR_CALL mercury__table_builtin__table_mm_suspend_consumer_2_p_0(
-    MR_C_Pointer subgoal_table_node);
-void MR_CALL mercury__table_builtin__table_mm_return_all_nondet_2_2_p_0(
-    MR_C_Pointer answer_list, MR_C_Pointer answer_block);
-void MR_CALL mercury__table_builtin__table_mm_return_all_multi_2_2_p_0(
-    MR_C_Pointer answer_list, MR_C_Pointer answer_block);
-void MR_CALL mercury__table_builtin__table_mm_answer_is_not_duplicate_1_p_0(
-    MR_C_Pointer subgoal_table_node);
-
 void MR_CALL
 mercury__table_builtin__table_mm_completion_1_p_0(
     MR_C_Pointer subgoal_table_node, MR_C_Pointer *answer_block,
@@ -1727,11 +1713,11 @@
 
 #else   /* ! MR_HIGHLEVEL_CODE */
 
-MR_define_extern_entry(MR_SUSPEND_ENTRY);
-MR_define_extern_entry(MR_COMPLETION_ENTRY);
-MR_define_extern_entry(MR_RET_ALL_NONDET_ENTRY);
-MR_define_extern_entry(MR_RET_ALL_MULTI_ENTRY);
-MR_define_extern_entry(MR_IS_NOT_DUPL_ENTRY);
+MR_define_extern_entry(MR_MMSC_SUSPEND_ENTRY);
+MR_define_extern_entry(MR_MMSC_COMPLETION_ENTRY);
+MR_define_extern_entry(MR_MMSC_RET_ALL_NONDET_ENTRY);
+MR_define_extern_entry(MR_MMSC_RET_ALL_MULTI_ENTRY);
+MR_define_extern_entry(MR_MMSC_IS_NOT_DUPL_ENTRY);
 
 MR_EXTERN_USER_PROC_ID_PROC_LAYOUT(MR_DETISM_NON, 0, -1,
     MR_PREDICATE, table_builtin, table_mm_suspend_consumer, 2, 0);
@@ -1744,39 +1730,39 @@
 MR_EXTERN_USER_PROC_ID_PROC_LAYOUT(MR_DETISM_NON, 0, -1,
     MR_PREDICATE, table_builtin, table_mm_answer_is_not_duplicate, 1, 0);
 
-#ifndef  MR_USE_MINIMAL_MODEL
+#ifndef  MR_USE_MINIMAL_MODEL_STACK_COPY
 
-MR_BEGIN_MODULE(table_mm_suspend_completion_module)
-    MR_init_entry_sl(MR_SUSPEND_ENTRY);
-    MR_init_entry_sl(MR_COMPLETION_ENTRY);
-    MR_init_entry_sl(MR_RET_ALL_NONDET_ENTRY);
-    MR_init_entry_sl(MR_RET_ALL_MULTI_ENTRY);
-    MR_init_entry_sl(MR_IS_NOT_DUPL_ENTRY);
-    MR_INIT_PROC_LAYOUT_ADDR(MR_SUSPEND_ENTRY);
-    MR_INIT_PROC_LAYOUT_ADDR(MR_COMPLETION_ENTRY);
-    MR_INIT_PROC_LAYOUT_ADDR(MR_RET_ALL_NONDET_ENTRY);
-    MR_INIT_PROC_LAYOUT_ADDR(MR_RET_ALL_MULTI_ENTRY);
-    MR_INIT_PROC_LAYOUT_ADDR(MR_IS_NOT_DUPL_ENTRY);
+MR_BEGIN_MODULE(mmsc_module)
+    MR_init_entry_sl(MR_MMSC_SUSPEND_ENTRY);
+    MR_init_entry_sl(MR_MMSC_COMPLETION_ENTRY);
+    MR_init_entry_sl(MR_MMSC_RET_ALL_NONDET_ENTRY);
+    MR_init_entry_sl(MR_MMSC_RET_ALL_MULTI_ENTRY);
+    MR_init_entry_sl(MR_MMSC_IS_NOT_DUPL_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_MMSC_SUSPEND_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_MMSC_COMPLETION_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_MMSC_RET_ALL_NONDET_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_MMSC_RET_ALL_MULTI_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_MMSC_IS_NOT_DUPL_ENTRY);
 MR_BEGIN_CODE
 
-MR_define_entry(MR_SUSPEND_ENTRY);
+MR_define_entry(MR_MMSC_SUSPEND_ENTRY);
     MR_fatal_error("call to table_mm_suspend_consumer/2 in a grade "
-        "without minimal model tabling");
-MR_define_entry(MR_COMPLETION_ENTRY);
+        "without stack copy minimal model tabling");
+MR_define_entry(MR_MMSC_COMPLETION_ENTRY);
     MR_fatal_error("call to table_mm_completion/1 in a grade "
-        "without minimal model tabling");
-MR_define_entry(MR_RET_ALL_NONDET_ENTRY);
+        "without stack copy minimal model tabling");
+MR_define_entry(MR_MMSC_RET_ALL_NONDET_ENTRY);
     MR_fatal_error("call to table_mm_return_all_nondet/2 in a grade "
-        "without minimal model tabling");
-MR_define_entry(MR_RET_ALL_MULTI_ENTRY);
+        "without stack copy minimal model tabling");
+MR_define_entry(MR_MMSC_RET_ALL_MULTI_ENTRY);
     MR_fatal_error("call to table_mm_return_all_multi/2 in a grade "
-        "without minimal model tabling");
-MR_define_entry(MR_IS_NOT_DUPL_ENTRY);
+        "without stack copy minimal model tabling");
+MR_define_entry(MR_MMSC_IS_NOT_DUPL_ENTRY);
     MR_fatal_error("call to table_mm_answer_is_not_duplicate/1 in a grade "
-        "without minimal model tabling");
+        "without stack copy minimal model tabling");
 MR_END_MODULE
 
-#else   /* MR_USE_MINIMAL_MODEL */
+#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 MR_Subgoal      *MR_cur_leader;
 
@@ -1820,13 +1806,13 @@
 MR_MAKE_USER_INTERNAL_LAYOUT(table_builtin, table_mm_return_all_multi, 2, 0,
     Next);
 
-MR_BEGIN_MODULE(table_mm_suspend_completion_module)
-    MR_init_entry_sl(MR_SUSPEND_ENTRY);
-    MR_INIT_PROC_LAYOUT_ADDR(MR_SUSPEND_ENTRY);
+MR_BEGIN_MODULE(mmsc_module)
+    MR_init_entry_sl(MR_MMSC_SUSPEND_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_MMSC_SUSPEND_ENTRY);
     MR_init_label_sl(SUSPEND_LABEL(Call));
 
-    MR_init_entry_sl(MR_COMPLETION_ENTRY);
-    MR_INIT_PROC_LAYOUT_ADDR(MR_COMPLETION_ENTRY);
+    MR_init_entry_sl(MR_MMSC_COMPLETION_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_MMSC_COMPLETION_ENTRY);
     MR_init_label_sl(COMPLETION_LABEL(StartCompletionOp));
     MR_init_label_sl(COMPLETION_LABEL(LoopOverSubgoals));
     MR_init_label_sl(COMPLETION_LABEL(LoopOverSuspensions));
@@ -1838,18 +1824,18 @@
 
     MR_init_entry_an(MR_table_mm_commit);
 
-    MR_init_entry_sl(MR_RET_ALL_NONDET_ENTRY);
-    MR_INIT_PROC_LAYOUT_ADDR(MR_RET_ALL_NONDET_ENTRY);
+    MR_init_entry_sl(MR_MMSC_RET_ALL_NONDET_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_MMSC_RET_ALL_NONDET_ENTRY);
     MR_init_label_sl(RET_ALL_NONDET_LABEL(Next));
 
-    MR_init_entry_sl(MR_RET_ALL_MULTI_ENTRY);
-    MR_INIT_PROC_LAYOUT_ADDR(MR_RET_ALL_MULTI_ENTRY);
+    MR_init_entry_sl(MR_MMSC_RET_ALL_MULTI_ENTRY);
+    MR_INIT_PROC_LAYOUT_ADDR(MR_MMSC_RET_ALL_MULTI_ENTRY);
     MR_init_label_sl(RET_ALL_MULTI_LABEL(Next));
 
-    MR_init_entry_sl(MR_IS_NOT_DUPL_ENTRY);
+    MR_init_entry_sl(MR_MMSC_IS_NOT_DUPL_ENTRY);
 MR_BEGIN_CODE
 
-MR_define_entry(MR_SUSPEND_ENTRY);
+MR_define_entry(MR_MMSC_SUSPEND_ENTRY);
     /*
     ** The suspend procedure saves the state of the Mercury runtime so that
     ** it may be used in the table_mm_completion procedure below to return
@@ -1873,7 +1859,7 @@
     ** nondet stack fragment. The framevar slot is for use by
     ** table_mm_completion.
     */
-    MR_mkframe(MR_STRINGIFY(MR_SUSPEND_ENTRY), 1, MR_ENTRY(MR_do_fail));
+    MR_mkframe(MR_STRINGIFY(MR_MMSC_SUSPEND_ENTRY), 1, MR_ENTRY(MR_do_fail));
 
 MR_define_label(SUSPEND_LABEL(Call));
 {
@@ -1951,7 +1937,7 @@
 }
     MR_fail();
 
-MR_define_entry(MR_COMPLETION_ENTRY);
+MR_define_entry(MR_MMSC_COMPLETION_ENTRY);
     /*
     ** The completion procedure restores answers to suspended consumers.
     ** It works by restoring the consumer state saved by the consumer's call
@@ -2194,16 +2180,20 @@
 #ifdef  MR_TABLE_DEBUG
     if (MR_tabledebug) {
         MR_AnswerList   answer_list;
+        MR_Consumer     *consumer;
 
+        consumer = completion_info->MR_ri_cur_consumer;
         printf("returning answers to consumer %s\n",
-            MR_consumer_addr_name(completion_info->MR_ri_cur_consumer));
+            MR_consumer_addr_name(consumer));
   #ifdef    MR_MINIMAL_MODEL_DEBUG
         printf("the list of answers to return:");
         for (answer_list = cur_consumer_answer_list;
             answer_list != NULL;
             answer_list = answer_list->MR_aln_next_answer)
         {
-            printf(" #%d", answer_list->MR_aln_answer_num);
+            MR_print_answerblock(stdout,
+                    consumer->MR_cns_subgoal->MR_sg_proc_layout,
+                    answer_list->MR_aln_answer_block);
         }
   #endif  /* MR_MINIMAL_MODEL_DEBUG */
         printf("\n");
@@ -2237,20 +2227,19 @@
     ** XXX we need to prove that assertion
     */
 
-    MR_r1 = (MR_Word) answer_list->MR_aln_answer_data.MR_answerblock;
+    MR_r1 = (MR_Word) answer_list->MR_aln_answer_block;
     consumer->MR_cns_remaining_answer_list_ptr =
         &(answer_list->MR_aln_next_answer);
     consumer->MR_cns_num_returned_answers++;
 
 #ifdef  MR_TABLE_DEBUG
     if (MR_tabledebug) {
-  #ifdef    MR_MINIMAL_MODEL_DEBUG
-        printf("returning answer %d to consumer %s\n",
-            answer_list->MR_aln_answer_num,
-            MR_consumer_addr_name(completion_info->MR_ri_cur_consumer));
-  #else
         printf("returning answer to consumer %s\n",
             MR_consumer_addr_name(completion_info->MR_ri_cur_consumer));
+  #ifdef MR_MINIMAL_MODEL_DEBUG
+            MR_print_answerblock(stdout, completion_info->MR_ri_cur_consumer->
+                MR_cns_subgoal->MR_sg_proc_layout,
+                answer_list->MR_aln_answer_block);
   #endif
     }
 #endif  /* MR_TABLE_DEBUG */
@@ -2264,7 +2253,7 @@
 }
 
 MR_define_label(COMPLETION_LABEL(RedoPoint));
-    MR_update_prof_current_proc(MR_LABEL(MR_COMPLETION_ENTRY));
+    MR_update_prof_current_proc(MR_LABEL(MR_MMSC_COMPLETION_ENTRY));
 
 #ifdef  MR_TABLE_STATISTICS
     MR_minmodel_stats_cnt_completion_redo_point++;
@@ -2422,7 +2411,7 @@
     MR_commit_cut();
     MR_fail();
 
-MR_define_entry(MR_RET_ALL_NONDET_ENTRY);
+MR_define_entry(MR_MMSC_RET_ALL_NONDET_ENTRY);
 {
     MR_SubgoalPtr   Subgoal;
     MR_AnswerList   CurNode0;
@@ -2443,7 +2432,7 @@
         MR_redo();
     }
 
-    AnswerBlock = CurNode0->MR_aln_answer_data.MR_answerblock;
+    AnswerBlock = CurNode0->MR_aln_answer_block;
     CurNode = CurNode0->MR_aln_next_answer;
 
     /* Consider not creating the stack frame if CurNode is NULL. */
@@ -2466,14 +2455,14 @@
         MR_fail();
     }
 
-    AnswerBlock = CurNode0->MR_aln_answer_data.MR_answerblock;
+    AnswerBlock = CurNode0->MR_aln_answer_block;
     CurNode = CurNode0->MR_aln_next_answer;
     MR_framevar(1) = (MR_Word) CurNode;
     MR_r1 = (MR_Word) AnswerBlock;
 }
     MR_succeed();
 
-MR_define_entry(MR_RET_ALL_MULTI_ENTRY);
+MR_define_entry(MR_MMSC_RET_ALL_MULTI_ENTRY);
 {
     MR_SubgoalPtr   Subgoal;
     MR_AnswerList   CurNode0;
@@ -2494,7 +2483,7 @@
         MR_fatal_error("table_mm_return_all_multi: no answers");
     }
 
-    AnswerBlock = CurNode0->MR_aln_answer_data.MR_answerblock;
+    AnswerBlock = CurNode0->MR_aln_answer_block;
     CurNode = CurNode0->MR_aln_next_answer;
 
     /* Consider not creating the stack frame if CurNode is NULL. */
@@ -2517,14 +2506,14 @@
         MR_fail();
     }
 
-    AnswerBlock = CurNode0->MR_aln_answer_data.MR_answerblock;
+    AnswerBlock = CurNode0->MR_aln_answer_block;
     CurNode = CurNode0->MR_aln_next_answer;
     MR_framevar(1) = (MR_Word) CurNode;
     MR_r1 = (MR_Word) AnswerBlock;
 }
     MR_succeed();
 
-MR_define_entry(MR_IS_NOT_DUPL_ENTRY);
+MR_define_entry(MR_MMSC_IS_NOT_DUPL_ENTRY);
 {
     MR_TrieNode T;
 
@@ -2535,38 +2524,40 @@
 
 MR_END_MODULE
 
-#endif /* MR_USE_MINIMAL_MODEL */
+#endif /* MR_USE_MINIMAL_MODEL_STACK_COPY */
 #endif /* MR_HIGHLEVEL_CODE */
 
 /* Ensure that the initialization code for the above modules gets to run. */
 /*
-INIT mercury_sys_init_table_modules
+INIT mercury_sys_init_mmsc_modules
 */
 
-MR_MODULE_STATIC_OR_EXTERN MR_ModuleFunc table_mm_suspend_completion_module;
+MR_MODULE_STATIC_OR_EXTERN MR_ModuleFunc mmsc_module;
 
 /* forward declarations to suppress gcc -Wmissing-decl warnings */
-void mercury_sys_init_table_modules_init(void);
-void mercury_sys_init_table_modules_init_type_tables(void);
+void mercury_sys_init_mmsc_modules_init(void);
+void mercury_sys_init_mmsc_modules_init_type_tables(void);
 #ifdef  MR_DEEP_PROFILING
-void mercury_sys_init_table_modules_write_out_proc_statics(FILE *fp);
+void mercury_sys_init_mmsc_modules_write_out_proc_statics(FILE *fp);
 #endif
 
-void mercury_sys_init_table_modules_init(void)
+void mercury_sys_init_mmsc_modules_init(void)
 {
 #ifndef MR_HIGHLEVEL_CODE
-    table_mm_suspend_completion_module();
+    mmsc_module();
 #endif  /* MR_HIGHLEVEL_CODE */
 }
 
-void mercury_sys_init_table_modules_init_type_tables(void)
+void mercury_sys_init_mmsc_modules_init_type_tables(void)
 {
     /* no types to register */
 }
 
 #ifdef  MR_DEEP_PROFILING
-void mercury_sys_init_table_modules_write_out_proc_statics(FILE *fp)
+void mercury_sys_init_mmsc_modules_write_out_proc_statics(FILE *fp)
 {
     /* no proc_statics to write out */
+    /* XXX we need to fix the deep profiling */
+    /* of minimal model tabled predicates */
 }
 #endif
Index: runtime/mercury_minimal_model.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_minimal_model.h,v
retrieving revision 1.10
diff -u -b -r1.10 mercury_minimal_model.h
--- runtime/mercury_minimal_model.h	31 May 2004 04:13:05 -0000	1.10
+++ runtime/mercury_minimal_model.h	17 Jul 2004 06:54:27 -0000
@@ -5,11 +5,11 @@
 */
 
 /*
-** mercury_minimal_model.h - definitions of some basic stuff used for tabling.
-** For tabling code, the Mercury compiler (compiler/table_gen.m) generates
-** references to special procedures defined in library/table_builtin.m.
-** The types and macros defined here are used by the procedures defined in
-** library/table_builtin.m.
+** mercury_minimal_model.h - definitions of some basic stuff used for the stack
+** copy style of minimal model tabling. For tabling code, the Mercury compiler
+** (compiler/table_gen.m) generates references to special procedures defined
+** in library/table_builtin.m. The types and macros defined here are used
+** by the procedures defined in library/table_builtin.m.
 */
 
 #ifndef	MERCURY_MINIMAL_MODEL_H
@@ -21,14 +21,7 @@
 #include "mercury_goto.h"		/* for MR_declare_entry */
 #include <stdio.h>
 
-struct MR_AnswerListNode_Struct {
-	MR_TableNode	MR_aln_answer_data;
-				/* always uses the MR_answerblock member */
-	MR_AnswerList	MR_aln_next_answer;
-#ifdef	MR_MINIMAL_MODEL_DEBUG
-	MR_Integer	MR_aln_answer_num;
-#endif
-};
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 
 /*
 ** The saved state of a generator or a consumer. While consumers get
@@ -104,6 +97,7 @@
 ** subgoal. The list of answers it points to expands transparently whenever
 ** the generator subgoal adds an answer to its answer list.
 */
+
 struct MR_Consumer_Struct {
 	MR_SavedState		MR_cns_saved_state;
 	MR_Subgoal		*MR_cns_subgoal;
@@ -201,8 +195,6 @@
 
 /*---------------------------------------------------------------------------*/
 
-#ifdef	MR_USE_MINIMAL_MODEL
-
 extern	const MR_Proc_Layout	*MR_subgoal_debug_cur_proc;
 
 extern	void		MR_enter_consumer_debug(MR_Consumer *consumer);
@@ -240,31 +232,50 @@
 /* XXX */
 #endif
 
-#endif	/* MR_USE_MINIMAL_MODEL */
+#endif	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+#ifdef	MR_HIGHLEVEL_CODE
+
+  extern void MR_CALL
+  	mercury__table_builtin__table_mm_completion_1_p_0(
+		MR_C_Pointer subgoal_table_node, MR_C_Pointer *answer_block,
+		MR_Cont cont, void *cont_env_ptr);
+  extern void MR_CALL
+  	mercury__table_builtin__table_mm_suspend_consumer_2_p_0(
+		MR_C_Pointer subgoal_table_node);
+  extern void MR_CALL
+  	mercury__table_builtin__table_mm_return_all_nondet_2_2_p_0(
+		MR_C_Pointer answer_list, MR_C_Pointer answer_block);
+  extern void MR_CALL
+  	mercury__table_builtin__table_mm_return_all_multi_2_2_p_0(
+		MR_C_Pointer answer_list, MR_C_Pointer answer_block);
+  extern void MR_CALL
+  	mercury__table_builtin__table_mm_answer_is_not_duplicate_1_p_0(
+		MR_C_Pointer subgoal_table_node);
 
-#ifndef	MR_HIGHLEVEL_CODE
+#else	/* ! MR_HIGHLEVEL_CODE */
 
-  #define MR_SUSPEND_ENTRY						\
+  #define MR_MMSC_SUSPEND_ENTRY						\
 	MR_proc_entry_user_name(table_builtin,				\
 		table_mm_suspend_consumer, 2, 0)
-  #define MR_COMPLETION_ENTRY						\
+  #define MR_MMSC_COMPLETION_ENTRY					\
 	MR_proc_entry_user_name(table_builtin,				\
 		table_mm_completion, 1, 0)
-  #define MR_RET_ALL_NONDET_ENTRY					\
+  #define MR_MMSC_RET_ALL_NONDET_ENTRY					\
 	MR_proc_entry_user_name(table_builtin,				\
 		table_mm_return_all_nondet, 2, 0)
-  #define MR_RET_ALL_MULTI_ENTRY					\
+  #define MR_MMSC_RET_ALL_MULTI_ENTRY					\
 	MR_proc_entry_user_name(table_builtin,				\
 		table_mm_return_all_multi, 2, 0)
-  #define MR_IS_NOT_DUPL_ENTRY						\
+  #define MR_MMSC_IS_NOT_DUPL_ENTRY					\
 	MR_proc_entry_user_name(table_builtin,				\
 		table_mm_answer_is_not_duplicate, 1, 0)
 
-  MR_declare_entry(MR_SUSPEND_ENTRY);
-  MR_declare_entry(MR_COMPLETION_ENTRY);
-  MR_declare_entry(MR_RET_ALL_NONDET_ENTRY);
-  MR_declare_entry(MR_RET_ALL_MULTI_ENTRY);
-  MR_declare_entry(MR_IS_NOT_DUPL_ENTRY);
+  MR_declare_entry(MR_MMSC_SUSPEND_ENTRY);
+  MR_declare_entry(MR_MMSC_COMPLETION_ENTRY);
+  MR_declare_entry(MR_MMSC_RET_ALL_NONDET_ENTRY);
+  MR_declare_entry(MR_MMSC_RET_ALL_MULTI_ENTRY);
+  MR_declare_entry(MR_MMSC_IS_NOT_DUPL_ENTRY);
 
 #endif	/* !MR_HIGHLEVEL_CODE */
 
Index: runtime/mercury_ml_expand_body.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_ml_expand_body.h,v
retrieving revision 1.33
diff -u -b -r1.33 mercury_ml_expand_body.h
--- runtime/mercury_ml_expand_body.h	28 Jun 2004 04:50:05 -0000	1.33
+++ runtime/mercury_ml_expand_body.h	28 Jun 2004 05:06:10 -0000
@@ -868,7 +868,7 @@
             return;
 
         case MR_TYPECTOR_REP_SUBGOAL:
-#if MR_USE_MINIMAL_MODEL
+#if MR_USE_MINIMAL_MODEL_STACK_COPY
             if (noncanon == MR_NONCANON_CC) {
                 handle_functor_name(MR_subgoal_addr_name(
                     (MR_SubgoalPtr) *data_word_ptr));
Index: runtime/mercury_mm_own_stacks.c
===================================================================
RCS file: runtime/mercury_mm_own_stacks.c
diff -N runtime/mercury_mm_own_stacks.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ runtime/mercury_mm_own_stacks.c	19 Jul 2004 04:10:14 -0000
@@ -0,0 +1,510 @@
+/*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
+** Copyright (C) 2004 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.
+*/
+
+/*
+** This module contains the functions related specifically to the own stack
+** style of minimal model tabling.
+*/
+
+#include "mercury_imp.h"
+#include "mercury_array_macros.h"
+#include "mercury_tabling.h"
+#include "mercury_mm_own_stacks.h"
+
+#include <stdio.h>
+
+#ifdef  MR_USE_MINIMAL_MODEL_OWN_STACKS
+
+static  void    make_gen_follow_leader(MR_Generator *this_follower,
+                    MR_Generator *leader);
+
+/*---------------------------------------------------------------------------*/
+
+/*
+** This part of the file maintains data structures that can be used
+** to debug minimal model tabling. It does so by allowing the debugger
+** to refer to tabling data structures such as subgoals and consumers
+** by small, easily remembered numbers, not memory addresses.
+*/
+
+/* set by MR_trace_event, used by table_nondet_setup */
+const MR_Proc_Layout          *MR_subgoal_debug_cur_proc = NULL;
+
+struct MR_ConsDebug_Struct
+{
+    MR_Consumer     *MR_cod_consumer;
+    int             MR_cod_sequence_num;
+    int             MR_cod_version_num;
+    int             MR_cod_valid;
+};
+
+struct MR_GenDebug_Struct
+{
+    MR_Generator    *MR_gd_generator;
+    int             MR_gd_sequence_num;
+    int             MR_gd_version_num;
+    int             MR_gd_valid;
+};
+
+#define MR_CONS_DEBUG_INIT      10
+#define MR_GEN_DEBUG_INIT       10
+#define MR_NAME_BUF             1024
+
+static  MR_ConsDebug    *MR_cons_debug_infos = NULL;
+static  int             MR_cons_debug_info_next = 0;
+static  int             MR_cons_debug_info_max  = 0;
+
+static  MR_GenDebug     *MR_gen_debug_infos = NULL;
+static  int             MR_gen_debug_info_next = 0;
+static  int             MR_gen_debug_info_max  = 0;
+
+void
+MR_enter_cons_debug(MR_Consumer *consumer)
+{
+    int i;
+
+    for (i = 0; i < MR_cons_debug_info_next; i++) {
+        if (MR_cons_debug_infos[i].MR_cod_consumer == consumer) {
+            MR_cons_debug_infos[i].MR_cod_version_num++;
+            MR_cons_debug_infos[i].MR_cod_valid = MR_TRUE;
+            return;
+        }
+    }
+
+    MR_ensure_room_for_next(MR_cons_debug_info, MR_ConsDebug,
+        MR_CONS_DEBUG_INIT);
+    i = MR_cons_debug_info_next;
+    MR_cons_debug_infos[i].MR_cod_consumer = consumer;
+    MR_cons_debug_infos[i].MR_cod_sequence_num = i;
+    MR_cons_debug_infos[i].MR_cod_version_num = 0;
+    MR_cons_debug_infos[i].MR_cod_valid = MR_TRUE;
+    MR_cons_debug_info_next++;
+}
+
+MR_ConsDebug *
+MR_lookup_cons_debug_addr(MR_Consumer *consumer)
+{
+    int i;
+
+    for (i = 0; i < MR_cons_debug_info_next; i++) {
+        if (MR_cons_debug_infos[i].MR_cod_consumer == consumer) {
+            return &MR_cons_debug_infos[i];
+        }
+    }
+
+    return NULL;
+}
+
+MR_ConsDebug *
+MR_lookup_cons_debug_num(int cons_index)
+{
+    int i;
+
+    for (i = 0; i < MR_cons_debug_info_next; i++) {
+        if (MR_cons_debug_infos[i].MR_cod_sequence_num == cons_index) {
+            return &MR_cons_debug_infos[i];
+        }
+    }
+
+    return NULL;
+}
+
+const char *
+MR_cons_debug_name(MR_ConsDebug *cons_debug)
+{
+    const char  *warning;
+    char        buf[MR_NAME_BUF];
+
+    if (cons_debug == NULL) {
+        return "unknown";
+    }
+
+    if (cons_debug->MR_cod_valid) {
+        warning = "";
+    } else {
+        warning = " INVALID";
+    }
+
+    if (cons_debug->MR_cod_version_num > 0) {
+        sprintf(buf, "con %d/%d (%p)%s", cons_debug->MR_cod_sequence_num,
+            cons_debug->MR_cod_version_num,
+            cons_debug->MR_cod_consumer, warning);
+    } else {
+        sprintf(buf, "con %d (%p)%s", cons_debug->MR_cod_sequence_num,
+            cons_debug->MR_cod_consumer, warning);
+    }
+
+    return strdup(buf);
+}
+
+const char *
+MR_cons_addr_name(MR_Consumer *consumer)
+{
+    MR_ConsDebug *cons_debug;
+
+    if (consumer == NULL) {
+        return "NULL";
+    }
+
+    cons_debug = MR_lookup_cons_debug_addr(consumer);
+    return MR_cons_debug_name(cons_debug);
+}
+
+const char *
+MR_cons_num_name(int cons_index)
+{
+    MR_ConsDebug *cons_debug;
+
+    cons_debug = MR_lookup_cons_debug_num(cons_index);
+    return MR_cons_debug_name(cons_debug);
+}
+
+void
+MR_enter_gen_debug(MR_Generator *generator)
+{
+    int i;
+
+    for (i = 0; i < MR_gen_debug_info_next; i++) {
+        if (MR_gen_debug_infos[i].MR_gd_generator == generator) {
+            MR_gen_debug_infos[i].MR_gd_version_num++;
+            MR_gen_debug_infos[i].MR_gd_valid = MR_TRUE;
+            return;
+        }
+    }
+
+    MR_ensure_room_for_next(MR_gen_debug_info, MR_GenDebug,
+        MR_GEN_DEBUG_INIT);
+    i = MR_gen_debug_info_next;
+    MR_gen_debug_infos[i].MR_gd_generator = generator;
+    MR_gen_debug_infos[i].MR_gd_sequence_num = i;
+    MR_gen_debug_infos[i].MR_gd_version_num = 0;
+    MR_gen_debug_infos[i].MR_gd_valid = MR_TRUE;
+    MR_gen_debug_info_next++;
+}
+
+MR_GenDebug *
+MR_lookup_gen_debug_addr(MR_Generator *generator)
+{
+    int i;
+
+    for (i = 0; i < MR_gen_debug_info_next; i++) {
+        if (MR_gen_debug_infos[i].MR_gd_generator == generator) {
+            return &MR_gen_debug_infos[i];
+        }
+    }
+
+    return NULL;
+}
+
+MR_GenDebug *
+MR_lookup_gen_debug_num(int gen_index)
+{
+    int i;
+
+    for (i = 0; i < MR_gen_debug_info_next; i++) {
+        if (MR_gen_debug_infos[i].MR_gd_sequence_num == gen_index) {
+            return &MR_gen_debug_infos[i];
+        }
+    }
+
+    return NULL;
+}
+
+const char *
+MR_gen_debug_name(MR_GenDebug *gen_debug)
+{
+    const char  *warning;
+    char        buf[MR_NAME_BUF];
+
+    if (gen_debug == NULL) {
+        return "unknown";
+    }
+
+    if (gen_debug->MR_gd_valid) {
+        warning = "";
+    } else {
+        warning = " INVALID";
+    }
+
+    if (gen_debug->MR_gd_version_num > 0) {
+        sprintf(buf, "sub %d/%d (%p)%s", gen_debug->MR_gd_sequence_num,
+            gen_debug->MR_gd_version_num,
+            gen_debug->MR_gd_generator, warning);
+    } else {
+        sprintf(buf, "sub %d (%p)%s", gen_debug->MR_gd_sequence_num,
+            gen_debug->MR_gd_generator, warning);
+    }
+
+    return strdup(buf);
+}
+
+const char *
+MR_gen_addr_name(MR_Generator *generator)
+{
+    MR_GenDebug *gen_debug;
+
+    if (generator == NULL) {
+        return "NULL";
+    }
+
+    gen_debug = MR_lookup_gen_debug_addr(generator);
+    return MR_gen_debug_name(gen_debug);
+}
+
+const char *
+MR_gen_num_name(int gen_index)
+{
+    MR_GenDebug *gen_debug;
+
+    gen_debug = MR_lookup_gen_debug_num(gen_index);
+    return MR_gen_debug_name(gen_debug);
+}
+
+void
+MR_print_gen_debug(FILE *fp, const MR_Proc_Layout *proc,
+    MR_GenDebug *gen_debug)
+{
+    if (gen_debug == NULL) {
+        fprintf(fp, "NULL gen_debug\n");
+    } else {
+        MR_print_generator(fp, proc, gen_debug->MR_gd_generator);
+    }
+}
+
+void
+MR_print_generator(FILE *fp, const MR_Proc_Layout *proc,
+    MR_Generator *generator)
+{
+    MR_SubgoalList  follower;
+    MR_ConsumerList consumer;
+    MR_AnswerList   answer_list;
+    MR_Word         *answer;
+    int             answer_num;
+
+    if (generator == NULL) {
+        fprintf(fp, "NULL generator\n");
+        return;
+    }
+
+#ifdef  MR_TABLE_DEBUG
+    if (proc == NULL && generator->MR_sg_proc_layout != NULL) {
+        proc = generator->MR_sg_proc_layout;
+    }
+#endif
+
+    fprintf(fp, "generator %s", MR_gen_addr_name(generator));
+    if (generator->MR_gen_back_ptr == NULL) {
+        fprintf(fp, ", DELETED");
+    }
+    fprintf(fp, "\n");
+
+    if (proc != NULL) {
+        fprintf(fp, "proc: ");
+        MR_print_proc_id(fp, proc);
+        fprintf(fp, "\n");
+    }
+
+#if 0
+    fprintf(fp, "leader: %s, ",
+        MR_gen_addr_name(generator->MR_sg_leader));
+    fprintf(fp, "followers:");
+    for (follower = generator->MR_sg_followers;
+        follower != NULL; follower = follower->MR_sl_next)
+    {
+        fprintf(fp, " %s", MR_gen_addr_name(follower->MR_sl_item));
+    }
+
+    fprintf(fp, "\nconsumers:");
+    for (consumer = generator->MR_sg_cons_list;
+        consumer != NULL; consumer = consumer->MR_cl_next)
+    {
+        fprintf(fp, " %s", MR_cons_addr_name(consumer->MR_cl_item));
+    }
+
+    fprintf(fp, "\n");
+    fprintf(fp, "answers: %d\n", generator->MR_sg_num_ans);
+
+    if (proc != NULL) {
+        answer_list = generator->MR_sg_answer_list;
+        answer_num = 1;
+        while (answer_list != NULL) {
+            fprintf(fp, "answer #%d: <", answer_num);
+            MR_print_answerblock(fp, proc, answer_list->MR_aln_answer_block);
+            fprintf(fp, ">\n");
+            answer_list = answer_list->MR_aln_next_answer;
+            answer_num++;
+        }
+    }
+#endif
+}
+
+void
+MR_print_cons_debug(FILE *fp, const MR_Proc_Layout *proc,
+    MR_ConsDebug *cons_debug)
+{
+    if (cons_debug == NULL) {
+        fprintf(fp, "NULL cons_debug\n");
+    } else {
+        MR_print_consumer(fp, proc, cons_debug->MR_cod_consumer);
+    }
+}
+
+void
+MR_print_consumer(FILE *fp, const MR_Proc_Layout *proc, MR_Consumer *consumer)
+{
+    if (consumer == NULL) {
+        fprintf(fp, "NULL consumer\n");
+        return;
+    }
+
+    fprintf(fp, "consumer %s", MR_cons_addr_name(consumer));
+
+    /* XXX check semantics of DELETED */
+    if (consumer->MR_cons_answer_generator == NULL) {
+        fprintf(fp, ", DELETED\n");
+    } else {
+        fprintf(fp, ", answer generator %s",
+            MR_gen_addr_name(consumer->MR_cons_answer_generator));
+        if (consumer->MR_cons_containing_generator != NULL) {
+            fprintf(fp, ", in generator %s\n",
+                MR_gen_addr_name(consumer->MR_cons_answer_generator));
+        } else {
+            fprintf(fp, ", in main context\n\n");
+        }
+        fprintf(fp, "returned answers %d, remaining answers ptr %p\n",
+            consumer->MR_cons_num_returned_answers,
+            consumer->MR_cons_remaining_answer_list_ptr);
+    }
+}
+
+/*---------------------------------------------------------------------------*/
+
+static  int MR_next_gen_context = 1;
+
+static MR_Context *
+MR_get_context_for_gen(MR_Generator *gen)
+{
+    MR_Dlist        *list;
+    MR_Dlist        *item;
+    MR_Context      *ctxt;
+
+    list = MR_ENGINE(MR_eng_free_contexts);
+    if (MR_dlist_length(list) > 0) {
+        item = MR_dlist_first_ptr(list);
+        ctxt = (MR_Context *) MR_dlist_data(item);
+        MR_dlist_delete(list, item, NULL);
+    } else {
+        char    buf[80];    /* ought to be plenty big enough */
+
+        sprintf(buf, "gen%d", MR_next_gen_context);
+        MR_next_gen_context++;
+        ctxt = MR_create_context(strdup(buf), gen);
+    }
+
+    ctxt->MR_ctxt_owner_generator = gen;
+    return ctxt;
+}
+
+MR_ConsumerPtr
+MR_table_setup_consumer(MR_TableNode trie_node, MR_Integer num_input_args,
+    MR_Word *generator_pred, MR_String pred_id)
+{
+    /* not yet implemented */
+}
+
+MR_Generator *
+MR_setup_generator(MR_String pred_id, MR_TrieNode trie_node)
+{
+    /*
+    ** Initialize the generator if this is the first time we see it.
+    ** If the subgoal structure already exists but is marked inactive,
+    ** then it was left by a previous generator that couldn't
+    ** complete the evaluation of the subgoal due to a commit.
+    ** In that case, we want to forget all about the old generator.
+    */
+
+    MR_restore_transient_registers();
+#if 0
+    if (trie_node->MR_generator == NULL) {
+        MR_Generator *gen;
+        MR_Context   *context;
+
+        gen = MR_TABLE_NEW(MR_Generator);
+        context = MR_get_context_for_gen(gen);
+
+        gen->MR_gen_back_ptr = trie_node;
+        gen->MR_gen_context = context;
+        gen->MR_gen_leader = gen;
+        gen->MR_gen_led_generators = MR_dlist_makelist(gen);
+        gen->MR_gen_consumers = MR_dlist_makelist0();
+        gen->MR_gen_num_answers = 0;
+        gen->MR_gen_answer_table.MR_integer = 0;
+        gen->MR_gen_answer_list = NULL;
+        gen->MR_gen_answer_list_tail = &gen->MR_gen_answer_list;
+
+        /*
+        ** MR_subgoal_debug_cur_proc refers to the last procedure
+        ** that executed a call event, if any. If the procedure that is
+        ** executing table_nondet_setup is traced, this will be that
+        ** procedure, and recording the layout structure of the
+        ** processor in the generator allows us to interpret the contents
+        ** of the generator's answer tables. If the procedure executing
+        ** table_nondet_setup is not traced, then the layout structure
+        ** belongs to another procedure and the any use of the
+        ** MR_gen_proc_layout field will probably cause a core dump.
+        ** For implementors debugging minimal model tabling, this is
+        ** the right tradeoff.
+        */
+        gen->MR_gen_proc_layout = MR_subgoal_debug_cur_proc;
+
+#ifdef  MR_TABLE_DEBUG
+        MR_enter_gen_debug(gen);
+
+        if (MR_tabledebug) {
+            printf("setting up generator %p -> %s, ",
+                trie_node, MR_gen_addr_name(gen));
+            printf("answer slot %p\n", subgoal->MR_sg_answer_list_tail);
+            if (subgoal->MR_gen_proc_layout != NULL) {
+                printf("proc: ");
+                MR_print_proc_id(stdout, gen->MR_gen_proc_layout);
+                printf("\n");
+            }
+        }
+
+        if (MR_maxfr != MR_curfr) {
+            MR_fatal_error("MR_maxfr != MR_curfr at table setup\n");
+        }
+#endif
+        trie_node->MR_generator = gen;
+    }
+
+#endif
+    return trie_node->MR_generator;
+    MR_save_transient_registers();
+}
+
+MR_AnswerBlock
+MR_table_consumer_get_next_answer(MR_ConsumerPtr consumer)
+{
+    /* not yet implemented */
+}
+
+MR_TrieNode
+MR_table_generator_get_answer_table(MR_GeneratorPtr generator)
+{
+    /* not yet implemented */
+}
+
+MR_TrieNode
+MR_table_generator_new_answer_slot(MR_GeneratorPtr generator)
+{
+    /* not yet implemented */
+}
+
+#endif  /* MR_USE_MINIMAL_MODEL_OWN_STACKS */
Index: runtime/mercury_mm_own_stacks.h
===================================================================
RCS file: runtime/mercury_mm_own_stacks.h
diff -N runtime/mercury_mm_own_stacks.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ runtime/mercury_mm_own_stacks.h	24 Jun 2004 09:22:16 -0000
@@ -0,0 +1,115 @@
+/*
+** Copyright (C) 2004 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_mm_own_stacks.h:
+** definitions of some basic stuff used for the own stack style of
+** minimal model tabling.
+*/
+
+#ifndef	MERCURY_MM_OWN_STACKS_H
+#define	MERCURY_MM_OWN_STACKS_H
+
+#include "mercury_imp.h"
+#include "mercury_tabling.h"
+#include "mercury_stack_layout.h"
+
+#ifdef	MR_USE_MINIMAL_MODEL_OWN_STACKS
+
+/*
+** There is one MR_Generator structure per active generator.
+**
+** The back_ptr field points back to the MR_TrieNode that points to this
+** generator.
+**
+** The stack_pair field points back to the MR_GenStackPair struct whose
+** MR_gen_pair_gen field points here; it is used to find the generator's
+** stacks.
+**
+** The proc_layout field is set only if debugging is enabled; it allows us
+** to find out what subgoal we are the generator for, and to interpret
+** the answer table.
+**
+** The pred_id field is currently always set to a string identifying the
+** main predicate of the subgoal we are the generator for. It is used for
+** debugging. Once this stuff is debugged, we can disable this field.
+**
+** The leader field points to the leader of the clique this generator belongs
+** to; if this generator is the leader, this field points to its own structure.
+**
+** If this generator is the leader of its clique, the led_generators field will
+** point to a list of all generators in the clique, including itself. If this
+** generator is not the leader of its clique, this field will contain an empty
+** list.
+*/
+
+struct MR_Generator_Struct {
+	MR_TrieNode		MR_gen_back_ptr;
+	MR_Context		*MR_gen_context;
+	const MR_Proc_Layout	*MR_gen_proc_layout;
+	MR_String		*MR_gen_pred_id;
+	MR_Generator		*MR_gen_leader;
+	MR_Dlist		*MR_gen_led_generators;
+	MR_Dlist		*MR_gen_consumers;
+	MR_Integer		MR_gen_num_answers;
+	MR_TableNode		MR_gen_answer_table;
+	MR_AnswerList		MR_gen_answer_list;
+	MR_AnswerList		*MR_gen_answer_list_tail;
+};
+
+struct MR_Consumer_Struct {
+	MR_Generator	*MR_cons_answer_generator;
+	MR_Generator	*MR_cons_containing_generator;
+	MR_Integer	MR_cons_num_returned_answers;
+	MR_AnswerList	*MR_cons_remaining_answer_list_ptr;
+};
+
+/*---------------------------------------------------------------------------*/
+
+extern	const MR_Proc_Layout	*MR_subgoal_debug_cur_proc;
+
+extern	void		MR_enter_cons_debug(MR_Consumer *consumer);
+extern	MR_ConsDebug 	*MR_lookup_cons_debug_addr(MR_Consumer *consumer);
+extern	MR_ConsDebug 	*MR_lookup_cons_debug_num(int consumer_index);
+extern	const char	*MR_cons_debug_name(MR_ConsDebug *consumer_dbg);
+extern	const char	*MR_cons_addr_name(MR_Consumer *consumer);
+extern	const char	*MR_cons_num_name(int consumer_index);
+
+extern	void		MR_enter_gen_debug(MR_Generator *gen);
+extern	MR_GenDebug	*MR_lookup_gen_debug_addr(MR_Generator *gen);
+extern	MR_GenDebug	*MR_lookup_gen_debug_num(int gen_index);
+extern	const char	*MR_gen_debug_name(MR_GenDebug *gen_debug);
+extern	const char	*MR_gen_addr_name(MR_Generator *gen);
+extern	const char	*MR_gen_num_name(int gen_index);
+
+extern	void		MR_print_gen_debug(FILE *fp,
+				const MR_Proc_Layout *proc,
+				MR_GenDebug *gen_debug);
+extern	void		MR_print_generator(FILE *fp,
+				const MR_Proc_Layout *proc,
+				MR_Generator *gen);
+extern	void		MR_print_cons_debug(FILE *fp,
+				const MR_Proc_Layout *proc,
+				MR_ConsDebug *consumer_debug);
+extern	void		MR_print_consumer(FILE *fp,
+				const MR_Proc_Layout *proc,
+				MR_Consumer *consumer);
+
+extern	MR_ConsumerPtr	MR_table_mmos_setup_consumer(MR_TableNode trie_node,
+				MR_Integer num_input_args,
+				MR_Word *generator_pred, MR_String pred_id);
+extern	MR_GeneratorPtr	MR_mmos_setup_generator(MR_String pred_id,
+				MR_TrieNode trie_node);
+extern	MR_AnswerBlock	MR_table_mmos_consumer_get_next_answer(
+				MR_ConsumerPtr consumer);
+extern	MR_TrieNode	MR_table_mmos_get_answer_table(MR_GeneratorPtr
+				generator);
+extern	MR_AnswerBlock	MR_table_mmos_create_answer_block(MR_GeneratorPtr
+				generator);
+
+#endif	/* MR_USE_MINIMAL_MODEL_OWN_STACKS */
+
+#endif	/* MERCURY_MM_OWN_STACKS_H */
Index: runtime/mercury_stack_layout.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_layout.h,v
retrieving revision 1.83
diff -u -b -r1.83 mercury_stack_layout.h
--- runtime/mercury_stack_layout.h	7 Jul 2004 07:11:16 -0000	1.83
+++ runtime/mercury_stack_layout.h	7 Jul 2004 07:17:06 -0000
@@ -748,7 +748,8 @@
 	MR_EVAL_METHOD_NORMAL,
 	MR_EVAL_METHOD_LOOP_CHECK,
 	MR_EVAL_METHOD_MEMO,
-	MR_EVAL_METHOD_MINIMAL,
+	MR_EVAL_METHOD_MINIMAL_STACK_COPY,
+	MR_EVAL_METHOD_MINIMAL_OWN_STACKS,
 	MR_EVAL_METHOD_TABLE_IO,
 	MR_EVAL_METHOD_TABLE_IO_DECL,
 	MR_EVAL_METHOD_TABLE_IO_UNITIZE,
Index: runtime/mercury_stack_trace.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stack_trace.c,v
retrieving revision 1.66
diff -u -b -r1.66 mercury_stack_trace.c
--- runtime/mercury_stack_trace.c	7 Jul 2004 07:11:16 -0000	1.66
+++ runtime/mercury_stack_trace.c	19 Jul 2004 02:46:07 -0000
@@ -92,14 +92,24 @@
 MR_dump_stack(MR_Code *success_pointer, MR_Word *det_stack_pointer,
     MR_Word *current_frame, MR_bool include_trace_data)
 {
-#ifndef MR_STACK_TRACE
-    fprintf(stderr, "Stack dump not available in this grade.\n");
-#else
-
     const MR_Internal       *label;
     const MR_Label_Layout   *layout;
     const char              *result;
+    MR_bool                 stack_dump_available;
+    char                    *env_suppress;
 
+    env_suppress = getenv("MERCURY_SUPPRESS_STACK_TRACE");
+    if (env_suppress != NULL) {
+        return;
+    }
+
+#ifdef MR_STACK_TRACE
+    stack_dump_available = MR_TRUE;
+#else
+    stack_dump_available = MR_FALSE;
+#endif
+
+    if (stack_dump_available) {
     fprintf(stderr, "Stack dump follows:\n");
 
     MR_do_init_modules();
@@ -116,7 +126,9 @@
             fprintf(stderr, "%s\n", result);
         }
     }
-#endif
+    } else {
+        fprintf(stderr, "Stack dump not available in this grade.\n");
+    }
 }
 
 const char *
@@ -487,7 +499,7 @@
             fprintf(fp, " succfr: ");
             MR_print_nondstackptr(fp, MR_succfr_slot(base_maxfr));
             fprintf(fp, "\n");
-#ifdef  MR_USE_MINIMAL_MODEL
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
             fprintf(fp, " detfr:  ");
             MR_print_detstackptr(fp, MR_table_detfr_slot(base_maxfr));
             fprintf(fp, "\n");
@@ -930,8 +942,8 @@
     if (ip == MR_ENTRY(MR_do_trace_redo_fail_deep)) {
         return MR_FALSE;
     }
-#ifdef  MR_USE_MINIMAL_MODEL
-    if (ip == MR_ENTRY(MR_COMPLETION_ENTRY)) {
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
+    if (ip == MR_ENTRY(MR_MMSC_COMPLETION_ENTRY)) {
         return MR_FALSE;
     }
 #endif
@@ -1227,6 +1239,8 @@
     }
 
 #if !defined(MR_HIGHLEVEL_CODE) && defined(MR_TABLE_DEBUG)
+  #if 0
+    /* reenable this code if you need to */
     if (MR_DETISM_DET_STACK(entry->MR_sle_detism)) {
         MR_print_detstackptr(fp, base_sp);
     } else {
@@ -1234,6 +1248,7 @@
     }
 
     fprintf(fp, " ");
+  #endif
 #endif
 }
 
Index: runtime/mercury_stacks.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stacks.c,v
retrieving revision 1.14
diff -u -b -r1.14 mercury_stacks.c
--- runtime/mercury_stacks.c	7 Jul 2004 07:11:17 -0000	1.14
+++ runtime/mercury_stacks.c	7 Jul 2004 07:17:06 -0000
@@ -116,7 +116,7 @@
 
 #undef MR_TABLE_DEBUG
 
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 
 MR_Integer		MR_gen_next_var;
 MR_GenStackFrame	*MR_gen_stack_var;
@@ -609,4 +609,4 @@
 
 /***************************************************************************/
 
-#endif	/* MR_USE_MINIMAL_MODEL */
+#endif	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
Index: runtime/mercury_stacks.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stacks.h,v
retrieving revision 1.48
diff -u -b -r1.48 mercury_stacks.h
--- runtime/mercury_stacks.h	7 Jul 2004 07:11:17 -0000	1.48
+++ runtime/mercury_stacks.h	7 Jul 2004 07:17:06 -0000
@@ -133,7 +133,7 @@
 
 #define	MR_NONDET_TEMP_SIZE	3 /* prevfr, redoip, redofr */
 #define	MR_DET_TEMP_SIZE	4 /* prevfr, redoip, redofr, detfr */
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 #define	MR_NONDET_FIXED_SIZE	6 /* prevfr, redoip, redofr, succip, succfr,
 				     sp */
 #else
@@ -179,7 +179,7 @@
 
 /* DEFINITIONS FOR MANIPULATING THE NONDET STACK */
 
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
   #define	MR_maybe_fill_table_detfr_slot()			\
 			do {						\
 				MR_table_detfr_slot_word(MR_curfr) =	\
@@ -476,7 +476,7 @@
 
 /*---------------------------------------------------------------------------*/
 
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 
 /* DEFINITIONS FOR GENERATOR STACK FRAMES */
 
@@ -623,6 +623,6 @@
 					MR_Integer pneg_next,
 					MR_PNegStackFrame *pneg_block);
 
-#endif	/* MR_USE_MINIMAL_MODEL */
+#endif	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 #endif	/* not MERCURY_STACKS_H */
Index: runtime/mercury_tabling.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_tabling.c,v
retrieving revision 1.63
diff -u -b -r1.63 mercury_tabling.c
--- runtime/mercury_tabling.c	28 Jun 2004 04:50:05 -0000	1.63
+++ runtime/mercury_tabling.c	18 Jul 2004 05:24:20 -0000
@@ -1154,10 +1154,14 @@
         MR_table_hash_resize_new_entries);
     fprintf(fp, "chunk allocations: %d\n", MR_table_hash_allocs);
 
-  #ifdef    MR_USE_MINIMAL_MODEL
+  #ifdef    MR_USE_MINIMAL_MODEL_STACK_COPY
     fprintf(fp, "\n");
     MR_minimal_model_report_stats(fp);
   #endif
+  #ifdef    MR_USE_MINIMAL_MODEL_OWN_STACKS
+    fprintf(fp, "\n");
+    MR_mm_own_stacks_report_stats(fp);
+  #endif
 #else
     fprintf(fp, "not enabled\n");
 #endif
@@ -1165,6 +1169,143 @@
 
 /*---------------------------------------------------------------------------*/
 
+const char *
+MR_loopcheck_status(MR_Unsigned status)
+{
+    switch (status) {
+        case MR_LOOP_INACTIVE:
+            return "INACTIVE";
+
+        case MR_LOOP_ACTIVE:
+            return "ACTIVE";
+    }
+
+    return "INVALID";
+}
+
+const char *
+MR_memo_status(MR_Unsigned status)
+{
+    switch (status) {
+        case MR_MEMO_INACTIVE:
+            return "INACTIVE";
+
+        case MR_MEMO_ACTIVE:
+            return "ACTIVE";
+
+        case MR_MEMO_SUCCEEDED:
+            return "SUCCEEDED";
+
+        case MR_MEMO_FAILED:
+            return "FAILED";
+
+        default:
+            return "SUCCESS_BLOCK";
+    }
+
+    return "INVALID";
+}
+
+const char *
+MR_memo_non_status(MR_MemoNonStatus status)
+{
+    switch (status) {
+        case MR_MEMO_NON_INACTIVE:
+            return "INACTIVE";
+
+        case MR_MEMO_NON_ACTIVE:
+            return "ACTIVE";
+
+        case MR_MEMO_NON_INCOMPLETE:
+            return "INCOMPLETE";
+
+        case MR_MEMO_NON_COMPLETE:
+            return "COMPLETE";
+    }
+
+    return "INVALID";
+}
+
+void
+MR_print_loopcheck_tip(FILE *fp, const MR_Proc_Layout *proc, MR_TrieNode table)
+{
+    switch (table->MR_loop_status) {
+        case MR_LOOP_INACTIVE:
+            fprintf(fp, "uninitialized\n");
+            break;
+        case MR_LOOP_ACTIVE:
+            fprintf(fp, "working\n");
+            break;
+        default:
+            MR_fatal_error("MR_print_loopcheck: bad status");
+    }
+}
+
+void
+MR_print_memo_tip(FILE *fp, const MR_Proc_Layout *proc, MR_TrieNode table)
+{
+    switch (table->MR_memo_status) {
+        case MR_MEMO_INACTIVE:
+            fprintf(fp, "uninitialized\n");
+            break;
+        case MR_MEMO_ACTIVE:
+            fprintf(fp, "working\n");
+            break;
+        case MR_MEMO_FAILED:
+            fprintf(fp, "failed\n");
+            break;
+        case MR_MEMO_SUCCEEDED:
+            fprintf(fp, "succeeded (no outputs)\n");
+            break;
+        default:
+            fprintf(fp, "succeeded <");
+            MR_print_answerblock(fp, proc, table->MR_answerblock);
+            fprintf(fp, ">\n");
+            break;
+    }
+}
+
+void
+MR_print_memo_non_record(FILE *fp, const MR_Proc_Layout *proc,
+    MR_MemoNonRecordPtr record)
+{
+    MR_AnswerList   answer_list;
+    int             i;
+
+    if (record == NULL) {
+        fprintf(fp, "inactive\n");
+        return;
+    }
+
+    switch (record->MR_mn_status) {
+        case MR_MEMO_NON_INACTIVE:
+            fprintf(fp, "inactive\n");
+            return;
+        case MR_MEMO_NON_ACTIVE:
+            fprintf(fp, "active\n");
+            break;
+        case MR_MEMO_NON_INCOMPLETE:
+            fprintf(fp, "incomplete\n");
+            break;
+        case MR_MEMO_NON_COMPLETE:
+            fprintf(fp, "complete\n");
+            break;
+        default:
+            MR_fatal_error("MR_print_memo_non_record: bad status");
+            break;
+    }
+
+    answer_list = record->MR_mn_answer_list;
+    i = 1;
+    while (answer_list != NULL) {
+        fprintf(fp, "answer #%d: <", i);
+        MR_print_answerblock(fp, proc, answer_list->MR_aln_answer_block);
+        fprintf(fp, ">\n");
+        answer_list = answer_list->MR_aln_next_answer;
+        i++;
+    }
+}
+
 void
 MR_print_answerblock(FILE *fp, const MR_Proc_Layout *proc,
 	MR_Word *answer_block)
@@ -1213,5 +1354,229 @@
 		}
 	}
 }
+
+#ifdef  MR_HIGHLEVEL_CODE
+
+static void MR_CALL
+    mercury__table_builtin__table_memo_return_all_answers_2_p_0(
+        MR_AnswerList answer_list0, MR_Box *boxed_answer_block,
+        MR_Cont cont, void *cont_env_ptr);
+
+static void MR_CALL
+mercury__table_builtin__table_memo_return_all_answers_2_p_0(
+    MR_AnswerList answer_list0, MR_Box *boxed_answer_block_ptr,
+    MR_Cont cont, void *cont_env_ptr)
+{
+    MR_AnswerList answer_list;
+
+    while (answer_list0 != NULL) {
+        answer_list = answer_list0->MR_aln_next_answer;
+        *boxed_answer_block_ptr = (MR_Box) answer_list0->MR_aln_answer_block;
+        cont(cont_env_ptr);
+        answer_list0 = answer_list;
+    }
+}
+
+void MR_CALL
+mercury__table_builtin__table_memo_return_all_answers_multi_2_p_0(
+    MR_Box boxed_record, MR_Box *boxed_answer_block_ptr,
+    MR_Cont cont, void *cont_env_ptr)
+{
+    MR_MemoNonRecordPtr record;
+    MR_AnswerList       list;
+
+    record = (MR_MemoNonRecordPtr) boxed_record;
+    list = record->MR_mn_answer_list;
+    if (list == NULL) {
+        MR_fatal_error("table_memo_return_all_answers_multi: no answers");
+    }
+    mercury__table_builtin__table_memo_return_all_answers_2_p_0(list,
+        boxed_answer_block_ptr, cont, cont_env_ptr);
+}
+
+void MR_CALL
+mercury__table_builtin__table_memo_return_all_answers_nondet_2_p_0(
+    MR_Box boxed_record, MR_Box *boxed_answer_block_ptr,
+    MR_Cont cont, void *cont_env_ptr)
+{
+    MR_MemoNonRecordPtr record;
+    MR_AnswerList       list;
+
+    record = (MR_MemoNonRecordPtr) boxed_record;
+    list = record->MR_mn_answer_list;
+    mercury__table_builtin__table_memo_return_all_answers_2_p_0(list,
+        boxed_answer_block_ptr, cont, cont_env_ptr);
+}
+
+#else   /* MR_HIGHLEVEL_CODE */
+
+MR_define_extern_entry(MR_MEMO_NON_RET_ALL_NONDET_ENTRY);
+MR_define_extern_entry(MR_MEMO_NON_RET_ALL_MULTI_ENTRY);
+
+MR_EXTERN_USER_PROC_ID_PROC_LAYOUT(MR_DETISM_NON, 0, -1,
+    MR_PREDICATE, table_builtin, table_memo_return_all_answers_nondet, 2, 0);
+MR_EXTERN_USER_PROC_ID_PROC_LAYOUT(MR_DETISM_NON, 0, -1,
+    MR_PREDICATE, table_builtin, table_memo_return_all_answers_multi, 2, 0);
+
+#define MEMO_NON_RET_ALL_NONDET_LABEL(name)                             \
+    MR_label_name(MR_MEMO_NON_RET_ALL_NONDET_ENTRY, name)
+#define MEMO_NON_RET_ALL_MULTI_LABEL(name)                             \
+    MR_label_name(MR_MEMO_NON_RET_ALL_MULTI_ENTRY, name)
+
+MR_declare_label(MEMO_NON_RET_ALL_NONDET_LABEL(Next));
+MR_declare_label(MEMO_NON_RET_ALL_MULTI_LABEL(Next));
+
+MR_MAKE_USER_INTERNAL_LAYOUT(table_builtin,
+    table_memo_return_all_answers_nondet, 2, 0, Next);
+MR_MAKE_USER_INTERNAL_LAYOUT(table_builtin,
+    table_memo_return_all_answers_multi, 2, 0, Next);
+
+MR_BEGIN_MODULE(table_memo_non_module)
+    MR_init_entry_sl(MR_MEMO_NON_RET_ALL_NONDET_ENTRY);
+    MR_init_label_sl(MEMO_NON_RET_ALL_NONDET_LABEL(Next));
+    MR_init_entry_sl(MR_MEMO_NON_RET_ALL_MULTI_ENTRY);
+    MR_init_label_sl(MEMO_NON_RET_ALL_MULTI_LABEL(Next));
+MR_BEGIN_CODE
+
+MR_define_entry(MR_MEMO_NON_RET_ALL_NONDET_ENTRY);
+{
+    MR_MemoNonRecordPtr record;
+    MR_AnswerList       cur_node0;
+    MR_AnswerList       cur_node;
+    MR_AnswerBlock      answer_block;
+
+    record = (MR_MemoNonRecordPtr) MR_r1;
+    cur_node0 = record->MR_mn_answer_list;
+
+  #ifdef MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("picking up all answers in %p -> %p\n",
+            record->MR_mn_back_ptr, record);
+    }
+  #endif
+
+    if (cur_node0 == NULL) {
+        MR_redo();
+    }
+
+    answer_block = cur_node0->MR_aln_answer_block;
+    cur_node = cur_node0->MR_aln_next_answer;
+
+    /* Consider not creating the stack frame if cur_node is NULL. */
+
+    MR_mkframe("pred table_builtin.table_memo_return_all_answers_nondet/2-0",
+        1, MR_LABEL(MEMO_NON_RET_ALL_NONDET_LABEL(Next)));
+    MR_framevar(1) = (MR_Word) cur_node;
+    MR_r1 = (MR_Word) answer_block;
+}
+    MR_succeed();
+
+MR_define_label(MEMO_NON_RET_ALL_NONDET_LABEL(Next));
+{
+    MR_AnswerList   cur_node0;
+    MR_AnswerList   cur_node;
+    MR_AnswerBlock  answer_block;
+
+    cur_node0 = (MR_AnswerList) MR_framevar(1);
+    if (cur_node0 == NULL) {
+        MR_fail();
+    }
+
+    answer_block = cur_node0->MR_aln_answer_block;
+    cur_node = cur_node0->MR_aln_next_answer;
+    MR_framevar(1) = (MR_Word) cur_node;
+    MR_r1 = (MR_Word) answer_block;
+}
+    MR_succeed();
+
+MR_define_entry(MR_MEMO_NON_RET_ALL_MULTI_ENTRY);
+{
+    MR_MemoNonRecordPtr record;
+    MR_AnswerList       cur_node0;
+    MR_AnswerList       cur_node;
+    MR_AnswerBlock      answer_block;
+
+    record = (MR_MemoNonRecordPtr) MR_r1;
+    cur_node0 = record->MR_mn_answer_list;
+
+  #ifdef MR_TABLE_DEBUG
+    if (MR_tabledebug) {
+        printf("picking up all answers in %p -> %p\n",
+            record->MR_mn_back_ptr, record);
+    }
+  #endif
+
+    if (cur_node0 == NULL) {
+        MR_fatal_error("table_memo_return_all_answers_multi: no answers");
+    }
+
+    answer_block = cur_node0->MR_aln_answer_block;
+    cur_node = cur_node0->MR_aln_next_answer;
+
+    /* Consider not creating the stack frame if cur_node is NULL. */
+
+    MR_mkframe("pred table_builtin.table_memo_return_all_answers_multi/2-0",
+        1, MR_LABEL(MEMO_NON_RET_ALL_MULTI_LABEL(Next)));
+    MR_framevar(1) = (MR_Word) cur_node;
+    MR_r1 = (MR_Word) answer_block;
+}
+    MR_succeed();
+
+MR_define_label(MEMO_NON_RET_ALL_MULTI_LABEL(Next));
+{
+    MR_AnswerList   cur_node0;
+    MR_AnswerList   cur_node;
+    MR_AnswerBlock  answer_block;
+
+    cur_node0 = (MR_AnswerList) MR_framevar(1);
+    if (cur_node0 == NULL) {
+        MR_fail();
+    }
+
+    answer_block = cur_node0->MR_aln_answer_block;
+    cur_node = cur_node0->MR_aln_next_answer;
+    MR_framevar(1) = (MR_Word) cur_node;
+    MR_r1 = (MR_Word) answer_block;
+}
+    MR_succeed();
+
+MR_END_MODULE
+
+#endif  /* MR_HIGHLEVEL_CODE */
+
+/* Ensure that the initialization code for the above modules gets to run. */
+/*
+INIT mercury_sys_init_table_modules
+*/
+
+MR_MODULE_STATIC_OR_EXTERN MR_ModuleFunc table_memo_non_module;
+
+/* forward declarations to suppress gcc -Wmissing-decl warnings */
+void mercury_sys_init_table_modules_init(void);
+void mercury_sys_init_table_modules_init_type_tables(void);
+#ifdef  MR_DEEP_PROFILING
+void mercury_sys_init_table_modules_write_out_proc_statics(FILE *fp);
+#endif
+
+void mercury_sys_init_table_modules_init(void)
+{
+#ifndef MR_HIGHLEVEL_CODE
+    table_memo_non_module();
+#endif  /* MR_HIGHLEVEL_CODE */
+}
+
+void mercury_sys_init_table_modules_init_type_tables(void)
+{
+    /* no types to register */
+}
+
+#ifdef  MR_DEEP_PROFILING
+void mercury_sys_init_table_modules_write_out_proc_statics(FILE *fp)
+{
+    /* no proc_statics to write out */
+    /* XXX we need to fix the deep profiling */
+    /* of model_non memo tabled predicates */
+}
+#endif
 
 /*---------------------------------------------------------------------------*/
Index: runtime/mercury_tabling.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_tabling.h,v
retrieving revision 1.33
diff -u -b -r1.33 mercury_tabling.h
--- runtime/mercury_tabling.h	31 May 2004 04:13:06 -0000	1.33
+++ runtime/mercury_tabling.h	18 Jul 2004 05:24:36 -0000
@@ -117,9 +117,6 @@
 ** MR_type_table field.
 */
 
-typedef	MR_Word		*MR_AnswerBlock;
-typedef	MR_Subgoal	*MR_SubgoalPtr;
-
 /* these macros are used to interpret the MR_loop_status field */
 #define	MR_LOOP_INACTIVE	0
 #define	MR_LOOP_ACTIVE		1
@@ -132,11 +129,23 @@
 #define	MR_MEMO_BLOCK		4
 
 typedef enum {
+	MR_MEMO_NON_INACTIVE,
+	MR_MEMO_NON_ACTIVE,
+	MR_MEMO_NON_INCOMPLETE,
+	MR_MEMO_NON_COMPLETE
+} MR_MemoNonStatus;
+
+typedef enum {
 	MR_SUBGOAL_INACTIVE,
 	MR_SUBGOAL_ACTIVE,
 	MR_SUBGOAL_COMPLETE
 } MR_SubgoalStatus;
 
+struct MR_AnswerListNode_Struct {
+	MR_Word			*MR_aln_answer_block;
+	MR_AnswerList		MR_aln_next_answer;
+};
+
 union MR_TableNode_Union {
 	MR_Integer	MR_integer;
 	MR_HashTable	*MR_hash_table;
@@ -145,10 +154,21 @@
 	MR_Unsigned	MR_loop_status;
 	MR_Unsigned	MR_memo_status;
 	MR_Subgoal	*MR_subgoal;
+	MR_MemoNonRecordPtr	MR_memo_non_record;
+	MR_Consumer		*MR_consumer;
 	MR_AnswerBlock	MR_answerblock;
 	MR_Dlist	*MR_type_table;
 };
 
+struct MR_MemoNonRecord_Struct {
+	MR_TrieNode		MR_mn_back_ptr;
+	MR_MemoNonStatus	MR_mn_status;
+	int			MR_mn_num_answers;
+	MR_TableNode		MR_mn_answer_table;
+	MR_AnswerList		MR_mn_answer_list;
+	MR_AnswerList		*MR_mn_answer_list_tail;
+};
+
 /*---------------------------------------------------------------------------*/
 
 /*
@@ -247,8 +267,31 @@
 extern	void		MR_table_report_statistics(FILE *fp);
 
 /*
+** These functions return printable representations of the MR_loop_status
+** MR_memo_status and MR_mn_status fields.
+*/
+
+extern	const char	*MR_loopcheck_status(MR_Unsigned);
+extern	const char	*MR_memo_status(MR_Unsigned);
+extern	const char	*MR_memo_non_status(MR_MemoNonStatus);
+
+/*
+** These functions print the tips of the call tables for loopcheck and memo
+** tabled predicates to fp.
+*/
+
+extern	void		MR_print_loopcheck_tip(FILE *fp,
+				const MR_Proc_Layout *proc, MR_TrieNode table);
+extern	void		MR_print_memo_tip(FILE *fp,
+				const MR_Proc_Layout *proc, MR_TrieNode table);
+extern	void		MR_print_memo_non_record(FILE *fp,
+				const MR_Proc_Layout *proc,
+				MR_MemoNonRecordPtr record);
+
+/*
 ** Prints the given answer_block of the given procedure to fp.
 */
+
 extern	void		MR_print_answerblock(FILE *fp,
 				const MR_Proc_Layout *proc,
 				MR_Word *answer_block);
@@ -350,6 +393,31 @@
 	(MR_CHECK_EXPR_TYPE((source), type *),				\
 	MR_memcpy((char *) (dest), (char *) (source),			\
 		sizeof(type) * (num))))
+
+/*---------------------------------------------------------------------------*/
+
+#ifdef	MR_HIGHLEVEL_CODE
+
+  extern void MR_CALL
+	mercury__table_builtin__table_memo_return_all_answers_multi_2_p_0(
+		MR_Box record, MR_Box *answer_block_ptr,
+		MR_Cont cont, void *cont_env_ptr);
+  extern void MR_CALL
+  	mercury__table_builtin__table_memo_return_all_answers_nondet_2_p_0(
+		MR_Box record, MR_Box *answer_block_ptr,
+		MR_Cont cont, void *cont_env_ptr);
+
+#else	/* ! MR_HIGHLEVEL_CODE */
+  #define MR_MEMO_NON_RET_ALL_NONDET_ENTRY				\
+	MR_proc_entry_user_name(table_builtin,				\
+		table_memo_return_all_answers_nondet, 2, 0)
+  #define MR_MEMO_NON_RET_ALL_MULTI_ENTRY				\
+	MR_proc_entry_user_name(table_builtin,				\
+		table_memo_return_all_answers_multi, 2, 0)
+
+  MR_declare_entry(MR_MEMO_NON_RET_ALL_NONDET_ENTRY);
+  MR_declare_entry(MR_MEMO_NON_RET_ALL_MULTI_ENTRY);
+#endif	/* MR_HIGHLEVEL_CODE */
 
 /*---------------------------------------------------------------------------*/
 
Index: runtime/mercury_tabling_macros.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_tabling_macros.h,v
retrieving revision 1.10
diff -u -b -r1.10 mercury_tabling_macros.h
--- runtime/mercury_tabling_macros.h	7 Jun 2004 09:07:21 -0000	1.10
+++ runtime/mercury_tabling_macros.h	17 Jul 2004 13:09:02 -0000
@@ -371,6 +371,15 @@
 				(int) (num_slots));			\
 	} while(0)
 
+#define MR_TABLE_CREATE_NODE_ANSWER_BLOCK(block_ptr, num_slots)		\
+	do {								\
+		*block_ptr = MR_TABLE_NEW_ARRAY(MR_Word, (num_slots));	\
+		if (MR_tabledebug)					\
+			printf("allocated node block %p -> %p, %d words\n",\
+				block_ptr, *block_ptr,			\
+				(int) (num_slots));			\
+	} while(0)
+
 #define MR_TABLE_GET_ANSWER(ab, offset)					\
 	(( MR_tabledebug ?						\
 		printf("using answer block: %p, slot %d\n",		\
@@ -396,6 +405,11 @@
 	do {								\
 		(table)->MR_answerblock = MR_TABLE_NEW_ARRAY(MR_Word,	\
 			(num_slots));					\
+	} while(0)
+
+#define MR_TABLE_CREATE_NODE_ANSWER_BLOCK(block_ptr, num_slots)		\
+	do {								\
+		*block_ptr = MR_TABLE_NEW_ARRAY(MR_Word, (num_slots));	\
 	} while(0)
 
 #define MR_TABLE_GET_ANSWER(ab, offset)					\
Index: runtime/mercury_tabling_preds.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_tabling_preds.h,v
retrieving revision 1.2
diff -u -b -r1.2 mercury_tabling_preds.h
--- runtime/mercury_tabling_preds.h	7 Jun 2004 09:07:21 -0000	1.2
+++ runtime/mercury_tabling_preds.h	19 Jul 2004 04:09:01 -0000
@@ -173,11 +173,18 @@
   #define MR_table_loop_mark_as_inactive_msg(T)                         \
     do {                                                                \
         if (MR_tabledebug) {                                            \
-            printf("marking %p as uninitialized\n", T);                 \
+            printf("marking %p as inactive\n", T);                      \
+        }                                                               \
+    } while (0)
+  #define MR_table_loop_mark_as_active_msg(T)                           \
+    do {                                                                \
+        if (MR_tabledebug) {                                            \
+            printf("marking %p as active\n", T);                        \
         }                                                               \
     } while (0)
 #else
   #define MR_table_loop_mark_as_inactive_msg(T)     ((void) 0)
+  #define MR_table_loop_mark_as_active_msg(T)       ((void) 0)
 #endif
 
 #define MR_table_loop_mark_as_inactive(T)                               \
@@ -186,6 +193,18 @@
         T->MR_loop_status = MR_LOOP_INACTIVE;                           \
     } while (0)
 
+#define MR_table_loop_mark_as_inactive_and_fail(T)                      \
+    do {                                                                \
+        MR_table_loop_mark_as_inactive_msg(T);                          \
+        T->MR_loop_status = MR_LOOP_INACTIVE;                           \
+    } while (0)
+
+#define MR_table_loop_mark_as_active_and_fail(T)                        \
+    do {                                                                \
+        MR_table_loop_mark_as_active_msg(T);                            \
+        T->MR_loop_status = MR_LOOP_ACTIVE;                             \
+    } while (0)
+
 /***********************************************************************/
 
 #ifdef  MR_TABLE_DEBUG
@@ -197,8 +216,24 @@
                 (long) T->MR_memo_status);                              \
         }                                                               \
     } while(0)
+  #define MR_table_memo_non_setup_msg(T)                                \
+    do {                                                                \
+        if (MR_tabledebug) {                                            \
+            printf("setting up of memo non table for %p\n", T);         \
+        }                                                               \
+    } while(0)
+  #define MR_table_memo_non_status_msg(R)                               \
+    do {                                                                \
+        if (MR_tabledebug) {                                            \
+            printf("status of memo non table %p -> %p: %s\n",           \
+                R->MR_mn_back_ptr, R,                                   \
+                MR_memo_non_status(R->MR_mn_status));                   \
+        }                                                               \
+    } while(0)
 #else
   #define MR_table_memo_setup_msg(T)            ((void) 0)
+  #define MR_table_memo_non_setup_msg(T)        ((void) 0)
+  #define MR_table_memo_non_status_msg(R)       ((void) 0)
 #endif
 
 #define MR_table_memo_setup(T, Status)                                  \
@@ -221,10 +256,35 @@
 #define MR_table_memo_semi_setup(T, Status)                             \
     MR_table_memo_setup(T, Status)
 
+#define MR_table_memo_non_setup(T, Record, Status)                      \
+    do {                                                                \
+        MR_save_transient_registers();                                  \
+        if (T->MR_memo_non_record == NULL) {                            \
+            MR_table_memo_non_setup_msg(T);                             \
+            Status = MR_MEMO_NON_INACTIVE;                              \
+            Record = MR_TABLE_NEW(MR_MemoNonRecord);                    \
+            Record->MR_mn_back_ptr = T;                                 \
+            Record->MR_mn_status = MR_MEMO_NON_ACTIVE;                  \
+            Record->MR_mn_num_answers = 0;                              \
+            Record->MR_mn_answer_table.MR_integer = 0;                  \
+            Record->MR_mn_answer_list = NULL;                           \
+            Record->MR_mn_answer_list_tail = &Record->MR_mn_answer_list;\
+            T->MR_memo_non_record = Record;                             \
+        } else {                                                        \
+            Record = T->MR_memo_non_record;                             \
+            Status = Record->MR_mn_status;                              \
+        }                                                               \
+        MR_table_memo_non_status_msg(Record);                           \
+        MR_restore_transient_registers();                               \
+        Status = MR_CONVERT_C_ENUM_CONSTANT(Status);                    \
+    } while(0)
+
 #define MR_table_memo_det_setup_shortcut(T0, T, Status)     ((void) 0)
 
 #define MR_table_memo_semi_setup_shortcut(T0, T, Status)    ((void) 0)
 
+#define MR_table_memo_non_setup_shortcut(T0, T, R, Status)  ((void) 0)
+
 /***********************************************************************/
 
 #ifdef  MR_TABLE_DEBUG
@@ -265,6 +325,51 @@
 
 /***********************************************************************/
 
+#ifdef  MR_TABLE_DEBUG
+  #define MR_table_memo_mark_as_complete_msg(R)                         \
+    do {                                                                \
+        if (MR_tabledebug) {                                            \
+            printf("marking %p as complete\n", R);                      \
+        }                                                               \
+    } while (0)
+  #define MR_table_memo_mark_as_incomplete_msg(R)                       \
+    do {                                                                \
+        if (MR_tabledebug) {                                            \
+            printf("marking %p as incomplete\n", R);                    \
+        }                                                               \
+    } while (0)
+  #define MR_table_memo_mark_as_active_msg(R)                           \
+    do {                                                                \
+        if (MR_tabledebug) {                                            \
+            printf("marking %p as active\n", R);                        \
+        }                                                               \
+    } while (0)
+#else
+  #define MR_table_memo_mark_as_complete_msg(R)     ((void) 0)
+  #define MR_table_memo_mark_as_incomplete_msg(R)   ((void) 0)
+  #define MR_table_memo_mark_as_active_msg(R)       ((void) 0)
+#endif
+
+#define MR_table_memo_mark_as_incomplete(R)                             \
+    do {                                                                \
+        MR_table_memo_mark_as_incomplete_msg(R);                        \
+        R->MR_mn_status = MR_MEMO_NON_INCOMPLETE;                       \
+    } while (0)
+
+#define MR_table_memo_mark_as_active_and_fail(R)                        \
+    do {                                                                \
+        MR_table_memo_mark_as_active_msg(R);                            \
+        R->MR_mn_status = MR_MEMO_NON_ACTIVE;                           \
+    } while (0)
+
+#define MR_table_memo_mark_as_complete_and_fail(R)                      \
+    do {                                                                \
+        MR_table_memo_mark_as_complete_msg(R);                          \
+        R->MR_mn_status = MR_MEMO_NON_COMPLETE;                         \
+    } while (0)
+
+/***********************************************************************/
+
 #define MR_table_memo_create_answer_block(T, Size, AnswerBlock)         \
     do {                                                                \
         MR_TABLE_CREATE_ANSWER_BLOCK(T, Size);                          \
@@ -306,6 +411,106 @@
 
 /***********************************************************************/
 
+#ifdef  MR_TABLE_DEBUG
+  #define MR_table_memo_non_get_answer_table_msg(Record)                \
+    do {                                                                \
+        if (MR_tabledebug) {                                            \
+            printf("getting answer table %p -> %p\n",                   \
+                Record,                                                 \
+                &(Record->MR_mn_answer_table));                         \
+        }                                                               \
+    } while(0)
+#else
+  #define MR_table_memo_non_get_answer_table_msg(Record) ((void) 0)
+#endif
+
+#define MR_table_memo_non_get_answer_table(Record, AnswerTable)         \
+    do {                                                                \
+        MR_table_memo_non_get_answer_table_msg(Record);                 \
+        AnswerTable = &(Record->MR_mn_answer_table);                    \
+    } while(0)
+
+/***********************************************************************/
+
+#ifdef  MR_TABLE_DEBUG
+  #define MR_table_memo_non_create_answer_block_msg(Record, answer_node)\
+    do {                                                                \
+        if (MR_tabledebug) {                                            \
+            printf("new answer slot %d at %p(%p)\n",                    \
+                Record->MR_mn_num_answers, answer_node,                 \
+                &answer_node->MR_aln_answer_block);                     \
+            printf("\tstoring into %p\n",                               \
+                Record->MR_mn_answer_list_tail);                        \
+        }                                                               \
+    } while(0)
+#else
+  #define MR_table_memo_non_create_answer_block_msg(Record, answer_node)\
+    ((void) 0)
+#endif
+
+#define MR_table_memo_non_create_answer_block(Record, Size, AnswerBlock)\
+    do {                                                                \
+        MR_AnswerListNode   *answer_node;                               \
+        MR_Word             **Slot;                                     \
+                                                                        \
+        Record->MR_mn_num_answers++;                                    \
+                                                                        \
+        /*                                                              \
+        ** We fill in the answer_data slot with a dummy value.          \
+        ** This slot will be filled in by the next piece of code        \
+        ** to be executed after we return, which is why we return       \
+        ** its address.                                                 \
+        */                                                              \
+                                                                        \
+        answer_node = MR_TABLE_NEW(MR_AnswerListNode);                  \
+        answer_node->MR_aln_answer_block = NULL;                        \
+        answer_node->MR_aln_next_answer = NULL;                         \
+                                                                        \
+        MR_table_memo_non_create_answer_block_msg(Record, answer_node); \
+        *(Record->MR_mn_answer_list_tail) = answer_node;                \
+        Record->MR_mn_answer_list_tail =                                \
+            &(answer_node->MR_aln_next_answer);                         \
+        Slot = &(answer_node->MR_aln_answer_block);                     \
+        MR_TABLE_CREATE_NODE_ANSWER_BLOCK(Slot, Size);                  \
+        AnswerBlock = *Slot;                                            \
+    } while(0)
+
+#define MR_table_memo_non_create_answer_block_shortcut(Record)          \
+    ((void) 0)
+
+/***********************************************************************/
+
+#define MR_table_memo_non_return_all_shortcut(Record)                   \
+    ((void) 0)
+
+/***********************************************************************/
+
+#ifdef  MR_TABLE_DEBUG
+  #define MR_table_memo_non_answer_is_not_duplicate_msg(T)              \
+    do {                                                                \
+        if (MR_tabledebug) {                                            \
+            printf("checking if %p is a duplicate answer: %ld\n",       \
+                T, (long) T->MR_integer);                               \
+        }                                                               \
+    } while(0)
+#else
+  #define MR_table_memo_non_answer_is_not_duplicate_msg(T)    ((void) 0)
+#endif
+
+#define MR_table_memo_non_answer_is_not_duplicate(T, succ)              \
+    do {                                                                \
+        MR_bool     is_new_answer;                                      \
+        MR_table_memo_non_answer_is_not_duplicate_msg(T);               \
+        is_new_answer = (T->MR_integer == 0);                           \
+        T->MR_integer = 1;  /* any nonzero value will do */             \
+        succ = is_new_answer;                                           \
+    } while(0)
+
+#define MR_table_memo_non_answer_is_not_duplicate_shortcut(R, succ)     \
+    ((void) 0)
+
+/***********************************************************************/
+
 #ifdef  MR_DEBUG_RETRY
   #define MR_table_io_in_range_check_msg                                \
     if (MR_io_tabling_debug) {                                          \
@@ -397,7 +602,7 @@
 
 /***********************************************************************/
 
-#ifdef  MR_USE_MINIMAL_MODEL
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
 
 /***********************************************************************/
 
@@ -484,16 +689,6 @@
 
 /***********************************************************************/
 
-#ifdef  MR_MINIMAL_MODEL_DEBUG
-  #define MR_table_mm_create_answer_block_set(Subgoal, answer_node)     \
-    do {                                                                \
-        answer_node->MR_aln_answer_num = Subgoal->MR_sg_num_ans;        \
-    } while(0)
-#else
-  #define MR_table_mm_create_answer_block_set(Subgoal, answer_node)     \
-    ((void) 0)
-#endif
-
 #ifdef  MR_TABLE_DEBUG
   #define MR_table_mm_create_answer_block_msg(Subgoal, answer_node)     \
     do {                                                                \
@@ -501,7 +696,7 @@
             printf("%s: new answer slot %d at %p(%p)\n",                \
                 MR_subgoal_addr_name(Subgoal),                          \
                 Subgoal->MR_sg_num_ans, answer_node,                    \
-                &answer_node->MR_aln_answer_data);                      \
+                &answer_node->MR_aln_answer_block);                     \
             printf("\tstoring into %p\n",                               \
                 Subgoal->MR_sg_answer_list_tail);                       \
         }                                                               \
@@ -514,7 +709,7 @@
 #define MR_table_mm_create_answer_block(Subgoal, Size, AnswerBlock)     \
     do {                                                                \
         MR_AnswerListNode   *answer_node;                               \
-        MR_TrieNode         Slot;                                       \
+        MR_Word             **Slot;                                     \
                                                                         \
         Subgoal->MR_sg_num_ans++;                                       \
                                                                         \
@@ -526,17 +721,16 @@
         */                                                              \
                                                                         \
         answer_node = MR_TABLE_NEW(MR_AnswerListNode);                  \
-        answer_node->MR_aln_answer_data.MR_integer = 0;                 \
+        answer_node->MR_aln_answer_block = NULL;                        \
         answer_node->MR_aln_next_answer = NULL;                         \
                                                                         \
-        MR_table_mm_create_answer_block_set(Subgoal, answer_node);      \
         MR_table_mm_create_answer_block_msg(Subgoal, answer_node);      \
         *(Subgoal->MR_sg_answer_list_tail) = answer_node;               \
         Subgoal->MR_sg_answer_list_tail =                               \
             &(answer_node->MR_aln_next_answer);                         \
-        Slot = &(answer_node->MR_aln_answer_data);                      \
-        MR_TABLE_CREATE_ANSWER_BLOCK(Slot, Size);                       \
-        AnswerBlock = Slot->MR_answerblock;                             \
+        Slot = &(answer_node->MR_aln_answer_block);                     \
+        MR_TABLE_CREATE_NODE_ANSWER_BLOCK(Slot, Size);                  \
+        AnswerBlock = *Slot;                                            \
     } while(0)
 
 /***********************************************************************/
@@ -545,33 +739,108 @@
 
 /***********************************************************************/
 
-#else   /* MR_USE_MINIMAL_MODEL */
+#else   /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+#define MR_MMSC_ERROR  \
+        "stack copy minimal model code entered when not enabled"
 
 #define MR_table_mm_setup(T, Subgoal, Status)                           \
     do {                                                                \
-        MR_fatal_error("minimal model code entered when not enabled");  \
+        MR_fatal_error(MR_MMSC_ERROR);                                  \
     } while(0)
 #define MR_table_mm_setup_shortcut(Subgoal, Status)                     \
     do {                                                                \
-        MR_fatal_error("minimal model code entered when not enabled");  \
+        MR_fatal_error(MR_MMSC_ERROR);                                  \
     } while(0)
 #define MR_table_mm_return_all_shortcut(AnswerBlock)                    \
     do {                                                                \
-        MR_fatal_error("minimal model code entered when not enabled");  \
+        MR_fatal_error(MR_MMSC_ERROR);                                  \
     } while(0)
 #define MR_table_mm_get_answer_table(Subgoal, AnswerTable)              \
     do {                                                                \
-        MR_fatal_error("minimal model code entered when not enabled");  \
+        MR_fatal_error(MR_MMSC_ERROR);                                  \
     } while(0)
 #define MR_table_mm_create_answer_block(Subgoal, Size, AnswerBlock)     \
     do {                                                                \
-        MR_fatal_error("minimal model code entered when not enabled");  \
+        MR_fatal_error(MR_MMSC_ERROR);                                  \
     } while(0)
 #define MR_table_mm_fill_answer_block_shortcut(Subgoal)                 \
     do {                                                                \
-        MR_fatal_error("minimal model code entered when not enabled");  \
+        MR_fatal_error(MR_MMSC_ERROR);                                  \
+    } while(0)
+
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
+
+/***********************************************************************/
+
+#ifdef  MR_USE_MINIMAL_MODEL_OWN_STACKS
+
+#define MR_MMOS_ERROR  \
+        "own stack minimal model code entered when not enabled"
+
+#define MR_table_mmos_save_inputs_shortcut(num_inputs)                  \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_setup_consumer(t, num_inputs, gen_pred, name, consumer) \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_consume_next_answer_nondet(consumer, answerblock, succ) \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_get_answer_table(generator, trienode)             \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_create_answer_block(generator, blocksize, answerblock) \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_return_answer(generator, answerblock)             \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_completion(generator)                             \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+
+#else   /* MR_USE_MINIMAL_MODEL_OWN_STACKS */
+
+#define MR_MMOS_ERROR  \
+        "own stack minimal model code entered when not enabled"
+
+#define MR_table_mmos_save_inputs_shortcut(num_inputs)                  \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_setup_consumer(t, num_inputs, gen_pred, name, consumer) \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_consume_next_answer_nondet(consumer, answerblock, succ) \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_get_answer_table(generator, trienode)             \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_create_answer_block(generator, blocksize, answerblock) \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_return_answer(generator, answerblock)             \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
+    } while(0)
+#define MR_table_mmos_completion(generator)                             \
+    do {                                                                \
+        MR_fatal_error(MR_MMOS_ERROR);                                  \
     } while(0)
 
-#endif  /* MR_USE_MINIMAL_MODEL */
+#endif  /* MR_USE_MINIMAL_MODEL_OWN_STACKS */
 
 /***********************************************************************/
Index: runtime/mercury_types.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_types.h,v
retrieving revision 1.38
diff -u -b -r1.38 mercury_types.h
--- runtime/mercury_types.h	7 Jul 2004 07:11:19 -0000	1.38
+++ runtime/mercury_types.h	15 Jul 2004 13:59:56 -0000
@@ -231,11 +231,14 @@
 typedef MR_TrieNode                             *MR_TrieNodePtr;
 
 typedef struct MR_HashTable_Struct              MR_HashTable;
+typedef struct MR_MemoNonRecord_Struct          MR_MemoNonRecord;
+typedef struct MR_MemoNonRecord_Struct          *MR_MemoNonRecordPtr;
+typedef struct MR_AnswerListNode_Struct         MR_AnswerListNode;
 typedef struct MR_Subgoal_Struct                MR_Subgoal;
 typedef struct MR_SubgoalListNode_Struct        MR_SubgoalListNode;
-typedef struct MR_AnswerListNode_Struct         MR_AnswerListNode;
 typedef struct MR_Consumer_Struct               MR_Consumer;
 typedef struct MR_ConsumerListNode_Struct       MR_ConsumerListNode;
+typedef struct MR_Generator_Struct              MR_Generator;
 
 typedef MR_SubgoalListNode                      *MR_SubgoalList;
 typedef MR_AnswerListNode                       *MR_AnswerList;
@@ -250,5 +253,12 @@
 
 typedef struct MR_ConsumerDebug_Struct          MR_ConsumerDebug;
 typedef struct MR_SubgoalDebug_Struct           MR_SubgoalDebug;
+typedef struct MR_ConsDebug_Struct              MR_ConsDebug;
+typedef struct MR_GenDebug_Struct               MR_GenDebug;
+
+typedef	MR_Word		                            *MR_AnswerBlock;
+typedef	MR_Subgoal	                            *MR_SubgoalPtr;
+typedef	MR_Consumer	                            *MR_ConsumerPtr;
+typedef	MR_Generator	                        *MR_GeneratorPtr;
 
 #endif /* not MERCURY_TYPES_H */
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.134
diff -u -b -r1.134 mercury_wrapper.c
--- runtime/mercury_wrapper.c	7 Jul 2004 07:11:19 -0000	1.134
+++ runtime/mercury_wrapper.c	19 Jul 2004 02:43:58 -0000
@@ -88,6 +88,8 @@
 size_t		MR_genstack_size =		  32;
 size_t		MR_cutstack_size =		  32;
 size_t		MR_pnegstack_size =		  32;
+size_t		MR_gen_detstack_size =		  64;
+size_t		MR_gen_nonstack_size =		  64;
 
 /*
 ** size of the redzones at the end of data areas, in kilobytes
@@ -121,6 +123,8 @@
 size_t		MR_genstack_zone_size =		  16;
 size_t		MR_cutstack_zone_size =		  16;
 size_t		MR_pnegstack_zone_size =	  16;
+size_t		MR_gen_detstack_zone_size =	  16;
+size_t		MR_gen_nonstack_zone_size =	  16;
 
 /*
 ** MR_heap_margin_size is used for accurate GC with the MLDS->C back-end.
@@ -848,7 +852,7 @@
 static void
 process_environment_options(void)
 {
-	char*	env_options;
+	char 	*env_options;
 
 	env_options = getenv("MERCURY_OPTIONS");
 	if (env_options == NULL) {
@@ -911,6 +915,10 @@
 	MR_TRAIL_REDZONE_SIZE,
 	MR_HEAP_MARGIN_SIZE,
 	MR_HEAP_EXPANSION_FACTOR,
+	MR_GEN_DETSTACK_SIZE,
+	MR_GEN_NONSTACK_SIZE,
+	MR_GEN_DETSTACK_REDZONE_SIZE,
+	MR_GEN_NONSTACK_REDZONE_SIZE,
 	MR_MDB_TTY,
 	MR_MDB_IN,
 	MR_MDB_OUT,
@@ -936,6 +944,10 @@
 	{ "trail-redzone-size", 	1, 0, MR_TRAIL_REDZONE_SIZE },
 	{ "heap-margin-size", 		1, 0, MR_HEAP_MARGIN_SIZE },
 	{ "heap-expansion-factor", 	1, 0, MR_HEAP_EXPANSION_FACTOR },
+	{ "gen-detstack-size", 		1, 0, MR_GEN_DETSTACK_SIZE },
+	{ "gen-nonstack-size", 		1, 0, MR_GEN_NONSTACK_SIZE },
+	{ "gen-detstack-zone-size", 	1, 0, MR_GEN_DETSTACK_REDZONE_SIZE },
+	{ "gen-nonstack-zone-size", 	1, 0, MR_GEN_NONSTACK_REDZONE_SIZE },
 	{ "mdb-tty", 			1, 0, MR_MDB_TTY },
 	{ "mdb-in", 			1, 0, MR_MDB_IN },
 	{ "mdb-out", 			1, 0, MR_MDB_OUT },
@@ -1044,6 +1056,34 @@
 			{
 				usage();
 			}
+			break;
+
+		case MR_GEN_DETSTACK_SIZE:
+			if (sscanf(MR_optarg, "%lu", &size) != 1)
+				usage();
+
+			MR_gen_detstack_size = size;
+			break;
+
+		case MR_GEN_NONSTACK_SIZE:
+			if (sscanf(MR_optarg, "%lu", &size) != 1)
+				usage();
+
+			MR_gen_nonstack_size = size;
+			break;
+
+		case MR_GEN_DETSTACK_REDZONE_SIZE:
+			if (sscanf(MR_optarg, "%lu", &size) != 1)
+				usage();
+
+			MR_gen_detstack_zone_size = size;
+			break;
+
+		case MR_GEN_NONSTACK_REDZONE_SIZE:
+			if (sscanf(MR_optarg, "%lu", &size) != 1)
+				usage();
+
+			MR_gen_nonstack_zone_size = size;
 			break;
 
 		case 'i':
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.62
diff -u -b -r1.62 mercury_wrapper.h
--- runtime/mercury_wrapper.h	22 Oct 2003 05:56:08 -0000	1.62
+++ runtime/mercury_wrapper.h	9 Apr 2004 18:37:09 -0000
@@ -197,6 +197,8 @@
 extern	size_t		MR_genstack_size;
 extern	size_t		MR_cutstack_size;
 extern	size_t		MR_pnegstack_size;
+extern	size_t		MR_gen_detstack_size;
+extern	size_t		MR_gen_nonstack_size;
 
 /* sizes of the red zones */
 extern	size_t		MR_heap_zone_size;
@@ -209,6 +211,8 @@
 extern	size_t		MR_genstack_zone_size;
 extern	size_t		MR_cutstack_zone_size;
 extern	size_t		MR_pnegstack_zone_size;
+extern	size_t		MR_gen_detstack_zone_size;
+extern	size_t		MR_gen_nonstack_zone_size;
 
 /* heap margin for MLDS->C accurate GC (documented in mercury_wrapper.c) */
 extern	size_t		MR_heap_margin_size;
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
Index: scripts/canonical_grade.sh-subr
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/canonical_grade.sh-subr,v
retrieving revision 1.10
diff -u -b -r1.10 canonical_grade.sh-subr
--- scripts/canonical_grade.sh-subr	31 May 2004 04:13:11 -0000	1.10
+++ scripts/canonical_grade.sh-subr	29 Jun 2004 14:00:10 -0000
@@ -115,9 +115,11 @@
 	false)		;;
 esac
 
-case $use_minimal_model,$minimal_model_debug in
-	true,false)	GRADE="$GRADE.mm" ;;
-	true,true)	GRADE="$GRADE.dmm" ;;
+case $use_minimal_model_stack_copy,$use_minimal_model_own_stack,$minimal_model_debug in
+	true,false,false)	GRADE="$GRADE.mmsc" ;;
+	true,false,true)	GRADE="$GRADE.dmmsc" ;;
+	false,true,false)	GRADE="$GRADE.mmos" ;;
+	false,true,true)	GRADE="$GRADE.dmmos" ;;
 	*)	;;
 esac
 
Index: scripts/final_grade_options.sh-subr
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/final_grade_options.sh-subr,v
retrieving revision 1.12
diff -u -b -r1.12 final_grade_options.sh-subr
--- scripts/final_grade_options.sh-subr	31 May 2004 04:13:11 -0000	1.12
+++ scripts/final_grade_options.sh-subr	24 Jun 2004 07:50:51 -0000
@@ -19,8 +19,20 @@
 #
 #---------------------------------------------------------------------------#
 
+use_minimal_model=false
+case $use_minimal_model_stack_copy in
+	true)
+		use_minimal_model=true
+		;;
+esac
+case $use_minimal_model_own_stacks in
+	true)
+		use_minimal_model=true
+		;;
+esac
+
 #
-# .tr grade is not compatible with .mm
+# .tr grade is not compatible with .*mm*
 #	(see comment in runtime/mercury_tabling.c for rationale)
 #
 case $use_trail,$use_minimal_model in true,true)
@@ -29,7 +41,7 @@
 esac
 
 #
-# .debug grade implies --use-trail in the absence of .mm
+# .debug grade implies --use-trail in the absence of .*mm*
 #	(see comment in compiler/handle_options.m for rationale)
 #
 case $debug,$use_minimal_model in true,false)
Index: scripts/init_grade_options.sh-subr
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/init_grade_options.sh-subr,v
retrieving revision 1.23
diff -u -b -r1.23 init_grade_options.sh-subr
--- scripts/init_grade_options.sh-subr	31 May 2004 04:13:12 -0000	1.23
+++ scripts/init_grade_options.sh-subr	24 Jun 2004 07:51:09 -0000
@@ -40,7 +40,8 @@
 	--record-term-sizes-as-cells
 	--use-trail
 	--reserve-tag
-	--use-minimal-model
+	--use-minimal-model-stack-copy
+	--use-minimal-model-own-stacks
 	--minimal-model-debug
 	--pic-reg
 	--no-stack-trace
@@ -71,7 +72,8 @@
 record_term_sizes_as_cells=false
 use_trail=false
 reserve_tag=false
-use_minimal_model=false
+use_minimal_model_stack_copy=false
+use_minimal_model_own_stacks=false
 minimal_model_debug=false
 pic_reg=false
 debug=false
Index: scripts/mgnuc.in
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/mgnuc.in,v
retrieving revision 1.104
diff -u -b -r1.104 mgnuc.in
--- scripts/mgnuc.in	7 Jul 2004 07:11:21 -0000	1.104
+++ scripts/mgnuc.in	7 Jul 2004 07:17:09 -0000
@@ -404,9 +404,20 @@
 	false)          RESERVE_TAG_OPTS="" ;;
 esac
 
+case $use_minimal_model_stack_copy,$use_minimal_model_own_stacks in
+	true,true)	progname=`basename $0`
+			echo "$progname: can't enable both forms of minimal model tabling at once"
+			exit 1 ;;
+	true,false)	MINIMAL_MODEL_OPTS="-DMR_USE_MINIMAL_MODEL_STACK_COPY"
+			;;
+	false,true)	MINIMAL_MODEL_OPTS="-DMR_USE_MINIMAL_MODEL_OWN_STACKS"
+			;;
+	false,false)	MINIMAL_MODEL_OPTS="" ;;
+esac
+
 case $use_minimal_model,$minimal_model_debug in
-	true,false)	MINIMAL_MODEL_OPTS="-DMR_USE_MINIMAL_MODEL" ;;
-	true,true)	MINIMAL_MODEL_OPTS="-DMR_USE_MINIMAL_MODEL -DMR_MINIMAL_MODEL_DEBUG" ;;
+	true,false)	;; # MINIMAL_MODEL_OPTS is already set
+	true,true)	MINIMAL_MODEL_OPTS="$MINIMAL_MODEL_OPTS -DMR_MINIMAL_MODEL_DEBUG" ;;
 	*)		MINIMAL_MODEL_OPTS="" ;;
 esac
 
Index: scripts/parse_grade_options.sh-subr
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/parse_grade_options.sh-subr,v
retrieving revision 1.29
diff -u -b -r1.29 parse_grade_options.sh-subr
--- scripts/parse_grade_options.sh-subr	31 May 2004 04:13:12 -0000	1.29
+++ scripts/parse_grade_options.sh-subr	29 Jun 2004 14:00:14 -0000
@@ -148,10 +148,15 @@
 	--no-reserve-tag)
 		reserve_tag=false ;;
 
-	--use-minimal-model)
-		use_minimal_model=true ;;
-	--no-use-minimal-model)
-		use_minimal_model=false ;;
+	--use-minimal-model-stack-copy)
+		use_minimal_model_stack_copy=true ;;
+	--no-use-minimal-model-stack-copy)
+		use_minimal_model_stack_copy=false ;;
+
+	--use-minimal-model-own-stacks)
+		use_minimal_model_own_stacks=true ;;
+	--no-use-minimal-model-own-stacks)
+		use_minimal_model_own_stacks=false ;;
 
 	--minimal-model-debug)
 		minimal_model_debug=true ;;
@@ -200,7 +205,8 @@
 		record_term_sizes_as_cells=false
 		use_trail=false
 		reserve_tag=false
-		use_minimal_model=false
+		use_minimal_model_stack_copy=false
+		use_minimal_model_own_stacks=false
 		minimal_model_debug=false
 		pic_reg=false
 		debug=false
@@ -397,12 +403,32 @@
 					;;
 
 				mm)
-					use_minimal_model=true
+					use_minimal_model_stack_copy=true
 					minimal_model_debug=false
 					;;
 
 				dmm)
-					use_minimal_model=true
+					use_minimal_model_stack_copy=true
+					minimal_model_debug=true
+					;;
+
+				mmsc)
+					use_minimal_model_stack_copy=true
+					minimal_model_debug=false
+					;;
+
+				dmmsc)
+					use_minimal_model_stack_copy=true
+					minimal_model_debug=true
+					;;
+
+				mmos)
+					use_minimal_model_own_stacks=true
+					minimal_model_debug=false
+					;;
+
+				dmmos)
+					use_minimal_model_own_stacks=true
 					minimal_model_debug=true
 					;;
 
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
Index: tests/debugger/print_table.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/print_table.exp,v
retrieving revision 1.6
diff -u -b -r1.6 print_table.exp
--- tests/debugger/print_table.exp	7 Jun 2004 09:07:21 -0000	1.6
+++ tests/debugger/print_table.exp	18 Jul 2004 03:21:50 -0000
@@ -348,6 +348,39 @@
 call table does not contain xyz in argument position 3.
 mdb> delete 1
  1: E stop  interface pred print_table.s/6-0 (det)
+mdb> b t
+ 1: + stop  interface pred print_table.t/3-0 (nondet)
+mdb> c
+     E29:    C15  2 CALL pred print_table.t/3-0 (nondet)
+mdb> table t
+memo table for pred print_table.t/3-0 (nondet):
+end of table (0 entries)
+mdb> s
+     E30:    C15  2 DISJ pred print_table.t/3-0 (nondet)
+mdb> table t
+memo table for pred print_table.t/3-0 (nondet):
+<1, 2>: active
+end of table (1 entry)
+mdb> finish
+     E31:    C15  2 EXIT pred print_table.t/3-0 (nondet)
+mdb> table t
+memo table for pred print_table.t/3-0 (nondet):
+<1, 2>: incomplete
+answer #1: <120>
+end of table (1 entry)
+mdb> delete 1
+ 1: E stop  interface pred print_table.t/3-0 (nondet)
+mdb> b tdone
+ 1: + stop  interface pred print_table.tdone/0-0 (det)
+mdb> c
+     E32:    C16  2 CALL pred print_table.tdone/0-0 (det)
+mdb> table t
+memo table for pred print_table.t/3-0 (nondet):
+<1, 2>: complete
+answer #1: <120>
+answer #2: <210>
+<2, 2>: complete
+end of table (2 entries)
 mdb> c -S -n
 75
 24
@@ -361,3 +394,5 @@
 [3.5xyz2][3.5xyz2][3.5xyz2] 6.50000000000000
 [3.5xyz2][3.5xyz2][3.5xyz2][3.5xyz2] 7.50000000000000
 [9.2def2][9.2def2][9.2def2][9.2def2][9.2def2] 14.2000000000000
+[120, 210]
+[]
Index: tests/debugger/print_table.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/print_table.inp,v
retrieving revision 1.2
diff -u -b -r1.2 print_table.inp
--- tests/debugger/print_table.inp	7 Jun 2004 09:07:21 -0000	1.2
+++ tests/debugger/print_table.inp	18 Jul 2004 03:20:09 -0000
@@ -92,4 +92,15 @@
 table s 9.2 2 def
 table s 9.2 2 xyz
 delete 1
+b t
+c
+table t
+s
+table t
+finish
+table t
+delete 1
+b tdone
+c
+table t
 c -S -n
Index: tests/debugger/print_table.m
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/print_table.m,v
retrieving revision 1.2
diff -u -b -r1.2 print_table.m
--- tests/debugger/print_table.m	4 May 2004 08:07:23 -0000	1.2
+++ tests/debugger/print_table.m	18 Jul 2004 03:20:51 -0000
@@ -31,6 +31,9 @@
 	{ s(3.5, 2, "xyz", 3, SC, TC) },
 	{ s(3.5, 2, "xyz", 4, SD, TD) },
 	{ s(9.2, 2, "def", 5, SE, TE) },
+	{ solutions(t(1, 2), T12) },
+	{ solutions(t(2, 2), T22) },
+	{ tdone },
 	io__write_int(P55),
 	io__nl,
 	io__write_int(P43),
@@ -64,6 +67,10 @@
 	io__write_string(SE),
 	io__write_string(" "),
 	io__write_float(TE),
+	io__nl,
+	io__write(T12),
+	io__nl,
+	io__write(T22),
 	io__nl.
 
 :- pred p(int::in, int::in, int::out) is det.
@@ -112,3 +119,21 @@
 	S = from_char_list(list__condense(
 		list__duplicate(D, to_char_list(S0)))),
 	T = A + float(D).
+
+:- pred t(int::in, int::in, int::out) is nondet.
+:- pragma memo(t/3).
+
+t(A, B, C) :-
+	( A = 1 ->
+		(
+			C = (A * 100) + (B * 10)
+		;
+			C = (B * 100) + (A * 10)
+		)
+	;
+		fail
+	).
+
+:- pred tdone is det.
+
+tdone.
Index: tests/debugger/retry.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/retry.exp,v
retrieving revision 1.8
diff -u -b -r1.8 retry.exp
--- tests/debugger/retry.exp	7 Jun 2004 09:07:22 -0000	1.8
+++ tests/debugger/retry.exp	18 Jul 2004 05:32:32 -0000
@@ -126,5 +126,32 @@
      E17:    C10  2 CALL pred retry.fib/2-0 (det)
 mdb> finish -n
      E23:    C10  2 EXIT pred retry.fib/2-0 (det)
-mdb> continue -n -S
+mdb> delete *
+ 0: E stop  interface pred retry.fib/2-0 (det)
+mdb> break t
+ 0: + stop  interface pred retry.t/3-0 (nondet)
+mdb> continue
 987
+     E24:    C14  2 CALL pred retry.t/3-0 (nondet)
+mdb> table t 1 2
+call table does not contain 1 in argument position 1.
+mdb> finish
+marker executed: t 1 2
+     E25:    C14  2 EXIT pred retry.t/3-0 (nondet)
+mdb> table t 1 2
+<1, 2>: incomplete
+answer #1: <120>
+mdb> retry
+     E24:    C14  2 CALL pred retry.t/3-0 (nondet)
+mdb> table t 1 2
+<1, 2>: inactive
+mdb> finish
+marker executed: t 1 2
+     E25:    C14  2 EXIT pred retry.t/3-0 (nondet)
+mdb> table t 1 2
+<1, 2>: incomplete
+answer #1: <120>
+mdb> delete *
+ 0: E stop  interface pred retry.t/3-0 (nondet)
+mdb> continue -n -S
+120 210 
Index: tests/debugger/retry.inp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/retry.inp,v
retrieving revision 1.3
diff -u -b -r1.3 retry.inp
--- tests/debugger/retry.inp	7 Jun 2004 09:07:22 -0000	1.3
+++ tests/debugger/retry.inp	18 Jul 2004 03:27:59 -0000
@@ -49,4 +49,15 @@
 next
 retry 1
 finish -n
+delete *
+break t
+continue
+table t 1 2
+finish
+table t 1 2
+retry
+table t 1 2
+finish
+table t 1 2
+delete *
 continue -n -S
Index: tests/debugger/retry.m
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/debugger/retry.m,v
retrieving revision 1.3
diff -u -b -r1.3 retry.m
--- tests/debugger/retry.m	26 May 2003 09:00:52 -0000	1.3
+++ tests/debugger/retry.m	18 Jul 2004 05:31:29 -0000
@@ -36,7 +36,9 @@
 	outputs(Ds),
 	outputs(Es),
 	{ fib(15, F) },
-	output(F).
+	output(F),
+	{ solutions(t(1, 2), T12) },
+	outputs(T12).
 
 %---------------------------------------------------------------------------%
 
@@ -119,6 +121,31 @@
 		fib(N - 2, F2),
 		F = F1 + F2
 	).
+
+:- pred t(int::in, int::in, int::out) is nondet.
+:- pragma memo(t/3).
+
+t(A, B, C) :-
+	marker("t", A, B, Zero),
+	( A = 1 ->
+		(
+			C = Zero + (A * 100) + (B * 10)
+		;
+			C = Zero + (B * 100) + (A * 10)
+		)
+	;
+		fail
+	).
+
+:- pred marker(string::in, int::in, int::in, int::out) is det.
+
+:- pragma foreign_proc("C",
+	marker(S::in, A::in, B::in, X::out),
+	[will_not_call_mercury, promise_pure],
+"
+	printf(""marker executed: %s %d %d\\n"", S, A, B);
+	X = 0;
+").
 
 %---------------------------------------------------------------------------%
 
cvs diff: Diffing tests/debugger/declarative
cvs diff: Diffing tests/dppd
cvs diff: Diffing tests/general
cvs diff: Diffing tests/general/accumulator
cvs diff: Diffing tests/general/string_format
cvs diff: Diffing tests/general/structure_reuse
cvs diff: Diffing tests/grade_subdirs
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/exceptions
cvs diff: Diffing tests/hard_coded/purity
cvs diff: Diffing tests/hard_coded/sub-modules
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/invalid/purity
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/mmc_make
cvs diff: Diffing tests/mmc_make/lib
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
Index: tests/tabling/Mmakefile
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/Mmakefile,v
retrieving revision 1.33
diff -u -b -r1.33 Mmakefile
--- tests/tabling/Mmakefile	21 Jun 2004 03:45:52 -0000	1.33
+++ tests/tabling/Mmakefile	18 Jul 2004 11:30:56 -0000
@@ -15,14 +15,20 @@
 	fib_list \
 	fib_string \
 	loopcheck_no_loop \
+	loopcheck_nondet_no_loop \
+	memo_non \
 	oota \
 	table_foreign_output \
 	unused_args
 
 SIMPLE_LOOP_PROGS = \
-	loopcheck
+	loopcheck \
+	loopcheck_nondet \
+	tc_loop \
+	tc_memo \
+	tc_memo2
 
-NONDET_NONLOOP_PROGS = \
+MINIMAL_NONLOOP_PROGS = \
 	combine \
 	completed_consumer_in_solutions \
 	consumer_in_commit \
@@ -47,15 +53,14 @@
 	tc_minimal \
 	tc_minimal2
 
-NONDET_LOOP_PROGS =
+MINIMAL_LOOP_PROGS =
 
 # The following programs do not work:
 #	semidet_minimal.m
 #	tc_minimal_semidet.m
-#	tc_loop
 
 ALL_SIMPLE_PROGS = $(SIMPLE_NONLOOP_PROGS) $(SIMPLE_LOOP_PROGS)
-ALL_NONDET_PROGS = $(NONDET_NONLOOP_PROGS) $(NONDET_LOOP_PROGS)
+ALL_MINIMAL_PROGS = $(MINIMAL_NONLOOP_PROGS)
 
 # Tabling does not yet work in .rt grades
 ifneq "$(findstring .gc,$(GRADE))" ""
@@ -64,9 +69,9 @@
 		NONLOOP_PROGS=
 	else
 		ifneq "$(findstring mm,$(GRADE))" ""
-			PROGS=$(ALL_SIMPLE_PROGS) $(ALL_NONDET_PROGS)
+			PROGS=$(ALL_SIMPLE_PROGS) $(ALL_MINIMAL_PROGS)
 			NONLOOP_PROGS=$(SIMPLE_NONLOOP_PROGS) \
-				$(NONDET_NONLOOP_PROGS)
+				$(MINIMAL_NONLOOP_PROGS)
 		else
 			PROGS=$(ALL_SIMPLE_PROGS)
 			NONLOOP_PROGS=$(SIMPLE_NONLOOP_PROGS)
@@ -106,6 +111,30 @@
 		rm -f $@.tmp; \
 	fi
 
+tc_memo.out: tc_memo
+	if ./$< > $@.tmp 2>&1; then \
+		grep . $@.tmp; \
+		exit 1; \
+	else \
+		sed	-e 's/exception.m:[0-9]*/exception.m:NNNN/g' \
+			-e 's/require.m:[0-9]*/require.m:NNNN/g' \
+			-e 's/std_util.m:[0-9]*/std_util.m:NNNN/g' \
+			< $@.tmp > $@; \
+		rm -f $@.tmp; \
+	fi
+
+tc_memo2.out: tc_memo2
+	if ./$< > $@.tmp 2>&1; then \
+		grep . $@.tmp; \
+		exit 1; \
+	else \
+		sed	-e 's/exception.m:[0-9]*/exception.m:NNNN/g' \
+			-e 's/require.m:[0-9]*/require.m:NNNN/g' \
+			-e 's/std_util.m:[0-9]*/std_util.m:NNNN/g' \
+			< $@.tmp > $@; \
+		rm -f $@.tmp; \
+	fi
+
 loopcheck.out: loopcheck
 	if ./$< > $@.tmp 2>&1; then \
 		grep . $@.tmp; \
@@ -117,6 +146,17 @@
 		rm -f $@.tmp; \
 	fi
 
+loopcheck_nondet.out: loopcheck_nondet
+	if ./$< > $@.tmp 2>&1; then \
+		grep . $@.tmp; \
+		exit 1; \
+	else \
+		sed	-e 's/exception.m:[0-9]*/exception.m:NNNN/g' \
+			-e 's/require.m:[0-9]*/require.m:NNNN/g' \
+			< $@.tmp > $@; \
+		rm -f $@.tmp; \
+	fi
+
 consumer_in_solutions.out: consumer_in_solutions
 	if ./$< > $@.tmp 2>&1; then \
 		grep . $@.tmp; \
@@ -133,9 +173,9 @@
 echo_nonloop_progs:
 	@echo $(NONLOOP_PROGS)
 
-.PHONY: echo_nondet_nonloop_progs
-echo_nondet_nonloop_progs:
-	@echo $(NONDET_NONLOOP_PROGS)
+.PHONY: echo_minimal_nonloop_progs
+echo_minimal_nonloop_progs:
+	@echo $(MINIMAL_NONLOOP_PROGS)
 
 .PHONY: echo_simple_nonloop_progs
 echo_simple_nonloop_progs:
Index: tests/tabling/loopcheck.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/loopcheck.exp,v
retrieving revision 1.3
diff -u -b -r1.3 loopcheck.exp
--- tests/tabling/loopcheck.exp	17 Jan 2003 05:57:15 -0000	1.3
+++ tests/tabling/loopcheck.exp	19 Jul 2004 02:57:51 -0000
@@ -1,3 +1,2 @@
 Uncaught Mercury exception:
 Software Error: detected infinite recursion in pred loopcheck.loop/1
-Stack dump not available in this grade.
Index: tests/tabling/loopcheck_nondet.exp
===================================================================
RCS file: tests/tabling/loopcheck_nondet.exp
diff -N tests/tabling/loopcheck_nondet.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/loopcheck_nondet.exp	19 Jul 2004 02:57:31 -0000
@@ -0,0 +1,2 @@
+Uncaught Mercury exception:
+Software Error: detected infinite recursion in pred loopcheck_nondet.loop/2
Index: tests/tabling/loopcheck_nondet.m
===================================================================
RCS file: tests/tabling/loopcheck_nondet.m
diff -N tests/tabling/loopcheck_nondet.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/loopcheck_nondet.m	15 Jul 2004 12:47:20 -0000
@@ -0,0 +1,33 @@
+:- module loopcheck_nondet.
+
+:- interface.
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int, std_util.
+
+main(!IO) :-
+	solutions(loop(2), Y),
+	io__write(Y, !IO),
+	io__write_string("\n", !IO).
+
+:- pragma loop_check(loop/2).
+:- pred loop(int::in, int::out) is nondet.
+
+loop(X, Y) :-
+	( X < 0 ->
+		fail
+	; X > 100 ->
+		fail
+	;
+		(
+			Y = X
+		;
+			loop(X - 2, Y)
+		;
+			loop(X * 2, Y)
+		)
+	).
Index: tests/tabling/loopcheck_nondet_no_loop.exp
===================================================================
RCS file: tests/tabling/loopcheck_nondet_no_loop.exp
diff -N tests/tabling/loopcheck_nondet_no_loop.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/loopcheck_nondet_no_loop.exp	18 Jul 2004 09:02:37 -0000
@@ -0,0 +1,2 @@
+[1, 2, 3, 5, 6, 10, 11]
+[1, 2, 3, 5, 6, 10, 11, 20, 21]
Index: tests/tabling/loopcheck_nondet_no_loop.m
===================================================================
RCS file: tests/tabling/loopcheck_nondet_no_loop.m
diff -N tests/tabling/loopcheck_nondet_no_loop.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/loopcheck_nondet_no_loop.m	15 Jul 2004 13:04:40 -0000
@@ -0,0 +1,54 @@
+% Check that loopcheck isn't overzealous.
+
+:- module loopcheck_nondet_no_loop.
+
+:- interface.
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module int, std_util.
+
+main(!IO) :-
+	solutions(non(10), N),
+	io__write(N, !IO),
+	io__write_string("\n", !IO),
+	solutions(mul(20), M),
+	io__write(M, !IO),
+	io__write_string("\n", !IO).
+
+:- pred non(int::in, int::out) is nondet.
+:- pragma loop_check(non/2).
+
+non(A, B) :-
+	( A < 0 ->
+		fail
+	;
+		(
+			B = A
+		;
+			B = A + 1
+		;
+			A > 1,
+			non(A / 2, B)
+		)
+	).
+
+:- pred mul(int::in, int::out) is nondet.
+:- pragma loop_check(mul/2).
+
+mul(A, B) :-
+	( A < 0 ->
+		B = -1
+	;
+		(
+			B = A
+		;
+			B = A + 1
+		;
+			A > 1,
+			mul(A / 2, B)
+		)
+	).
Index: tests/tabling/memo_non.exp
===================================================================
RCS file: tests/tabling/memo_non.exp
diff -N tests/tabling/memo_non.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/memo_non.exp	18 Jul 2004 11:06:01 -0000
@@ -0,0 +1,12 @@
+marker executed: non 1 2
+[120, 210]
+[120, 210]
+marker executed: non 2 2
+[]
+[]
+marker executed: multi 1 2
+[120, 210]
+[120, 210]
+marker executed: multi 2 2
+[220]
+[220]
Index: tests/tabling/memo_non.m
===================================================================
RCS file: tests/tabling/memo_non.m
diff -N tests/tabling/memo_non.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/memo_non.m	17 Jul 2004 06:21:28 -0000
@@ -0,0 +1,75 @@
+% Test the memoization of model_non predicates.
+
+:- module memo_non.
+
+:- interface.
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+:- import_module int, std_util.
+
+main(!IO) :-
+	solutions(test_non(1, 2), NonSoln1),
+	io__write(NonSoln1, !IO),
+	io__nl(!IO),
+	solutions(test_non(1, 2), NonSoln2),
+	io__write(NonSoln2, !IO),
+	io__nl(!IO),
+	solutions(test_non(2, 2), NonSoln3),
+	io__write(NonSoln3, !IO),
+	io__nl(!IO),
+	solutions(test_non(2, 2), NonSoln4),
+	io__write(NonSoln4, !IO),
+	io__nl(!IO),
+
+	solutions(test_multi(1, 2), MultiSoln1),
+	io__write(MultiSoln1, !IO),
+	io__nl(!IO),
+	solutions(test_multi(1, 2), MultiSoln2),
+	io__write(MultiSoln2, !IO),
+	io__nl(!IO),
+	% This tests the duplicate detection machinery.
+	solutions(test_multi(2, 2), MultiSoln3),
+	io__write(MultiSoln3, !IO),
+	io__nl(!IO),
+	solutions(test_multi(2, 2), MultiSoln4),
+	io__write(MultiSoln4, !IO),
+	io__nl(!IO).
+
+:- pred test_non(int::in, int::in, int::out) is nondet.
+:- pragma memo(test_non/3).
+
+test_non(A, B, C) :-
+	marker("non", A, B, Zero),
+	( A = 1 ->
+		(
+			C = Zero + (A * 100) + (B * 10)
+		;
+			C = Zero + (B * 100) + (A * 10)
+		)
+	;
+		fail
+	).
+
+:- pred test_multi(int::in, int::in, int::out) is multi.
+:- pragma memo(test_multi/3).
+
+test_multi(A, B, C) :-
+	marker("multi", A, B, Zero),
+	(
+		C = Zero + (A * 100) + (B * 10)
+	;
+		C = Zero + (B * 100) + (A * 10)
+	).
+
+:- pred marker(string::in, int::in, int::in, int::out) is det.
+
+:- pragma foreign_proc("C",
+	marker(S::in, A::in, B::in, X::out),
+	[will_not_call_mercury, promise_pure],
+"
+	printf(""marker executed: %s %d %d\\n"", S, A, B);
+	X = 0;
+").
Index: tests/tabling/tc_loop.exp
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/tc_loop.exp,v
retrieving revision 1.4
diff -u -b -r1.4 tc_loop.exp
--- tests/tabling/tc_loop.exp	17 Jan 2003 05:57:15 -0000	1.4
+++ tests/tabling/tc_loop.exp	19 Jul 2004 02:57:29 -0000
@@ -1,3 +1,2 @@
 Uncaught Mercury exception:
 Software Error: detected infinite recursion in pred tc_loop.tc/2
-Stack dump not available in this grade.
Index: tests/tabling/tc_memo.exp
===================================================================
RCS file: tests/tabling/tc_memo.exp
diff -N tests/tabling/tc_memo.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/tc_memo.exp	19 Jul 2004 02:57:27 -0000
@@ -0,0 +1,2 @@
+Uncaught Mercury exception:
+Software Error: detected infinite recursion in pred tc_memo.tc/2
Index: tests/tabling/tc_memo.m
===================================================================
RCS file: tests/tabling/tc_memo.m
diff -N tests/tabling/tc_memo.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/tc_memo.m	17 Jul 2004 06:10:02 -0000
@@ -0,0 +1,34 @@
+:- module tc_memo.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module std_util, list.
+
+main(!IO) :-
+	solutions(tc(1), Solns),
+	io__write(Solns, !IO),
+	io__write_string("\n", !IO).
+
+:- pred tc(int::in, int::out) is nondet.
+:- pragma memo(tc/2).
+
+tc(A, B) :-
+	edge(A, C),
+	(
+		B = C
+	;
+		tc(C, B)
+	).
+
+:- pred edge(int::in, int::out) is nondet.
+
+edge(1, 2).
+edge(1, 3).
+edge(2, 1).
+edge(3, 4).
Index: tests/tabling/tc_memo2.exp
===================================================================
RCS file: tests/tabling/tc_memo2.exp
diff -N tests/tabling/tc_memo2.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/tc_memo2.exp	19 Jul 2004 02:57:22 -0000
@@ -0,0 +1,2 @@
+Uncaught Mercury exception:
+Software Error: detected need for minimal model in pred tc_memo2.tc/2
Index: tests/tabling/tc_memo2.m
===================================================================
RCS file: tests/tabling/tc_memo2.m
diff -N tests/tabling/tc_memo2.m
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tests/tabling/tc_memo2.m	18 Jul 2004 10:18:44 -0000
@@ -0,0 +1,38 @@
+:- module tc_memo2.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is det.
+
+:- implementation.
+
+:- import_module std_util, list.
+
+main(!IO) :-
+	(
+		tc(1, 4),
+		tc(3, 4)
+	->
+		io__write_string("yes\n", !IO)
+	;
+		io__write_string("no\n", !IO)
+	).
+
+:- pred tc(int::in, int::out) is nondet.
+:- pragma memo(tc/2).
+
+tc(A, B) :-
+	edge(A, C),
+	(
+		B = C
+	;
+		tc(C, B)
+	).
+
+:- pred edge(int::in, int::out) is nondet.
+
+edge(1, 2).
+edge(1, 3).
+edge(3, 4).
Index: tests/tabling/test_tabling
===================================================================
RCS file: /home/mercury/mercury1/repository/tests/tabling/test_tabling,v
retrieving revision 1.4
diff -u -b -r1.4 test_tabling
--- tests/tabling/test_tabling	21 Jun 2004 03:15:04 -0000	1.4
+++ tests/tabling/test_tabling	15 Jul 2004 12:51:15 -0000
@@ -39,7 +39,7 @@
 then
 	testcases=`mmake echo_simple_nonloop_progs`
 else
-	testcases=`mmake echo_nondet_nonloop_progs echo_simple_nonloop_progs`
+	testcases=`mmake echo_minimal_nonloop_progs echo_simple_nonloop_progs`
 fi
 
 status=0
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
Index: tools/bootcheck
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/tools/bootcheck,v
retrieving revision 1.160
diff -u -b -r1.160 bootcheck
--- tools/bootcheck	11 Jun 2004 09:09:18 -0000	1.160
+++ tools/bootcheck	19 Jul 2004 02:54:51 -0000
@@ -1201,6 +1201,9 @@
 	MERCURY_DEBUGGER_INIT=$root/scripts/test_mdbrc
 	export MERCURY_DEBUGGER_INIT
 
+	MERCURY_SUPPRESS_STACK_TRACE=yes
+	export MERCURY_SUPPRESS_STACK_TRACE
+
 	if test "$test_grade" != ""
 	then
 		test_grade_opt="GRADE=$test_grade"
Index: tools/test_mercury
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/tools/test_mercury,v
retrieving revision 1.246
diff -u -b -r1.246 test_mercury
--- tools/test_mercury	11 Jun 2004 09:09:18 -0000	1.246
+++ tools/test_mercury	19 Jul 2004 02:55:18 -0000
@@ -906,6 +906,8 @@
 for grade in $GRADES
 do
 	echo "test_mercury starting tests for grade $grade at `date`" 1>&2
+	MERCURY_SUPPRESS_STACK_TRACE=yes
+	export MERCURY_SUPPRESS_STACK_TRACE
 	case $BRANCH in
 	    0.10)
 		./runtests -f "$TEST_MCFLAGS" -c "$TEST_CFLAGS" -g "$grade" \
cvs diff: Diffing trace
Index: trace/mercury_trace.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace.c,v
retrieving revision 1.71
diff -u -b -r1.71 mercury_trace.c
--- trace/mercury_trace.c	7 Jul 2004 07:11:22 -0000	1.71
+++ trace/mercury_trace.c	18 Jul 2004 05:14:45 -0000
@@ -93,7 +93,7 @@
                         MR_Word *base_curfr, MR_uint_least16_t var_num,
                         MR_bool *succeeded);
 
-#ifdef  MR_USE_MINIMAL_MODEL
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
 static  MR_Retry_Result
                     MR_check_minimal_model_calls(MR_Event_Info *event_info,
                         int ancestor_level, MR_Word *target_maxfr,
@@ -148,7 +148,7 @@
         depth = (MR_Unsigned) MR_call_depth_framevar(MR_curfr);
     }
 
-#if defined(MR_USE_MINIMAL_MODEL) && defined(MR_MINIMAL_MODEL_DEBUG)
+#if defined(MR_USE_MINIMAL_MODEL_STACK_COPY) && defined(MR_MINIMAL_MODEL_DEBUG)
     if ((MR_Trace_Port) layout->MR_sll_port == MR_PORT_CALL) {
         MR_subgoal_debug_cur_proc = layout->MR_sll_entry;
     }
@@ -513,7 +513,7 @@
     MR_bool                 has_io_state;
     MR_bool                 found_io_action_counter;
     MR_Unsigned             saved_io_action_counter;
-#ifdef  MR_USE_MINIMAL_MODEL
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
     MR_Retry_Result         result;
 #endif
 
@@ -692,7 +692,7 @@
         }
     }
 
-#ifdef  MR_USE_MINIMAL_MODEL
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
 
     result = MR_check_minimal_model_calls(event_info, ancestor_level,
             base_maxfr, problem);
@@ -717,7 +717,7 @@
         goto report_problem;
     }
 
-#endif  /* MR_USE_MINIMAL_MODEL */
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
     /*
     ** At this point, we are now sure that we can carry out the retry
@@ -1136,7 +1136,7 @@
 
 /*****************************************************************************/
 
-#ifdef  MR_USE_MINIMAL_MODEL
+#ifdef  MR_USE_MINIMAL_MODEL_STACK_COPY
 
 /*
 ** MR_check_minimal_model_calls scans the nondet stack region about to be
@@ -1244,7 +1244,9 @@
             return MR_RETRY_ERROR;
         }
 
-        if (MR_sle_eval_method(proc_layout) != MR_EVAL_METHOD_MINIMAL) {
+        if (MR_sle_eval_method(proc_layout)
+            != MR_EVAL_METHOD_MINIMAL_STACK_COPY)
+        {
             continue;
         }
 
@@ -1303,7 +1305,9 @@
         label_layout = event_info->MR_event_sll;
         proc_layout = label_layout->MR_sll_entry;
 
-        if (MR_sle_eval_method(proc_layout) == MR_EVAL_METHOD_MINIMAL) {
+        if (MR_sle_eval_method(proc_layout)
+            == MR_EVAL_METHOD_MINIMAL_STACK_COPY)
+        {
             return MR_RETRY_OK_FAIL_FIRST;
         } else {
             return MR_RETRY_OK_FINISH_FIRST;
@@ -1313,7 +1317,7 @@
     }
 }
 
-#endif  /* MR_USE_MINIMAL_MODEL */
+#endif  /* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 /*****************************************************************************/
 
@@ -1349,6 +1353,7 @@
     MR_Word *base_sp, MR_Word *base_curfr)
 {
     MR_TrieNode call_table;
+    MR_EvalMethod   eval_method;
 
     if (! MR_PROC_LAYOUT_HAS_EXEC_TRACE(level_layout)) {
         /*
@@ -1360,7 +1365,8 @@
                 "in MR_maybe_record_call_table");
     }
 
-    switch (MR_sle_eval_method(level_layout)) {
+    eval_method = MR_sle_eval_method(level_layout);
+    switch (eval_method) {
 
     case MR_EVAL_METHOD_NORMAL:
         /* nothing to do */
@@ -1372,9 +1378,22 @@
             call_table = (MR_TrieNode) MR_based_stackvar(base_sp,
                 level_layout->MR_sle_maybe_call_table);
         } else {
+            if (eval_method == MR_EVAL_METHOD_MEMO) {
+                MR_MemoNonRecordPtr record;
+
+                record = (MR_MemoNonRecordPtr) MR_based_framevar(base_curfr,
+                    level_layout->MR_sle_maybe_call_table);
+                call_table = record->MR_mn_back_ptr;
+
+#ifdef  MR_DEBUG_RETRY
+                printf("reset: memo non record %p, call_table %p\n",
+                        record, call_table);
+#endif
+            } else {
             call_table = (MR_TrieNode) MR_based_framevar(base_curfr,
                 level_layout->MR_sle_maybe_call_table);
         }
+        }
 
         if (call_table != NULL) {
             MR_GC_ensure_room_for_next(MR_call_table_ptr, MR_TrieNode,
@@ -1386,7 +1405,11 @@
 
         return;
 
-    case MR_EVAL_METHOD_MINIMAL:
+    case MR_EVAL_METHOD_MINIMAL_OWN_STACKS:
+        MR_fatal_error("retry with MR_EVAL_METHOD_MINIMAL_OWN_STACKS: "
+            "not yet implemented");
+
+    case MR_EVAL_METHOD_MINIMAL_STACK_COPY:
         /*
         ** We want to process all the minimal model calls whose
         ** stack frames are in the part of the nondet stack to be
Index: trace/mercury_trace_internal.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_internal.c,v
retrieving revision 1.176
diff -u -b -r1.176 mercury_trace_internal.c
--- trace/mercury_trace_internal.c	19 Jul 2004 03:37:55 -0000	1.176
+++ trace/mercury_trace_internal.c	19 Jul 2004 03:41:01 -0000
@@ -591,6 +591,12 @@
 static	void	MR_trace_print_subgoal_debug(const MR_Proc_Layout *proc,
 			MR_SubgoalDebug *subgoal_debug);
 
+/* Prints the given generator of the given procedure to MR_mdb_out. */
+static	void	MR_trace_print_generator(const MR_Proc_Layout *proc,
+			MR_Generator *generator);
+static	void	MR_trace_print_generator_debug(const MR_Proc_Layout *proc,
+			MR_GenDebug *generator_debug);
+
 /* Prints the given consumer of the given procedure to MR_mdb_out. */
 static	void	MR_trace_print_consumer(const MR_Proc_Layout *proc,
 			MR_Consumer *consumer);
@@ -1519,12 +1525,14 @@
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
 {
-	MR_Determinism	detism = event_info->MR_event_sll->
-				MR_sll_entry->MR_sle_detism;
-	MR_Unsigned	depth = event_info->MR_call_depth;
+	MR_Determinism	detism;
+	MR_Unsigned	depth;
 	int		stop_depth;
 	int		n;
 
+	detism = event_info->MR_event_sll->MR_sll_entry->MR_sle_detism;
+	depth = event_info->MR_call_depth;
+
 	cmd->MR_trace_strict = MR_TRUE;
 	cmd->MR_trace_print_level = MR_default_print_level;
 	MR_init_trace_check_integrity(cmd);
@@ -3475,7 +3483,7 @@
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 
 	MR_SubgoalDebug	*subgoal_debug;
 	MR_Subgoal	*subgoal;
@@ -3494,12 +3502,12 @@
 		MR_trace_usage("developer", "subgoal");
 	}
 
-#else	/* MR_USE_MINIMAL_MODEL */
+#else	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	fprintf(MR_mdb_out, "mdb: the `subgoal' command is available "
-		"only in minimal model tabling grades.\n");
+		"only in stack copy minimal model tabling grades.\n");
 
-#endif	/* MR_USE_MINIMAL_MODEL */
+#endif	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	return KEEP_INTERACTING;
 }
@@ -3509,7 +3517,7 @@
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 
 	MR_ConsumerDebug	*consumer_debug;
 	MR_Consumer		*consumer;
@@ -3528,12 +3536,12 @@
 		MR_trace_usage("developer", "consumer");
 	}
 
-#else	/* MR_USE_MINIMAL_MODEL */
+#else	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	fprintf(MR_mdb_out, "mdb: the `consumer' command is available "
-		"only in minimal model tabling grades.\n");
+		"only in stack copy minimal model tabling grades.\n");
 
-#endif	/* MR_USE_MINIMAL_MODEL */
+#endif	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	return KEEP_INTERACTING;
 }
@@ -3544,7 +3552,7 @@
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 
 	if (word_count == 1) {
 		MR_bool	saved_tabledebug;
@@ -3558,12 +3566,12 @@
 		MR_trace_usage("developer", "gen_stack");
 	}
 
-#else	/* MR_USE_MINIMAL_MODEL */
+#else	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	fprintf(MR_mdb_out, "mdb: the `gen_stack' command is available "
-		"only in minimal model grades.\n");
+		"only in stack copy minimal model tabling grades.\n");
 
-#endif	/* MR_USE_MINIMAL_MODEL */
+#endif	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	return KEEP_INTERACTING;
 }
@@ -3573,7 +3581,7 @@
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 
 	if (word_count == 1) {
 		MR_bool	saved_tabledebug;
@@ -3587,12 +3595,12 @@
 		MR_trace_usage("developer", "cut_stack");
 	}
 
-#else	/* MR_USE_MINIMAL_MODEL */
+#else	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	fprintf(MR_mdb_out, "mdb: the `cut_stack' command is available "
-		"only in minimal model grades.\n");
+		"only in stack copy minimal model tabling grades.\n");
 
-#endif	/* MR_USE_MINIMAL_MODEL */
+#endif	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	return KEEP_INTERACTING;
 }
@@ -3602,7 +3610,7 @@
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 
 	if (word_count == 1) {
 		MR_bool	saved_tabledebug;
@@ -3616,12 +3624,12 @@
 		MR_trace_usage("developer", "pneg_stack");
 	}
 
-#else	/* MR_USE_MINIMAL_MODEL */
+#else	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	fprintf(MR_mdb_out, "mdb: the `pneg_stack' command is available "
-		"only in minimal model grades.\n");
+		"only in stack copy minimal model tabling grades.\n");
 
-#endif	/* MR_USE_MINIMAL_MODEL */
+#endif	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	return KEEP_INTERACTING;
 }
@@ -3631,7 +3639,7 @@
 	MR_Event_Info *event_info, MR_Event_Details *event_details,
 	MR_Code **jumpaddr)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 
 	if (word_count == 1) {
 		MR_bool	saved_tabledebug;
@@ -3649,12 +3657,12 @@
 		MR_trace_usage("developer", "pneg_stack");
 	}
 
-#else	/* MR_USE_MINIMAL_MODEL */
+#else	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	fprintf(MR_mdb_out, "mdb: the `pneg_stack' command is available "
-		"only in minimal model grades.\n");
+		"only in stack copy minimal model tabling grades.\n");
 
-#endif	/* MR_USE_MINIMAL_MODEL */
+#endif	/* MR_USE_MINIMAL_MODEL_STACK_COPY */
 
 	return KEEP_INTERACTING;
 }
@@ -4108,7 +4116,8 @@
 
 		case MR_EVAL_METHOD_LOOP_CHECK:
 		case MR_EVAL_METHOD_MEMO:
-		case MR_EVAL_METHOD_MINIMAL:
+		case MR_EVAL_METHOD_MINIMAL_STACK_COPY:
+		case MR_EVAL_METHOD_MINIMAL_OWN_STACKS:
 			break;
 
 		case MR_EVAL_METHOD_TABLE_IO:
@@ -4246,7 +4255,8 @@
 			fprintf(MR_mdb_out, ":\n");
 			break;
 
-		case MR_EVAL_METHOD_MINIMAL:
+		case MR_EVAL_METHOD_MINIMAL_STACK_COPY:
+		case MR_EVAL_METHOD_MINIMAL_OWN_STACKS:
 			fprintf(MR_mdb_out, "minimal model table for ");
 			MR_print_proc_id(MR_mdb_out, proc);
 			fprintf(MR_mdb_out, ":\n");
@@ -4289,7 +4299,7 @@
 	** value of the last argument. We also do this whenever we run out of
 	** values in any trie.
 	**
-	** We step when we are about to backtrack out of the outermost loop.
+	** We stop when we are about to backtrack out of the outermost loop.
 	*/
 
 	cur_arg = word_count;
@@ -4620,6 +4630,7 @@
 	MR_Call_Table_Arg *call_table_args, MR_TrieNode table)
 {
 	int	i;
+	MR_EvalMethod	eval_method;
 
 	fprintf(MR_mdb_out, "<");
 	for (i = 0; i < num_inputs; i++) {
@@ -4654,7 +4665,8 @@
 
 	fprintf(MR_mdb_out, ">: ");
 
-	if (MR_sle_eval_method(proc) == MR_EVAL_METHOD_MINIMAL) {
+	eval_method = MR_sle_eval_method(proc);
+	if (eval_method == MR_EVAL_METHOD_MINIMAL_STACK_COPY) {
 		MR_Subgoal	*subgoal;
 		int		subgoal_num;
 
@@ -4665,39 +4677,30 @@
 		} else {
 			MR_trace_print_subgoal(proc, subgoal);
 		}
-	} else if (MR_sle_eval_method(proc) == MR_EVAL_METHOD_MEMO) {
-		switch (table->MR_memo_status) {
-			case MR_MEMO_INACTIVE:
+	} else if (eval_method == MR_EVAL_METHOD_MINIMAL_OWN_STACKS) {
+		MR_Consumer	*consumer;
+
+		fprintf(MR_mdb_out, "trie node %p\n", table);
+		consumer = table->MR_consumer;
+		if (consumer == NULL) {
 				fprintf(MR_mdb_out, "uninitialized\n");
-				break;
-			case MR_MEMO_ACTIVE:
-				fprintf(MR_mdb_out, "working\n");
-				break;
-			case MR_MEMO_FAILED:
-				fprintf(MR_mdb_out, "failed\n");
-				break;
-			case MR_MEMO_SUCCEEDED:
-				fprintf(MR_mdb_out, "succeeded (no outputs)\n");
-				break;
-			default:
-				fprintf(MR_mdb_out, "succeeded <");
-				MR_print_answerblock(MR_mdb_out, proc,
-					table->MR_answerblock);
-				fprintf(MR_mdb_out, ">\n");
-				break;
+		} else {
+			MR_trace_print_consumer(proc, consumer);
 		}
-	} else if (MR_sle_eval_method(proc) == MR_EVAL_METHOD_LOOP_CHECK) {
-		switch (table->MR_loop_status) {
-			case MR_LOOP_INACTIVE:
-				fprintf(MR_mdb_out, "uninitialized\n");
-				break;
-			case MR_LOOP_ACTIVE:
-				fprintf(MR_mdb_out, "working\n");
-				break;
-			default:
-				MR_fatal_error("MR_trace_cmd_table_print_tip: "
-					"bad loopcheck status");
+	} else if (eval_method == MR_EVAL_METHOD_MEMO) {
+		MR_Determinism	detism;
+		
+		detism = proc->MR_sle_detism;
+		if (MR_DETISM_DET_STACK(detism)) {
+			MR_print_memo_tip(MR_mdb_out, proc, table);
+		} else {
+			MR_MemoNonRecordPtr	record;
+
+			record = table->MR_memo_non_record;
+			MR_print_memo_non_record(MR_mdb_out, proc, record);
 		}
+	} else if (eval_method == MR_EVAL_METHOD_LOOP_CHECK) {
+		MR_print_loopcheck_tip(MR_mdb_out, proc, table);
 	} else {
 		MR_fatal_error("MR_trace_cmd_table_print_tip: bad eval method");
 	}
@@ -4706,7 +4709,7 @@
 static void
 MR_trace_print_subgoal(const MR_Proc_Layout *proc, MR_Subgoal *subgoal)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 	MR_print_subgoal(MR_mdb_out, proc, subgoal);
 #else
 	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
@@ -4717,7 +4720,7 @@
 MR_trace_print_subgoal_debug(const MR_Proc_Layout *proc,
 	MR_SubgoalDebug *subgoal_debug)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
 	MR_print_subgoal_debug(MR_mdb_out, proc, subgoal_debug);
 #else
 	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
@@ -4725,9 +4728,31 @@
 }
 
 static void
+MR_trace_print_generator(const MR_Proc_Layout *proc, MR_Generator *generator)
+{
+#ifdef	MR_USE_MINIMAL_MODEL_OWN_STACKS
+	MR_print_generator(MR_mdb_out, proc, generator);
+#else
+	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
+
+static void
+MR_trace_print_generator_debug(const MR_Proc_Layout *proc,
+	MR_GenDebug *generator_debug)
+{
+#ifdef	MR_USE_MINIMAL_MODEL_OWN_STACKS
+	MR_print_generator_debug(MR_mdb_out, proc, generator_debug);
+#else
+	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
+#endif
+}
+
+static void
 MR_trace_print_consumer(const MR_Proc_Layout *proc, MR_Consumer *consumer)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#if	defined(MR_USE_MINIMAL_MODEL_STACK_COPY) \
+		|| defined(MR_USE_MINIMAL_MODEL_OWN_STACKS)
 	MR_print_consumer(MR_mdb_out, proc, consumer);
 #else
 	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
@@ -4738,7 +4763,8 @@
 MR_trace_print_consumer_debug(const MR_Proc_Layout *proc,
 	MR_ConsumerDebug *consumer_debug)
 {
-#ifdef	MR_USE_MINIMAL_MODEL
+#if	defined(MR_USE_MINIMAL_MODEL_STACK_COPY) \
+		|| defined(MR_USE_MINIMAL_MODEL_OWN_STACKS)
 	MR_print_consumer_debug(MR_mdb_out, proc, consumer_debug);
 #else
 	fprintf(MR_mdb_out, "minimal model tabling is not enabled\n");
Index: trace/mercury_trace_util.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/trace/mercury_trace_util.c,v
retrieving revision 1.12
diff -u -b -r1.12 mercury_trace_util.c
--- trace/mercury_trace_util.c	7 Jul 2004 07:11:22 -0000	1.12
+++ trace/mercury_trace_util.c	7 Jul 2004 07:17:14 -0000
@@ -112,7 +112,7 @@
 void
 MR_print_tabling_regs(FILE *fp, MR_Word *saved_regs)
 {
-#ifdef MR_USE_MINIMAL_MODEL
+#ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
 	fprintf(fp, "gen_next = %ld\n", (long) MR_saved_gen_next(saved_regs));
 	fprintf(fp, "cut_next = %ld\n", (long) MR_saved_cut_next(saved_regs));
 #endif
cvs diff: Diffing util
cvs diff: Diffing vim
cvs diff: Diffing vim/after
cvs diff: Diffing vim/ftplugin
cvs diff: Diffing vim/syntax
--------------------------------------------------------------------------
mercury-reviews mailing list
post:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list