[m-rev.] for review: fix bugs in runtime support of deep profiling

Zoltan Somogyi zs at csse.unimelb.edu.au
Wed Oct 11 13:40:21 AEST 2006


For review by Julien. The corresponding update of the deep profiler
is in the next message.

Zoltan.

Fix three bugs in the runtime system's support for deep profiling.

runtime/mercury_heap.h:
	One bug was that information about memory allocations wasn't being
	collected. The problem was that code fragment that incremented
	the relevant fields of the current call site dynamic structure was
	being invoked from a set of macros that the compiler doesn't emit
	in deep profiling grades.

	The fix is to invoke that code fragment from the basic macros that
	all the others in mercury_heap.h are built upon. Apply the same fix
	to the code fragment that gathers information for complexity analysis.

	To prevent such problems from arising in the future, document the
	layers of macros defined in this module. Move some macros around
	to yield a consistent structure (to make the documentation easier).

	Convert to four-space indentation.

runtime/mercury_deep_*_port_body.h:
	The second bug was that we collected the wrong sort of call sequence
	number information. We tried to define the call sequence number field
	(MR_own_call_seqs) of call dynamic structures to make them contain,
	for each call, a number proportional to the time from the start of
	the call to the end of the call. The problems with this is that
	all the other cost measure fields of the call site structure
	(time quanta, number of memory allocations, number of words allocated)
	were non-cumulative; e.g. the time quanta field was incremented only
	when a clock interrupt happened inside the code of the called
	predicate, not in its descendants. Propagating the costs of
	descendants to the ancestors is the deep profiler's job. By including
	the cost of descendants in the MR_own_call_seqs field, the propagation
	algorithm of the deep profiler actually screws up the call sequence
	number information, by including the cost of descendants twice.
	We could modify the propagation algorithm to avoid double-propagating
	call sequence number information, but it would be a significant coding
	job.

	The much simpler fix is to treat the increment of the call sequence
	number the same way we handle a profiling interrupt: we increment
	the relevant field of the current call site dynamic structure.

runtime/mercury_deep_profiling.h:
	The third bug was that we were using the mask value of 0x10 to signify
	both the presence of a nonzero exception count and a nonzero number of
	allocations count. The former was a typo.

	Change the data format number, since the meaning of the call sequence
	number field has changed.

runtime/mercury_context.h:
	Add a missing MR_ prefix in a comment.

runtime/mercury_heap_profile.h:
	Fix some formatting.

cvs diff: Diffing .
cvs diff: Diffing analysis
cvs diff: Diffing bindist
cvs diff: Diffing boehm_gc
cvs diff: Diffing boehm_gc/Mac_files
cvs diff: Diffing boehm_gc/cord
cvs diff: Diffing boehm_gc/cord/private
cvs diff: Diffing boehm_gc/doc
cvs diff: Diffing boehm_gc/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing boehm_gc/libatomic_ops-1.2
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/doc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/gcc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/hpc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/ibmc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/icc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/msftc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/src/atomic_ops/sysdeps/sunc
cvs diff: Diffing boehm_gc/libatomic_ops-1.2/tests
cvs diff: Diffing boehm_gc/tests
cvs diff: Diffing boehm_gc/windows-untested
cvs diff: Diffing boehm_gc/windows-untested/vc60
cvs diff: Diffing boehm_gc/windows-untested/vc70
cvs diff: Diffing boehm_gc/windows-untested/vc71
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing debian/patches
cvs diff: Diffing deep_profiler
cvs diff: Diffing deep_profiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/concurrency
cvs diff: Diffing extras/curs
cvs diff: Diffing extras/curs/samples
cvs diff: Diffing extras/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
cvs diff: Diffing extras/error
cvs diff: Diffing extras/gator
cvs diff: Diffing extras/gator/generations
cvs diff: Diffing extras/gator/generations/1
cvs diff: Diffing extras/graphics
cvs diff: Diffing extras/graphics/easyx
cvs diff: Diffing extras/graphics/easyx/samples
cvs diff: Diffing extras/graphics/mercury_glut
cvs diff: Diffing extras/graphics/mercury_opengl
cvs diff: Diffing extras/graphics/mercury_tcltk
cvs diff: Diffing extras/graphics/samples
cvs diff: Diffing extras/graphics/samples/calc
cvs diff: Diffing extras/graphics/samples/gears
cvs diff: Diffing extras/graphics/samples/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/lazy_evaluation
cvs diff: Diffing extras/lex
cvs diff: Diffing extras/lex/samples
cvs diff: Diffing extras/lex/tests
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
cvs diff: Diffing extras/moose/tests
cvs diff: Diffing extras/morphine
cvs diff: Diffing extras/morphine/non-regression-tests
cvs diff: Diffing extras/morphine/scripts
cvs diff: Diffing extras/morphine/source
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/posix
cvs diff: Diffing extras/quickcheck
cvs diff: Diffing extras/quickcheck/tutes
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/solver_types
cvs diff: Diffing extras/solver_types/library
cvs diff: Diffing extras/stream
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing extras/windows_installer_generator
cvs diff: Diffing extras/windows_installer_generator/sample
cvs diff: Diffing extras/windows_installer_generator/sample/images
cvs diff: Diffing extras/xml
cvs diff: Diffing extras/xml/samples
cvs diff: Diffing extras/xml_stylesheets
cvs diff: Diffing java
cvs diff: Diffing java/runtime
cvs diff: Diffing library
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/mercury_context.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_context.h,v
retrieving revision 1.33
diff -u -r1.33 mercury_context.h
--- runtime/mercury_context.h	3 Oct 2006 11:41:46 -0000	1.33
+++ runtime/mercury_context.h	10 Oct 2006 05:32:56 -0000
@@ -120,11 +120,11 @@
 **
 ** 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 macro set_min_heap_reclamation_point below.
+**                  before the macro MR_set_min_heap_reclamation_point below.
 */
 
