diff: AGC: round 2.

Tyson Dowd trd at cs.mu.OZ.AU
Fri Jul 3 16:56:05 AEST 1998


Here's a diff relative to my previous changes.
I've addressed the concerns raised in the review.

(there are a few indenting problems in mercury_deep_copy_body.h in
this diff, please ignore them I'll fix them before committing).

===================================================================

Estimated hours taken: 70

An initial implementation of the accurate garbage collector.

library/builtin.m:
library/mercury_builtin.m:
library/std_util.m:
runtime/mercury_tabling.h:
	Deep copy terms using the address of the value instead of
	just the value.

library/io.m:
	Initialize the garbage rootset with the globals.

runtime/Mmakefile:
	Add new files to the Mmakefile.

runtime/mercury_accurate_gc.h:
runtime/mercury_accurate_gc.c:
	The new garbage collector.

runtime/mercury_agc_debug.c:
runtime/mercury_agc_debug.h:
	Debugging utilities for the new garbage collector.

runtime/mercury_deep_copy.c:
runtime/mercury_deep_copy.h:
runtime/mercury_deep_copy_body.h:
	Put the deep copy code in mercury_deep_copy_body.h, and #include
	it with appropriate #defines in order to get a variant for
	deep_copy(), and one for agc_deep_copy().

	agc_deep_copy() forwards pointers as it copies.

	Also, deep_copy (all variants) have been modified to take
	a pointer to the data to be copied, because some variants
	need to be able to modify it.

runtime/mercury_engine.c:
runtime/mercury_engine.h:
	Add a second heap_zone which is the to-space of
	the copying collector.
	Add a debug_heap_zone, which is used as a scratch
	heap for debugging.

runtime/mercury_goto.h:
runtime/mercury_label.c:
runtime/mercury_label.h:
	Keep track of which labels are entry labels, and which ones
	aren't.  (This is a temporary change, until Zoltan commits
	his dual label tables).

runtime/mercury_imp.h:
	Include mercury_debug.h before most of the modules. 
	(mercury_engine.h adds a new MemoryZone only if we are
	debugging accurate GC).

runtime/mercury_memory.c:
	Setup the debug_memory_zone sizes.
	Remove an unnecessary prototype.

runtime/mercury_memory_handlers.c:
	Add code to get the program counter and the stack pointer
	from the signal context.

	Call MR_schedule_agc() from default_handler() if doing accurate gc.

runtime/mercury_memory_zones.c:
	Setup the hardzone regardless of whether redzones are used.

	Add some more debugging information.

runtime/mercury_regorder.h:
runtime/machdeps/alpha_regs.h:
runtime/machdeps/i386_regs.h:
	Add definitions to make the real machine registers name/number
	for MR_sp available.

runtime/mercury_trace_internal.c:
runtime/mercury_trace_util.c:
runtime/mercury_trace_util.h:
	Add MR_trace_write_variable(), which writes terms given their
	value and type_info.

runtime/mercury_wrapper.c:
runtime/mercury_wrapper.h:
	Change the size of the heap redzone when doing accurate GC.
	Use a small heap when debugging agc.

runtime/mercury_debug.h:
runtime/mercury_conf_param.h:
	Add new debugging macros and document them.

runtime/mercury_type_info.c:
	Add const to the pointer arguments of MR_make_type_info.



===================================================================

diff -u runtime2/mercury_accurate_gc.c runtime/mercury_accurate_gc.c
--- runtime2/mercury_accurate_gc.c	Tue Jun 30 14:10:40 1998
+++ runtime/mercury_accurate_gc.c	Fri Jul  3 15:22:33 1998
@@ -8,16 +8,17 @@
 ** This module contains the accurate garbage collector.
 */
 
+#include "mercury_imp.h"
+
 #ifdef NATIVE_GC
 
-#include "mercury_imp.h"
 #include "mercury_trace_util.h"
 #include "mercury_deep_copy.h"
 #include "mercury_agc_debug.h"
 
-	/*
-	** Function prototypes.
-	*/
+/*
+** Function prototypes.
+*/
 static	void	garbage_collect(Code *saved_success, Word *stack_pointer, Word
 			*current_frame);
 static	void	garbage_collect_roots(void);
@@ -26,38 +27,38 @@
 static	void	copy_value(MR_Live_Lval locn, Word *type_info, bool copy_regs,
 			Word *stack_pointer, Word *current_frame);
 
-	/*
-	** Global variables (only used in this module, however).
-	*/
+/*
+** Global variables (only used in this module, however).
+*/
 static Code	*saved_success = (Code *) NULL;
 static Word	*saved_success_location = (Word *) NULL;
 static bool	gc_scheduled = FALSE;
 static bool	gc_running = FALSE;
 
-	/* The list of roots */
+/* The list of roots */
 static MR_RootList root_list = NULL;
 
-	/* The last root on the list */
+/* The last root on the list */
 static MR_RootList last_root = NULL;
 
 
 Define_extern_entry(mercury__garbage_collect_0_0);
 
 