-typedef struct MR_Context_Struct MR_Context;
-typedef struct MR_Spark_Struct MR_Spark;
+typedef struct MR_Context_Struct    MR_Context;
+typedef struct MR_Spark_Struct      MR_Spark;
 
 typedef enum {
     MR_CONTEXT_SIZE_REGULAR,
@@ -185,18 +185,19 @@
 /*
 ** A spark contains just enough information to begin execution of a parallel
 ** conjunct.  Sparks are allocated on the heap, and can be stored in a
-** context's spark stack, or in the global spark queue.  In the former case, a
-** spark will eventually be executed in the same context (same detstack, etc.)
-** as the code that generated the spark.  In the latter case the spark can be
-** picked up and executed by any idle engine in a different context.
+** context's spark stack, or in the global spark queue.  In the former case,
+** a spark will eventually be executed in the same context (same detstack,
+** etc.) as the code that generated the spark. In the latter case the spark
+** can be picked up and executed by any idle engine in a different context.
 **
 ** In the current implementation a spark is put on the global spark queue if,
 ** at the time a fork instruction is reached, we think the spark has a chance
 ** of being picked up for execution by an idle engine.  Otherwise the spark
-** goes on the context's spark stack. At the moment is an irrevocable decision.
-** A future possibility is to allow idle engines to steal work from the cold
-** end of some context's spark stack.
+** goes on the context's spark stack. At the moment this is an irrevocable
+** decision. A future possibility is to allow idle engines to steal work
+** from the cold end of some context's spark stack.
 */
+
 #ifndef MR_HIGHLEVEL_CODE
 struct MR_Spark_Struct {
     MR_Spark            *MR_spark_next;
@@ -212,6 +213,7 @@
 ** computations which have already started) over sparks (which are
 ** computations which have not begun).
 */
+
 extern      MR_Context  *MR_runqueue_head;
 extern      MR_Context  *MR_runqueue_tail;
 #ifndef MR_HIGHLEVEL_CODE
Index: runtime/mercury_deep_call_port_body.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_deep_call_port_body.h,v
retrieving revision 1.6
diff -u -r1.6 mercury_deep_call_port_body.h
--- runtime/mercury_deep_call_port_body.h	4 Oct 2006 06:59:22 -0000	1.6
+++ runtime/mercury_deep_call_port_body.h	10 Oct 2006 09:43:37 -0000
@@ -68,8 +68,8 @@
   #endif
 
   #ifdef MR_DEEP_PROFILING_CALL_SEQ
+	csd->MR_csd_own.MR_own_call_seqs++;
 	MR_deep_prof_cur_call_seq++;
-	csd->MR_csd_own.MR_own_call_seqs -= MR_deep_prof_cur_call_seq;
   #endif
 
   #ifdef MR_DEEP_PROFILING_LOWLEVEL_DEBUG
Index: runtime/mercury_deep_leave_port_body.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_deep_leave_port_body.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_deep_leave_port_body.h
--- runtime/mercury_deep_leave_port_body.h	4 Oct 2006 06:59:23 -0000	1.5
+++ runtime/mercury_deep_leave_port_body.h	10 Oct 2006 09:43:46 -0000
@@ -58,10 +58,6 @@
     #endif
   #endif
 
-  #ifdef MR_DEEP_PROFILING_CALL_SEQ
-	csd->MR_csd_own.MR_own_call_seqs += MR_deep_prof_cur_call_seq;
-  #endif
-
 	MR_deep_assert(csd, NULL, NULL, csd->MR_csd_callee_ptr != NULL);
 	pl = csd->MR_csd_callee_ptr->MR_pd_proc_layout;
 	MR_deep_assert(csd, pl, NULL, pl != NULL);
Index: runtime/mercury_deep_profiling.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_deep_profiling.c,v
retrieving revision 1.23
diff -u -r1.23 mercury_deep_profiling.c
--- runtime/mercury_deep_profiling.c	5 Oct 2006 04:37:59 -0000	1.23
+++ runtime/mercury_deep_profiling.c	10 Oct 2006 09:43:19 -0000
@@ -649,7 +649,7 @@
 MR_write_out_id_string(FILE *fp)
 {
     /* Must be the same as id_string in deep_profiler/read_profile.m */
-    const char  *id_string = "Mercury deep profiler data version 2\n";
+    const char  *id_string = "Mercury deep profiler data version 3\n";
 
     fputs(id_string, fp);
 }
@@ -925,7 +925,7 @@
         bitmask |= 0x0040;
     }
     if (csd->MR_csd_own.MR_own_excps != 0) {
-        bitmask |= 0x0010;
+        bitmask |= 0x0080;
     }
 #endif
 #ifdef MR_DEEP_PROFILING_TIMING
Index: runtime/mercury_deep_redo_port_body.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_deep_redo_port_body.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_deep_redo_port_body.h
--- runtime/mercury_deep_redo_port_body.h	4 Oct 2006 06:59:23 -0000	1.5
+++ runtime/mercury_deep_redo_port_body.h	10 Oct 2006 09:43:53 -0000
@@ -43,10 +43,6 @@
 	csd->MR_csd_own.MR_own_redos++;
   #endif
 
-  #ifdef MR_DEEP_PROFILING_CALL_SEQ
-	csd->MR_csd_own.MR_own_call_seqs -= MR_deep_prof_cur_call_seq;
-  #endif
-
 	pd = csd->MR_csd_callee_ptr;
 	MR_deep_assert(csd, NULL, NULL, pd != NULL);
 	pl = pd->MR_pd_proc_layout;
Index: runtime/mercury_heap.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_heap.h,v
retrieving revision 1.36
diff -u -r1.36 mercury_heap.h
--- runtime/mercury_heap.h	20 Aug 2006 05:01:48 -0000	1.36
+++ runtime/mercury_heap.h	10 Oct 2006 09:45:29 -0000
@@ -1,25 +1,43 @@
 /*
+** vim: ts=4 sw=4 et
+*/
+/*
 ** Copyright (C) 1995-2006 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
 */
 
-/* mercury_heap.h - definitions for manipulating the Mercury heap */
+/*
+** mercury_heap.h - definitions for manipulating the Mercury heap.
+**
+** This file defines several levels of macros for allocating space on
+** the Mercury heap.
+**
+** It would be simpler if all these macros expanded out to statements. However,
+** many cannot, since they must be usable inside expressions. The ultimate
+** reason for this is MR_float_to_word, which is used not just as an operand
+** in expressions, but also as an initializer in static cells generated
+** by the compiler.
+**
+** Note: the macros that take a proclabel as argument do not put parentheses
+** around it. The reason is that we may need to put the `_entry_' prefix
+** in front of the label name, which wouldn't work if it was parenthesized.
+*/
 
 #ifndef MERCURY_HEAP_H
 #define MERCURY_HEAP_H
 
-#include "mercury_conf.h"		/* for MR_CONSERVATIVE_GC */
-#include "mercury_conf_param.h"		/* for MR_RECORD_TERM_SIZES */
-#include "mercury_types.h"		/* for `MR_Word' */
-#include "mercury_context.h"		/* for min_heap_reclamation_point() */
-#include "mercury_heap_profile.h"	/* for MR_record_allocation() */
-#include "mercury_deep_profiling.h"	/* for MR_current_call_site_dynamic */
-#include "mercury_std.h"		/* for MR_EXTERN_INLINE */
-#include "mercury_reg_workarounds.h"	/* for MR_memcpy */
-#include "mercury_debug.h"		/* for MR_debugtagoffsetincrhp* */
+#include "mercury_conf.h"               /* for MR_CONSERVATIVE_GC */
+#include "mercury_conf_param.h"         /* for MR_RECORD_TERM_SIZES */
+#include "mercury_types.h"              /* for `MR_Word' */
+#include "mercury_context.h"            /* for min_heap_reclamation_point() */
+#include "mercury_heap_profile.h"       /* for MR_record_allocation() */
+#include "mercury_deep_profiling.h"     /* for MR_current_call_site_dynamic */
+#include "mercury_std.h"               /* for MR_EXTERN_INLINE */
+#include "mercury_reg_workarounds.h"    /* for MR_memcpy */
+#include "mercury_debug.h"              /* for MR_debugtagoffsetincrhp* */
 #ifdef MR_HIGHLEVEL_CODE
-  #include "mercury.h"			/* for MR_new_object() */
+  #include "mercury.h"                  /* for MR_new_object() */
 #endif
 
 #ifdef MR_CONSERVATIVE_GC
@@ -32,47 +50,71 @@
   #endif
 #endif
 
+/***************************************************************************/
+
 /*
-** Unfortunately, the following macros cannot expand to statements;
-** they must be usable inside expressions. The ultimate reason for this is
-** MR_float_to_word, which is used not just as an operand in expressions,
-** but also as an initializer in static cells generated by the compiler.
+** The first level of heap allocation macros. These are concerned with
+** the raw business of allocating memory, taking and restoring snapshots
+** of the state of the heap, and recording profiling information for the
+** profdeep grade and complexity experiments.
 */
 
 #ifdef MR_DEBUG_HEAP_ALLOC
+  #define   MR_tag_offset_sanity_check(offset, count)                       \
+            ( ((offset) >= (count))                                         \
+                ? MR_fatal_error("MR_tag_offset_sanity_check failed")       \
+                : ((void) 0)                                                \
+            )
+#else
+  #define   MR_tag_offset_sanity_check(offset, count)                       \
+            ((void) 0)
+#endif
 
-    #define MR_tag_offset_sanity_check(offset, count)			\
-	( ((offset) >= (count))						\
-		? MR_fatal_error("MR_tag_offset_sanity_check failed")	\
-		: ((void) 0)						\
-	)
-
-#else /* ! MR_DEBUG_HEAP_ALLOC */
-
-  #define MR_tag_offset_sanity_check(offset, count)	((void) 0)
+#ifdef  MR_RECORD_TERM_SIZES
+  #define   MR_maybe_increment_complexity_counters(count)                   \
+            (                                                               \
+                MR_complexity_word_counter += (count),                      \
+                MR_complexity_cell_counter += 1                             \
+            )
+#else
+  #define   MR_maybe_increment_complexity_counters(count)                   \
+            ((void) 0)
+#endif
 
-#endif /* MR_DEBUG_HEAP_ALLOC */
+#if defined (MR_DEEP_PROFILING) && defined(MR_DEEP_PROFILING_MEMORY)
+  #define   MR_profdeep_maybe_record_allocation(count)                      \
+            (                                                               \
+                MR_current_call_site_dynamic->MR_csd_own.MR_own_allocs += 1,\
+                MR_current_call_site_dynamic->MR_csd_own.MR_own_words       \
+                    += (count)                                              \
+            )
+#else
+  #define   MR_profdeep_maybe_record_allocation(count)                      \
+            ((void) 0)
+#endif
 
 #ifdef MR_CONSERVATIVE_GC
 
-  #define MR_tag_offset_incr_hp_base(dest, tag, offset, count,		\
-		alloc, is_atomic)					\
-	(								\
-		MR_tag_offset_sanity_check((offset), (count)),		\
-		(dest) = (MR_Word) MR_mkword((tag), (MR_Word)		\
-			(((MR_Word *) alloc((count) * sizeof(MR_Word)))	\
-				+ (offset))),				\
-		MR_debug_tag_offset_incr_hp_base((dest), (tag), (offset), \
-			(count), (is_atomic)),				\
-		/* return */ (dest)					\
-	)
-
-  #define MR_tag_offset_incr_hp_n(dest, tag, offset, count)		\
-	MR_tag_offset_incr_hp_base(dest, tag, offset, count,		\
-		GC_MALLOC, 0)
-  #define MR_tag_offset_incr_hp_atomic(dest, tag, offset, count)	\
-	MR_tag_offset_incr_hp_base(dest, tag, offset, count,		\
-		GC_MALLOC_ATOMIC, 1)
+  #define   MR_tag_offset_incr_hp_base(dest, tag, offset, count, alloc,     \
+                is_atomic)                                                  \
+            (                                                               \
+                MR_tag_offset_sanity_check((offset), (count)),              \
+                MR_maybe_increment_complexity_counters((count)),            \
+                MR_profdeep_maybe_record_allocation((count)),               \
+                (dest) = (MR_Word) MR_mkword((tag), (MR_Word)               \
+                    (((MR_Word *) alloc((count) * sizeof(MR_Word)))         \
+                        + (offset))),                                       \
+                MR_debug_tag_offset_incr_hp_base((dest), (tag), (offset),   \
+                    (count), (is_atomic)),                                  \
+                /* return */ (dest)                                         \
+            )
+
+  #define   MR_tag_offset_incr_hp_n(dest, tag, offset, count)               \
+            MR_tag_offset_incr_hp_base(dest, tag, offset, count,            \
+                GC_MALLOC, 0)
+  #define   MR_tag_offset_incr_hp_atomic(dest, tag, offset, count)          \
+            MR_tag_offset_incr_hp_base(dest, tag, offset, count,            \
+                GC_MALLOC_ATOMIC, 1)
 
   #ifdef MR_INLINE_ALLOC
 
@@ -105,206 +147,327 @@
     #endif
 
     #include "gc_inline.h"
-    #define MR_tag_offset_incr_hp(dest, tag, offset, count)		\
-	( __builtin_constant_p(count) && (count) < 16			\
-	? ({	void * temp;						\
-		/* if size > 1, round up to an even number of words */	\
-		MR_Word num_words = ((count) == 1 ? 1 :			\
-			2 * (((count) + 1) / 2));			\
-		GC_MALLOC_WORDS(temp, num_words);			\
-		temp = (void *) (((MR_Word *) temp) + (offset));	\
-		(dest) = (MR_Word) MR_mkword((tag), temp);		\
-	  })								\
-	: MR_tag_offset_incr_hp_n((dest), (tag), (offset), (count))	\
-	)
-
-  #else /* not MR_INLINE_ALLOC */
-
-    #define MR_tag_offset_incr_hp(dest, tag, offset, count)		\
-	MR_tag_offset_incr_hp_n((dest), (tag), (offset), (count))
-
-  #endif /* not MR_INLINE_ALLOC */
-
-  #define MR_mark_hp(dest)		((void)0)
-  #define MR_restore_hp(src)		((void)0)
-
-		/* we use `MR_hp' as a convenient temporary here */
-  #define MR_hp_alloc(count) (						\
-		MR_offset_incr_hp(MR_hp_word, 0, (count)),		\
-		MR_hp_word = (MR_Word) (MR_hp + (count)),		\
-		(void) 0						\
-	)
-  #define MR_hp_alloc_atomic(count) (					\
-		MR_offset_incr_hp_atomic(MR_hp_word, 0, (count)),	\
-		MR_hp_word = (MR_Word) (MR_hp + (count)),		\
-		(void) 0						\
-	)
-
-  #define MR_free_heap(ptr)	GC_FREE((ptr))
+    #define MR_tag_offset_incr_hp(dest, tag, offset, count)                 \
+            ( __builtin_constant_p(count) && (count) < 16                   \
+            ? ({                                                            \
+                void    *temp;                                              \
+                                                                            \
+                MR_tag_offset_sanity_check((offset), (count)),              \
+                MR_maybe_increment_complexity_counters((count)),            \
+                MR_profdeep_maybe_record_allocation((count)),               \
+                /* if size > 1, round up to an even number of words */      \
+                MR_Word num_words = ((count) == 1 ? 1 :                     \
+                    2 * (((count) + 1) / 2));                               \
+                GC_MALLOC_WORDS(temp, num_words);                           \
+                temp = (void *) (((MR_Word *) temp) + (offset));            \
+                (dest) = (MR_Word) MR_mkword((tag), temp);                  \
+              })                                                            \
+            : MR_tag_offset_incr_hp_n((dest), (tag), (offset), (count))     \
+            )
+
+  #else /* !MR_INLINE_ALLOC */
+
+    #define MR_tag_offset_incr_hp(dest, tag, offset, count)                 \
+            MR_tag_offset_incr_hp_n((dest), (tag), (offset), (count))
+
+  #endif /* MR_INLINE_ALLOC */
+
+  #define   MR_mark_hp(dest)        ((void) 0)
+  #define   MR_restore_hp(src)      ((void) 0)
+  #define   MR_free_heap(ptr)       GC_FREE((ptr))
 
 #else /* not MR_CONSERVATIVE_GC */
 
-  #define MR_tag_offset_incr_hp_base(dest, tag, offset, count, is_atomic) \
-	(								\
-		MR_tag_offset_sanity_check((offset), (count)),		\
-		(dest) = (MR_Word) MR_mkword(tag, (MR_Word)		\
-			(((MR_Word *) MR_hp) + (offset))),		\
-		MR_debug_tag_offset_incr_hp_base((dest), (tag), (offset), \
-			(count), (is_atomic)),				\
-		MR_hp_word = (MR_Word) (MR_hp + (count)),		\
-		MR_heap_overflow_check(),				\
-		(void) 0						\
-	)
-
-  #define MR_tag_offset_incr_hp(dest, tag, offset, count)		\
-	MR_tag_offset_incr_hp_base((dest), (tag), (offset), (count), 0)
-  #define MR_tag_offset_incr_hp_atomic(dest, tag, offset, count)	\
-	MR_tag_offset_incr_hp_base((dest), (tag), (offset), (count), 1)
+  #define   MR_tag_offset_incr_hp_base(dest, tag, offset, count, is_atomic) \
+            (                                                               \
+                MR_tag_offset_sanity_check((offset), (count)),              \
+                MR_maybe_increment_complexity_counters((count)),            \
+                MR_profdeep_maybe_record_allocation((count)),               \
+                (dest) = (MR_Word) MR_mkword(tag, (MR_Word)                 \
+                    (((MR_Word *) MR_hp) + (offset))),                      \
+                MR_debug_tag_offset_incr_hp_base((dest), (tag), (offset),   \
+                    (count), (is_atomic)),                                  \
+                MR_hp_word = (MR_Word) (MR_hp + (count)),                   \
+                MR_heap_overflow_check(),                                   \
+                (void) 0                                                    \
+            )
+
+  #define   MR_tag_offset_incr_hp(dest, tag, offset, count)                 \
+            MR_tag_offset_incr_hp_base((dest), (tag), (offset), (count), 0)
+  #define   MR_tag_offset_incr_hp_atomic(dest, tag, offset, count)          \
+            MR_tag_offset_incr_hp_base((dest), (tag), (offset), (count), 1)
 