-	/*
-	** MR_schedule_agc:
-	** 	Schedule garbage collection.  
-	** 	
-	** 	We do this by replacing the succip that is saved in
-	** 	the current procedure's stack frame with the address
-	** 	of the garbage collector.  When the current procedure
-	** 	returns, it will call the garbage collectior.
-	**
-	** 	(We go to this trouble because then the stacks will
-	** 	be in a known state -- each stack frame is described
-	** 	by information associated with the continuation label
-	** 	that the code will return to).
-	*/
+/*
+** MR_schedule_agc:
+** 	Schedule garbage collection.  
+** 	
+** 	We do this by replacing the succip that is saved in
+** 	the current procedure's stack frame with the address
+** 	of the garbage collector.  When the current procedure
+** 	returns, it will call the garbage collectior.
+**
+** 	(We go to this trouble because then the stacks will
+** 	be in a known state -- each stack frame is described
+** 	by information associated with the continuation label
+** 	that the code will return to).
+*/
 void
 MR_schedule_agc(Code *pc_at_signal, Word *sp_at_signal)
 {
@@ -70,18 +71,16 @@
 	int			determinism, number;
 
 	if (gc_running) {
-			/*
-			** This is bad news, but it can happen if
-			** you don't collect any garbage.
-			** We should try to avoid it by resizing
-			** the heaps so they don't become too full.
-			**
-			** It might also be worthwhile eventually
-			** turning off the redzone in the destination
-			** heap (but only when the large problem of
-			** handling collections with little garbage
-			** has been solved).
-			*/
+		/*
+		** This is bad news, but it can happen if you don't
+		** collect any garbage.  We should try to avoid it by
+		** resizing the heaps so they don't become too full.
+		**
+		** It might also be worthwhile eventually turning off
+		** the redzone in the destination heap (but only when
+		** the large problem of handling collections with little
+		** garbage has been solved).
+		*/
 
 		fprintf(stderr, "Garbage collection scheduled while "
 				"collector is already running\n");
@@ -97,13 +96,13 @@
 	fflush(NULL);
 #endif
 
-		/* Search for the entry label */
+	/* Search for the entry label */
 	label = lookup_label_addr(pc_at_signal);
 	while (label == NULL || label->e_layout == NULL) {
 		/* 
-		** Linear search through the label table
-		** (should be replaced with a binary search through
-		** a different table).
+		** Linear search through the label table (should be
+		** replaced with a binary search through a different
+		** table).
 		*/
 		pc_at_signal = (Code *) ((Word) pc_at_signal - 1);
 		label = lookup_label_addr(pc_at_signal);
@@ -135,10 +134,10 @@
 	fflush(NULL);
 #endif
 
-		/* 
-		** If we have already scheduled a garbage collection,
-		** undo the last change, and do a new one.
-		*/
+	/* 
+	** If we have already scheduled a garbage collection, undo the
+	** last change, and do a new one.
+	*/
 	if (gc_scheduled) {
 #ifdef MR_DEBUG_AGC_SCHEDULING
 		fprintf(stderr, "GC scheduled again. Replacing old scheduling,"
@@ -157,9 +156,9 @@
 			fatal_error("can only handle stackvars");
 		}
 
-			/*
-			** Save the old succip and its location.
-			*/
+		/*
+		** Save the old succip and its location.
+		*/
 		saved_success_location = (Word *) sp_at_signal - number;
 		saved_success = (Code *) *saved_success_location;
 
@@ -171,10 +170,10 @@
 			(long) ENTRY(mercury__garbage_collect_0_0));
 #endif
 
-			/*
-			** Replace the old succip with the address
-			** of the garbage collector.
-			*/
+		/*
+		** Replace the old succip with the address of the
+		** garbage collector.
+		*/
 		*saved_success_location = (Word) mercury__garbage_collect_0_0;
 
 	} else {
@@ -193,12 +192,12 @@
 BEGIN_MODULE(native_gc)
 BEGIN_CODE
 
-	/*
-	** Our garbage collection entry label.
-	**
-	** It saves the registers -- we use the saved registers
-	** for garbage collection and leave the real ones alone.
-	*/
+/*
+** Our garbage collection entry label.
+**
+** It saves the registers -- we use the saved registers
+** for garbage collection and leave the real ones alone.
+*/
 Define_entry(mercury__garbage_collect_0_0);
 
         /* record that the collector is running */
@@ -218,13 +217,13 @@
 
 /*---------------------------------------------------------------------------*/
 
-	/*
-	** garbage_collect:
-	**
-	** 	The main garbage collection routine.
-	**
-	**  (We use 4 space tabs here because of the depth of indentation).
-	*/
+/*
+** garbage_collect:
+**
+** 	The main garbage collection routine.
+**
+**  (We use 4 space tabs here because of the depth of indentation).
+*/
 void
 garbage_collect(Code *success_ip, Word *stack_pointer, Word *current_frame)
 {
@@ -258,18 +257,18 @@
 
     old_hp = MR_virtual_hp;
 
-        /*
-        ** The new heap pointer starts at the bottom of
-        ** the new heap.
-        */
+    /*
+    ** The new heap pointer starts at the bottom of
+    ** the new heap.
+    */
     MR_virtual_hp = new_heap->min;
 
-        /*
-        ** Swap the two heaps (this just swaps them in
-        ** the MR_ENGINE data structure -- we still have
-        ** new_heap and old_heap that point to the
-        ** new and old heaps).
-        */
+    /*
+    ** Swap the two heaps (this just swaps them in
+    ** the MR_ENGINE data structure -- we still have
+    ** new_heap and old_heap that point to the
+    ** new and old heaps).
+    */
     {
         MemoryZone *tmp;
 
@@ -297,9 +296,9 @@
     MR_agc_dump_roots(root_list);
 #endif
 
-        /*
-        ** For each stack frame ...
-        */
+    /*
+    ** For each stack frame ...
+    */
     while (MR_DETISM_DET_STACK(entry_layout->MR_sle_detism)) {
 #ifdef MR_DEBUG_AGC_COLLECTION
         fprintf(stderr, "label: %s\n", label->e_name);
@@ -311,17 +310,17 @@
         var_count = layout->MR_sll_var_count;
         vars = &(layout->MR_sll_var_info);
 
-            /*
-            ** Get the type parameters from the stack frame.
-            */
+        /*
+        ** Get the type parameters from the stack frame.
+        */
         if (vars->MR_slvs_tvars != NULL) {
             count = (int) (Integer) vars->MR_slvs_tvars[0];
             type_params = checked_malloc((count + 1) * sizeof(Word));
 
-                /*
-                ** type_params should look like a typeinfo;
-                ** type_params[0] is empty and will not be referred to
-                */
+            /*
+            ** type_params should look like a typeinfo;
+            ** type_params[0] is empty and will not be referred to
+            */
             for (i = 1; i <= count; i++) {
                 if (vars->MR_slvs_tvars[i] != 0) {
                     type_params[i] = get_live_lval(vars->MR_slvs_tvars[i],
@@ -335,9 +334,9 @@
             type_params = NULL;
         }
 
-            /* 
-            ** Copy each live variable
-            */
+        /* 
+        ** Copy each live variable
+        */
         for (i = 0; i < var_count; i++) {
             MR_Stack_Layout_Var sl_var;
             MR_Live_Type sl_type;
@@ -356,9 +355,9 @@
             }
         }
 
-            /* 
-            ** Find the next stack frame.
-            */
+        /* 
+        ** Find the next stack frame.
+        */
         {
             MR_Live_Lval            location;
             MR_Lval_Type            type;
@@ -370,7 +369,7 @@
                 if (type != MR_LVAL_TYPE_STACKVAR) {
                     fatal_error("can only handle stackvars");
                 }
-                success_ip = (Code *) field(0, stack_pointer, -number);
+                success_ip = (Code *) based_detstackvar(stack_pointer, number);
                 stack_pointer = stack_pointer - 
                     entry_layout->MR_sle_stack_slots;
         }
@@ -381,9 +380,9 @@
         entry_layout = layout->MR_sll_entry;
     } /* end for each stack frame... */
 
-        /*
-        ** Copy any roots that are not on the stack.
-        */
+    /*
+    ** Copy any roots that are not on the stack.
+    */
     garbage_collect_roots();
 
 #ifdef MR_DEBUG_AGC_COLLECTION
@@ -401,7 +400,7 @@
         ((char *) MR_virtual_hp - (char *) new_heap->min));
 #endif
 
-        /* Reset the redzone on the old heap */
+    /* Reset the redzone on the old heap */
     reset_redzone(old_heap);
 
 #ifdef MR_DEBUG_AGC_COLLECTION
@@ -410,16 +409,16 @@
 
 }
 
-	/*
-	** copy_value:
-	** 	Copies a value in a register or stack frame,
-	** 	replacing the original with the new copy.
-	**
-	** 	The copying is done using agc_deep_copy, which is
-	** 	the accurate GC verison of deep_copy (it leaves
-	** 	forwarding pointers in the old copy of the data, if
-	** 	it is on the old heap).
-	*/
+/*
+** copy_value:
+** 	Copies a value in a register or stack frame,
+** 	replacing the original with the new copy.
+**
+** 	The copying is done using agc_deep_copy, which is
+** 	the accurate GC verison of deep_copy (it leaves
+** 	forwarding pointers in the old copy of the data, if
+** 	it is on the old heap).
+*/
 void
 copy_value(MR_Live_Lval locn, Word *type_info, bool copy_regs,
 	Word *stack_pointer, Word *current_frame)
@@ -441,10 +440,11 @@
 			break;
 
 		case MR_LVAL_TYPE_STACKVAR:
-			stack_pointer[-locn_num] = agc_deep_copy(
-				&stack_pointer[-locn_num], type_info,
-				MR_ENGINE(heap_zone2->min),
-				MR_ENGINE(heap_zone2->hardmax));
+			based_detstackvar(stack_pointer, locn_num) =
+				agc_deep_copy(&based_detstackvar(
+						stack_pointer,locn_num),
+					type_info, MR_ENGINE(heap_zone2->min),
+					MR_ENGINE(heap_zone2->hardmax));
 			break;
 
 		case MR_LVAL_TYPE_FRAMEVAR:
@@ -477,14 +477,14 @@
 	}
 }
 
-	/*
-	** get_live_lval:
-	** 	Retrieves the lval from the stack or registers and
-	** 	returns it.  Succeeded is set to TRUE if the lval
-	** 	was a variable in a register or the stack, otherwise
-	** 	it is FALSE.  If false, the data returned is meaningless
-	** 	and should not be used.
-	*/
+/*
+** get_live_lval:
+** 	Retrieves the lval from the stack or registers and
+** 	returns it.  Succeeded is set to TRUE if the lval
+** 	was a variable in a register or the stack, otherwise
+** 	it is FALSE.  If false, the data returned is meaningless
+** 	and should not be used.
+*/
 Word
 get_live_lval(MR_Live_Lval locn, Word *stack_pointer, Word *current_frame,
 		bool *succeeded)
@@ -540,14 +540,14 @@
 	return value;
 }
 
-	/*
-	** garbage_collect_roots:
-	** 
-	** 	Copies the extra roots.  The roots are overwritten
-	** 	with the new data.
-	*/
+/*
+** garbage_collect_roots:
+** 
+** 	Copies the extra roots.  The roots are overwritten
+** 	with the new data.
+*/
 void
-garbage_collect_roots() 
+garbage_collect_roots(void) 
 {
 	MR_RootList current = root_list;
 
@@ -560,11 +560,11 @@
 
 }
 
-	/*
-	** MR_agc_add_root:
-	** 
-	** 	Adds a new root to the extra roots.
-	*/
+/*
+** MR_agc_add_root_internal:
+** 
+** 	Adds a new root to the extra roots.
+*/
 void
 MR_agc_add_root(Word *root_addr, Word *type_info)
 {
diff -u runtime2/mercury_accurate_gc.h runtime/mercury_accurate_gc.h
--- runtime2/mercury_accurate_gc.h	Tue Jun 30 14:10:22 1998
+++ runtime/mercury_accurate_gc.h	Fri Jul  3 14:52:26 1998
@@ -15,25 +15,25 @@
 
 /*---------------------------------------------------------------------------*/
 
-	/*
-	** MR_schedule_agc:
-	** 	Schedule a garbage collection as soon as possible.  The
-	** 	PC (program counter) is used to find the procedure that
-	** 	is executing.  The stack pointer is then used to replace
-	** 	the saved continuation pointer with the address of the
-	** 	garbage collector routine.
-	*/
+/*
+** MR_schedule_agc:
+** 	Schedule a garbage collection as soon as possible.  The PC
+** 	(program counter) is used to find the procedure that is
+** 	executing.  The stack pointer is then used to replace the saved
+** 	continuation pointer with the address of the garbage collector
+** 	routine.
+*/
 extern	void	MR_schedule_agc(Code *pc_at_signal, Word *sp_at_signal);
 
-	/*
-	** Roots apart from the stacks are stored in this data structure.
-	**
-	** Essentially, this is a list of any pointers into the heap
-	** that are not stored on the heap or the det/nondet stacks.
-	**
-	** Each node stores the address of the root, and its type.
-	** When a garbage collection occurs, the root will be modified.
-	*/
+/*
+** Roots apart from the stacks are stored in this data structure.
+**
+** Essentially, this is a list of any pointers into the heap that are
+** not stored on the heap or the det/nondet stacks.
+**
+** Each node stores the address of the root, and its type.  When a
+** garbage collection occurs, the root will be modified.
+*/
 
 struct	MR_RootNode {
 	Word *root;
@@ -43,12 +43,12 @@
 
 typedef	struct MR_RootNode	*MR_RootList;
 
-	/*
-	** MR_agc_add_root:
-	** 	Adds the root whose address is supplied in root_addr
-	** 	with type described by type_info to the list of
-	** 	additional roots.
-	*/
+/*
+** MR_agc_add_root:
+** 	Adds the root whose address is supplied in root_addr with type
+** 	described by type_info to the list of additional roots.
+*/
+
 extern	void	MR_agc_add_root(Word *root_addr, Word *type_info);
 
 /*---------------------------------------------------------------------------*/
diff -u runtime2/mercury_agc_debug.c runtime/mercury_agc_debug.c
--- runtime2/mercury_agc_debug.c	Tue Jun 30 15:38:37 1998
+++ runtime/mercury_agc_debug.c	Fri Jul  3 15:19:44 1998
@@ -72,9 +72,9 @@
 	layout = (MR_Stack_Layout_Label *) label->e_layout;
 	entry_layout = layout->MR_sll_entry;
 
-		/* 
-		** For each stack frame... 
-		*/
+	/* 
+	** For each stack frame... 
+	*/
 
 	while (MR_DETISM_DET_STACK(entry_layout->MR_sle_detism)) {
 		fprintf(stderr, "    label: %s\n", label->e_name);
@@ -137,9 +137,9 @@
 		}
 		free(type_params);
 
-			/* 
-			** Move to the next stack frame.
-			*/
+		/* 
+		** Move to the next stack frame.
+		*/
 		{
 			MR_Live_Lval            location;
 			MR_Lval_Type            type;
@@ -151,13 +151,15 @@
 			if (type != MR_LVAL_TYPE_STACKVAR) {
 				fatal_error("can only handle stackvars");
 			}
-			success_ip = (Code *) field(0, stack_pointer, -number);
+			                                
+			success_ip = (Code *) 
+				based_detstackvar(stack_pointer, number);
 			stack_pointer = stack_pointer - 
 				entry_layout->MR_sle_stack_slots;
 			label = lookup_label_addr(success_ip);
 		}
 
-		top_frame = top_frame && FALSE;
+		top_frame = FALSE;
 
 		layout = (MR_Stack_Layout_Label *) label->e_layout;
 		entry_layout = layout->MR_sll_entry;
@@ -188,7 +190,7 @@
 			break;
 
 		case MR_LVAL_TYPE_STACKVAR:
-			value = stack_pointer[-locn_num];
+			value = based_detstackvar(stack_pointer, locn_num);
 			have_value = TRUE;
 			fprintf(stderr, "stackvar%d", locn_num);
 			break;
diff -u runtime2/mercury_agc_debug.h runtime/mercury_agc_debug.h
--- runtime2/mercury_agc_debug.h	Mon Jun 29 17:22:44 1998
+++ runtime/mercury_agc_debug.h	Fri Jul  3 14:53:48 1998
@@ -14,23 +14,22 @@
 
 /*---------------------------------------------------------------------------*/
 
-	/*
-	** MR_agc_dump_stack_frames:
-	** 	Dump the stack, writing all information available about
-	** 	each stack frame.
-	** 	
-	** 	label is the topmost label on the stack, heap_zone is
-	** 	the zone which the data is stored upon. 
-	*/
+/*
+** MR_agc_dump_stack_frames:
+** 	Dump the stack, writing all information available about each
+** 	stack frame.
+** 	
+** 	label is the topmost label on the stack, heap_zone is the zone
+** 	which the data is stored upon. 
+*/
 
 extern	void	MR_agc_dump_stack_frames(Label *label, MemoryZone *heap_zone,
 			Word * stack_pointer, Word *current_frame);
 
-	/*
-	** MR_agc_dump_roots:
-	** 	Dump the extra rootset, writing all information about
-	** 	each root.
-	*/
+/*
+** MR_agc_dump_roots:
+** 	Dump the extra rootset, writing all information about each root.
+*/
 extern	void	MR_agc_dump_roots(MR_RootList roots);
 
 /*---------------------------------------------------------------------------*/
diff -u runtime2/mercury_conf_param.h runtime/mercury_conf_param.h
--- runtime2/mercury_conf_param.h	Wed Jun 24 12:25:43 1998
+++ runtime/mercury_conf_param.h	Fri Jul  3 15:11:52 1998
@@ -124,6 +124,26 @@
 **	Include a "name" field in the nondet stack frames.
 **	(Since this affects binary compatibility,
 **	this is a "compilation model" option which affects the grade.)
+**
+** MR_DEBUG_AGC_SCHEDULING
+**	Display debugging information while scheduling accurate garbage
+**	collection.
+**
+** MR_DEBUG_AGC_COLLECTION
+**	Display debugging information while collecting garbage using the
+**	accurate garbage collector.
+**
+** MR_DEBUG_AGC_FORWARDING
+**	Display debugging information when leaving or finding forwarding
+**     pointers during accurate garbage collection.
+**
+** MR_DEBUG_AGC_PRINT_VARS
+**	Display the values of live variables during accurate garbage
+**	collection.
+**
+** MR_DEBUG_AGC
+** 	Turn on all debugging information for accurate garbage
+** 	collection.  (Equivalent to all MR_DEBUG_AGC_* macros above).
 */
 
 /*
diff -u runtime2/mercury_deep_copy.c runtime/mercury_deep_copy.c
--- runtime2/mercury_deep_copy.c	Tue Jun 30 16:56:26 1998
+++ runtime/mercury_deep_copy.c	Fri Jul  3 15:17:48 1998
@@ -9,7 +9,7 @@
 **
 ** Deep copy is used for a number of different purposes.  Each variant
 ** has the same basic control structure, but differs in how memory
-** is allocated, or forwarding pointers left behind, or 
+** is allocated, or whether forwarding pointers are left behind.
 */
 
 #include "mercury_imp.h"
@@ -29,6 +29,9 @@
 #define in_range(X)	(lower_limit == NULL || ((X) >= lower_limit &&	\
 				(X) <= upper_limit))
 
+#undef	maybeconst
+#define	maybeconst	const
+
 #undef  copy
 #define copy		deep_copy
 
@@ -53,6 +56,9 @@
 
 #undef  in_range
 #define in_range(X)	((X) >= lower_limit && (X) <= upper_limit)
+
+#undef	maybeconst
+#define	maybeconst
 
 #undef  copy
 #define copy		agc_deep_copy
diff -u runtime2/mercury_deep_copy.h runtime/mercury_deep_copy.h
--- runtime2/mercury_deep_copy.h	Tue Jun 30 16:55:49 1998
+++ runtime/mercury_deep_copy.h	Fri Jul  3 15:13:51 1998
@@ -65,8 +65,8 @@
 **	deep_copy to do both.
 */
 
-Word deep_copy(Word *data_ptr, Word *type_info, Word *lower_limit, 
-	Word *upper_limit);
+Word deep_copy(const Word *data_ptr, const Word *type_info, 
+	const Word *lower_limit, const Word *upper_limit);
 
 /*
 ** agc_deep_copy:
@@ -92,8 +92,8 @@
 **	Note: You cannot pass NULL as the lower_limit to agc_deep_copy
 **	(which is possible with normal deep_copy).
 */
-Word agc_deep_copy(Word *data_ptr, Word *type_info, Word *lower_limit, 
-	Word *upper_limit);
+Word agc_deep_copy(Word *data_ptr, const Word *type_info, 
+	const Word *lower_limit, const Word *upper_limit);
 
 /*
 ** MR_make_permanent:
diff -u runtime2/mercury_deep_copy_body.h runtime/mercury_deep_copy_body.h
--- runtime2/mercury_deep_copy_body.h	Tue Jun 30 16:14:37 1998
+++ runtime/mercury_deep_copy_body.h	Fri Jul  3 15:42:32 1998
@@ -16,14 +16,15 @@
 /*
 ** Prototypes.
 */
-static	Word	copy_arg(Word *data_ptr, Word *type_info, Word
-			*arg_type_info, Word *lower_limit, Word *upper_limit);
-static	Word	*copy_type_info(Word *type_info,
-			Word *lower_limit, Word *upper_limit);
+static	Word	copy_arg(maybeconst Word *data_ptr, const Word *type_info,
+			const Word *arg_type_info, const Word *lower_limit,
+			const Word *upper_limit);
+static	Word	*copy_type_info(maybeconst Word *type_info,
+			const Word *lower_limit, const Word *upper_limit);
 
 Word 
-copy(Word *data_ptr, Word *type_info, Word *lower_limit,
-		Word *upper_limit)
+copy(maybeconst Word *data_ptr, const Word *type_info, 
+		const Word *lower_limit, const Word *upper_limit)
 {
     Word *base_type_info, *base_type_layout, *base_type_functors;
     Word functors_indicator;
@@ -60,10 +61,10 @@
 	    Word *argument_vector, *type_info_vector;
             int arity, i;
 
-                /*
-                ** if the vector containing the secondary tags and the
-                ** arguments is in range, copy it.
-                */
+            /*
+            ** if the vector containing the secondary tags and the
+            ** arguments is in range, copy it.
+            */
             if (in_range(data_value)) {
                 secondary_tag = *data_value;
                 argument_vector = data_value + 1;
@@ -71,13 +72,13 @@
                 arity = new_entry[TYPELAYOUT_SIMPLE_ARITY_OFFSET];
                 type_info_vector = new_entry + TYPELAYOUT_SIMPLE_ARGS_OFFSET;
 
-                    /* allocate space for new args, and secondary tag */
+                /* allocate space for new args, and secondary tag */
                 incr_saved_hp(new_data, arity + 1);
 
-                    /* copy secondary tag */
+                /* copy secondary tag */
                 field(0, new_data, 0) = secondary_tag;
 
-                    /* copy arguments */
+                /* copy arguments */
                 for (i = 0; i < arity; i++) {
                     field(0, new_data, i + 1) = copy_arg(
                         &argument_vector[i], type_info,
@@ -85,7 +86,7 @@
                         upper_limit);
                 }
 
-                    /* tag this pointer */
+                /* tag this pointer */
                 new_data = (Word) mkword(data_tag, new_data);
                 leave_forwarding_pointer(data_ptr, new_data);
             } else {
@@ -100,21 +101,21 @@
 	    Word *argument_vector, *type_info_vector;
             argument_vector = data_value;
 
-                /* If the argument vector is in range, copy the arguments */
+            /* If the argument vector is in range, copy the arguments */
             if (in_range(argument_vector)) {
                 arity = entry_value[TYPELAYOUT_SIMPLE_ARITY_OFFSET];
                 type_info_vector = entry_value + TYPELAYOUT_SIMPLE_ARGS_OFFSET;
 
-                    /* allocate space for new args. */
+                /* allocate space for new args. */
                 incr_saved_hp(new_data, arity);
 
-                    /* copy arguments */
+                /* copy arguments */
                 for (i = 0; i < arity; i++) {
                     field(0, new_data, i) = copy_arg(&argument_vector[i],
                         type_info, (Word *) type_info_vector[i], lower_limit,
                         upper_limit);
                 }
-                    /* tag this pointer */
+                /* tag this pointer */
                 new_data = (Word) mkword(data_tag, new_data);
                 leave_forwarding_pointer(data_ptr, new_data);
             } else {
@@ -132,8 +133,9 @@
 
         case MR_DATAREP_EQUIV: 
             new_data = copy_arg(data_ptr, type_info, 
-                    (Word *) MR_TYPELAYOUT_EQUIV_TYPE((Word *) entry_value),
-                    lower_limit, upper_limit);
+		    (const Word *) MR_TYPELAYOUT_EQUIV_TYPE((Word *)
+                        entry_value),
+		    lower_limit, upper_limit);
             break;
 
         case MR_DATAREP_EQUIV_VAR:
@@ -149,10 +151,10 @@
         case MR_DATAREP_FLOAT:
 			#ifdef BOXED_FLOAT
                 if (in_range(data_value)) {
-                        /*
-                        ** force a deep copy by converting to float
-                        ** and back
-                        */
+                    /*
+                    ** force a deep copy by converting to float
+                    ** and back
+                    */
                     new_data = float_to_word(word_to_float(data));
                     leave_forwarding_pointer(data_ptr, new_data);
                 } else {
@@ -178,36 +180,35 @@
             break;
 
         case MR_DATAREP_PRED: {
-                /*
-                ** predicate closures store the number of curried
-                ** arguments as their first argument, the
-                ** Code * as their second, and then the
-                ** arguments
-                **
-                ** Their type-infos have a pointer to
-                ** base_type_info for pred/0, arity, and then
-                ** argument typeinfos.
-                **/
+            /*
+	    ** predicate closures store the number of curried arguments
+	    ** as their first argument, the Code * as their second, and
+	    ** then the arguments
+            **
+	    ** Their type-infos have a pointer to base_type_info for
+	    ** pred/0, arity, and then argument typeinfos.
+	    **/
             if (in_range(data_value)) {
                 int args, i;
                 Word *new_closure;
 
-                    /* get number of curried arguments */
+                /* get number of curried arguments */
                 args = data_value[0];
 
-                    /* create new closure */
+                /* create new closure */
                 incr_saved_hp(LVALUE_CAST(Word, new_closure), args + 2);
 
-                    /* copy number of arguments */
+                /* copy number of arguments */
                 new_closure[0] = args;
 
-                    /* copy pointer to code for closure */
+                /* copy pointer to code for closure */
                 new_closure[1] = data_value[1];
 
-                    /* copy arguments */
+                /* copy arguments */
                 for (i = 0; i < args; i++) {
                     new_closure[i + 2] = copy(&data_value[i + 2],
-                        (Word *) type_info[i + TYPEINFO_OFFSET_FOR_PRED_ARGS],
+                        (const Word *) 
+                        type_info[i + TYPEINFO_OFFSET_FOR_PRED_ARGS],
                         lower_limit, upper_limit);
                 }
                 new_data = (Word) new_closure;
@@ -220,11 +221,11 @@
             break;
         
         case MR_DATAREP_UNIV: 
-                /* if the univ is stored in range, copy it */ 
+            /* if the univ is stored in range, copy it */ 
             if (in_range(data_value)) {
                 Word *new_data_ptr;
 
-                    /* allocate space for a univ */
+                /* allocate space for a univ */
                 incr_saved_hp(new_data, 2);
                 new_data_ptr = (Word *) new_data;
                 new_data_ptr[UNIV_OFFSET_FOR_TYPEINFO] = 
@@ -233,7 +234,7 @@
                         lower_limit, upper_limit);
                 new_data_ptr[UNIV_OFFSET_FOR_DATA] = copy(
                         &data_value[UNIV_OFFSET_FOR_DATA], 
-                        (Word *) data_value[UNIV_OFFSET_FOR_TYPEINFO],
+                        (const Word *) data_value[UNIV_OFFSET_FOR_TYPEINFO],
                         lower_limit, upper_limit);
                 leave_forwarding_pointer(data_ptr, new_data);
             } else {
@@ -261,7 +262,7 @@
                 for (i = 0; i < array_size; i++) {
                     new_array->elements[i] = copy_arg(
                         &old_array->elements[i], type_info, 
-                        (Word *) 1, lower_limit, upper_limit);
+                        (const Word *) 1, lower_limit, upper_limit);
                 }
                 new_data = (Word) new_array;
                 leave_forwarding_pointer(data_ptr, new_data);
@@ -306,8 +307,9 @@
 ** which refer to arguments of the term_type_info.
 */
 static Word
-copy_arg(Word *data_ptr, Word *term_type_info, Word *arg_pseudo_type_info,
-		Word *lower_limit, Word *upper_limit)
+copy_arg(maybeconst Word *data_ptr, const Word *term_type_info,
+		const Word *arg_pseudo_type_info, const Word *lower_limit,
+		const Word *upper_limit)
 {
 	MR_MemoryList allocated_memory_cells;
 	Word *new_type_info;
@@ -324,7 +326,8 @@
 
 
 Word *
-copy_type_info(Word *type_info_ptr, Word *lower_limit, Word *upper_limit)
+copy_type_info(maybeconst Word *type_info_ptr, const Word *lower_limit,
+		const Word *upper_limit)
 {
 	Word *type_info = (Word *) *type_info_ptr;
 
@@ -335,7 +338,8 @@
 
 		/* XXX this doesn't handle higher-order types properly */
 
-		base_type_info = MR_TYPEINFO_GET_BASE_TYPEINFO(type_info);
+		base_type_info = MR_TYPEINFO_GET_BASE_TYPEINFO((Word *)
+			type_info);
 		arity = MR_BASE_TYPEINFO_GET_TYPE_ARITY(base_type_info);
 		incr_saved_hp(LVALUE_CAST(Word, new_type_info), arity + 1);
 		new_type_info[0] = type_info[0];
diff -u runtime2/mercury_label.h runtime/mercury_label.h
--- runtime2/mercury_label.h	Wed Jun 24 12:26:15 1998
+++ runtime/mercury_label.h	Fri Jul  3 15:44:55 1998
@@ -22,7 +22,7 @@
 	const char	*e_name;   /* name of the procedure	     */
 	Code		*e_addr;   /* address of the code	     */
 	Word		*e_layout; /* layout info for the label      */
-	bool		*e_entry;  /* yes if this is an entry        */
+	bool		e_entry;  /* yes if this is an entry        */
 } Label;
 
 extern	void	do_init_entries(void);
diff -u runtime2/mercury_memory.h runtime/mercury_memory.h
--- runtime2/mercury_memory.h	Wed Jun 24 12:25:47 1998
+++ runtime/mercury_memory.h	Fri Jul  3 14:38:11 1998
@@ -105,5 +105,16 @@
 extern size_t          unit;
 extern size_t          page_size;
 
+/*
+** Users need to call MR_add_root() for any global variable which
+** contains pointers to the Mercury heap.  This information is only
+** used for agc grades.
+*/
+#ifdef NATIVE_GC
+  #define MR_add_root(root_ptr, type_info) \
+	MR_agc_add_root((root_ptr), (type_info))
+#else
+  #define MR_add_root(root_ptr, type_info) /* nothing */
+#endif
 
 #endif /* not MERCURY_MEMORY_H */
diff -u runtime2/mercury_trace_util.c runtime/mercury_trace_util.c
--- runtime2/mercury_trace_util.c	Tue Jun 30 14:39:36 1998
+++ runtime/mercury_trace_util.c	Fri Jul  3 14:57:17 1998
@@ -335,10 +335,10 @@
 	** them.
 	*/
 
-		restore_transient_registers();
-		r1 = type_info;
-		r2 = value;
-		save_transient_registers();
-		call_engine(MR_library_trace_browser);
+	restore_transient_registers();
+	r1 = type_info;
+	r2 = value;
+	save_transient_registers();
+	call_engine(MR_library_trace_browser);
 }
 
diff -u runtime2/mercury_trace_util.h runtime/mercury_trace_util.h
--- runtime2/mercury_trace_util.h	Wed Jul  1 15:03:11 1998
+++ runtime/mercury_trace_util.h	Fri Jul  3 14:57:42 1998
@@ -28,10 +28,10 @@
 			bool saved_regs_valid, Word *base_sp, Word *base_curfr,
 			Word *type_params, Word *type_info, Word *value);
 
-	/*
-	** MR_trace_write_variable:
-	** 	Write a variable to stdout.
-	*/
+/*
+** MR_trace_write_variable:
+**	Write a variable to stdout.
+*/
 extern	void	MR_trace_write_variable(Word type_info, Word value);
 
 #endif	/* MERCURY_TRACE_UTIL_H */
diff -u runtime2/mercury_type_info.c runtime/mercury_type_info.c
--- runtime2/mercury_type_info.c	Mon Jun 29 17:25:51 1998
+++ runtime/mercury_type_info.c	Fri Jul  3 15:50:26 1998
@@ -452,7 +452,7 @@
 	*/
 
 Word *
-MR_make_type_info(Word *term_type_info, Word *arg_pseudo_type_info,
+MR_make_type_info(const Word *term_type_info, const Word *arg_pseudo_type_info,
 	MR_MemoryList *allocated) 
 {
 	int i, arity, extra_args;
@@ -478,7 +478,7 @@
 
 	/* no arguments - optimise common case */
 	if (base_type_info == arg_pseudo_type_info) {
-		return arg_pseudo_type_info;
+		return base_type_info;
 	} 
 
 	if (MR_BASE_TYPEINFO_IS_HO(base_type_info)) {
@@ -533,7 +533,7 @@
 		}
 	}
 	if (type_info == NULL) {
-		return arg_pseudo_type_info;
+		return (Word *) (Word) arg_pseudo_type_info;
 	} else {
 		return type_info;
 	}
diff -u runtime2/mercury_type_info.h runtime/mercury_type_info.h
--- runtime2/mercury_type_info.h	Fri Jun 26 16:38:12 1998
+++ runtime/mercury_type_info.h	Fri Jul  3 15:48:40 1998
@@ -662,7 +662,7 @@
 	*/
 
 #define MR_TYPEINFO_GET_BASE_TYPEINFO(TypeInfo)				\
-		((*TypeInfo) ? ((Word *) *TypeInfo) : TypeInfo)
+		((*TypeInfo) ? (Word *) *TypeInfo : (Word *) (Word) TypeInfo)
 
 #define MR_TYPEINFO_GET_HIGHER_ARITY(TypeInfo)				\
 		((Integer) (Word *) (TypeInfo)[TYPEINFO_OFFSET_FOR_PRED_ARITY]) 
@@ -795,10 +795,8 @@
 };
 typedef struct MR_MemoryCellNode *MR_MemoryList;
 
-Word * MR_make_type_info(Word *term_type_info, Word *arg_pseudo_type_info,
-	MR_MemoryList *allocated);
-Word * MR_make_type_info_tabled(Word *term_type_info,
-	Word *arg_pseudo_type_info);
+Word * MR_make_type_info(const Word *term_type_info, 
+	const Word *arg_pseudo_type_info, MR_MemoryList *allocated);
 void MR_deallocate(MR_MemoryList allocated_memory_cells);
 
 /*---------------------------------------------------------------------------*/

-- 
       Tyson Dowd           # There isn't any reason why Linux can't be
                            # implemented as an enterprise computing solution.
     trd at cs.mu.oz.au        # Find out what you've been missing while you've
http://www.cs.mu.oz.au/~trd # been rebooting Windows NT. -- InfoWorld, 1998.



More information about the developers mailing list