-  #define MR_mark_hp(dest)		((dest) = MR_hp_word)
+  #define   MR_mark_hp(dest)      ((dest) = MR_hp_word)
 
   /*
   ** When restoring MR_hp, we must make sure that we don't truncate the heap
   ** further than it is safe to. We can only truncate it as far as
   ** min_heap_reclamation_point. See the comments in mercury_context.h next to
-  ** the set_min_heap_reclamation_point() macro.
+  ** the MR_set_min_heap_reclamation_point() macro.
   */
-  #define MR_restore_hp(src)						\
-		(							\
-			MR_hp_word = (MR_Word) (src),			\
-			(void) 0					\
-		)
+  #define   MR_restore_hp(src)                                              \
+            (                                                               \
+                MR_hp_word = (MR_Word) (src),                               \
+                (void) 0                                                    \
+            )
+
+#if 0
+  #define   MR_restore_hp(src)                                              \
+            (                                                               \
+                MR_hp_word = (MR_Word)                                      \
+                  ( (MR_Word) MR_min_hp_rec < (src) ?                       \
+                  (src) : (MR_Word) MR_min_hp_rec ),                        \
+                (void) 0                                                    \
+            )
+#endif
 
-  /*
-  #define	MR_restore_hp(src)					\
-		(							\
-			MR_hp_word = (MR_Word)
-			  ( (MR_Word) MR_min_hp_rec < (src) ?		\
-			  (src) : (MR_Word) MR_min_hp_rec ),		\
-			(void) 0					\
-		)
-  */
+  #define   MR_free_heap(ptr)     ((void) 0)
 
-  #define MR_hp_alloc(count)		MR_offset_incr_hp(MR_hp_word,	\
-						0, (count))
-  #define MR_hp_alloc_atomic(count)	MR_offset_incr_hp_atomic(MR_hp_word, \
-						0, (count))
+#endif /* not MR_CONSERVATIVE_GC */
 
-  #define MR_free_heap(ptr)		((void) 0)
+/***************************************************************************/
 
-#endif /* not MR_CONSERVATIVE_GC */
+/*
+** The second level of heap allocation macros. These are concerned with
+** recording profiling information for profmem grades.
+*/
 
-#ifdef	MR_RECORD_TERM_SIZES
-  #define MR_maybe_increment_allocation_counters(count)			\
-	(								\
-	 	MR_complexity_word_counter += (count),			\
-		MR_complexity_cell_counter += 1				\
-	)
+#if defined(MR_MPROF_PROFILE_MEMORY)
+  #define   MR_profmem_record_allocation(count, proclabel, type)            \
+            MR_record_allocation((count), MR_ENTRY(proclabel),              \
+                MR_STRINGIFY(proclabel), (type))
 #else
-  #define MR_maybe_increment_allocation_counters(count)			\
-	((void) 0)
+  #define   MR_profmem_record_allocation(count, proclabel, type)            \
+            ((void) 0)
 #endif
 
-#if	defined (MR_DEEP_PROFILING) && defined(MR_DEEP_PROFILING_MEMORY)
-  #define MR_prof_record_allocation(count, proclabel, type)		\
-	(								\
-		MR_current_call_site_dynamic->MR_csd_own.MR_own_allocs	\
-			+= 1,						\
-		MR_current_call_site_dynamic->MR_csd_own.MR_own_words	\
-			+= (count)					\
-	)
-#elif	defined(MR_MPROF_PROFILE_MEMORY)
-  #define MR_prof_record_allocation(count, proclabel, type)		\
-	MR_record_allocation((count), MR_ENTRY(proclabel),		\
-		MR_STRINGIFY(proclabel), (type))
-#else
-  #define MR_prof_record_allocation(count, proclabel, type)		\
-	((void) 0)
-#endif
+#define     MR_tag_offset_incr_hp_msg(dest, tag, offset, count,             \
+                proclabel, type)                                            \
+            (                                                               \
+                MR_profmem_record_allocation((count), proclabel, (type)),   \
+                MR_tag_offset_incr_hp((dest), (tag), (offset), (count))     \
+            )
+#define     MR_tag_offset_incr_hp_atomic_msg(dest, tag, offset, count,      \
+                proclabel, type)                                            \
+            (                                                               \
+                MR_profmem_record_allocation((count), proclabel, (type)),   \
+                MR_tag_offset_incr_hp_atomic((dest), (tag), (offset),       \
+                    (count))                                                \
+            )
 
-#define	MR_maybe_record_allocation(count, proclabel, type)		\
-	(								\
-		MR_prof_record_allocation((count), proclabel, (type)),	\
-		MR_maybe_increment_allocation_counters(count)		\
-	)
-
-#define MR_tag_offset_incr_hp_msg(dest, tag, offset, count, proclabel, type) \
-	(								\
-		MR_maybe_record_allocation((count), proclabel, (type)),	\
-		MR_tag_offset_incr_hp((dest), (tag), (offset), (count))	\
-	)
-#define MR_tag_offset_incr_hp_atomic_msg(dest, tag, offset, count, proclabel, type) \
-	(								\
-		MR_maybe_record_allocation((count), proclabel, (type)),	\
-		MR_tag_offset_incr_hp_atomic((dest), (tag), (offset), (count)) \
-	)
-
-#define MR_tag_incr_hp(dest, tag, count)				\
-	MR_tag_offset_incr_hp((dest), (tag), 0, (count))
-#define MR_tag_incr_hp_atomic(dest, tag, count)				\
-	MR_tag_offset_incr_hp_atomic((dest), (tag), 0, (count))
-#define MR_tag_incr_hp_msg(dest, tag, count, proclabel, type)		\
-	MR_tag_offset_incr_hp_msg((dest), (tag), 0, (count),		\
-		proclabel, (type))
-#define MR_tag_incr_hp_atomic_msg(dest, tag, count, proclabel, type)	\
-	MR_tag_offset_incr_hp_atomic_msg((dest), (tag), 0, (count),	\
-		proclabel, (type))
+/***************************************************************************/
+
+/*
+** The third level of heap allocation macros. These are shorthands, supplying
+** default values of some of the parameters of the previous macros.
+*/
+
+#define     MR_tag_incr_hp(dest, tag, count)                                \
+            MR_tag_offset_incr_hp((dest), (tag), 0, (count))
+#define     MR_tag_incr_hp_atomic(dest, tag, count)                         \
+            MR_tag_offset_incr_hp_atomic((dest), (tag), 0, (count))
+#define     MR_tag_incr_hp_msg(dest, tag, count, proclabel, type)           \
+            MR_tag_offset_incr_hp_msg((dest), (tag), 0, (count),            \
+                proclabel, (type))
+#define     MR_tag_incr_hp_atomic_msg(dest, tag, count, proclabel, type)    \
+            MR_tag_offset_incr_hp_atomic_msg((dest), (tag), 0, (count),     \
+                proclabel, (type))
 
 /*
 ** The MR_offset_incr_hp*() macros are defined in terms of the
-** MR_tag_offset_incr_hp*() macros. Note: the `proclabel' argument is not
-** parenthesized, since it must be a label name; we may need to prefix
-** `_entry_' in front of it, which wouldn't work if it was parenthesized.
-*/
-
-#define	MR_offset_incr_hp(dest, offset, count)				\
-	MR_tag_offset_incr_hp((dest), MR_mktag(0), (offset), (count))
-#define	MR_offset_incr_hp_msg(dest, offset, count, proclabel, type)	\
-	MR_tag_offset_incr_hp_msg((dest), MR_mktag(0),			\
-		(offset), (count), proclabel, (type))
-#define	MR_offset_incr_hp_atomic(dest, offset, count)			\
-	MR_tag_offset_incr_hp_atomic((dest), MR_mktag(0), (offset), (count))
-#define	MR_offset_incr_hp_atomic_msg(dest, offset, count, proclabel, type) \
-	MR_tag_offset_incr_hp_atomic_msg((dest), MR_mktag(0),		\
-		(offset), (count), proclabel, (type))
-
-#ifndef	MR_RECORD_TERM_SIZES
-
-#define	MR_incr_hp(dest, count)					\
-	MR_offset_incr_hp((dest), 0, (count))
-#define	MR_incr_hp_msg(dest, count, proclabel, type)		\
-	MR_offset_incr_hp_msg((dest), 0, (count), proclabel, (type))
-#define	MR_incr_hp_atomic(dest, count)				\
-	MR_offset_incr_hp_atomic((dest), 0, (count))
-#define	MR_incr_hp_atomic_msg(dest, count, proclabel, type)	\
-	MR_offset_incr_hp_atomic_msg((dest), 0, (count), proclabel, (type))
+** MR_tag_offset_incr_hp*() macros.
+*/
+
+#define     MR_offset_incr_hp(dest, offset, count)                          \
+            MR_tag_offset_incr_hp((dest), MR_mktag(0), (offset), (count))
+#define     MR_offset_incr_hp_msg(dest, offset, count, proclabel, type)     \
+            MR_tag_offset_incr_hp_msg((dest), MR_mktag(0),                  \
+                (offset), (count), proclabel, (type))
+#define     MR_offset_incr_hp_atomic(dest, offset, count)                   \
+            MR_tag_offset_incr_hp_atomic((dest), MR_mktag(0), (offset),     \
+                (count))
+#define     MR_offset_incr_hp_atomic_msg(dest, offset, count, proclabel,    \
+                type)                                                       \
+            MR_tag_offset_incr_hp_atomic_msg((dest), MR_mktag(0), (offset), \
+                (count), proclabel, (type))
+
+#ifdef  MR_CONSERVATIVE_GC
+            /* we use `MR_hp_word' as a convenient temporary here */
+  #define   MR_hp_alloc(count) (                                            \
+                MR_offset_incr_hp(MR_hp_word, 0, (count)),                  \
+                MR_hp_word = (MR_Word) (MR_hp + (count)),                   \
+                (void) 0                                                    \
+            )
+  #define   MR_hp_alloc_atomic(count) (                                     \
+                MR_offset_incr_hp_atomic(MR_hp_word, 0, (count)),           \
+                MR_hp_word = (MR_Word) (MR_hp + (count)),                   \
+                (void) 0                                                    \
+            )
+
+#else /* !MR_CONSERVATIVE_GC */
+
+  #define   MR_hp_alloc(count)                                              \
+            MR_offset_incr_hp(MR_hp_word, 0, (count))
+  #define   MR_hp_alloc_atomic(count)                                       \
+            MR_offset_incr_hp_atomic(MR_hp_word, 0, (count))
+
+#endif /* MR_CONSERVATIVE_GC */
+
+/***************************************************************************/
+
+/*
+** The fourth level of heap allocation macros. These implement the various
+** cases of the incr_hp LLDS instruction, and look after recording term sizes.
+*/
+
+#ifndef MR_RECORD_TERM_SIZES
+
+#define     MR_incr_hp(dest, count)                                         \
+            MR_offset_incr_hp((dest), 0, (count))
+#define     MR_incr_hp_msg(dest, count, proclabel, type)                    \
+            MR_offset_incr_hp_msg((dest), 0, (count), proclabel, (type))
+#define     MR_incr_hp_atomic(dest, count)                                  \
+            MR_offset_incr_hp_atomic((dest), 0, (count))
+#define     MR_incr_hp_atomic_msg(dest, count, proclabel, type)             \
+            MR_offset_incr_hp_atomic_msg((dest), 0, (count), proclabel, (type))
 
 #endif
 
-#define	MR_incr_hp_type(dest, typename)					\
-		do {							\
-			MR_Word	tmp;					\
-			MR_tag_incr_hp(tmp, MR_mktag(0),		\
-				(MR_bytes_to_words(sizeof(typename))));	\
-			(dest) = (typename *) tmp;			\
-		} while (0)
-#define	MR_incr_hp_type_msg(dest, typename, proclabel, type)		\
-		do {							\
-			MR_Word	tmp;					\
-			MR_tag_incr_hp_msg(tmp, MR_mktag(0),		\
-				(MR_bytes_to_words(sizeof(typename))),	\
-				proclabel, (type));			\
-			(dest) = (typename *) tmp;			\
-		} while (0)
-
-#define	MR_alloc_heap(dest, count)					\
-	MR_tag_offset_incr_hp((dest), MR_mktag(0), 0, (count))
-#define	MR_alloc_heap_atomic(dest, count)				\
-	MR_tag_offset_incr_hp_atomic((dest), MR_mktag(0), 0, (count))
-#define	MR_tag_alloc_heap(dest, tag, count)				\
-	MR_tag_offset_incr_hp((dest), MR_mktag(tag), 0, (count))
-#define	MR_tag_alloc_heap_atomic(dest, tag, count)			\
-	MR_tag_offset_incr_hp_atomic((dest), MR_mktag(tag), 0, (count))
+#define     MR_incr_hp_type(dest, typename)                                 \
+            do {                                                            \
+                MR_Word tmp;                                                \
+                MR_tag_incr_hp(tmp, MR_mktag(0),                            \
+                    (MR_bytes_to_words(sizeof(typename))));                 \
+                (dest) = (typename *) tmp;                                  \
+            } while (0)
+#define     MR_incr_hp_type_msg(dest, typename, proclabel, type)            \
+            do {                                                            \
+                MR_Word tmp;                                                \
+                MR_tag_incr_hp_msg(tmp, MR_mktag(0),                        \
+                    (MR_bytes_to_words(sizeof(typename))),                  \
+                    proclabel, (type));                                     \
+                (dest) = (typename *) tmp;                                  \
+            } while (0)
+
+#define     MR_alloc_heap(dest, count)                                      \
+            MR_tag_offset_incr_hp((dest), MR_mktag(0), 0, (count))
+#define     MR_alloc_heap_atomic(dest, count)                               \
+            MR_tag_offset_incr_hp_atomic((dest), MR_mktag(0), 0, (count))
+#define     MR_tag_alloc_heap(dest, tag, count)                             \
+            MR_tag_offset_incr_hp((dest), MR_mktag(tag), 0, (count))
+#define     MR_tag_alloc_heap_atomic(dest, tag, count)                      \
+            MR_tag_offset_incr_hp_atomic((dest), MR_mktag(tag), 0, (count))
+
+#ifdef MR_HIGHLEVEL_CODE
+
+/* term size profiling is not supported with MR_HIGHLEVEL_CODE */
+  #define       MR_SIZE_SLOT_SIZE                           0
+  #define       MR_cell_size(arity)                         0
+  #define       MR_define_size_slot(ptag, new, size)        0
+  #define       MR_copy_size_slot(nptag, new, optag, old)   0
+
+#else /* ! MR_HIGHLEVEL_CODE */
+
+  #ifdef  MR_RECORD_TERM_SIZES
+    #define MR_SIZE_SLOT_SIZE 1
+    #ifdef MR_RECORD_TERM_SIZES_AS_CELLS
+        #define MR_cell_size(arity)                         1
+    #else
+        #define MR_cell_size(arity)                         arity
+    #endif
+
+    #define     MR_define_size_slot(ptag, new, size)                        \
+                do {                                                        \
+                    MR_field(ptag, new, -1) = size;                         \
+                } while(0)
+    #define     MR_copy_size_slot(nptag, new, optag, old)                   \
+                do {                                                        \
+                    MR_field(nptag, new, -1) = MR_field(optag, old, -1);    \
+                } while(0)
+  #else
+    #define     MR_SIZE_SLOT_SIZE                             0
+    #define     MR_cell_size(arity)                           0
+    #define     MR_define_size_slot(ptag, new, size)          0
+    #define     MR_copy_size_slot(nptag, new, optag, old)     0
+  #endif
+
+#endif /* ! MR_HIGHLEVEL_CODE */
+
+/***************************************************************************/
+
+/*
+** Macros to box/unbox types declared with `pragma foreign_type'.
+*/
+
+/*
+** void MR_MAYBE_BOX_FOREIGN_TYPE(type T, const T &value, MR_Box &box):
+** Copy a value of type T from `value' to `box', boxing it if necessary
+** (i.e. if type T won't fit in type MR_Box).
+*/
+
+#define MR_MAYBE_BOX_FOREIGN_TYPE(T, value, box)                            \
+        do {                                                                \
+            MR_CHECK_EXPR_TYPE((value), T);                                 \
+            MR_CHECK_EXPR_TYPE((box), MR_Box);                              \
+            if (sizeof(T) > sizeof(MR_Box)) {                               \
+                MR_Word     box_word;                                       \
+                size_t size_in_words =                                      \
+                    (sizeof(T) + sizeof(MR_Word) - 1) / sizeof(MR_Word);    \
+                /* XXX this assumes that nothing requires */                \
+                /* stricter alignment than MR_Float */                      \
+                MR_make_hp_float_aligned();                                 \
+                /*                                                          \
+                ** This assumes that we don't keep term sizes               \
+                ** in grades that use boxes.                                \
+                */                                                          \
+                MR_offset_incr_hp(box_word, 0, size_in_words);              \
+                box = (MR_Box) box_word;                                    \
+                MR_assign_structure(*(T *)(box), (value));                  \
+                MR_profmem_record_allocation(size_in_words,                   \
+                    "", "foreign type: " MR_STRINGIFY(T));                  \
+            } else {                                                        \
+                /* We can't take the address of `box' here, */              \
+                /* since it might be a global register. */                  \
+                /* Hence we need to use a temporary copy. */                \
+                MR_Box box_copy;                                            \
+                if (sizeof(T) < sizeof(MR_Box)) {                           \
+                    /* make sure we don't leave any */                      \
+                    /* part of it uninitialized */                          \
+                    box_copy = 0;                                           \
+                }                                                           \
+                MR_memcpy(&box_copy, &(value), sizeof(T));                  \
+                (box) = box_copy;                                           \
+            }                                                               \
+        } while (0)
+
+/*
+** void MR_MAYBE_UNBOX_FOREIGN_TYPE(type T, MR_Box box, T &value):
+** Copy a value of type T from `box' to `value', unboxing it if necessary.
+*/
+
+#define MR_MAYBE_UNBOX_FOREIGN_TYPE(T, box, value)                          \
+        do {                                                                \
+            MR_CHECK_EXPR_TYPE((value), T);                                 \
+            MR_CHECK_EXPR_TYPE((box), MR_Box);                              \
+            if (sizeof(T) > sizeof(MR_Word)) {                              \
+                MR_assign_structure((value), * (T *) (box));                \
+            } else {                                                        \
+                /* We can't take the address of `box' here, */              \
+                /* since it might be a global register. */                  \
+                /* Hence we need to use a temporary copy. */                \
+                MR_Box box_copy = (box);                                    \
+                MR_memcpy(&(value), &box_copy, sizeof(T));                  \
+            }                                                               \
+        } while (0)
+
+/***************************************************************************/
+
+/*
+** The rest of this file defines macros designed to help hand-written C code
+** create cells on the heap. These macros can be used directly, or indirectly
+** via macros built on top of them. mercury_string.h and mercury_tags.h define
+** some such macros.
+*/
 
 #ifdef MR_HIGHLEVEL_CODE
 
@@ -319,95 +482,73 @@
 MR_EXTERN_INLINE MR_Word
 MR_create1_func(MR_Word w1)
 {
-	MR_Word *p = (MR_Word *) MR_new_object(MR_Word, 1 * sizeof(MR_Word),
-			"create1");
-	p[0] = w1;
-	return (MR_Word) p;
+    MR_Word *p;
+
+    p = (MR_Word *) MR_new_object(MR_Word, 1 * sizeof(MR_Word), "create1");
+    p[0] = w1;
+    return (MR_Word) p;
 }
 
 MR_EXTERN_INLINE MR_Word
 MR_create2_func(MR_Word w1, MR_Word w2)
 {
-	MR_Word *p = (MR_Word *) MR_new_object(MR_Word, 2 * sizeof(MR_Word),
-			"create2");
-	p[0] = w1;
-	p[1] = w2;
-	return (MR_Word) p;
+    MR_Word *p;
+
+    p == (MR_Word *) MR_new_object(MR_Word, 2 * sizeof(MR_Word), "create2");
+    p[0] = w1;
+    p[1] = w2;
+    return (MR_Word) p;
 }
 
 MR_EXTERN_INLINE MR_Word
 MR_create3_func(MR_Word w1, MR_Word w2, MR_Word w3)
 {
-	MR_Word *p = (MR_Word *) MR_new_object(MR_Word, 3 * sizeof(MR_Word),
-			"create3");
-	p[0] = w1;
-	p[1] = w2;
-	p[2] = w3;
-	return (MR_Word) p;
+    MR_Word *p;
+
+    p = (MR_Word *) MR_new_object(MR_Word, 3 * sizeof(MR_Word), "create3");
+    p[0] = w1;
+    p[1] = w2;
+    p[2] = w3;
+    return (MR_Word) p;
 }
 
-#define MR_create1(ti1, w1) \
-	MR_create1_func((w1))
-#define MR_create2(ti1, w1, ti2, w2) \
-	MR_create2_func((w1), (w2))
-#define MR_create3(ti1, w1, ti2, w2, ti3, w3) \
-	MR_create3_func((w1), (w2), (w3))
-
-#define MR_create1_msg(ti1, w1, proclabel, type) \
-	MR_create1((ti1), (w1))
-#define MR_create2_msg(ti1, w1, ti2, w2, proclabel, type)	\
-	MR_create2((ti1), (w1), (ti2), (w2))
-#define MR_create3_msg(ti1, w1, ti2, w2, ti3, w3, proclabel, type) \
-	MR_create3((ti1), (w1), (ti2), (w2), (ti3), (w3))
-
-/* term size profiling is not supported with MR_HIGHLEVEL_CODE */
-#define MR_SIZE_SLOT_SIZE				0
-#define MR_cell_size(arity)				0
-#define MR_define_size_slot(ptag, new, size)		0
-#define MR_copy_size_slot(nptag, new, optag, old)	0
+  #define   MR_create1(ti1, w1)                                             \
+            MR_create1_func((w1))
+  #define   MR_create2(ti1, w1, ti2, w2)                                    \
+            MR_create2_func((w1), (w2))
+  #define   MR_create3(ti1, w1, ti2, w2, ti3, w3)                           \
+            MR_create3_func((w1), (w2), (w3))
+
+  #define   MR_create1_msg(ti1, w1, proclabel, type)                        \
+            MR_create1((ti1), (w1))
+  #define   MR_create2_msg(ti1, w1, ti2, w2, proclabel, type)               \
+            MR_create2((ti1), (w1), (ti2), (w2))
+  #define   MR_create3_msg(ti1, w1, ti2, w2, ti3, w3, proclabel, type)      \
+            MR_create3((ti1), (w1), (ti2), (w2), (ti3), (w3))
 
 #else /* ! MR_HIGHLEVEL_CODE */
 
-#ifdef	MR_RECORD_TERM_SIZES
-  #define MR_SIZE_SLOT_SIZE	1
-  #ifdef MR_RECORD_TERM_SIZES_AS_CELLS
-    #define MR_cell_size(arity)	1
+  #ifdef  MR_RECORD_TERM_SIZES
+    #define     MR_fill_create1_size(hp, ti1, w1)                           \
+                (                                                           \
+                    hp[-2] = MR_term_size(ti1, w1) + MR_cell_size(1)        \
+                )
+    #define     MR_fill_create2_size(hp, ti1, w1, ti2, w2)                  \
+                (                                                           \
+                    hp[-3] = MR_term_size(ti1, w1) + MR_term_size(ti2, w2)  \
+                        + MR_cell_size(2)                                   \
+                )
+    #define     MR_fill_create3_size(hp, ti1, w1, ti2, w2, ti3, w3)         \
+                (                                                           \
+                    hp[-4] = MR_term_size(ti1, w1) + MR_term_size(ti2, w2)  \
+                        + MR_term_size(ti3, w3) + MR_cell_size(3)           \
+                )
   #else
-    #define MR_cell_size(arity)	arity
+    #define     MR_fill_create1_size(hp, ti1, w1)                     0
+    #define     MR_fill_create2_size(hp, ti1, w1, ti2, w2)            0
+    #define     MR_fill_create3_size(hp, ti1, w1, ti2, w2, ti3, w3)   0
   #endif
 
-  #define MR_define_size_slot(ptag, new, size)                          \
-        do {                                                            \
-                MR_field(ptag, new, -1) = size;				\
-        } while(0)
-  #define MR_copy_size_slot(nptag, new, optag, old)                     \
-        do {                                                            \
-                MR_field(nptag, new, -1) = MR_field(optag, old, -1);    \
-        } while(0)
-  #define MR_fill_create1_size(hp, ti1, w1)				\
-	(								\
-		hp[-2] = MR_term_size(ti1, w1) + MR_cell_size(1)	\
-	)
-  #define MR_fill_create2_size(hp, ti1, w1, ti2, w2)			\
-	(								\
-		hp[-3] = MR_term_size(ti1, w1) + MR_term_size(ti2, w2)	\
-			+ MR_cell_size(2)				\
-	)
-  #define MR_fill_create3_size(hp, ti1, w1, ti2, w2, ti3, w3)		\
-	(								\
-		hp[-4] = MR_term_size(ti1, w1) + MR_term_size(ti2, w2)	\
-			+ MR_term_size(ti3, w3) + MR_cell_size(3)	\
-	)
-#else
-  #define MR_SIZE_SLOT_SIZE					0
-  #define MR_cell_size(arity)					0
-  #define MR_define_size_slot(ptag, new, size)			0
-  #define MR_copy_size_slot(nptag, new, optag, old)		0
-  #define MR_fill_create1_size(hp, ti1, w1)			0
-  #define MR_fill_create2_size(hp, ti1, w1, ti2, w2)		0
-  #define MR_fill_create3_size(hp, ti1, w1, ti2, w2, ti3, w3)	0
-#endif
-
 /*
 ** Note that gcc optimizes `hp += 2; return hp - 2;'
 ** to `tmp = hp; hp += 2; return tmp;', so we don't need to use
@@ -415,76 +556,76 @@
 */
 
 /* used only by hand-written code not by the automatically generated code */
-#define MR_create1(ti1, w1)						\
-	(								\
-		MR_hp_alloc(MR_SIZE_SLOT_SIZE + 1),			\
-		MR_hp[-1] = (MR_Word) (w1),				\
-		MR_fill_create1_size(MR_hp, ti1, w1),			\
-		MR_debugcr1(MR_hp),					\
-		/* return */ (MR_Word) (MR_hp - 1)			\
-	)
+  #define   MR_create1(ti1, w1)                                             \
+            (                                                               \
+                MR_hp_alloc(MR_SIZE_SLOT_SIZE + 1),                         \
+                MR_hp[-1] = (MR_Word) (w1),                                 \
+                MR_fill_create1_size(MR_hp, ti1, w1),                       \
+                MR_debugcr1(MR_hp),                                         \
+                /* return */ (MR_Word) (MR_hp - 1)                          \
+            )
 
 /* used only by hand-written code not by the automatically generated code */
-#define MR_create2(ti1, w1, ti2, w2)					\
-	(								\
-		MR_hp_alloc(MR_SIZE_SLOT_SIZE + 2),			\
-		MR_hp[-2] = (MR_Word) (w1),				\
-		MR_hp[-1] = (MR_Word) (w2),				\
-		MR_fill_create2_size(MR_hp, ti1, w1, ti2, w2),		\
-		MR_debugcr2(MR_hp),					\
-		/* return */ (MR_Word) (MR_hp - 2)			\
-	)
+  #define   MR_create2(ti1, w1, ti2, w2)                                    \
+            (                                                               \
+                MR_hp_alloc(MR_SIZE_SLOT_SIZE + 2),                         \
+                MR_hp[-2] = (MR_Word) (w1),                                 \
+                MR_hp[-1] = (MR_Word) (w2),                                 \
+                MR_fill_create2_size(MR_hp, ti1, w1, ti2, w2),              \
+                MR_debugcr2(MR_hp),                                         \
+                /* return */ (MR_Word) (MR_hp - 2)                          \
+            )
 
 /* used only by hand-written code not by the automatically generated code */
-#define MR_create3(ti1, w1, ti2, w2, ti3, w3)				\
-	(								\
-		MR_hp_alloc(MR_SIZE_SLOT_SIZE + 3),			\
-		MR_hp[-3] = (MR_Word) (w1),				\
-		MR_hp[-2] = (MR_Word) (w2),				\
-		MR_hp[-1] = (MR_Word) (w3),				\
-		MR_fill_create3_size(MR_hp, ti1, w1, ti2, w2, ti3, w3),	\
-		MR_debugcr3(MR_hp),					\
-		/* return */ (MR_Word) (MR_hp - 3)			\
-	)
+  #define   MR_create3(ti1, w1, ti2, w2, ti3, w3)                           \
+            (                                                               \
+                MR_hp_alloc(MR_SIZE_SLOT_SIZE + 3),                         \
+                MR_hp[-3] = (MR_Word) (w1),                                 \
+                MR_hp[-2] = (MR_Word) (w2),                                 \
+                MR_hp[-1] = (MR_Word) (w3),                                 \
+                MR_fill_create3_size(MR_hp, ti1, w1, ti2, w2, ti3, w3),     \
+                MR_debugcr3(MR_hp),                                         \
+                /* return */ (MR_Word) (MR_hp - 3)                              \
+            )
 
 /* used only by hand-written code not by the automatically generated code */
-#define MR_create1_msg(ti1, w1, proclabel, type)			\
-	(								\
-		MR_maybe_record_allocation(MR_SIZE_SLOT_SIZE + 1,	\
-			proclabel, (type)),				\
-		MR_hp_alloc(MR_SIZE_SLOT_SIZE + 1),			\
-		MR_hp[-1] = (MR_Word) (w1),				\
-		MR_fill_create1_size(MR_hp, ti1, w1),			\
-		MR_debugcr1(MR_hp),					\
-		/* return */ (MR_Word) (MR_hp - 1)			\
-	)
+  #define   MR_create1_msg(ti1, w1, proclabel, type)                        \
+            (                                                               \
+                MR_profmem_record_allocation(MR_SIZE_SLOT_SIZE + 1,         \
+                    proclabel, (type)),                                     \
+                MR_hp_alloc(MR_SIZE_SLOT_SIZE + 1),                         \
+                MR_hp[-1] = (MR_Word) (w1),                                 \
+                MR_fill_create1_size(MR_hp, ti1, w1),                       \
+                MR_debugcr1(MR_hp),                                         \
+                /* return */ (MR_Word) (MR_hp - 1)                          \
+            )
 
 /* used only by hand-written code not by the automatically generated code */
-#define MR_create2_msg(ti1, w1, ti2, w2, proclabel, type)		\
-	(								\
-		MR_maybe_record_allocation(MR_SIZE_SLOT_SIZE + 2,	\
-			proclabel, (type)),				\
-		MR_hp_alloc(MR_SIZE_SLOT_SIZE + 2),			\
-		MR_hp[-2] = (MR_Word) (w1),				\
-		MR_hp[-1] = (MR_Word) (w2),				\
-		MR_fill_create2_size(MR_hp, ti1, w1, ti2, w2),		\
-		MR_debugcr2(MR_hp),					\
-		/* return */ (MR_Word) (MR_hp - 2)			\
-	)
+  #define   MR_create2_msg(ti1, w1, ti2, w2, proclabel, type)               \
+            (                                                               \
+                MR_profmem_record_allocation(MR_SIZE_SLOT_SIZE + 2,         \
+                    proclabel, (type)),                                     \
+                MR_hp_alloc(MR_SIZE_SLOT_SIZE + 2),                         \
+                MR_hp[-2] = (MR_Word) (w1),                                 \
+                MR_hp[-1] = (MR_Word) (w2),                                 \
+                MR_fill_create2_size(MR_hp, ti1, w1, ti2, w2),              \
+                MR_debugcr2(MR_hp),                                         \
+                /* return */ (MR_Word) (MR_hp - 2)                          \
+            )
 
 /* used only by hand-written code not by the automatically generated code */
-#define MR_create3_msg(ti1, w1, ti2, w2, ti3, w3, proclabel, type)	\
-	(								\
-		MR_maybe_record_allocation(MR_SIZE_SLOT_SIZE + 3,	\
-			proclabel, (type)),				\
-		MR_hp_alloc(MR_SIZE_SLOT_SIZE + 3),			\
-		MR_hp[-3] = (MR_Word) (w1),				\
-		MR_hp[-2] = (MR_Word) (w2),				\
-		MR_hp[-1] = (MR_Word) (w3),				\
-		MR_fill_create3_size(MR_hp, ti1, w1, ti2, w2, ti3, w3),	\
-		MR_debugcr3(MR_hp),					\
-		/* return */ (MR_Word) (MR_hp - 3)			\
-	)
+  #define   MR_create3_msg(ti1, w1, ti2, w2, ti3, w3, proclabel, type)      \
+            (                                                               \
+                MR_profmem_record_allocation(MR_SIZE_SLOT_SIZE + 3,         \
+                    proclabel, (type)),                                     \
+                MR_hp_alloc(MR_SIZE_SLOT_SIZE + 3),                         \
+                MR_hp[-3] = (MR_Word) (w1),                                 \
+                MR_hp[-2] = (MR_Word) (w2),                                 \
+                MR_hp[-1] = (MR_Word) (w3),                                 \
+                MR_fill_create3_size(MR_hp, ti1, w1, ti2, w2, ti3, w3),     \
+                MR_debugcr3(MR_hp),                                         \
+                /* return */ (MR_Word) (MR_hp - 3)                          \
+            )
 
 #endif /* ! MR_HIGHLEVEL_CODE */
 
@@ -497,86 +638,21 @@
 **
 ** There are intentionally no versions that do not specify an offset;
 ** this is to force anyone who wants to allocate cells on the saved heap
-** to think about the impliciations of their code for term size profiling.
+** to think about the implications of their code for term size profiling.
 */
 
-#define MR_offset_incr_saved_hp(dest, offset, count)		\
-	do {							\
-		MR_restore_transient_hp();			\
-		MR_offset_incr_hp((dest), (offset), (count));	\
-		MR_save_transient_hp();				\
-	} while (0)
-
-#define MR_offset_incr_saved_hp_atomic(dest, offset, count)	\
-	do {							\
-		MR_restore_transient_hp();			\
-		MR_offset_incr_hp_atomic((dest), (offset), (count)); \
-		MR_save_transient_hp();				\
-	} while (0)
-
-/*
-** Code to box/unbox types declared with `pragma foreign_type'.
-*/
-
-/*
-** void MR_MAYBE_BOX_FOREIGN_TYPE(type T, const T &value, MR_Box &box);
-**	Copy a value of type T from `value' to `box',
-**	boxing it if necessary (i.e. if type T won't fit in type MR_Box).
-*/
-#define MR_MAYBE_BOX_FOREIGN_TYPE(T, value, box)			\
-	do {								\
-		MR_CHECK_EXPR_TYPE((value), T);				\
-		MR_CHECK_EXPR_TYPE((box), MR_Box);			\
-		if (sizeof(T) > sizeof(MR_Box)) {			\
-			MR_Word box_word;				\
-			size_t size_in_words =				\
-				(sizeof(T) + sizeof(MR_Word) - 1)	\
-				 / sizeof(MR_Word);			\
-			/* XXX this assumes that nothing requires */	\
-			/* stricter alignment than MR_Float */		\
-			MR_make_hp_float_aligned();			\
-			/*						\
-			** This assumes that we don't keep term sizes	\
-			** in grades that use boxes.			\
-			*/						\
-			MR_offset_incr_hp(box_word, 0, size_in_words);	\
-			box = (MR_Box) box_word;			\
-			MR_assign_structure(*(T *)(box), (value));	\
-			MR_maybe_record_allocation(size_in_words,	\
-				"", "foreign type: " MR_STRINGIFY(T));	\
-		} else {						\
-			/* We can't take the address of `box' here, */	\
-			/* since it might be a global register. */	\
-			/* Hence we need to use a temporary copy. */	\
-			MR_Box box_copy;				\
-			if (sizeof(T) < sizeof(MR_Box)) {		\
-				/* make sure we don't leave any */	\
-				/* part of it uninitialized */		\
-				box_copy = 0;				\
-			}						\
-			MR_memcpy(&box_copy, &(value), sizeof(T));	\
-			(box) = box_copy;				\
-		}							\
-	} while (0)
-
-/*
-** void MR_MAYBE_UNBOX_FOREIGN_TYPE(type T, MR_Box box, T &value);
-**	Copy a value of type T from `box' to `value',
-**	unboxing it if necessary.
-*/
-#define MR_MAYBE_UNBOX_FOREIGN_TYPE(T, box, value)			\
-	do {								\
-		MR_CHECK_EXPR_TYPE((value), T);				\
-		MR_CHECK_EXPR_TYPE((box), MR_Box);			\
-		if (sizeof(T) > sizeof(MR_Word)) {			\
-			MR_assign_structure((value), *(T *)(box));	\
-		} else {						\
-			/* We can't take the address of `box' here, */	\
-			/* since it might be a global register. */	\
-			/* Hence we need to use a temporary copy. */	\
-			MR_Box box_copy = (box);			\
-			MR_memcpy(&(value), &box_copy, sizeof(T));	\
-		}							\
-	} while (0)
+#define MR_offset_incr_saved_hp(dest, offset, count)                        \
+        do {                                                                \
+            MR_restore_transient_hp();                                      \
+            MR_offset_incr_hp((dest), (offset), (count));                   \
+            MR_save_transient_hp();                                         \
+        } while (0)
+
+#define MR_offset_incr_saved_hp_atomic(dest, offset, count)                 \
+        do {                                                                \
+            MR_restore_transient_hp();                                      \
+            MR_offset_incr_hp_atomic((dest), (offset), (count));            \
+            MR_save_transient_hp();                                         \
+        } while (0)
 
 #endif /* not MERCURY_HEAP_H */
Index: runtime/mercury_heap_profile.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_heap_profile.h,v
retrieving revision 1.5
diff -u -r1.5 mercury_heap_profile.h
--- runtime/mercury_heap_profile.h	26 Sep 2006 07:08:19 -0000	1.5
+++ runtime/mercury_heap_profile.h	10 Oct 2006 05:32:56 -0000
@@ -90,21 +90,24 @@
 
 /*
 ** MR_record_allocation(size, proc_addr, proc_name, type):
-**	Record heap profiling information for an allocation of one cell
-**	of `size' words by procedure `proc_name' with address `proc_addr'
-**	for an object of type `type'.
-**	The heap profiling information is recorded in the three global
-**	variables above.
+**
+** Record heap profiling information for an allocation of one cell of `size'
+** words by procedure `proc_name' with address `proc_addr' for an object of
+** type `type'. The heap profiling information is recorded in the three global
+** variables above.
 */
-extern void MR_record_allocation(int size, MR_Code *proc_addr,
-		const char *proc_name, const char *type);
+
+extern void	MR_record_allocation(int size, MR_Code *proc_addr,
+			const char *proc_name, const char *type);
 
 /*
 ** MR_prof_output_mem_tables():
-**	Write out the information recorded by MR_record_allocation()
-**	to a pair of files `Prof.MemoryMR_Words' and `Prof.MemoryCells'.
+**
+** Write out the information recorded by MR_record_allocation() to a pair
+** of files `Prof.MemoryMR_Words' and `Prof.MemoryCells'.
 */
-extern void MR_prof_output_mem_tables(void);
+
+extern void	MR_prof_output_mem_tables(void);
 
 /*---------------------------------------------------------------------------*/
 
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
cvs diff: Diffing slice
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
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/par_conj
cvs diff: Diffing tests/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/trailing
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
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 messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list