[m-rev.] for post-commit review: stack extension

Zoltan Somogyi zs at cs.mu.OZ.AU
Tue Sep 13 18:24:11 AEST 2005


For review by anyone. Don't bother mentioning the places marked by XXX;
I will work on them.

Zoltan.

Introduce a mechanism for extending the det and nondet stacks when needed.
The mechanism takes the form of a new grade component, .exts ("extend stacks").

While the new mechanism may be useful in its own right, it is intended mainly
to support a new implementation of minimal model tabling, which will use a
separate Mercury context for each distinct subgoal. Each context has its own
det and nondet stack. Clearly, we can't have hundreds of contexts each with
megabyte sized det stacks. The intention is that the stacks of the subgoals
will start small, and be expanded when needed.

The runtime expansion of stacks doesn't work yet, but it is unnecessarily
hard to debug without an installed compiler that understands the new grade
component, which is why this diff will be committed before that is fixed.

compiler/handle_options.m:
compiler/options.m:
runtime/mercury_grade.h:
scripts/canonical_grade.sh-subr
scripts/init_grade_options.sh-subr
scripts/parse_grade_options.sh-subr
scripts/mgnuc.in
	Handle the new grade component.

runtime/mercury_memory_zones.h:
	Add MR_ prefixes to the names of the fields of the zone structure.

	Record not just the actual size of each zone, which includes various
	kinds of buffers, but also the desired size of the zone exclusive of
	buffers.

	Format the documentation of the zone structure fields more
	comprehensibly.

runtime/mercury_memory_zones.c:
	Instead of implementing memalign if it is not provided by the operating
	system, implement a function that allows us to reallocate the returned
	area of memory.

	Provide a prototype implementation of memory zone extension. It doesn't
	work yet.

	Factor out the code for setting up redzones, since it is now needed
	in more than place.

	Convert to four space indentation.

	Make the debugging functions a bit more flexible.

runtime/mercury_wrapper.c:
	Conform to the improved interface of the debugging functions.

runtime/mercury_overflow.h:
runtime/mercury_std.h:
	Move a generally useful macro from mercury_overflow.h to mercury_std.h.

runtime/mercury_stacks.c:
	Add functions to extend the stacks.

runtime/mercury_stacks.h:
	Add the tests required to invoke the functions that extend the stacks.

	Add the macros needed by the change to compiler/llds.m.

	Convert to four space indentation.

runtime/mercury_conf.h.in:
	Prepare for the use of the posix_memalign function, which is the
	current replacement of the obsolete memalign library function.
	We don't yet use it.

runtime/mercury_context.h:
	Format the documentation of the context structure fields more
	comprehensibly.

	Put MR_ prefixes on the names of the fields of some structures
	that didn't previously have them.

	Conform to the new names of the fields of the zone structure.

runtime/mercury_context.c:
runtime/mercury_debug.c:
runtime/mercury_deep_copy.c:
runtime/mercury_engine.c:
runtime/mercury_memory_handlers.c:
library/benchmarking.m:
library/exception.m:
	Conform to the new names of the fields of the zone structure.

	In some cases, add missing MR_ prefixes to function names
	and/or convert to four space indentation.

runtime/mercury_engine.h:
	Add a new low level debug flag for debugging stack extensions.

	Format the documentation of the engine structure fields more
	comprehensibly.

	Convert to four space indentation.

runtime/mercury_conf_param.h:
	Document a new low level debug flag for debugging stack extensions.

compiler/compile_target_code.m:
compiler/handle_options.m:
compiler/options.m:
	Handle the new grade component.

compiler/llds.m:
	Add two new kinds of LLDS instructions, save_maxfr and restore_maxfr.
	These are needed because the nondet stack may be relocated between
	saving and the restoring of maxfr, and the saved maxfr may point to
	the old stack. In .exts grades, these instructions will save not a
	pointer but the offset of maxfr from the start of the nondet stack,
	since offsets are not affected by the movement of the nondet stack.

compiler/code_info.m:
	Use the new instructions where relevant. (Some more work may be
	needed on this score; the relevant places are marked with XXX.)

compiler/dupelim.m:
compiler/dupproc.m:
compiler/exprn_aux.m:
compiler/jumpopt.m:
compiler/livemap.m:
compiler/llds_out.m:
compiler/middle_rec.m:
compiler/opt_debug.m:
compiler/opt_util.m:
compiler/reassign.m:
compiler/use_local_vars.m:
	Handle the new LLDS instructions.

tools/bootcheck:
	Provide a mechanism for setting the initial stack sizes for a
	bootcheck.

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/tests
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing compiler
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.304
diff -u -b -r1.304 code_info.m
--- compiler/code_info.m	13 Sep 2005 04:55:59 -0000	1.304
+++ compiler/code_info.m	13 Sep 2005 04:56:36 -0000
@@ -1677,6 +1677,7 @@
                 - "soft cut for temp frame ite"
         ]),
         ElseCode = node([
+            % XXX, search /assign(maxfr
             assign(maxfr, lval(prevfr(lval(MaxfrSlot))))
                 - "restore maxfr for temp frame ite"
         ])
@@ -1693,8 +1694,7 @@
                     - "restore redoip for quarter ite hijack"
             ])
         ;
-            % This can happen only if ResumePoint is unreachable
-            % from here.
+            % This can happen only if ResumePoint is unreachable from here.
             ThenCode = empty
         ),
         ElseCode = ThenCode
@@ -1746,8 +1746,7 @@
         % will not be referenced.
     set__to_sorted_list(ResumeVars, ResumeVarList),
     map__init(ResumeMap0),
-    code_info__make_fake_resume_map(ResumeVarList,
-        ResumeMap0, ResumeMap),
+    code_info__make_fake_resume_map(ResumeVarList, ResumeMap0, ResumeMap),
     ResumePoint = orig_only(ResumeMap, do_redo),
     code_info__effect_resume_point(ResumePoint, model_semi, Code, !CI),
     require(unify(Code, empty), "nonempty code for simple neg"),
@@ -1783,8 +1782,7 @@
         CurfrMaxfr = may_be_different,
         code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot, !CI),
         SaveMaxfrCode = node([
-            assign(MaxfrSlot, lval(maxfr))
-                - "save the value of maxfr"
+            save_maxfr(MaxfrSlot) - "save the value of maxfr"
         ]),
         MaybeMaxfrSlot = yes(MaxfrSlot)
     ;
@@ -1801,7 +1799,7 @@
     (
         MaybeMaxfrSlot = yes(MaxfrSlot),
         RestoreMaxfrCode = node([
-            assign(maxfr, lval(MaxfrSlot))
+            restore_maxfr(MaxfrSlot)
                 - "restore the value of maxfr - perform commit"
         ]),
         code_info__release_temp_slot(MaxfrSlot, !CI)
@@ -1866,17 +1864,15 @@
     ->
         code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot, !CI),
         MaxfrCode = node([
-            assign(MaxfrSlot, lval(maxfr))
+            save_maxfr(MaxfrSlot)
                 - "prepare for temp frame commit"
         ]),
         code_info__create_temp_frame(StackLabel,
             "prepare for temp frame commit", TempFrameCode, !CI),
         code_info__get_globals(!.CI, Globals),
-        globals__lookup_bool_option(Globals,
-            use_minimal_model_stack_copy_cut,
-            UseMinimalModelStackCopyCut),
-        HijackInfo = commit_temp_frame(MaxfrSlot,
+        globals__lookup_bool_option(Globals, use_minimal_model_stack_copy_cut,
             UseMinimalModelStackCopyCut),
+        HijackInfo = commit_temp_frame(MaxfrSlot, UseMinimalModelStackCopyCut),
         (
             UseMinimalModelStackCopyCut = yes,
             % If the code we are committing across starts but
@@ -1924,8 +1920,8 @@
         % Here ResumeKnown must be resume_point_unknown or
         % resume_point_known(wont_be_done).
 
-        code_info__acquire_temp_slot(lval(redoip(lval(curfr))),
-            RedoipSlot, !CI),
+        code_info__acquire_temp_slot(lval(redoip(lval(curfr))), RedoipSlot,
+            !CI),
         HijackInfo = commit_half_hijack(RedoipSlot),
         HijackCode = node([
             assign(RedoipSlot, lval(redoip(lval(curfr))))
@@ -1946,7 +1942,7 @@
                 - "prepare for full commit hijack",
             assign(RedofrSlot, lval(redofr(lval(maxfr))))
                 - "prepare for full commit hijack",
-            assign(MaxfrSlot, lval(maxfr))
+            save_maxfr(MaxfrSlot)
                 - "prepare for full commit hijack",
             assign(redofr(lval(maxfr)), lval(curfr))
                 - "hijack the redofr slot",
@@ -1968,7 +1964,7 @@
     (
         HijackInfo = commit_temp_frame(MaxfrSlot, UseMinimalModel),
         MaxfrCode = node([
-            assign(maxfr, lval(MaxfrSlot))
+            restore_maxfr(MaxfrSlot)
                 - "restore maxfr for temp frame hijack"
         ]),
         (
@@ -2019,7 +2015,7 @@
     ;
         HijackInfo = commit_full_hijack(RedoipSlot, RedofrSlot, MaxfrSlot),
         SuccessUndoCode = node([
-            assign(maxfr, lval(MaxfrSlot))
+            restore_maxfr(MaxfrSlot)
                 - "restore maxfr for full commit hijack",
             assign(redoip(lval(maxfr)), lval(RedoipSlot))
                 - "restore redoip for full commit hijack",
Index: compiler/compile_target_code.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/compile_target_code.m,v
retrieving revision 1.69
diff -u -b -r1.69 compile_target_code.m
--- compiler/compile_target_code.m	18 Aug 2005 05:18:27 -0000	1.69
+++ compiler/compile_target_code.m	18 Aug 2005 08:12:23 -0000
@@ -565,6 +565,14 @@
 	;
 		ExecTraceOpt = ""
 	),
+	globals__io_lookup_bool_option(extend_stacks_when_needed, Extend, !IO),
+	(
+		Extend = yes,
+		ExtendOpt = "-DMR_EXTEND_STACKS_WHEN_NEEDED "
+	;
+		Extend = no,
+		ExtendOpt = ""
+	),
 	globals__io_lookup_bool_option(target_debug, Target_Debug, !IO),
 	( Target_Debug = yes ->
 		globals__io_lookup_string_option(cflags_for_debug,
@@ -699,6 +707,7 @@
 		RecordTermSizesOpt, 
 		PIC_Reg_Opt, 
 		TagsOpt, NumTagBitsOpt, 
+		ExtendOpt,
 		Target_DebugOpt, LL_DebugOpt, DeclDebugOpt, ExecTraceOpt,
 		UseTrailOpt, 
 		ReserveTagOpt, 
Index: compiler/dupelim.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dupelim.m,v
retrieving revision 1.67
diff -u -b -r1.67 dupelim.m
--- compiler/dupelim.m	7 Sep 2005 06:51:52 -0000	1.67
+++ compiler/dupelim.m	13 Sep 2005 03:14:20 -0000
@@ -351,6 +351,14 @@
         standardize_rval(Rval1, Rval),
         Instr = if_val(Rval, CodeAddr)
     ;
+        Instr1 = save_maxfr(Lval1),
+        standardize_lval(Lval1, Lval),
+        Instr = save_maxfr(Lval)
+    ;
+        Instr1 = restore_maxfr(Lval1),
+        standardize_lval(Lval1, Lval),
+        Instr = restore_maxfr(Lval)
+    ;
         Instr1 = incr_hp(Lval1, MaybeTag, MaybeOffset, Rval1, Msg),
         standardize_lval(Lval1, Lval),
         standardize_rval(Rval1, Rval),
@@ -568,7 +576,7 @@
         Instr1 = Uinstr1 - Comment1,
         Instr2 = Uinstr2 - Comment2,
         (
-            most_specific_instr(Uinstr1, Uinstr2, Uinstr)
+            most_specific_instr(Uinstr1, Uinstr2, yes(Uinstr))
         ->
             ( Comment1 = Comment2 ->
                 Comment = Comment1
@@ -611,113 +619,236 @@
     % This predicate computes the most specific instruction that
     % generalizes both input instructions.
     %
-:- pred most_specific_instr(instr::in, instr::in, instr::out) is semidet.
+:- pred most_specific_instr(instr::in, instr::in, maybe(instr)::out) is det.
 
-most_specific_instr(Instr1, Instr2, Instr) :-
+most_specific_instr(Instr1, Instr2, MaybeInstr) :-
     (
-        Instr1 = livevals(_),
-        Instr2 = Instr1,
-        Instr = Instr1
-    ;
-        Instr1 = block(_, _, _),
-        Instr2 = Instr1,
-        Instr = Instr1
-    ;
         Instr1 = assign(Lval1, Rval1),
+        (
         Instr2 = assign(Lval2, Rval2),
         most_specific_lval(Lval1, Lval2, Lval),
-        most_specific_rval(Rval1, Rval2, Rval),
-        Instr = assign(Lval, Rval)
-    ;
-        Instr1 = call(_, _, _, _, _, _),
-        Instr2 = Instr1,
-        Instr = Instr1
-    ;
-        Instr1 = mkframe(_, _),
-        Instr2 = Instr1,
-        Instr = Instr1
-    ;
-        Instr1 = label(_),
-        Instr2 = Instr1,
-        Instr = Instr1
-    ;
-        Instr1 = goto(_),
-        Instr2 = Instr1,
-        Instr = Instr1
-    ;
-        Instr1 = computed_goto(_, _),
-        Instr2 = Instr1,
-        Instr = Instr1
+            most_specific_rval(Rval1, Rval2, Rval)
+        ->
+            MaybeInstr = yes(assign(Lval, Rval))
     ;
-        Instr1 = c_code(_, _),
-        Instr2 = Instr1,
-        Instr = Instr1
+            MaybeInstr = no
+        )
     ;
-        Instr1 = if_val(Rval1, CodeAddr),
-        Instr2 = if_val(Rval2, CodeAddr),
+        Instr1 = if_val(Rval1, CodeAddr1),
+        (
+            Instr2 = if_val(Rval2, CodeAddr2),
         most_specific_rval(Rval1, Rval2, Rval),
-        Instr = if_val(Rval, CodeAddr)
+            CodeAddr1 = CodeAddr2
+        ->
+            MaybeInstr = yes(if_val(Rval, CodeAddr1))
     ;
-        Instr1 = incr_hp(Lval1, MaybeTag, MaybeOffset, Rval1, Msg),
-        Instr2 = incr_hp(Lval2, MaybeTag, MaybeOffset, Rval2, Msg),
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = incr_hp(Lval1, MaybeTag1, MaybeOffset1, Rval1, Msg1),
+        (
+            Instr2 = incr_hp(Lval2, MaybeTag2, MaybeOffset2, Rval2, Msg2),
         most_specific_lval(Lval1, Lval2, Lval),
         most_specific_rval(Rval1, Rval2, Rval),
-        Instr = incr_hp(Lval, MaybeTag, MaybeOffset, Rval, Msg)
+            MaybeTag1 = MaybeTag2,
+            MaybeOffset1 = MaybeOffset2,
+            Msg1 = Msg2
+        ->
+            MaybeInstr = yes(incr_hp(Lval, MaybeTag1, MaybeOffset1, Rval,
+                Msg1))
+        ;
+            MaybeInstr = no
+        )
     ;
         Instr1 = mark_hp(Lval1),
+        (
         Instr2 = mark_hp(Lval2),
-        most_specific_lval(Lval1, Lval2, Lval),
-        Instr = mark_hp(Lval)
+            most_specific_lval(Lval1, Lval2, Lval)
+        ->
+            MaybeInstr = yes(mark_hp(Lval))
+        ;
+            MaybeInstr = no
+        )
     ;
         Instr1 = restore_hp(Rval1),
+        (
         Instr2 = restore_hp(Rval2),
-        most_specific_rval(Rval1, Rval2, Rval),
-        Instr = restore_hp(Rval)
+            most_specific_rval(Rval1, Rval2, Rval)
+        ->
+            MaybeInstr = yes(restore_hp(Rval))
+        ;
+            MaybeInstr = no
+        )
     ;
         Instr1 = free_heap(Rval1),
+        (
         Instr2 = free_heap(Rval2),
-        most_specific_rval(Rval1, Rval2, Rval),
-        Instr = free_heap(Rval)
+            most_specific_rval(Rval1, Rval2, Rval)
+        ->
+            MaybeInstr = yes(free_heap(Rval))
+        ;
+            MaybeInstr = no
+        )
     ;
         Instr1 = store_ticket(Lval1),
+        (
         Instr2 = store_ticket(Lval2),
-        most_specific_lval(Lval1, Lval2, Lval),
-        Instr = store_ticket(Lval)
+            most_specific_lval(Lval1, Lval2, Lval)
+        ->
+            MaybeInstr = yes(store_ticket(Lval))
+        ;
+            MaybeInstr = no
+        )
     ;
         Instr1 = reset_ticket(Rval1, Reason),
+        (
         Instr2 = reset_ticket(Rval2, Reason),
-        most_specific_rval(Rval1, Rval2, Rval),
-        Instr = reset_ticket(Rval, Reason)
-    ;
-        Instr1 = discard_ticket,
-        Instr2 = Instr1,
-        Instr = Instr1
+            most_specific_rval(Rval1, Rval2, Rval)
+        ->
+            MaybeInstr = yes(reset_ticket(Rval, Reason))
     ;
-        Instr1 = prune_ticket,
-        Instr2 = Instr1,
-        Instr = Instr1
+            MaybeInstr = no
+        )
     ;
         Instr1 = mark_ticket_stack(Lval1),
+        (
         Instr2 = mark_ticket_stack(Lval2),
-        most_specific_lval(Lval1, Lval2, Lval),
-        Instr = mark_ticket_stack(Lval)
+            most_specific_lval(Lval1, Lval2, Lval)
+        ->
+            MaybeInstr = yes(mark_ticket_stack(Lval))
+        ;
+            MaybeInstr = no
+        )
     ;
         Instr1 = prune_tickets_to(Rval1),
+        (
         Instr2 = prune_tickets_to(Rval2),
-        most_specific_rval(Rval1, Rval2, Rval),
-        Instr = prune_tickets_to(Rval)
+            most_specific_rval(Rval1, Rval2, Rval)
+        ->
+            MaybeInstr = yes(prune_tickets_to(Rval))
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = livevals(_),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = block(_, _, _),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = call(_, _, _, _, _, _),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = mkframe(_, _),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = label(_),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = goto(_),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = computed_goto(_, _),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = c_code(_, _),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = save_maxfr(_),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = restore_maxfr(_),
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = discard_ticket,
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = prune_ticket,
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
     ;
         Instr1 = incr_sp(_, _),
-        Instr2 = Instr1,
-        Instr = Instr1
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
     ;
         Instr1 = decr_sp(_),
-        Instr2 = Instr1,
-        Instr = Instr1
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
     ;
         Instr1 = pragma_c(_, _, _, _, _, _, _, _, _),
-        Instr2 = Instr1,
-        Instr = Instr1
+        ( Instr1 = Instr2 ->
+            MaybeInstr = yes(Instr1)
+        ;
+            MaybeInstr = no
+        )
+    ;
+        Instr1 = comment(_),
+        MaybeInstr = no
+    ;
+        Instr1 = fork(_, _, _),
+        MaybeInstr = no
+    ;
+        Instr1 = init_sync_term(_, _),
+        MaybeInstr = no
+    ;
+        Instr1 = join_and_continue(_, _),
+        MaybeInstr = no
+    ;
+        Instr1 = join_and_terminate(_),
+        MaybeInstr = no
     ).
 
     % This predicate computes the most specific lval that
Index: compiler/dupproc.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/dupproc.m,v
retrieving revision 1.2
diff -u -b -r1.2 dupproc.m
--- compiler/dupproc.m	29 Aug 2005 15:44:19 -0000	1.2
+++ compiler/dupproc.m	30 Aug 2005 22:45:00 -0000
@@ -217,6 +217,12 @@
 		Instr = c_code(_, _),
 		StdInstr = Instr
 	;
+		Instr = save_maxfr(_),
+		StdInstr = Instr
+	;
+		Instr = restore_maxfr(_),
+		StdInstr = Instr
+	;
 		Instr = if_val(Rval, Target),
 		standardize_rval(Rval, StdRval, DupProcMap),
 		standardize_code_addr(Target, StdTarget, DupProcMap),
Index: compiler/exprn_aux.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/exprn_aux.m,v
retrieving revision 1.59
diff -u -b -r1.59 exprn_aux.m
--- compiler/exprn_aux.m	7 Sep 2005 06:51:52 -0000	1.59
+++ compiler/exprn_aux.m	7 Sep 2005 07:15:07 -0000
@@ -388,6 +388,16 @@
 			Rval0, Rval, !N),
 		Uinstr = if_val(Rval, CodeAddr)
 	;
+		Uinstr0 = save_maxfr(Lval0),
+		exprn_aux__substitute_lval_in_lval_count(OldLval, NewLval,
+			Lval0, Lval, !N),
+		Uinstr = save_maxfr(Lval)
+	;
+		Uinstr0 = restore_maxfr(Lval0),
+		exprn_aux__substitute_lval_in_lval_count(OldLval, NewLval,
+			Lval0, Lval, !N),
+		Uinstr = restore_maxfr(Lval)
+	;
 		Uinstr0 = incr_hp(Lval0, MaybeTag, MO, Rval0, TypeCtor),
 		exprn_aux__substitute_lval_in_lval_count(OldLval, NewLval,
 			Lval0, Lval, !N),
Index: compiler/handle_options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/handle_options.m,v
retrieving revision 1.236
diff -u -b -r1.236 handle_options.m
--- compiler/handle_options.m	13 Sep 2005 04:56:02 -0000	1.236
+++ compiler/handle_options.m	13 Sep 2005 04:56:36 -0000
@@ -1856,7 +1856,8 @@
     ;   minimal_model   % whether we set up for minimal model tabling
     ;   pic     % Do we need to reserve a register for
                 % PIC (position independent code)?
-    ;   trace.      % tracing/debugging options
+    ;       trace           % tracing/debugging options
+	;	    stack_extend.	% automatic stack extension
 
 convert_grade_option(GradeString, Options0, Options) :-
     reset_grade_options(Options0, Options1),
@@ -1960,11 +1961,12 @@
             % can have more then one possible target, ensure that
             % the target in the options table matches one of the
             % possible targets.
-        ( MaybeTargets = yes(Targets) ->
+		(
+            MaybeTargets = yes(Targets),
             list__member(Target, Targets),
             map__search(Options, target, Target)
         ;
-            true
+            MaybeTargets = no
         ),
         CompData = Comp - Name
     ), GradeComponents).
@@ -1975,11 +1977,12 @@
     % `IncludeGradeStr' is `yes' if the component should
     % be included in the grade string.  It is `no' for
     % those components that are just synonyms for other
-    % comments. e.g. .mm and .mmsc
+	% comments, as .mm is for .mmsc.
     %
-    % NOTE: .picreg components are handles separately.
+	% NOTE: .picreg components are handled separately.
     % (see compute_grade_components/3).
     %
+
 :- pred grade_component_table(string, grade_component,
     list(pair(option, option_data)), maybe(list(option_data)),
     bool).
@@ -2175,6 +2178,10 @@
 grade_component_table("debug", trace,
     [exec_trace - bool(yes), decl_debug - bool(no)], no, yes).
 
+	% Stack extension components
+grade_component_table("exts", stack_extend,
+	[extend_stacks_when_needed - bool(yes)], no, yes).
+
 :- pred reset_grade_options(option_table::in, option_table::out) is det.
 
 reset_grade_options(Options0, Options) :-
@@ -2206,6 +2213,7 @@
 grade_start_values(pic_reg - bool(no)).
 grade_start_values(exec_trace - bool(no)).
 grade_start_values(decl_debug - bool(no)).
+grade_start_values(extend_stacks_when_needed - bool(no)).
 
 :- pred split_grade_string(string::in, list(string)::out) is semidet.
 
Index: compiler/jumpopt.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/jumpopt.m,v
retrieving revision 1.78
diff -u -b -r1.78 jumpopt.m
--- compiler/jumpopt.m	7 Sep 2005 06:51:53 -0000	1.78
+++ compiler/jumpopt.m	7 Sep 2005 07:15:07 -0000
@@ -758,6 +758,14 @@
         NewInstrs = [Instr0],
         RemainInstrs = Instrs0
     ;
+        Uinstr0 = save_maxfr(_),
+        NewInstrs = [Instr0],
+        RemainInstrs = Instrs0
+    ;
+        Uinstr0 = restore_maxfr(_),
+        NewInstrs = [Instr0],
+        RemainInstrs = Instrs0
+    ;
         Uinstr0 = incr_sp(_, _),
         NewInstrs = [Instr0],
         RemainInstrs = Instrs0
Index: compiler/livemap.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/livemap.m,v
retrieving revision 1.66
diff -u -b -r1.66 livemap.m
--- compiler/livemap.m	7 Sep 2005 06:51:53 -0000	1.66
+++ compiler/livemap.m	7 Sep 2005 07:15:07 -0000
@@ -218,6 +218,14 @@
             MaybeSpecial = no
         )
     ;
+        Uinstr0 = save_maxfr(Lval),
+        set__delete(!.Livevals, Lval, !:Livevals),
+        opt_util__lval_access_rvals(Lval, Rvals),
+        livemap__make_live_in_rvals(Rvals, !Livevals)
+    ;
+        Uinstr0 = restore_maxfr(Lval),
+        livemap__make_live_in_rval(lval(Lval), !Livevals)
+    ;
         Uinstr0 = incr_hp(Lval, _, _, Rval, _),
 
         % Make dead the variable assigned, but make any variables
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.316
diff -u -b -r1.316 llds.m
--- compiler/llds.m	7 Sep 2005 06:51:53 -0000	1.316
+++ compiler/llds.m	7 Sep 2005 07:15:08 -0000
@@ -273,6 +273,16 @@
     ;       if_val(rval, code_addr)
             % If rval is true, then goto code_addr.
 
+    ;       save_maxfr(lval)
+            % Save the current value of maxfr to the given lval. In most
+            % grades, this does a straightforward copy, but in grades in which
+            % stacks can be reallocated, it saves the offset of maxfr from the
+            % start of the nondet stack.
+
+    ;       restore_maxfr(lval)
+            % Restore maxfr from the saved copy in the given lval. Assumes the
+            % lval was saved with save_maxfr.
+
     ;       incr_hp(lval, maybe(tag), maybe(int), rval, string)
             % Get a memory block of a size given by an rval and put its address
             % in the given lval, possibly after incrementing it by N words
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.256
diff -u -b -r1.256 llds_out.m
--- compiler/llds_out.m	13 Sep 2005 04:56:06 -0000	1.256
+++ compiler/llds_out.m	13 Sep 2005 04:56:37 -0000
@@ -1822,6 +1822,10 @@
 output_instr_decls(_, if_val(Rval, Target), !DeclSet, !IO) :-
     output_rval_decls(Rval, !DeclSet, !IO),
     output_code_addr_decls(Target, !DeclSet, !IO).
+output_instr_decls(_, save_maxfr(Lval), !DeclSet, !IO) :-
+    output_lval_decls(Lval, !DeclSet, !IO).
+output_instr_decls(_, restore_maxfr(Lval), !DeclSet, !IO) :-
+    output_lval_decls(Lval, !DeclSet, !IO).
 output_instr_decls(_, incr_hp(Lval, _Tag, _, Rval, _), !DeclSet, !IO) :-
     output_lval_decls(Lval, !DeclSet, !IO),
     output_rval_decls(Rval, !DeclSet, !IO).
@@ -2145,6 +2149,16 @@
     io__write_string(") {\n\t\t", !IO),
     output_goto(Target, CallerLabel, !IO),
     io__write_string("\t}\n", !IO).
+
+output_instruction(save_maxfr(Lval), _, !IO) :-
+    io__write_string("\tMR_save_maxfr(", !IO),
+    output_lval(Lval, !IO),
+    io__write_string(");\n", !IO).
+
+output_instruction(restore_maxfr(Lval), _, !IO) :-
+    io__write_string("\tMR_restore_maxfr(", !IO),
+    output_lval(Lval, !IO),
+    io__write_string(");\n", !IO).
 
 output_instruction(incr_hp(Lval, MaybeTag, MaybeOffset, Rval, TypeMsg),
         ProfInfo, !IO) :-
Index: compiler/middle_rec.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/middle_rec.m,v
retrieving revision 1.105
diff -u -b -r1.105 middle_rec.m
--- compiler/middle_rec.m	13 Sep 2005 04:56:08 -0000	1.105
+++ compiler/middle_rec.m	13 Sep 2005 04:57:32 -0000
@@ -460,6 +460,10 @@
 middle_rec__find_used_registers_instr(c_code(_, _), !Used).
 middle_rec__find_used_registers_instr(if_val(Rval, _), !Used) :-
     middle_rec__find_used_registers_rval(Rval, !Used).
+middle_rec__find_used_registers_instr(save_maxfr(Lval), !Used) :-
+    middle_rec__find_used_registers_lval(Lval, !Used).
+middle_rec__find_used_registers_instr(restore_maxfr(Lval), !Used) :-
+    middle_rec__find_used_registers_lval(Lval, !Used).
 middle_rec__find_used_registers_instr(incr_hp(Lval, _, _, Rval, _), !Used) :-
     middle_rec__find_used_registers_lval(Lval, !Used),
     middle_rec__find_used_registers_rval(Rval, !Used).
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.155
diff -u -b -r1.155 opt_debug.m
--- compiler/opt_debug.m	13 Sep 2005 04:56:09 -0000	1.155
+++ compiler/opt_debug.m	13 Sep 2005 04:56:38 -0000
@@ -691,6 +691,12 @@
         Str = "if (" ++ dump_rval(Rval) ++ ") goto "
             ++ dump_code_addr(ProcLabel, CodeAddr)
     ;
+        Instr = save_maxfr(Lval),
+        Str = "save_maxfr(" ++ dump_lval(Lval) ++ ")"
+    ;
+        Instr = restore_maxfr(Lval),
+        Str = "restore_maxfr(" ++ dump_lval(Lval) ++ ")"
+    ;
         Instr = incr_hp(Lval, MaybeTag, MaybeOffset, Size, _),
         (
             MaybeTag = no,
Index: compiler/opt_util.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/opt_util.m,v
retrieving revision 1.133
diff -u -b -r1.133 opt_util.m
--- compiler/opt_util.m	7 Sep 2005 06:51:56 -0000	1.133
+++ compiler/opt_util.m	7 Sep 2005 07:41:41 -0000
@@ -768,6 +768,14 @@
         rval_refers_stackvars(Rval, Use),
         Need = Use
     ;
+        Uinstr0 = save_maxfr(Lval),
+        lval_refers_stackvars(Lval, Use),
+        need_if_use_or_refers_stackvars(Use, Instrs0, Need)
+    ;
+        Uinstr0 = restore_maxfr(Lval),
+        lval_refers_stackvars(Lval, Use),
+        need_if_use_or_refers_stackvars(Use, Instrs0, Need)
+    ;
         Uinstr0 = incr_hp(Lval, _, _, Rval, _),
         lval_refers_stackvars(Lval, Use1),
         rval_refers_stackvars(Rval, Use2),
@@ -921,6 +929,8 @@
 can_instr_branch_away(computed_goto(_, _), yes).
 can_instr_branch_away(c_code(_, _), no).
 can_instr_branch_away(if_val(_, _), yes).
+can_instr_branch_away(save_maxfr(_), no).
+can_instr_branch_away(restore_maxfr(_), no).
 can_instr_branch_away(incr_hp(_, _, _, _, _), no).
 can_instr_branch_away(mark_hp(_), no).
 can_instr_branch_away(restore_hp(_), no).
@@ -995,6 +1005,8 @@
 can_instr_fall_through(computed_goto(_, _), no).
 can_instr_fall_through(c_code(_, _), yes).
 can_instr_fall_through(if_val(_, _), yes).
+can_instr_fall_through(save_maxfr(_), yes).
+can_instr_fall_through(restore_maxfr(_), yes).
 can_instr_fall_through(incr_hp(_, _, _, _, _), yes).
 can_instr_fall_through(mark_hp(_), yes).
 can_instr_fall_through(restore_hp(_), yes).
@@ -1039,6 +1051,8 @@
 can_use_livevals(computed_goto(_, _), no).
 can_use_livevals(c_code(_, _), no).
 can_use_livevals(if_val(_, _), yes).
+can_use_livevals(save_maxfr(_), no).
+can_use_livevals(restore_maxfr(_), no).
 can_use_livevals(incr_hp(_, _, _, _, _), no).
 can_use_livevals(mark_hp(_), no).
 can_use_livevals(restore_hp(_), no).
@@ -1100,6 +1114,8 @@
 instr_labels_2(computed_goto(_, Labels), Labels, []).
 instr_labels_2(c_code(_, _), [], []).
 instr_labels_2(if_val(_, Addr), [], [Addr]).
+instr_labels_2(save_maxfr(_), [], []).
+instr_labels_2(restore_maxfr(_), [], []).
 instr_labels_2(incr_hp(_, _, _, _, _), [], []).
 instr_labels_2(mark_hp(_), [], []).
 instr_labels_2(restore_hp(_), [], []).
@@ -1154,6 +1170,8 @@
         Labels = [],
         CodeAddrs = [CodeAddr]
     ).
+possible_targets(save_maxfr(_), [], []).
+possible_targets(restore_maxfr(_), [], []).
 possible_targets(incr_hp(_, _, _, _, _), [], []).
 possible_targets(mark_hp(_), [], []).
 possible_targets(restore_hp(_), [], []).
@@ -1223,6 +1241,8 @@
 instr_rvals_and_lvals(computed_goto(Rval, _), [Rval], []).
 instr_rvals_and_lvals(c_code(_, _), [], []).
 instr_rvals_and_lvals(if_val(Rval, _), [Rval], []).
+instr_rvals_and_lvals(save_maxfr(Lval), [], [Lval]).
+instr_rvals_and_lvals(restore_maxfr(Lval), [], [Lval]).
 instr_rvals_and_lvals(incr_hp(Lval, _, _, Rval, _), [Rval], [Lval]).
 instr_rvals_and_lvals(mark_hp(Lval), [], [Lval]).
 instr_rvals_and_lvals(restore_hp(Rval), [Rval], []).
@@ -1354,6 +1374,10 @@
 count_temps_instr(if_val(Rval, _), !R, !F) :-
     count_temps_rval(Rval, !R, !F).
 count_temps_instr(c_code(_, _), !R, !F).
+count_temps_instr(save_maxfr(Lval), !R, !F) :-
+    count_temps_lval(Lval, !R, !F).
+count_temps_instr(restore_maxfr(Lval), !R, !F) :-
+    count_temps_lval(Lval, !R, !F).
 count_temps_instr(incr_hp(Lval, _, _, Rval, _), !R, !F) :-
     count_temps_lval(Lval, !R, !F),
     count_temps_rval(Rval, !R, !F).
@@ -1718,6 +1742,23 @@
         Rval = Rval0
     ),
     replace_labels_code_addr(Target0, ReplMap, Target).
+replace_labels_instr(save_maxfr(Lval0), ReplMap, ReplData, save_maxfr(Lval)) :-
+    (
+        ReplData = yes,
+        replace_labels_lval(Lval0, ReplMap, Lval)
+    ;
+        ReplData = no,
+        Lval = Lval0
+    ).
+replace_labels_instr(restore_maxfr(Lval0), ReplMap, ReplData,
+        restore_maxfr(Lval)) :-
+    (
+        ReplData = yes,
+        replace_labels_lval(Lval0, ReplMap, Lval)
+    ;
+        ReplData = no,
+        Lval = Lval0
+    ).
 replace_labels_instr(incr_hp(Lval0, MaybeTag, MO, Rval0, Msg),
         ReplMap, ReplData, incr_hp(Lval, MaybeTag, MO, Rval, Msg)) :-
     (
Index: compiler/options.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.467
diff -u -b -r1.467 options.m
--- compiler/options.m	13 Sep 2005 04:56:10 -0000	1.467
+++ compiler/options.m	13 Sep 2005 04:56:39 -0000
@@ -268,6 +268,7 @@
 		;	minimal_model_debug
 		;	type_layout
 		;	maybe_thread_safe
+		;	extend_stacks_when_needed
 
 		% Data representation compilation model options
 		;	reserve_tag
@@ -995,6 +996,7 @@
 	parallel		-	bool(no),
 	use_trail		-	bool(no),
 	maybe_thread_safe	-	string("no"),
+	extend_stacks_when_needed	-	bool(no),
 	use_minimal_model_stack_copy	-	bool(no),
 	use_minimal_model_own_stacks	-	bool(no),
 	minimal_model_debug	-	bool(no),
@@ -1706,6 +1708,7 @@
 long_option("use-trail",		use_trail).
 long_option("type-layout",		type_layout).
 long_option("maybe-thread-safe",	maybe_thread_safe).
+long_option("extend-stacks-when-needed",	extend_stacks_when_needed).
 long_option("aditi",			aditi).
 long_option("aditi-calls-mercury",	aditi_calls_mercury).
 	% Data representation options
@@ -3431,7 +3434,10 @@
 		"\t`maybe_thread_safe' option is treated as though it has a",
 		"\t`thread_safe' attribute.  `no' means that the foreign",
 		"\tprocedure is treated as though it has a `not_thread_safe'",
-		"\tattribute.  The default is no."
+		"\tattribute.  The default is no.",
+		"--extend-stacks-when-needed",
+		"\tSpecify that code that increments a stack pointer must",
+		"\textend the stack when this is needed."
 	]),
 
 	io__write_string("\n    LLDS back-end compilation model options:\n"),
Index: compiler/reassign.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/reassign.m,v
retrieving revision 1.10
diff -u -b -r1.10 reassign.m
--- compiler/reassign.m	22 Mar 2005 06:40:21 -0000	1.10
+++ compiler/reassign.m	15 Aug 2005 15:36:03 -0000
@@ -1,4 +1,6 @@
 %-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=4 sw=4 et
+%-----------------------------------------------------------------------------%
 % Copyright (C) 2002-2005 The University of Melbourne.
 % This file may only be copied under the terms of the GNU General
 % Public License - see the file COPYING in the Mercury distribution.
@@ -112,6 +114,7 @@
 :- import_module require.
 :- import_module set.
 :- import_module std_util.
+:- import_module svmap.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -127,39 +130,30 @@
 	dependent_lval_map::in, list(instruction)::in, list(instruction)::out)
 	is det.
 
-remove_reassign_loop([], _, _, RevInstrs, RevInstrs).
-remove_reassign_loop([Instr0 | Instrs0], KnownContentsMap0, DepLvalMap0,
-		RevInstrs0, RevInstrs) :-
+remove_reassign_loop([], _, _, !RevInstrs).
+remove_reassign_loop([Instr0 | Instrs0], !.KnownContentsMap, !.DepLvalMap,
+        !RevInstrs) :-
 	Instr0 = Uinstr0 - _,
 	(
 		Uinstr0 = comment(_),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		KnownContentsMap = KnownContentsMap0,
-		DepLvalMap = DepLvalMap0
+        !:RevInstrs = [Instr0 | !.RevInstrs]
 	;
 		Uinstr0 = livevals(_),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		KnownContentsMap = KnownContentsMap0,
-		DepLvalMap = DepLvalMap0
+        !:RevInstrs = [Instr0 | !.RevInstrs]
 	;
 		Uinstr0 = block(_, _, _),
 		error("remove_reassign_loop: block")
 	;
 		Uinstr0 = assign(Target, Source),
 		(
-			map__search(KnownContentsMap0, Target, KnownContents),
+            map__search(!.KnownContentsMap, Target, KnownContents),
 			KnownContents = Source
 		->
-				% By not including Instr0 in RevInstrs1,
-				% we are deleting Instr0.
-			RevInstrs1 = RevInstrs0,
-			KnownContentsMap = KnownContentsMap0,
-			DepLvalMap = DepLvalMap0
-		;
-			RevInstrs1 = [Instr0 | RevInstrs0],
-			clobber_dependents(Target,
-				KnownContentsMap0, KnownContentsMap1,
-				DepLvalMap0, DepLvalMap1),
+            % By not including Instr0 in !RevInstrs, we are deleting it.
+            true
+        ;
+            !:RevInstrs = [Instr0 | !.RevInstrs],
+            clobber_dependents(Target, !KnownContentsMap, !DepLvalMap),
 			(
 				% For Targets of the following form, the code
 				% generator ensures that the storage location
@@ -171,179 +165,166 @@
 
 				no_implicit_alias_target(Target)
 			->
-				record_known(Target, Source,
-					KnownContentsMap1, KnownContentsMap,
-					DepLvalMap1, DepLvalMap)
+                record_known(Target, Source, !KnownContentsMap, !DepLvalMap)
 			;
-				KnownContentsMap = KnownContentsMap1,
-				DepLvalMap = DepLvalMap1
+                true
 			)
 		)
 	;
 		Uinstr0 = call(_, _, _, _, _, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% The call may clobber any lval.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = mkframe(_, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:RevInstrs = [Instr0 | !.RevInstrs],
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = label(_),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% We don't know what is stored where at the
 			% instructions that jump here.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = goto(_),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% The value of KnownContentsMap doesn't really matter
 			% since the next instruction (which must be a label)
 			% will reset it to empty anyway.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = computed_goto(_, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% The value of KnownContentsMap doesn't really matter
 			% since the next instruction (which must be a label)
 			% will reset it to empty anyway.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = c_code(_, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% The C code may clobber any lval.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = if_val(_, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		KnownContentsMap = KnownContentsMap0,
-		DepLvalMap = DepLvalMap0
+        !:RevInstrs = [Instr0 | !.RevInstrs]
+    ;
+        Uinstr0 = save_maxfr(Target),
+        !:RevInstrs = [Instr0 | !.RevInstrs],
+        clobber_dependents(Target, !KnownContentsMap, !DepLvalMap)
+    ;
+        Uinstr0 = restore_maxfr(_),
+        !:RevInstrs = [Instr0 | !.RevInstrs],
+        clobber_dependents(hp, !KnownContentsMap, !DepLvalMap)
 	;
 		Uinstr0 = incr_hp(Target, _, _, _, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		clobber_dependents(Target,
-			KnownContentsMap0, KnownContentsMap1,
-			DepLvalMap0, DepLvalMap1),
-		clobber_dependents(hp, KnownContentsMap1, KnownContentsMap,
-			DepLvalMap1, DepLvalMap)
+        !:RevInstrs = [Instr0 | !.RevInstrs],
+        clobber_dependents(Target, !KnownContentsMap, !DepLvalMap),
+        clobber_dependents(hp, !KnownContentsMap, !DepLvalMap)
 	;
 		Uinstr0 = mark_hp(Target),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		clobber_dependents(Target, KnownContentsMap0, KnownContentsMap,
-			DepLvalMap0, DepLvalMap)
+        !:RevInstrs = [Instr0 | !.RevInstrs],
+        clobber_dependents(Target, !KnownContentsMap, !DepLvalMap)
 	;
 		Uinstr0 = restore_hp(_),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		clobber_dependents(hp, KnownContentsMap0, KnownContentsMap,
-			DepLvalMap0, DepLvalMap)
+        !:RevInstrs = [Instr0 | !.RevInstrs],
+        clobber_dependents(hp, !KnownContentsMap, !DepLvalMap)
 	;
 		Uinstr0 = free_heap(_),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs]
 			% There is no need to update KnownContentsMap since
 			% later code should never refer to the freed cell.
-		KnownContentsMap = KnownContentsMap0,
-		DepLvalMap = DepLvalMap0
 	;
 		Uinstr0 = store_ticket(Target),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		clobber_dependents(Target, KnownContentsMap0, KnownContentsMap,
-			DepLvalMap0, DepLvalMap)
+        !:RevInstrs = [Instr0 | !.RevInstrs],
+        clobber_dependents(Target, !KnownContentsMap, !DepLvalMap)
 	;
 		Uinstr0 = reset_ticket(_, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% The reset operation may modify any lval.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = prune_ticket,
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		KnownContentsMap = KnownContentsMap0,
-		DepLvalMap = DepLvalMap0
+        !:RevInstrs = [Instr0 | !.RevInstrs]
 	;
 		Uinstr0 = discard_ticket,
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		KnownContentsMap = KnownContentsMap0,
-		DepLvalMap = DepLvalMap0
+        !:RevInstrs = [Instr0 | !.RevInstrs]
 	;
 		Uinstr0 = mark_ticket_stack(Target),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		clobber_dependents(Target, KnownContentsMap0, KnownContentsMap,
-			DepLvalMap0, DepLvalMap)
+        !:RevInstrs = [Instr0 | !.RevInstrs],
+        clobber_dependents(Target, !KnownContentsMap, !DepLvalMap)
 	;
 		Uinstr0 = prune_tickets_to(_),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		KnownContentsMap = KnownContentsMap0,
-		DepLvalMap = DepLvalMap0
+        !:RevInstrs = [Instr0 | !.RevInstrs]
 %	;
 %		Uinstr0 = discard_tickets_to(_),
-%		RevInstrs1 = [Instr0 | RevInstrs0],
-%		KnownContentsMap = KnownContentsMap0,
-%		DepLvalMap = DepLvalMap0
+%       !:RevInstrs = [Instr0 | !.RevInstrs],
+%       !:KnownContentsMap = KnownContentsMap0,
+%       !:DepLvalMap = DepLvalMap0
 	;
 		Uinstr0 = incr_sp(_, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% All stackvars now refer to new locations.
 			% Rather than delete only stackvars from
 			% KnownContentsMap0, we delete everything.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = decr_sp(_),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% All stackvars now refer to new locations.
 			% Rather than delete only stackvars from
 			% KnownContentsMap0, we delete everything.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = pragma_c(_, _, _, _, _, _, _, _, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% The C code may clobber any lval.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = init_sync_term(Target, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
-		clobber_dependents(Target, KnownContentsMap0, KnownContentsMap,
-			DepLvalMap0, DepLvalMap)
+        !:RevInstrs = [Instr0 | !.RevInstrs],
+        clobber_dependents(Target, !KnownContentsMap, !DepLvalMap)
 	;
 		Uinstr0 = fork(_, _, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% Both the parent and the child thread jump to labels
 			% specified by the fork instruction, so the value of
 			% KnownContentsMap doesn't really matter since the
 			% next instruction (which must be a label) will
 			% reset it to empty anyway.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = join_and_terminate(_),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% The value of KnownContentsMap doesn't really matter
 			% since this instruction terminates the execution of
 			% this thread.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	;
 		Uinstr0 = join_and_continue(_, _),
-		RevInstrs1 = [Instr0 | RevInstrs0],
+        !:RevInstrs = [Instr0 | !.RevInstrs],
 			% Other threads may modify any lval.
-		KnownContentsMap = map__init,
-		DepLvalMap = map__init
+        !:KnownContentsMap = map__init,
+        !:DepLvalMap = map__init
 	),
-	remove_reassign_loop(Instrs0, KnownContentsMap, DepLvalMap,
-		RevInstrs1, RevInstrs).
-
-% Succeed iff the lval cannot have an alias created for it without the use of
-% a mem_ref lval or an instruction with embedded C code, both of which cause
-% us to clobber the known contents map.
+    remove_reassign_loop(Instrs0, !.KnownContentsMap, !.DepLvalMap,
+        !RevInstrs).
 
+    % Succeed iff the lval cannot have an alias created for it without
+    % the use of a mem_ref lval or an instruction with embedded C code,
+    % both of which cause us to clobber the known contents map.
+    %
 :- pred no_implicit_alias_target(lval::in) is semidet.
 
 no_implicit_alias_target(temp(_, _)).
@@ -392,13 +373,13 @@
 record_known(TargetLval, SourceRval, !KnownContentsMap, !DepLvalMap) :-
 	code_util__lvals_in_rval(SourceRval, SourceSubLvals),
 	( list__member(TargetLval, SourceSubLvals) ->
-		% The act of assigning to TargetLval has modified
-		% the value of SourceRval, so we can't eliminate
-		% any copy of this assignment or its converse.
+        % The act of assigning to TargetLval has modified the value of
+        % SourceRval, so we can't eliminate any copy of this assignment
+        % or its converse.
 		true
 	;
-		record_known_lval_rval(TargetLval, SourceRval,
-			!KnownContentsMap, !DepLvalMap),
+        record_known_lval_rval(TargetLval, SourceRval, !KnownContentsMap,
+            !DepLvalMap),
 		( SourceRval = lval(SourceLval) ->
 			record_known_lval_rval(SourceLval, lval(TargetLval),
 				!KnownContentsMap, !DepLvalMap)
@@ -421,8 +402,7 @@
 		%
 		% TargetLval still depends on the lvals inside it.
 		code_util__lvals_in_rval(OldRval, OldSubLvals),
-		list__foldl(make_not_dependent(TargetLval), OldSubLvals,
-			!DepLvalMap)
+        list__foldl(make_not_dependent(TargetLval), OldSubLvals, !DepLvalMap)
 	;
 		true
 	),
@@ -430,8 +410,7 @@
 	code_util__lvals_in_rval(SourceRval, SourceSubLvals),
 	list__append(TargetSubLvals, SourceSubLvals, AllSubLvals),
 	list__foldl(make_dependent(TargetLval), AllSubLvals, !DepLvalMap),
-	map__set(!.KnownContentsMap, TargetLval, SourceRval,
-		!:KnownContentsMap).
+    svmap__set(TargetLval, SourceRval, !KnownContentsMap).
 
 :- pred make_not_dependent(lval::in, lval::in,
 	dependent_lval_map::in, dependent_lval_map::out) is det.
@@ -439,7 +418,7 @@
 make_not_dependent(Target, SubLval, !DepLvalMap) :-
 	( map__search(!.DepLvalMap, SubLval, DepLvals0) ->
 		set__delete(DepLvals0, Target, DepLvals),
-		map__det_update(!.DepLvalMap, SubLval, DepLvals, !:DepLvalMap)
+        svmap__det_update(SubLval, DepLvals, !DepLvalMap)
 	;
 		true
 	).
@@ -450,8 +429,8 @@
 make_dependent(Target, SubLval, !DepLvalMap) :-
 	( map__search(!.DepLvalMap, SubLval, DepLvals0) ->
 		set__insert(DepLvals0, Target, DepLvals),
-		map__det_update(!.DepLvalMap, SubLval, DepLvals, !:DepLvalMap)
+        svmap__det_update(SubLval, DepLvals, !DepLvalMap)
 	;
 		DepLvals = set__make_singleton_set(Target),
-		map__det_insert(!.DepLvalMap, SubLval, DepLvals, !:DepLvalMap)
+        svmap__det_insert(SubLval, DepLvals, !DepLvalMap)
 	).
Index: compiler/use_local_vars.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/use_local_vars.m,v
retrieving revision 1.15
diff -u -b -r1.15 use_local_vars.m
--- compiler/use_local_vars.m	7 Sep 2005 06:51:57 -0000	1.15
+++ compiler/use_local_vars.m	7 Sep 2005 07:15:09 -0000
@@ -475,6 +475,10 @@
         Uinstr0 = if_val(_, _),
         exprn_aux__substitute_lval_in_instr(OldLval, NewLval, !Instr, !N)
     ;
+        Uinstr0 = save_maxfr(_)
+    ;
+        Uinstr0 = restore_maxfr(_)
+    ;
         Uinstr0 = incr_hp(Lval, _, _, _, _),
         ( Lval = OldLval ->
             % If we alter any lval that occurs in OldLval, we must stop
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/aditi
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/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/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
Index: library/benchmarking.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/benchmarking.m,v
retrieving revision 1.63
diff -u -b -r1.63 benchmarking.m
--- library/benchmarking.m	16 Jun 2005 04:07:59 -0000	1.63
+++ library/benchmarking.m	19 Jun 2005 09:42:12 -0000
@@ -207,10 +207,12 @@
 #ifndef MR_HIGHLEVEL_CODE
 	fprintf(stderr, "" D Stack: %.3fk, ND Stack: %.3fk,"",
 		((char *) MR_sp - (char *)
-			eng->MR_eng_context.MR_ctxt_detstack_zone->min)
+			eng->MR_eng_context.
+				MR_ctxt_detstack_zone->MR_zone_min)
 				/ 1024.0,
 		((char *) MR_maxfr - (char *)
-			eng->MR_eng_context.MR_ctxt_nondetstack_zone->min)
+			eng->MR_eng_context.
+				MR_ctxt_nondetstack_zone->MR_zone_min)
 				/ 1024.0
 	);
 #endif
@@ -228,7 +230,7 @@
 	fprintf(stderr,
 		"" Trail: %.3fk,"",
 		((char *) MR_trail_ptr - (char *)
-			MR_trail_zone->min) / 1024.0
+			MR_trail_zone->MR_zone_min) / 1024.0
 	);
 #endif
 
@@ -263,7 +265,8 @@
 #else /* !MR_CONSERVATIVE_GC */
 	fprintf(stderr,
 		""\\nHeap: %.3fk"",
-		((char *) MR_hp - (char *) eng->MR_eng_heap_zone->min) / 1024.0
+		((char *) MR_hp -
+			(char *) eng->MR_eng_heap_zone->MR_zone_min) / 1024.0
 	);
 #endif /* !MR_CONSERVATIVE_GC */
 
Index: library/exception.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/exception.m,v
retrieving revision 1.98
diff -u -b -r1.98 exception.m
--- library/exception.m	16 Jun 2005 04:08:00 -0000	1.98
+++ library/exception.m	19 Jun 2005 09:44:28 -0000
@@ -2208,7 +2208,9 @@
 		!= MR_ENTRY(MR_exception_handler_do_fail))
 	{
 		MR_curfr_word = MR_succfr_slot_word(MR_curfr);
-		if (MR_curfr < MR_CONTEXT(MR_ctxt_nondetstack_zone)->min) {
+		if (MR_curfr <
+			MR_CONTEXT(MR_ctxt_nondetstack_zone)->MR_zone_min)
+		{
 			MR_Word save_succip_word;
 			/*
 			** There was no exception handler.
@@ -2561,8 +2563,10 @@
 #else
 	int	slack = 1024;
 
-	if (((MR_maxfr + slack) < MR_CONTEXT(MR_ctxt_nondetstack_zone)->top)
-		&& ((MR_sp + slack) < MR_CONTEXT(MR_ctxt_detstack_zone)->top))
+	if (((MR_maxfr + slack) <
+		MR_CONTEXT(MR_ctxt_nondetstack_zone)->MR_zone_top)
+	&& ((MR_sp + slack) <
+		MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_top))
 	{
 		SUCCESS_INDICATOR = MR_FALSE;
 	} else {
cvs diff: Diffing mdbcomp
cvs diff: Diffing profiler
cvs diff: Diffing robdd
cvs diff: Diffing runtime
Index: runtime/mercury_conf.h.in
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_conf.h.in,v
retrieving revision 1.51
diff -u -b -r1.51 mercury_conf.h.in
--- runtime/mercury_conf.h.in	30 Jun 2005 06:08:33 -0000	1.51
+++ runtime/mercury_conf.h.in	13 Sep 2005 07:56:38 -0000
@@ -195,6 +195,7 @@
 **	MR_HAVE_GETPAGESIZE 	we have the getpagesize() system call.
 **	MR_HAVE_MPROTECT    	we have the mprotect() system call.
 **	MR_HAVE_MEMALIGN    	we have the memalign() function.
+**	MR_HAVE_POSIX_MEMALIGN  we have the posix_memalign() function.
 **	MR_HAVE_STRERROR    	we have the strerror() function.
 **	MR_HAVE_SIGINTERRUPT	we have the siginterrupt() function.
 **	MR_HAVE_SETITIMER   	we have the setitimer() function.
@@ -251,6 +252,7 @@
 #undef	MR_HAVE_SIGACTION
 #undef	MR_HAVE_GETPAGESIZE
 #undef	MR_HAVE_MEMALIGN
+#undef	MR_HAVE_POSIX_MEMALIGN
 #undef	MR_HAVE_MPROTECT
 #undef	MR_HAVE_STRERROR
 #undef	MR_HAVE_SIGINTERRUPT
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.84
diff -u -b -r1.84 mercury_conf_param.h
--- runtime/mercury_conf_param.h	7 Sep 2005 06:57:39 -0000	1.84
+++ runtime/mercury_conf_param.h	11 Sep 2005 02:47:25 -0000
@@ -271,6 +271,9 @@
 **	Enables low-level debugging messages from the signal handling
 **	functions in the deep profiler.
 **
+** MP_STACK_EXTEND_DEBUG
+**	Enables low-level debugging messages when extending the stacks.
+**
 ** MR_TRACE_CHECK_INTEGRITY
 **	Enables the -i and --integrity options on mdb's forward movement
 **	commands, which cause the debugger to check the integrity of the
Index: runtime/mercury_context.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_context.c,v
retrieving revision 1.40
diff -u -b -r1.40 mercury_context.c
--- runtime/mercury_context.c	29 Jun 2005 06:22:46 -0000	1.40
+++ runtime/mercury_context.c	11 Sep 2005 02:41:03 -0000
@@ -1,4 +1,7 @@
 /*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
 INIT mercury_sys_init_scheduler_wrapper
 ENDINIT
 */
@@ -62,17 +65,11 @@
 #ifdef	MR_THREAD_SAFE
 
 	pthread_mutex_init(&MR_runqueue_lock, MR_MUTEX_ATTR);
-
 	pthread_cond_init(&MR_runqueue_cond, MR_COND_ATTR);
-
 	pthread_mutex_init(&free_context_list_lock, MR_MUTEX_ATTR);
-
 	pthread_mutex_init(&MR_global_lock, MR_MUTEX_ATTR);
-
 	pthread_mutex_init(&MR_pending_contexts_lock, MR_MUTEX_ATTR);
-
 	MR_KEY_CREATE(&MR_engine_base_key, NULL);
-
 	MR_KEY_CREATE(&MR_exception_handler_key, NULL);
 
 #endif
@@ -112,7 +109,7 @@
 			0, MR_detstack_size, MR_next_offset(),
 			MR_detstack_zone_size, MR_default_handler);
 	}
-	c->MR_ctxt_sp = c->MR_ctxt_detstack_zone->min;
+    c->MR_ctxt_sp = c->MR_ctxt_detstack_zone->MR_zone_min;
 
 	if (c->MR_ctxt_nondetstack_zone != NULL) {
 		MR_reset_redzone(c->MR_ctxt_nondetstack_zone);
@@ -131,7 +128,7 @@
 	** minus one word, to the base address to get the maxfr/curfr pointer
 	** for the first frame on the nondet stack.
 	*/
-	c->MR_ctxt_maxfr = c->MR_ctxt_nondetstack_zone->min +
+    c->MR_ctxt_maxfr = c->MR_ctxt_nondetstack_zone->MR_zone_min +
 		MR_NONDET_FIXED_SIZE - 1;
 	c->MR_ctxt_curfr = c->MR_ctxt_maxfr;
 	MR_redoip_slot_word(c->MR_ctxt_curfr) = (MR_Word)
@@ -183,8 +180,7 @@
 
 #ifdef MR_USE_TRAIL
 	if (gen != NULL) {
-		MR_fatal_error("MR_init_context_maybe_generator: "
-			"generator and trail");
+        MR_fatal_error("MR_init_context_maybe_generator: generator and trail");
 	}
 
 	if (c->MR_ctxt_trail_zone != NULL) {
@@ -201,8 +197,7 @@
 
 #ifndef	MR_CONSERVATIVE_GC
 	if (gen != NULL) {
-		MR_fatal_error("MR_init_context: "
-			"generator and no conservative gc");
+        MR_fatal_error("MR_init_context: generator and no conservative gc");
 	}
 
 	c->MR_ctxt_hp = NULL;
@@ -233,7 +228,6 @@
 	}
 
 	MR_init_context(c, id, gen);
-
 	return c;
 }
 
@@ -258,13 +252,17 @@
 ** The parameter specifies whether or not the call to select should
 ** block or not.
 */
+
 static int
 MR_check_pending_contexts(MR_bool block)
 {
 #ifdef	MR_CAN_DO_PENDING_IO
-
-	int	err, max_id, n_ids;
-	fd_set	rd_set, wr_set, ex_set;
+    int                 err;
+    int                 max_id;
+    int                 n_ids;
+    fd_set              rd_set;
+    fd_set              wr_set;
+    fd_set              ex_set;
 	struct timeval timeout;
 	MR_PendingContext *pctxt;
 
@@ -363,7 +361,8 @@
 MR_define_entry(MR_do_runnext);
 #ifdef MR_THREAD_SAFE
 {
-	MR_Context *tmp, *prev;
+    MR_Context      *tmp;
+    MR_Context      *prev;
 	unsigned depth;
 	MercuryThread thd;
 
@@ -380,10 +379,9 @@
 		tmp = MR_runqueue_head;
 		/* XXX check pending io */
 		prev = NULL;
-		while(tmp != NULL) {
+        while (tmp != NULL) {
 			if ((depth > 0 && tmp->MR_ctxt_owner_thread == thd) ||
-				(tmp->MR_ctxt_owner_thread ==
-					(MercuryThread) NULL))
+                (tmp->MR_ctxt_owner_thread == (MercuryThread) NULL))
 			{
 				break;
 			}
Index: runtime/mercury_context.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_context.h,v
retrieving revision 1.27
diff -u -b -r1.27 mercury_context.h
--- runtime/mercury_context.h	3 Jun 2005 07:04:22 -0000	1.27
+++ runtime/mercury_context.h	11 Sep 2005 02:47:25 -0000
@@ -63,67 +63,84 @@
   #define MR_IF_THREAD_SAFE(x)
 #endif
 
+/*
+** MR_Context structures have the following fields:
+**
+** id               A string to identify the context for humans who want to
+**                  debug the handling of contexts.
+**
+** next             If this context is in the free-list `next' will point to
+**                  the next free context. If this context is suspended waiting
+**                  for a variable to become bound, `next' will point to the
+**                  next waiting context. If this context is runnable but not
+**                  currently running then `next' points to the next runnable
+**                  context in the runqueue.
+**
+** resume           A pointer to the code at which execution should resume
+**                  when this context is next scheduled.
+**
+** owner_thread     The owner_thread field is used to ensure that when we
+**                  enter a Mercury engine from C, we return to the same
+**                  engine. See the coments in mercury_engine.h.
+**
+** succip           The succip for this context.
+**
+** detstack_zone    The detstack zone for this context.
+** sp               The saved sp for this context.
+**
+** nondetstack_zone The nondetstack zone for this context.
+** curfr            The saved curfr for this context.
+** maxfr            The saved maxfr for this context.
+**
+** genstack_zone    The generator stack zone for this context.
+** gen_next         The saved gen_next for this context.
+**
+** cutstack_zone    The cut stack zone for this context.
+** cut_next         The saved cut_next for this context.
+**
+** pnegstack_zone   The possibly_negated_context stack zone for this context.
+** pneg_next        The saved pneg_next for this context.
+**
+** trail_zone       The trail zone for this context.
+** trail_ptr        The saved MR_trail_ptr for this context.
+** ticket_counter   The saved MR_ticket_counter for this context.
+** ticket_highwater The saved MR_ticket_high_water for this context.
+**
+** hp               The saved hp for this context.
+**
+** 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.
+*/
+
 typedef struct MR_Context_Struct MR_Context;
 struct MR_Context_Struct {
     const char          *MR_ctxt_id;
-
     MR_Context          *MR_ctxt_next; 
-                        /*
-                        ** If this context is in the free-list `next' will
-                        ** point to the next free context. If this context
-                        ** is suspended waiting for a variable to become bound,
-                        ** `next' will point to the next waiting context.
-                        ** If this context is runnable but not currently
-                        ** running then `next' points to the next runnable
-                        ** context in the runqueue.
-                        */
-
     MR_Code             *MR_ctxt_resume;
-                        /*
-                        ** A pointer to the code at which execution should
-                        ** resume when this context is next scheduled.
-                        */
-
 #ifdef  MR_THREAD_SAFE
     MercuryThread       MR_ctxt_owner_thread;
-                        /*
-                        ** The owner_thread field is used to ensure that when
-                        ** we enter a mercury engine from C, we return to the
-                        ** same engine. See the coments in mercury_engine.h
-                        */
 #endif
 
 #ifndef MR_HIGHLEVEL_CODE
     MR_Code             *MR_ctxt_succip;
-                        /* succip for this context */
 
     MR_MemoryZone       *MR_ctxt_detstack_zone;
-                        /* pointer to the detstack_zone for this context */
     MR_Word             *MR_ctxt_sp;
-                        /* saved stack pointer for this context */
 
     MR_MemoryZone       *MR_ctxt_nondetstack_zone;
-                        /* pointer to the nondetstack_zone for this context */
     MR_Word             *MR_ctxt_maxfr;
-                        /* saved maxfr pointer for this context */
     MR_Word             *MR_ctxt_curfr;
-                        /* saved curfr pointer for this context */
 
   #ifdef MR_USE_MINIMAL_MODEL_STACK_COPY
     MR_MemoryZone       *MR_ctxt_genstack_zone;
-                        /* pointer to the genstack_zone for this context */
     MR_Integer          MR_ctxt_gen_next;
-                        /* saved generator stack index for this context */
 
     MR_MemoryZone       *MR_ctxt_cutstack_zone;
-                        /* pointer to the cutstack_zone for this context */
     MR_Integer          MR_ctxt_cut_next;
-                        /* saved cut stack index for this context */
 
     MR_MemoryZone       *MR_ctxt_pnegstack_zone;
-                        /* pointer to the pnegstack_zone for this context */
     MR_Integer          MR_ctxt_pneg_next;
-                        /* saved pneg stack index for this context */
 
   #endif /* MR_USE_MINIMAL_MODEL_STACK_COPY */
   #ifdef MR_USE_MINIMAL_MODEL_OWN_STACKS
@@ -133,25 +150,14 @@
 
 #ifdef  MR_USE_TRAIL
     MR_MemoryZone       *MR_ctxt_trail_zone;
-                        /* pointer to the MR_trail_zone for this context */
     MR_TrailEntry       *MR_ctxt_trail_ptr;
-                        /* saved MR_trail_ptr for this context */
     MR_ChoicepointId    MR_ctxt_ticket_counter;
-                         /* saved MR_ticket_counter for this context */
     MR_ChoicepointId    MR_ctxt_ticket_high_water;
-                        /* saved MR_ticket_high_water for this context */
 #endif
 
 #ifndef MR_CONSERVATIVE_GC
     MR_Word             *MR_ctxt_hp;
-                        /* saved hp for this context */
     MR_Word             *MR_ctxt_min_hp_rec;
-                        /*
-                        ** This pointer marks the minimum value of MR_hp to
-                        ** which we can truncate the heap on backtracking.
-                        ** See comments before the macro
-                        ** set_min_heap_reclamation_point (below).
-                        */
 #endif
 };
 
@@ -277,8 +283,7 @@
             fork_new_context_i > 0;                             \
             fork_new_context_i--)                               \
         {                                                       \
-            *(f_n_c_context->context_sp) =                      \
-                MR_stackvar(fork_new_context_i);                \
+            *(f_n_c_context->context_sp) = MR_stackvar(fork_new_context_i); \
             f_n_c_context->MR_ctxt_sp++;                        \
         }                                                       \
         f_n_c_context->MR_ctxt_resume = (child);                \
@@ -319,9 +324,7 @@
   */
   #define MR_set_min_heap_reclamation_point(ctxt)           \
     do {                                                    \
-        if (MR_hp != (ctxt)->MR_ctxt_hp                     \
-            || (ctxt)->MR_ctxt_hp == NULL)                  \
-        {                                                   \
+        if (MR_hp != (ctxt)->MR_ctxt_hp || (ctxt)->MR_ctxt_hp == NULL) { \
             MR_min_hp_rec = MR_hp;                          \
             (ctxt)->MR_ctxt_min_hp_rec = MR_hp;             \
         } else {                                            \
@@ -456,34 +459,38 @@
 typedef struct MR_Sync_Term_Struct MR_SyncTerm;
 struct MR_Sync_Term_Struct {
   #ifdef MR_THREAD_SAFE
-    MercuryLock     lock;
+    MercuryLock     MR_st_lock;
   #endif
-    int             count;
-    MR_Context      *parent;
+    int             MR_st_count;
+    MR_Context      *MR_st_parent;
 };
 
 #define MR_init_sync_term(sync_term, nbranches)             \
     do {                                                    \
-        SyncTerm *st = (SyncTerm *) sync_term;              \
+        MR_SyncTerm *st;                                            \
+                                                                    \
+        st = (MR_SyncTerm *) sync_term;                             \
         MR_IF_THREAD_SAFE(                                  \
-            pthread_mutex_init(&(st->lock), MR_MUTEX_ATTR); \
+            pthread_mutex_init(&(st->MR_st_lock), MR_MUTEX_ATTR);   \
         )                                                   \
-        st->count = (nbranches);                            \
-        st->parent = NULL;                                  \
+        st->MR_st_count = (nbranches);                              \
+        st->MR_st_parent = NULL;                                    \
     } while (0)
 
 #define MR_join_and_terminate(sync_term)                    \
     do {                                                    \
-        SyncTerm *st = (SyncTerm *) sync_term;              \
-        MR_LOCK(&(st->lock), "terminate");                  \
-        (st->count)--;                                      \
-        if (st->count == 0) {                               \
-            assert(st->parent != NULL);                     \
-            MR_UNLOCK(&(st->lock), "terminate i");          \
-            MR_schedule(st->parent);                        \
+        MR_SyncTerm *st;                                            \
+                                                                    \
+        st = (MR_SyncTerm *) sync_term;                             \
+        MR_LOCK(&(st->MR_st_lock), "terminate");                    \
+        (st->MR_st_count)--;                                        \
+        if (st->MR_st_count == 0) {                                 \
+            assert(st->MR_st_parent != NULL);                       \
+            MR_UNLOCK(&(st->MR_st_lock), "terminate i");            \
+            MR_schedule(st->MR_st_parent);                          \
         } else {                                            \
-            assert(st->count > 0);                          \
-            MR_UNLOCK(&(st->lock), "terminate ii");         \
+            assert(st->MR_st_count > 0);                            \
+            MR_UNLOCK(&(st->MR_st_lock), "terminate ii");           \
         }                                                   \
         MR_destroy_context(MR_ENGINE(MR_eng_this_context)); \
         MR_runnext();                       \
@@ -491,18 +498,20 @@
 
 #define MR_join_and_continue(sync_term, where_to)           \
     do {                                                    \
-        SyncTerm *st = (SyncTerm *) sync_term;              \
-        MR_LOCK(&(st->lock), "continue");                   \
-        (st->count)--;                                      \
-        if (st->count == 0) {                               \
-            MR_UNLOCK(&(st->lock), "continue i");           \
+        MR_SyncTerm *st;                                            \
+                                                                    \
+        st = (MR_SyncTerm *) sync_term;                             \
+        MR_LOCK(&(st->MR_st_lock), "continue");                     \
+        (st->MR_st_count)--;                                        \
+        if (st->MR_st_count == 0) {                                 \
+            MR_UNLOCK(&(st->MR_st_lock), "continue i");             \
             MR_GOTO((where_to));                            \
         }                                                   \
-        assert(st->count > 0);                              \
+        assert(st->MR_st_count > 0);                                \
         MR_save_context(MR_ENGINE(MR_eng_this_context));    \
         MR_ENGINE(MR_eng_this_context)->MR_ctxt_resume = (where_to);\
-        st->parent = MR_ENGINE(MR_eng_this_context);        \
-        MR_UNLOCK(&(st->lock), "continue ii");              \
+        st->MR_st_parent = MR_ENGINE(MR_eng_this_context);          \
+        MR_UNLOCK(&(st->MR_st_lock), "continue ii");                \
         MR_runnext();                                       \
     } while (0)
 
Index: runtime/mercury_debug.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_debug.c,v
retrieving revision 1.23
diff -u -b -r1.23 mercury_debug.c
--- runtime/mercury_debug.c	20 Jul 2004 04:41:21 -0000	1.23
+++ runtime/mercury_debug.c	11 Sep 2005 02:41:03 -0000
@@ -1,4 +1,7 @@
 /*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
 ** Copyright (C) 1996-2004 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
@@ -36,9 +39,9 @@
   #define MR_non_zone(fr)	(MR_CONTEXT(MR_ctxt_nondetstack_zone))
 #endif
 
-#define MR_det_stack_min(fr)	(MR_det_zone(fr)->min)
+#define MR_det_stack_min(fr)    (MR_det_zone(fr)->MR_zone_min)
 #define MR_det_stack_offset(fr) (fr - MR_det_stack_min(fr))
-#define MR_non_stack_min(fr)	(MR_non_zone(fr)->min)
+#define MR_non_stack_min(fr)    (MR_non_zone(fr)->MR_zone_min)
 #define MR_non_stack_offset(fr) (fr - MR_non_stack_min(fr))
 
 /*--------------------------------------------------------------------*/
@@ -193,8 +196,7 @@
 	if (MR_lld_print_enabled && MR_heapdebug) {
 		printf("tag_offset_incr_hp: "
 			"tag %d, offset %d, count %d%s => %p\n",
-			tag, offset, count, (is_atomic ? ", atomic" : ""),
-				(void *) ptr);
+            tag, offset, count, (is_atomic ? ", atomic" : ""), (void *) ptr);
 		fflush(stdout);
 	}
 }
@@ -550,11 +552,10 @@
 	for(i=1; i<=8; i++) {
 		x = (MR_Integer) MR_get_reg(i);
 #ifndef MR_CONSERVATIVE_GC
-		if ((MR_Integer) MR_ENGINE(MR_eng_heap_zone)->min <= x
-				&& x < (MR_Integer)
-					MR_ENGINE(MR_eng_heap_zone)->top)
+        if ((MR_Integer) MR_ENGINE(MR_eng_heap_zone)->MR_zone_min <= x
+            && x < (MR_Integer) MR_ENGINE(MR_eng_heap_zone)->MR_zone_top)
 		{
-			x -= (MR_Integer) MR_ENGINE(MR_eng_heap_zone)->min;
+            x -= (MR_Integer) MR_ENGINE(MR_eng_heap_zone)->MR_zone_min;
 		}
 #endif
 		printf("%8lx ", (long) x);
@@ -973,7 +974,7 @@
 	fprintf(fp, "heap %ld", (long) s);
 #else
 	fprintf(fp, "heap %3ld",
-		(long) (MR_Integer) (s - MR_ENGINE(MR_eng_heap_zone)->min));
+        (long) (MR_Integer) (s - MR_ENGINE(MR_eng_heap_zone)->MR_zone_min));
 #endif
 
 	if (MR_print_raw_addrs) {
Index: runtime/mercury_deep_copy.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_deep_copy.c,v
retrieving revision 1.34
diff -u -b -r1.34 mercury_deep_copy.c
--- runtime/mercury_deep_copy.c	14 Dec 2004 01:07:24 -0000	1.34
+++ runtime/mercury_deep_copy.c	11 Sep 2005 02:41:03 -0000
@@ -154,10 +154,10 @@
 
 	MR_restore_transient_hp();	/* Because we play with MR_hp */
 
-	if (lower_limit < MR_ENGINE(MR_eng_heap_zone)->bottom ||
-			lower_limit > MR_ENGINE(MR_eng_heap_zone)->top)
+	if (lower_limit < MR_ENGINE(MR_eng_heap_zone)->MR_zone_bottom ||
+		lower_limit > MR_ENGINE(MR_eng_heap_zone)->MR_zone_top)
 	{
-		lower_limit = MR_ENGINE(MR_eng_heap_zone)->bottom;
+		lower_limit = MR_ENGINE(MR_eng_heap_zone)->MR_zone_bottom;
 	}
 
 	/* temporarily swap the heap with the global heap */
@@ -168,7 +168,7 @@
 	/* copy values from the heap to the global heap */
 	MR_save_transient_hp();
 	result = MR_deep_copy(term, type_info, lower_limit,
-			MR_ENGINE(MR_eng_global_heap_zone)->top);
+		MR_ENGINE(MR_eng_global_heap_zone)->MR_zone_top);
 	MR_restore_transient_hp();
 
 	/* swap the heap and global heap back again */
Index: runtime/mercury_engine.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_engine.c,v
retrieving revision 1.49
diff -u -b -r1.49 mercury_engine.c
--- runtime/mercury_engine.c	20 Jul 2004 04:41:21 -0000	1.49
+++ runtime/mercury_engine.c	11 Sep 2005 02:41:03 -0000
@@ -108,7 +108,7 @@
 	eng->MR_eng_heap_zone = MR_create_zone("heap", 1,
 		MR_heap_size, MR_next_offset(),
 		MR_heap_zone_size, MR_default_handler);
-	eng->MR_eng_hp = eng->MR_eng_heap_zone->min;
+	eng->MR_eng_hp = eng->MR_eng_heap_zone->MR_zone_min;
 
   #ifdef MR_NATIVE_GC
 	eng->MR_eng_heap_zone2 = MR_create_zone("heap2", 1,
@@ -126,12 +126,12 @@
 	eng->MR_eng_solutions_heap_zone = MR_create_zone("solutions_heap", 1,
 		MR_solutions_heap_size, MR_next_offset(),
 		MR_solutions_heap_zone_size, MR_default_handler);
-	eng->MR_eng_sol_hp = eng->MR_eng_solutions_heap_zone->min;
+	eng->MR_eng_sol_hp = eng->MR_eng_solutions_heap_zone->MR_zone_min;
 
 	eng->MR_eng_global_heap_zone = MR_create_zone("global_heap", 1,
 		MR_global_heap_size, MR_next_offset(),
 		MR_global_heap_zone_size, MR_default_handler);
-	eng->MR_eng_global_hp = eng->MR_eng_global_heap_zone->min;
+	eng->MR_eng_global_hp = eng->MR_eng_global_heap_zone->MR_zone_min;
   #endif /* MR_MIGHT_RECLAIM_HP_ON_FAILURE */
 #endif /* !MR_CONSERVATIVE_GC */
 
Index: runtime/mercury_engine.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_engine.h,v
retrieving revision 1.36
diff -u -b -r1.36 mercury_engine.h
--- runtime/mercury_engine.h	20 Jul 2004 04:41:22 -0000	1.36
+++ runtime/mercury_engine.h	13 Sep 2005 04:53:35 -0000
@@ -1,4 +1,7 @@
 /*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
 ** Copyright (C) 1994-2004 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
@@ -13,11 +16,10 @@
 #ifndef	MERCURY_ENGINE_H
 #define	MERCURY_ENGINE_H
 
-	/*
-	** include mercury_regs.h first so that we don't have
-	** any function prototypes before the global register
-	** declarations.
-	*/
+/*
+** Include mercury_regs.h first so that we don't have any function prototypes
+** before the global register declarations.
+*/
 #include "mercury_regs.h"		/* for MR_NUM_REAL_REGS */
 
 #include <setjmp.h>
@@ -65,8 +67,9 @@
 #define	MR_NOT_NEAREST_FLAG 		19
 #define	MR_DEBUG_SLOTS_FLAG		20
 #define	MR_DEEP_PROF_DEBUG_FILE_FLAG 	21
-#define	MR_DETAILFLAG			22
-#define	MR_MAXFLAG			23
+#define MR_STACK_EXTEND_FLAG            22
+#define MR_DETAILFLAG                   23
+#define MR_MAXFLAG                      24
 /* MR_DETAILFLAG should be the last real flag */
 
 /*
@@ -135,6 +138,9 @@
 ** MR_deep_prof_debug_file_flag, if set, causes the runtime, whenever it is
 ** generating a Deep.data file, to also generate a human-readable Deep.debug
 ** file.
+**
+** MR_stack_extend_debug controls whether the runtime prints diagnostics
+** whenever it extends a stack.
 */
 
 #define	MR_progdebug		MR_debugflag[MR_PROGFLAG]
@@ -160,6 +166,7 @@
 #define	MR_debug_slots_flag	MR_debugflag[MR_DEBUG_SLOTS_FLAG]
 #define	MR_deep_prof_debug_file_flag	MR_debugflag[\
 						MR_DEEP_PROF_DEBUG_FILE_FLAG]
+#define MR_stack_extend_debug       MR_debugflag[MR_STACK_EXTEND_FLAG]
 #define	MR_detaildebug		MR_debugflag[MR_DETAILFLAG]
 
 typedef struct {
@@ -169,23 +176,17 @@
 
 extern	MR_Debug_Flag_Info	MR_debug_flag_info[MR_MAXFLAG];
 
-	/* 
-	** MR_setjmp and MR_longjmp are wrappers around setjmp and longjmp 
-	** to ensure that
-	**	 call C -> setjmp -> call Mercury -> call C -> longjmp 
-	** works correctly. This is used by the exception handling code for
-	** the ODBC interface, and probably shouldn't be used for anything
-	** else.
-	*/ 
+/* 
+** MR_setjmp and MR_longjmp are wrappers around setjmp and longjmp to ensure
+** that
+**   call C -> setjmp -> call Mercury -> call C -> longjmp 
+** works correctly. This is used by the exception handling code for
+** the ODBC interface, and probably shouldn't be used for anything else.
+*/ 
 
 typedef struct {
-		jmp_buf *mercury_env;	/* 
-					** used to save
-					** MR_ENGINE(MR_eng_jmp_buf )
-					*/
-		jmp_buf env;		/* 
-					** used by calls to setjmp and longjmp 
-					*/
+        jmp_buf     *mercury_env;   /* used to save MR_ENGINE(MR_eng_jmp_buf) */
+        jmp_buf     env;            /* used by calls to setjmp and longjmp */
 		MR_Word *saved_succip;
 		MR_Word *saved_sp;
 		MR_Word *saved_curfr;
@@ -197,7 +198,6 @@
 #if MR_NUM_REAL_REGS > 0
 		MR_Word regs[MR_NUM_REAL_REGS];
 #endif /* MR_NUM_REAL_REGS > 0 */
-
 	} MR_jmp_buf;
 
 /*---------------------------------------------------------------------------*/
@@ -207,23 +207,23 @@
 ** across calls to Mercury code.
 */
 
-	/*
-	** MR_setjmp(MR_jmp_buf *env, longjmp_label)
-	**
-	** Save MR_ENGINE(MR_eng_jmp_buf), save the Mercury state,
-	** call setjmp(env),  then fall through.
-	**
-	** When setjmp returns via a call to longjmp, control will pass to
-	** longjmp_label.
-	**
-	** Notes:
-	** - The Mercury registers must be valid before the call to MR_setjmp.
-	** - The general-purpose registers MR_r1, MR_r2... are not restored
-	** and must be saved by the caller.
-	** - In grades without conservative garbage collection, the caller
-	** must save and restore hp, sol_hp, heap_zone 
-	** and solutions_heap_zone.
-	*/
+/*
+** MR_setjmp(MR_jmp_buf *env, longjmp_label)
+**
+** Save MR_ENGINE(MR_eng_jmp_buf), save the Mercury state, call setjmp(env),
+** then fall through.
+**
+** When setjmp returns via a call to longjmp, control will pass to
+** longjmp_label.
+**
+** Notes:
+** - The Mercury registers must be valid before the call to MR_setjmp.
+** - The general-purpose registers MR_r1, MR_r2... are not restored
+**   and must be saved by the caller.
+** - In grades without conservative garbage collection, the caller must save
+**   and restore hp, sol_hp, heap_zone and solutions_heap_zone.
+*/
+
 #define MR_setjmp(setjmp_env, longjmp_label)				\
 	    do {							\
 		(setjmp_env)->mercury_env = MR_ENGINE(MR_eng_jmp_buf);	\
@@ -232,21 +232,19 @@
 		(setjmp_env)->saved_sp = MR_sp;				\
 		(setjmp_env)->saved_curfr = MR_curfr;			\
 		(setjmp_env)->saved_maxfr = MR_maxfr;			\
-		MR_IF_USE_TRAIL((setjmp_env)->saved_trail_ptr = 	\
-			MR_trail_ptr);					\
+        MR_IF_USE_TRAIL((setjmp_env)->saved_trail_ptr = MR_trail_ptr);        \
 		MR_IF_USE_TRAIL((setjmp_env)->saved_ticket_counter =	\
 			MR_ticket_counter);				\
 		MR_IF_USE_TRAIL((setjmp_env)->saved_ticket_high_water =	\
 			MR_ticket_high_water);				\
 		if (setjmp((setjmp_env)->env)) {			\
-			MR_ENGINE(MR_eng_jmp_buf) = (setjmp_env)->mercury_env;\
+            MR_ENGINE(MR_eng_jmp_buf) = (setjmp_env)->mercury_env;\           \
 			MR_restore_regs_from_mem((setjmp_env)->regs);	\
-			MR_succip_word = (MR_Word) (setjmp_env)->saved_succip;\
+            MR_succip_word = (MR_Word) (setjmp_env)->saved_succip;\           \
 			MR_sp_word = (MR_Word) (setjmp_env)->saved_sp;	\
-			MR_curfr_word = (MR_Word) (setjmp_env)->saved_curfr;\
-			MR_maxfr_word = (MR_Word) (setjmp_env)->saved_maxfr;\
-			MR_IF_USE_TRAIL(MR_trail_ptr = 			\
-					(setjmp_env)->saved_trail_ptr);	\
+            MR_curfr_word = (MR_Word) (setjmp_env)->saved_curfr;\             \
+            MR_maxfr_word = (MR_Word) (setjmp_env)->saved_maxfr;\             \
+            MR_IF_USE_TRAIL(MR_trail_ptr = (setjmp_env)->saved_trail_ptr);    \
 			MR_IF_USE_TRAIL(MR_ticket_counter = 		\
 				(setjmp_env)->saved_ticket_counter);	\
 			MR_IF_USE_TRAIL(MR_ticket_high_water = 		\
@@ -255,11 +253,11 @@
 		}							\
 	    } while (0)
 
-	/*
-	** MR_longjmp(MR_jmp_buf *env)
-	** 
-	** Call longjmp(), MR_setjmp() will handle the rest.
-	*/
+/*
+** MR_longjmp(MR_jmp_buf *env)
+** 
+** Call longjmp(), MR_setjmp() will handle the rest.
+*/
 #define MR_longjmp(setjmp_env)	longjmp((setjmp_env)->env, 1)
 
 /*---------------------------------------------------------------------------*/
@@ -272,75 +270,106 @@
 #endif
 
 /*
-** The Mercury engine structure.
-**	Normally there is one of these for each Posix thread.
+** The Mercury engine structure. Normally there is one of these for each
+** Posix thread. It contains the following fields.
+**
+** fake_reg     The fake reg vector for this engine.
+**
+** hp           The heap pointer for this engine.
+**
+** sol_hp       The solutions heap pointer for this engine.
+**
+** global_hp    The global heap pointer for this engine.
+**
+** this_context Points to the context currently executing on this engine.
+**
+** context      This field stores all the context information for the context
+**              executing in this engine.
+**
+**              MR_init_engine, invoked by mercury_runtime_init in
+**              mercury_wrapper.c through MR_init_thread and MR_create_engine,
+**              sets up the initial context for the engine, and puts the
+**              pointer to it in the this_context field. Later,
+**              mercury_runtime_init invokes MR_save_context to copy the info
+**              from there into the context field. Beyond this, the
+**              relationship between the this_context and context fields
+**              is not well documented XXX.
+**
+** main_context The context of the main computation. The owner_generator field
+**              of this context must be NULL.
+**
+** gen_contexts The contexts of the active generators in this engine.
+**              The owner_generator fields of these contexts will point
+**              to their generators.
+**
+** free_contexts
+**              Contexts that used to belong to active generators, but which
+**              are no longer needed. They are cached here to allow new
+**              generators to be created without redoing the work required
+**              to allocate a new context.
+**
+** owner_thred
+** c_depth
+** saved_owners
+**              These three fields are used to ensure that when a thread
+**              executing C code calls the Mercury engine associated with that
+**              thread, the Mercury code will finish in the same engine and
+**              return appropriately. Each time C calls Mercury in a thread,
+**              the c_depth is incremented, and the owner_thread field of the
+**              current context is set to the id of the thread. While the
+**              owner_thread is set, the context will not be scheduled for
+**              execution by any other thread. When the call to the Mercury
+**              engine finishes, c_depth is decremented and the owner_thread
+**              field of the current context is restored to its previous value.
+**              The list `saved_owners' is used in call_engine_inner to store
+**              the owner of a context across calls into Mercury. At the moment
+**              this is only used for sanity checking - that execution never
+**              returns into C in the wrong thread.
+**
+** jmp_buf      The jump buffer used by library/exception.m to return to the
+**              runtime system on otherwise unhandled exceptions.
+**
+** exception    This field is used by library/exception.m to return the
+**              identity of the exception that terminates the execution of an
+**              engine to the runtime.
+**
+** heap_zone    The heap zone for this engine.
+**
+** solutions_heap_zone
+**              The solutions heap zone for this engine. We store terms on this
+**              heap temporarily while looking for more solutions in an
+**              all-solutions predicate.
+**
+** global_heap_zone
+**              The global heap zone for this engine. We store terms on this
+**              heap when we want to make them survive resets of hp by
+**              backtracking, e.g. for global data structures in the debugger.
+**
+** heap_zone2   The other heap zone in our two-space collector.
+**
+** debug_heap_zone
+**              A zone used for debugging the accurate gc. Probably not
+**              terribly functional.
 */
 
 typedef struct MR_mercury_engine_struct {
 	MR_Word		MR_eng_fake_reg[MR_MAX_FAKE_REG];
-			/* The fake reg vector for this engine. */
 #ifndef MR_CONSERVATIVE_GC
 	MR_Word		*MR_eng_hp;
-			/* The heap pointer for this engine */
 	MR_Word		*MR_eng_sol_hp;
-			/* The solutions heap pointer for this engine */
 	MR_Word		*MR_eng_global_hp;
-			/* The global heap pointer for this engine */
 #endif
 	MR_Context	*MR_eng_this_context;
-			/*
-			** MR_eng_this_context points to the context currently
-			** executing in this engine.
-			*/
 	MR_Context	MR_eng_context;
-			/*
-			** MR_eng_context stores all the context information
-			** for the context executing in this engine.
-			*/
 #ifdef	MR_USE_MINIMAL_MODEL_OWN_STACKS
 	MR_Context	*MR_eng_main_context;
-			/*
-			** The context of the main computation. The
-			** owner_generator field of this context must be NULL.
-			*/
 	MR_Dlist	*MR_eng_gen_contexts;	/* elements are MR_Context */
-			/*
-			** The contexts of the active generators. The
-			** owner_generator fields of these contexts will point
-			** to their generators.
-			*/
 	MR_Dlist	*MR_eng_free_contexts;	/* elements are MR_Context */
-			/*
-			** Contexts that used to belong to active generators,
-			** but which are no longer needed. They are cached here
-			** to allow new generators to be created without
-			** redoing the work required to allocate a new context.
-			*/
 #endif
 #ifdef	MR_THREAD_SAFE
 	MercuryThread	MR_eng_owner_thread;
 	unsigned	MR_eng_c_depth;
 	MercuryThreadList *MR_eng_saved_owners;
-			/*
-			** These three fields are used to ensure that when a
-			** thread executing C code calls the Mercury engine
-			** associated with that thread, the Mercury code
-			** will finish in the same engine and return
-			** appropriately. Each time C calls Mercury in a
-			** thread, the c_depth is incremented, and the
-			** owner_thread field of the current context is set
-			** to the id of the thread. While the owner_thread
-			** is set, the context will not be scheduled for
-			** execution by any other thread. When the call to
-			** the Mercury engine finishes, c_depth is decremented
-			** and the owner_thread field of the current context
-			** is restored to its previous value. The list
-			** `saved_owners' is used in call_engine_inner to store
-			** the owner of a context across calls into Mercury.
-			** At the moment this is only used for sanity checking
-			** - that execution never returns into C in the
-			** wrong thread.
-			*/
 #endif
 	jmp_buf		*MR_eng_jmp_buf;
 	MR_Word		*MR_eng_exception;
@@ -428,6 +457,7 @@
 /*
 ** Functions for creating/destroying a MercuryEngine.
 */
+
 extern	MercuryEngine	*MR_create_engine(void);
 extern	void		MR_destroy_engine(MercuryEngine *engine);
 
@@ -436,6 +466,7 @@
 ** These are like create/destroy except that they don't allocate/deallocate
 ** the MercuryEngine structure.
 */
+
 extern	void		MR_init_engine(MercuryEngine *engine);
 extern	void		MR_finalize_engine(MercuryEngine *engine);
 
@@ -443,6 +474,7 @@
 ** Functions that act on the current Mercury engine.
 ** See the comments in mercury_engine.c for documentation on MR_call_engine().
 */
+
 extern	MR_Word		*MR_call_engine(MR_Code *entry_point,
 				MR_bool catch_exceptions);
 extern	void		MR_terminate_engine(void);
Index: runtime/mercury_grade.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_grade.h,v
retrieving revision 1.60
diff -u -b -r1.60 mercury_grade.h
--- runtime/mercury_grade.h	3 Jun 2005 07:04:22 -0000	1.60
+++ runtime/mercury_grade.h	11 Sep 2005 02:47:25 -0000
@@ -377,9 +377,19 @@
     #endif
 #endif
 
+#if defined(MR_EXTEND_STACKS_WHEN_NEEDED)
+  #define MR_GRADE_PART_15	MR_PASTE2(MR_GRADE_PART_14, _exts)
+  #define MR_GRADE_OPT_PART_15	MR_GRADE_OPT_PART_14 ".exts"
+  #if defined(MR_HIGHLEVEL_CODE)
+    #error "--extend-stacks-when-needed and --high-level-code are not compatible"
+  #endif
+#else
+  #define MR_GRADE_PART_15	MR_GRADE_PART_14
+  #define MR_GRADE_OPT_PART_15	MR_GRADE_OPT_PART_14
+#endif
 
-#define MR_GRADE		MR_GRADE_PART_14
-#define MR_GRADE_OPT		MR_GRADE_OPT_PART_14
+#define MR_GRADE		MR_GRADE_PART_15
+#define MR_GRADE_OPT		MR_GRADE_OPT_PART_15
 
 #define MR_GRADE_VAR		MR_PASTE2(MR_grade_,MR_GRADE)
 #define MR_GRADE_STRING 	MR_STRINGIFY(MR_GRADE)
Index: runtime/mercury_memory_handlers.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_memory_handlers.c,v
retrieving revision 1.28
diff -u -b -r1.28 mercury_memory_handlers.c
--- runtime/mercury_memory_handlers.c	18 Oct 2004 20:51:28 -0000	1.28
+++ runtime/mercury_memory_handlers.c	11 Sep 2005 02:41:03 -0000
@@ -1,4 +1,7 @@
 /*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
 ** Copyright (C) 1998, 2000, 2002 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.
@@ -74,7 +77,6 @@
   static	void	simple_sighandler(int);
 #endif
 
-
 #ifdef MR_HAVE_SIGINFO
   #if defined(MR_HAVE_SIGCONTEXT_STRUCT)
     #if defined(MR_HAVE_SIGCONTEXT_STRUCT_3ARG)
@@ -95,15 +97,14 @@
     #define     segv_handler	simple_sighandler
 #endif
 
-
 /*
 ** round_up(amount, align) returns `amount' rounded up to the nearest
 ** alignment boundary.  `align' must be a power of 2.
 */
 
-static	void	print_dump_stack(void);
-static	MR_bool	try_munprotect(void *address, void *context);
-static	char	*explain_context(void *context);
+static  void    MR_print_dump_stack(void);
+static  MR_bool MR_try_munprotect(void *address, void *context);
+static  char    *MR_explain_context(void *context);
 static	MR_Code	*get_pc_from_context(void *the_context);
 static	MR_Word	*get_sp_from_context(void *the_context);
 static	MR_Word	*get_curfr_from_context(void *the_context);
@@ -119,12 +120,12 @@
 */
 
 static MR_bool 
-try_munprotect(void *addr, void *context)
+MR_try_munprotect(void *addr, void *context)
 {
 #if !(defined(MR_HAVE_SIGINFO) || defined(MR_WIN32_VIRTUAL_ALLOC))
 	return MR_FALSE;
 #else
-	MR_Word *    fault_addr;
+    MR_Word         *fault_addr;
 	MR_MemoryZone *zone;
 
 	fault_addr = (MR_Word *) addr;
@@ -139,21 +140,23 @@
   #ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
 		if (MR_memdebug) {
 			fprintf(stderr, "checking %s#%d: %p - %p\n",
-				zone->name, zone->id, (void *) zone->redzone,
-				(void *) zone->top);
+                zone->MR_zone_name, zone->MR_zone_id,
+                (void *) zone->MR_zone_redzone,
+                (void *) zone->MR_zone_top);
 		}
 
-		if (zone->redzone <= fault_addr && fault_addr <= zone->top) {
-
+        if (zone->MR_zone_redzone <= fault_addr
+            && fault_addr <= zone->MR_zone_top)
+        {
 			if (MR_memdebug) {
 				fprintf(stderr, "address is in %s#%d redzone\n",
-					zone->name, zone->id);
+                    zone->MR_zone_name, zone->MR_zone_id);
 			}
 
-			return zone->handler(fault_addr, zone, context);
+            return zone->MR_zone_handler(fault_addr, zone, context);
 		}
   #endif
-		zone = zone->next;
+        zone = zone->MR_zone_next;
 	}
 
 	if (MR_memdebug) {
@@ -181,13 +184,13 @@
 {
 	char	*context_msg;
 
-	context_msg = explain_context(context);
+    context_msg = MR_explain_context(context);
 	write(STDERR, main_msg, strlen(main_msg));
 	write(STDERR, context_msg, strlen(context_msg));
 	MR_trace_report_raw(STDERR);
 
 	if (dump) {
-		print_dump_stack();
+        MR_print_dump_stack();
 	}
 
 	_exit(1);
@@ -205,30 +208,31 @@
     new_zone = (MR_Word *) MR_round_up((MR_Unsigned) fault_addr
 		    + sizeof(MR_Word), MR_unit);
 
-    if (new_zone <= zone->hardmax) {
-	zone_size = (char *)new_zone - (char *)zone->redzone;
+    if (new_zone <= zone->MR_zone_hardmax) {
+        zone_size = (char *) new_zone - (char *) zone->MR_zone_redzone;
 
 	if (MR_memdebug) {
 	    fprintf(stderr, "trying to unprotect %s#%d from %p to %p (%x)\n",
-	    zone->name, zone->id, (void *) zone->redzone, (void *) new_zone,
-	    (int)zone_size);
+            zone->MR_zone_name, zone->MR_zone_id,
+            (void *) zone->MR_zone_redzone, (void *) new_zone,
+            (int) zone_size);
 	}
-	if (MR_protect_pages((char *)zone->redzone, zone_size,
+        if (MR_protect_pages((char *) zone->MR_zone_redzone, zone_size,
 		PROT_READ|PROT_WRITE) < 0)
 	{
 	    char buf[2560];
 	    sprintf(buf, "Mercury runtime: cannot unprotect %s#%d zone",
-		zone->name, zone->id);
+                zone->MR_zone_name, zone->MR_zone_id);
 	    perror(buf);
 	    exit(1);
 	}
 
-	zone->redzone = new_zone;
+        zone->MR_zone_redzone = new_zone;
 
 	if (MR_memdebug) {
 	    fprintf(stderr, "successful: %s#%d redzone now %p to %p\n",
-		zone->name, zone->id, (void *) zone->redzone,
-		(void *) zone->top);
+                zone->MR_zone_name, zone->MR_zone_id,
+                (void *) zone->MR_zone_redzone, (void *) zone->MR_zone_top);
 	}
   #if defined(MR_NATIVE_GC) && !defined(MR_HIGHLEVEL_CODE)
 	MR_schedule_agc(get_pc_from_context(context),
@@ -240,11 +244,16 @@
 	char buf[2560];
 	if (MR_memdebug) {
 	    fprintf(stderr, "can't unprotect last page of %s#%d\n",
-		zone->name, zone->id);
+                zone->MR_zone_name, zone->MR_zone_id);
 	    fflush(stdout);
 	}
+#ifdef  MR_STACK_EXTEND_DEBUG
+        MR_restore_transient_registers();
+        fprintf(stderr, "sp = %p, maxfr = %p\n", MR_sp, MR_maxfr);
+        MR_debug_memory_zone(stderr, zone);
+#endif
 	sprintf(buf, "\nMercury runtime: memory zone %s#%d overflowed\n",
-		zone->name, zone->id);
+            zone->MR_zone_name, zone->MR_zone_id);
 	MR_fatal_abort(context, buf, MR_TRUE);
     }
 
@@ -271,7 +280,7 @@
 }
 
 static char *
-explain_context(void *the_context)
+MR_explain_context(void *the_context)
 {
 	static	char	buf[100];
 
@@ -339,16 +348,16 @@
 		case SIGSEGV:
 			/*
 			** If we're debugging, print the segv explanation
-			** messages before we call try_munprotect.  But if
+            ** messages before we call MR_try_munprotect.  But if
 			** we're not debugging, only print them if
-			** try_munprotect fails.
+            ** MR_try_munprotect fails.
 			*/
 			if (MR_memdebug) {
 				fflush(stdout);
 				fprintf(stderr, "\n*** Mercury runtime: "
 					"caught segmentation violation ***\n");
 			}
-			if (try_munprotect(address, &sigcontext)) {
+            if (MR_try_munprotect(address, &sigcontext)) {
 				if (MR_memdebug) {
 					fprintf(stderr, "returning from "
 						"signal handler\n\n");
@@ -384,13 +393,12 @@
 	fprintf(stderr, "address involved: %p\n", address);
 
 	MR_trace_report(stderr);
-	print_dump_stack();
+    MR_print_dump_stack();
 	MR_dump_prev_locations();
 	fprintf(stderr, "exiting from signal handler\n");
 	exit(1);
 } /* end complex_sighandler() */
 
-
 #elif defined(MR_HAVE_SIGINFO_T)
 
 static void 
@@ -459,20 +467,20 @@
 
 		} /* end switch */
 
-		fprintf(stderr, "%s", explain_context(context));
+        fprintf(stderr, "%s", MR_explain_context(context));
 		fprintf(stderr, "address involved: %p\n",
 			(void *) info->si_addr);
 	} /* end if */
 
 	MR_trace_report(stderr);
-	print_dump_stack();
+    MR_print_dump_stack();
 	MR_dump_prev_locations();
 	fprintf(stderr, "exiting from signal handler\n");
 	exit(1);
 } /* end complex_bushandler() */
 
 static void 
-explain_segv(siginfo_t *info, void *context)
+MR_explain_segv(siginfo_t *info, void *context)
 {
 	fflush(stdout);
 
@@ -504,12 +512,12 @@
 			break;
 		}
 
-		fprintf(stderr, "%s", explain_context(context));
+        fprintf(stderr, "%s", MR_explain_context(context));
 		fprintf(stderr, "address involved: %p\n",
 			(void *) info->si_addr);
 
 	} /* end if */
-} /* end explain_segv() */
+}
 
 static void 
 complex_segvhandler(int sig, siginfo_t *info, void *context)
@@ -522,15 +530,15 @@
 
 	/*
 	** If we're debugging, print the segv explanation messages
-	** before we call try_munprotect.  But if we're not debugging,
-	** only print them if try_munprotect fails.
+    ** before we call MR_try_munprotect.  But if we're not debugging,
+    ** only print them if MR_try_munprotect fails.
 	*/
 
 	if (MR_memdebug) {
-		explain_segv(info, context);
+        MR_explain_segv(info, context);
 	}
 
-	if (try_munprotect(info->si_addr, context)) {
+    if (MR_try_munprotect(info->si_addr, context)) {
 		if (MR_memdebug) {
 			fprintf(stderr, "returning from signal handler\n\n");
 		}
@@ -539,11 +547,11 @@
 	}
 
 	if (!MR_memdebug) {
-		explain_segv(info, context);
+        MR_explain_segv(info, context);
 	}
 
 	MR_trace_report(stderr);
-	print_dump_stack();
+    MR_print_dump_stack();
 	MR_dump_prev_locations();
 	fprintf(stderr, "exiting from signal handler\n");
 	exit(1);
@@ -574,7 +582,7 @@
 		break;
 	}
 
-	print_dump_stack();
+    MR_print_dump_stack();
 	MR_dump_prev_locations();
 	fprintf(stderr, "exiting from signal handler\n");
 	exit(1);
@@ -627,7 +635,6 @@
 	DEFINE_EXCEPTION_NAME(EXCEPTION_INVALID_HANDLE)
 };
 
-
 /*
 ** Retrieve the name of a Win32 exception code as a string
 */
@@ -769,7 +776,6 @@
 	MR_dump_exception_record(rec->ExceptionRecord);
 }
 
-
 /*
 ** Return MR_TRUE iff exception_ptrs indicates an access violation.
 ** If MR_TRUE, the dereferenced address_ptr is set to the accessed address and
@@ -790,7 +796,6 @@
 	return MR_FALSE;
 }
 
-
 /*
 ** Filter a Win32 exception (to be called in the __except filter part).
 ** Possible return values are:
@@ -823,7 +828,7 @@
 	{
 
 			/* If we can unprotect the memory zone */
-		if (try_munprotect(address, exception_ptrs)) {
+        if (MR_try_munprotect(address, exception_ptrs)) {
 			if (MR_memdebug) {
 				fprintf(stderr, "returning from "
 						"signal handler\n\n");
@@ -841,7 +846,7 @@
 	MR_dump_exception_record(exception_ptrs->ExceptionRecord);
 
 	printf("\n");
-	print_dump_stack();
+    MR_print_dump_stack();
 	MR_dump_prev_locations();
 	
 	fprintf(stderr, "\n\n*** Now passing exception to default handler\n\n");
@@ -857,7 +862,6 @@
 }
 #endif /* MR_MSVC_STRUCTURED_EXCEPTIONS */
 
-
 /*
 ** get_pc_from_context:
 ** 	Given the signal context, return the program counter at the time
@@ -998,7 +1002,7 @@
 }
 
 static void 
-print_dump_stack(void)
+MR_print_dump_stack(void)
 {
 	const char *msg =
 		"This may have been caused by a stack overflow, due to unbounded recursion.\n";
Index: runtime/mercury_memory_zones.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_memory_zones.c,v
retrieving revision 1.25
diff -u -b -r1.25 mercury_memory_zones.c
--- runtime/mercury_memory_zones.c	20 Jul 2004 04:41:22 -0000	1.25
+++ runtime/mercury_memory_zones.c	11 Sep 2005 02:41:03 -0000
@@ -1,4 +1,7 @@
 /*
+** vim:sw=4 ts=4 expandtab
+*/
+/*
 ** Copyright (C) 1998-2000, 2002-2004 The University of Melbourne.
 ** This file may only be copied under the terms of the GNU Library General
 ** Public License - see the file COPYING.LIB in the Mercury distribution.
@@ -31,6 +34,10 @@
 #include <stdio.h>
 #include <string.h>
 
+#ifdef MR_HAVE_STDLIB_H
+  #include <stdlib.h>       /* for memalign and posix_memalign */
+#endif
+
 #ifdef MR_HAVE_SYS_SIGINFO_H
   #include <sys/siginfo.h>
 #endif 
@@ -60,23 +67,35 @@
   #include <windows.h>
 #endif
 
+static  void    MR_setup_redzones(MR_MemoryZone *zone);
+
+static  void    *MR_alloc_zone_memory(size_t size);
+static  void    *MR_realloc_zone_memory(void *old_base, size_t copy_size,
+                    size_t new_size);
+
 /*---------------------------------------------------------------------------*/
 
 /*
 ** MR_PROTECTPAGE is now defined if we have some sort of mprotect like
-** functionality, all checks for MR_HAVE_MPROTECT should now use MR_PROTECTPAGE.
+** functionality, all checks for MR_HAVE_MPROTECT should now use
+** MR_PROTECTPAGE.
 */
+
 #if defined(MR_HAVE_MPROTECT)
+
 int
 MR_protect_pages(void *addr, size_t size, int prot_flags)
 {
 	return mprotect((char *) addr, size, prot_flags);
 }
+
 #elif defined(MR_WIN32_VIRTUAL_ALLOC)
+
 /*
 ** Emulate mprotect under Win32.
 ** Return -1 on failure
 */
+
 int
 MR_protect_pages(void *addr, size_t size, int prot_flags)
 {
@@ -94,54 +113,149 @@
 	rc = (VirtualAlloc(addr, size, MEM_COMMIT, flags) ? 0 : -1);
 	if (rc < 0) {
 		fprintf(stderr,
-			"Error in VirtualAlloc(addr=0x%08lx, size=0x%08lx):"
-			" 0x%08lx\n", (unsigned long) addr,
-			(unsigned long) size, (unsigned long) GetLastError());
+            "Error in VirtualAlloc(addr=0x%08lx, size=0x%08lx): 0x%08lx\n",
+            (unsigned long) addr, (unsigned long) size,
+            (unsigned long) GetLastError());
 	}
 
 	return rc;
 }
-#endif	/* MR_WIN32_VIRTUAL_ALLOC */
 
+#endif  /* MR_WIN32_VIRTUAL_ALLOC */
 
 /*---------------------------------------------------------------------------*/
 
-
 #if defined(MR_WIN32_VIRTUAL_ALLOC)
+
 /*
 ** Under Win32, we use VirtualAlloc instead of the standard malloc,
 ** since we will have to call VirtualProtect later on the pages
 ** allocated here.
 */
-void *
-memalign(size_t unit, size_t size)
+
+static void *
+MR_alloc_zone_memory(size_t size)
 {
 	void *ptr;
 
-	/*
-	** We don't need to use the 'unit' value as the memory is always
-	** aligned under Win32.
-	*/
 	ptr = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
 	if (ptr == NULL) {
-		fprintf(stderr, "Error in VirtualAlloc(size=0x%08lx):"
-				" 0x%08lx\n", (unsigned long) size,
-				(unsigned long) GetLastError());
+        fprintf(stderr, "Error in VirtualAlloc(size=0x%08lx): 0x%08lx\n",
+            (unsigned long) size, (unsigned long) GetLastError());
 	}
 
   #ifdef MR_CONSERVATIVE_GC
 	if (ptr != NULL) {
-		GC_add_roots((char *)ptr, (char *)ptr + size);
+        GC_add_roots((char *) ptr, (char *) ptr + size);
 	}
   #endif
 	return ptr;
 }
+
+static void *
+MR_realloc_zone_memory(void *old_base, size_t copy_size, size_t new_size)
+{
+    void    *ptr;
+
+    ptr = MR_alloc_zone_memory(new_size);
+    (void) MR_memcpy(ptr, old_base, copy_size);
+    /*
+    ** XXX We should of course release old_base's memory, but I don't know
+    ** enough about Windows even to implement that. -zs
+    */
+    return ptr;
+}
+
 #elif defined(MR_CONSERVATIVE_GC)
-  #define	memalign(a,s)   GC_MALLOC_UNCOLLECTABLE(s)
+
+static void *
+MR_alloc_zone_memory(size_t size)
+{
+    return GC_MALLOC_UNCOLLECTABLE(size);
+}
+
+static void *
+MR_realloc_zone_memory(void *old_base, size_t copy_size, size_t new_size)
+{
+    void    *ptr;
+    
+    ptr = GC_MALLOC_UNCOLLECTABLE(new_size);
+    (void) MR_memcpy(ptr, old_base, copy_size);
+    GC_free(old_base);
+    return ptr;
+}
+
+#elif defined(MR_HAVE_POSIX_MEMALIGN_XXX)
+
+static void *
+MR_alloc_zone_memory(size_t size)
+{
+    void    *ptr;
+    int     res;
+    
+    res = posix_memalign(&ptr, MR_unit, size);
+    if (res != 0) {
+        return NULL;
+    }
+
+    return ptr;
+}
+
+static void *
+MR_realloc_zone_memory(void *old_base, size_t copy_size, size_t new_size)
+{
+    void    *ptr;
+    int     res;
+    
+    res = posix_memalign(&ptr, MR_unit, new_size);
+    if (res != 0) {
+        return NULL;
+    }
+
+    (void) MR_memcpy(ptr, old_base, copy_size);
+    free(old_base);
+    return ptr;
+}
+
 #elif defined(MR_HAVE_MEMALIGN)
-  extern void	*memalign(size_t, size_t);
+
+static void *
+MR_alloc_zone_memory(size_t size)
+{
+    return memalign(MR_unit, size);
+}
+
+static void *
+MR_realloc_zone_memory(void *old_base, size_t copy_size, size_t new_size)
+{
+    void    *ptr;
+    
+    ptr = memalign(MR_unit, new_size);
+    (void) MR_memcpy(ptr, old_base, copy_size);
+    /*
+    ** We should call free(old_base) here. However, there is no guarantee that
+    ** the system supports the freeing of memory allocated with memalign via
+    ** calls to free(). We therefore don't free old_base. This is why we prefer
+    ** posix_memalign if it is available.
+    */
+    return ptr;
+}
+
 #else
-  #define	memalign(a,s)	malloc(s)
+
+static void *
+MR_alloc_zone_memory(size_t size)
+{
+    return malloc(size);
+}
+
+static void *
+MR_realloc_zone_memory(void *old_base, size_t copy_size, size_t new_size)
+{
+    /* the copying is done by realloc */
+    return realloc(old_base, new_size);
+}
+
 #endif
 
 /*
@@ -157,6 +271,7 @@
 ** PROT_EXEC    page can be executed
 ** PROT_NONE    page can not be accessed
 */
+
 #ifdef MR_PROTECTPAGE
 
   #define NORMAL_PROT (PROT_READ|PROT_WRITE)
@@ -207,12 +322,11 @@
 
 static	size_t		*offset_vector;
 static	int		offset_counter;
-size_t	next_offset(void);
+extern  size_t          next_offset(void);
 
 void
 MR_init_zones()
 {
-
 #ifdef  MR_THREAD_SAFE
 	pthread_mutex_init(&free_memory_zones_lock, MR_MUTEX_ATTR);
 #endif
@@ -237,8 +351,7 @@
 			(fake_reg_offset + MR_pcache_size * i / CACHE_SLICES)
 			% MR_pcache_size;
 	}
-} /* end init_offsets() */
-
+}
 
 static MR_MemoryZone *
 MR_get_zone(void)
@@ -254,10 +367,10 @@
 		zone = MR_GC_NEW(MR_MemoryZone);
 	} else {
 		zone = free_memory_zones;
-		free_memory_zones = free_memory_zones->next;
+        free_memory_zones = free_memory_zones->MR_zone_next;
 	}
 
-	zone->next = used_memory_zones;
+    zone->MR_zone_next = used_memory_zones;
 	used_memory_zones = zone;
 	MR_UNLOCK(&free_memory_zones_lock, "get_zone");
 
@@ -265,34 +378,36 @@
 }
 
 #if 0
-
 /* this function is not currently used */
 
 static void 
 MR_unget_zone(MR_MemoryZone *zone)
 {
-	MR_MemoryZone *prev, *tmp;
+    MR_MemoryZone   *prev;
+    MR_MemoryZone   *tmp;
 
 	/*
 	** Find the zone on the used list, and unlink it from
 	** the list, then link it onto the start of the free-list.
 	*/
 	MR_LOCK(&free_memory_zones_lock, "unget_zone");
-	for(prev = NULL, tmp = used_memory_zones;
-		tmp && tmp != zone; prev = tmp, tmp = tmp->next) 
+    for(prev = NULL, tmp = used_memory_zones; tmp != NULL && tmp != zone;
+        prev = tmp, tmp = tmp->MR_zone_next)
 	{
 		/* VOID */
 	}
+
 	if (tmp == NULL) {
 		MR_fatal_error("memory zone not found!");
 	}
+
 	if (prev == NULL) {
-		used_memory_zones = used_memory_zones->next;
+        used_memory_zones = used_memory_zones->MR_zone_next;
 	} else {
-		prev->next = tmp->next;
+        prev->MR_zone_next = tmp->MR_zone_next;
 	}
 
-	zone->next = free_memory_zones;
+    zone->MR_zone_next = free_memory_zones;
 	free_memory_zones = zone;
 	MR_UNLOCK(&free_memory_zones_lock, "unget_zone");
 }
@@ -309,22 +424,20 @@
 ** a fixed amount (eg 2Kb) so that as primary caches get bigger, we
 ** allocate more offsets across them.
 */
+
 size_t	
 MR_next_offset(void)
 {
 	size_t offset;
 
 	offset = offset_vector[offset_counter];
-
 	offset_counter = (offset_counter + 1) % CACHE_SLICES;
-
 	return offset;
 }
 
 MR_MemoryZone *
-MR_create_zone(const char *name, int id, size_t size,
-	size_t offset, size_t redsize,
-	MR_bool ((*handler)(MR_Word *addr, MR_MemoryZone *zone, void *context)))
+MR_create_zone(const char *name, int id, size_t size, size_t offset,
+    size_t redsize, MR_ZoneHandler handler)
 {
 	MR_Word		*base;
 	size_t		total_size;
@@ -333,8 +446,7 @@
 		** total allocation is:
 		**	unit		(roundup to page boundary)
 		**	size		(including redzone)
-		**	unit		(an extra page for protection if
-		**			 mprotect is being used)
+    **  unit        (an extra page for protection if mprotect is being used)
 		*/
 #ifdef	MR_PROTECTPAGE
 	total_size = size + 2 * MR_unit;
@@ -342,39 +454,40 @@
 	total_size = size + MR_unit;
 #endif
 
-	base = (MR_Word *) memalign(MR_unit, total_size);
+    base = (MR_Word *) MR_alloc_zone_memory(total_size);
 	if (base == NULL) {
 		char buf[2560];
 		sprintf(buf, "unable allocate memory zone: %s#%d", name, id);
 		MR_fatal_error(buf);
 	}
 
-	return MR_construct_zone(name, id, base, size, offset,
-		redsize, handler);
-} /* end MR_create_zone() */
+    return MR_construct_zone(name, id, base, size, offset, redsize, handler);
+}
 
 MR_MemoryZone *
 MR_construct_zone(const char *name, int id, MR_Word *base,
-	size_t size, size_t offset, size_t redsize,
-	MR_ZoneHandler handler)
+    size_t size, size_t offset, size_t redsize, MR_ZoneHandler handler)
 {
 	MR_MemoryZone	*zone;
 	size_t		total_size;
+    int             res;
 
 	if (base == NULL) {
-		MR_fatal_error("construct_zone called with NULL pointer");
+        MR_fatal_error("MR_construct_zone called with NULL pointer");
 	}
 
 	zone = MR_get_zone();
 
-	zone->name = name;
-	zone->id = id;
+    zone->MR_zone_name = name;
+    zone->MR_zone_id = id;
+    zone->MR_zone_desired_size = size;
+    zone->MR_zone_redzone_size = redsize;
 
 #ifdef	MR_CHECK_OVERFLOW_VIA_MPROTECT
-	zone->handler = handler;
+    zone->MR_zone_handler = handler;
 #endif /* MR_CHECK_OVERFLOW_VIA_MPROTECT */
 
-	zone->bottom = base;
+    zone->MR_zone_bottom = base;
 
 #ifdef 	MR_PROTECTPAGE
 	total_size = size + MR_unit;
@@ -382,26 +495,106 @@
 	total_size = size;
 #endif	/* MR_PROTECTPAGE */
 
-	zone->top = (MR_Word *) ((char *)base + total_size);
-	zone->min = (MR_Word *) ((char *)base + offset);
+    zone->MR_zone_top = (MR_Word *) ((char *) base + total_size);
+    zone->MR_zone_min = (MR_Word *) ((char *) base + offset);
 #ifdef	MR_LOWLEVEL_DEBUG
-	zone->max = zone->min;
+    zone->MR_zone_max = zone->MR_zone_min;
 #endif	/* MR_LOWLEVEL_DEBUG */
 
+    MR_setup_redzones(zone);
+
+    return zone;
+}
+
+MR_Integer
+MR_extend_zone(MR_MemoryZone *zone, size_t new_size)
+{
+    void            *old_base;
+    void            *new_base;
+    size_t          offset;
+    size_t          redsize;
+    size_t          copy_size;
+    size_t          new_total_size;
+    MR_Integer      base_incr;
+    int             res;
+
+    if (zone == NULL) {
+        MR_fatal_error("MR_extend_zone called with NULL pointer");
+    }
+
+#ifdef  MR_PROTECTPAGE
+    new_total_size = new_size + 2 * MR_unit;
+#else
+    new_total_size = new_size + MR_unit;
+#endif
+
+    old_base = zone->MR_zone_bottom;
+    copy_size = zone->MR_zone_end - zone->MR_zone_bottom;
+    offset = zone->MR_zone_min - zone->MR_zone_bottom;
+
+#ifdef  MR_CHECK_OVERFLOW_VIA_MPROTECT
+    /* unprotect the entire zone area */
+    res = MR_protect_pages((char *) zone->MR_zone_bottom,
+        ((char *) zone->MR_zone_top) - ((char *) zone->MR_zone_bottom),
+        NORMAL_PROT);
+    if (res < 0) {
+        char buf[2560];
+        sprintf(buf, "unable to reset %s#%d total area\nbase=%p, redzone=%p",
+            zone->MR_zone_name, zone->MR_zone_id,
+            zone->MR_zone_bottom, zone->MR_zone_top);
+        MR_fatal_error(buf);
+    }
+#endif  /* MR_CHECK_OVERFLOW_VIA_MPROTECT */
+
+    new_base = MR_realloc_zone_memory(old_base, copy_size, new_size);
+    if (new_base == NULL) {
+        char buf[2560];
+        sprintf(buf, "unable reallocate memory zone: %s#%d",
+            zone->MR_zone_name, zone->MR_zone_id);
+        MR_fatal_error(buf);
+    }
+
+    base_incr = new_base - old_base;
+
+    zone->MR_zone_desired_size = new_size;
+    zone->MR_zone_bottom = new_base;
+    zone->MR_zone_top = (MR_Word *) ((char *) new_base + new_total_size);
+    zone->MR_zone_min = (MR_Word *) ((char *) new_base + offset);
+#ifdef  MR_LOWLEVEL_DEBUG
+    zone->MR_zone_max = zone->MR_zone_min;
+#endif  /* MR_LOWLEVEL_DEBUG */
+
+    MR_setup_redzones(zone);
+
+    return base_incr;
+}
+
+static void
+MR_setup_redzones(MR_MemoryZone *zone)
+{
+    size_t      size;
+    size_t      redsize;
+    int         res;
+
+    size = zone->MR_zone_desired_size;
+    redsize = zone->MR_zone_redzone_size;
+
 	/*
 	** setup the redzone
 	*/
 #ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
-	zone->redzone_base = zone->redzone = (MR_Word *)
-			MR_round_up((MR_Unsigned)base + size - redsize,
+    zone->MR_zone_redzone = (MR_Word *)
+        MR_round_up((MR_Unsigned) zone->MR_zone_bottom + size - redsize,
 				MR_unit);
-	if (MR_protect_pages((char *)zone->redzone,
-			redsize + MR_unit, REDZONE_PROT) < 0)
-	{
+    zone->MR_zone_redzone_base = zone->MR_zone_redzone;
+
+    res = MR_protect_pages((char *) zone->MR_zone_redzone, redsize + MR_unit,
+        REDZONE_PROT);
+    if (res < 0) {
 		char buf[2560];
-		sprintf(buf, "unable to set %s#%d redzone\n"
-			"base=%p, redzone=%p",
-			zone->name, zone->id, zone->bottom, zone->redzone);
+        sprintf(buf, "unable to set %s#%d redzone\nbase=%p, redzone=%p",
+            zone->MR_zone_name, zone->MR_zone_id,
+            zone->MR_zone_bottom, zone->MR_zone_redzone);
 		MR_fatal_error(buf);
 	}
 #endif /* MR_CHECK_OVERFLOW_VIA_MPROTECT */
@@ -410,51 +603,53 @@
 	** setup the hardzone
 	*/
 #if	defined(MR_PROTECTPAGE)
-	zone->hardmax = (MR_Word *) MR_round_up(
-			(MR_Unsigned)zone->top - MR_unit, MR_unit);
-	if (MR_protect_pages((char *)zone->hardmax, MR_unit, REDZONE_PROT) < 0) {
+    zone->MR_zone_hardmax = (MR_Word *)
+        MR_round_up((MR_Unsigned) zone->MR_zone_top - MR_unit, MR_unit);
+    res = MR_protect_pages((char *) zone->MR_zone_hardmax, MR_unit,
+        REDZONE_PROT);
+    if (res < 0) {
 		char buf[2560];
-		sprintf(buf, "unable to set %s#%d hardmax\n"
-			"base=%p, hardmax=%p top=%p",
-			zone->name, zone->id, zone->bottom, zone->hardmax,
-			zone->top);
+        sprintf(buf, "unable to set %s#%d hardmax\nbase=%p, hardmax=%p top=%p",
+            zone->MR_zone_name, zone->MR_zone_id,
+            zone->MR_zone_bottom, zone->MR_zone_hardmax, zone->MR_zone_top);
 		MR_fatal_error(buf);
 	}
 #endif	/* MR_PROTECTPAGE */
 
 #if defined(MR_NATIVE_GC) && defined(MR_HIGHLEVEL_CODE)
-	zone->gc_threshold = (char *) zone->MR_zone_end - MR_heap_margin_size;
+    zone->MR_zone_gc_threshold = (char *) zone->MR_zone_end
+        - MR_heap_margin_size;
 #endif
-
-	return zone;
-} /* end MR_construct_zone() */
+}
 
 void 
 MR_reset_redzone(MR_MemoryZone *zone)
 {
 #ifdef	MR_CHECK_OVERFLOW_VIA_MPROTECT
-	zone->redzone = zone->redzone_base;
+    int res;
+
+    zone->MR_zone_redzone = zone->MR_zone_redzone_base;
 
 	/* unprotect the non-redzone area */
-	if (MR_protect_pages((char *)zone->bottom,
-		((char *)zone->redzone) - ((char *) zone->bottom),
-		NORMAL_PROT) < 0)
-	{
+    res = MR_protect_pages((char *) zone->MR_zone_bottom,
+        ((char *) zone->MR_zone_redzone) - ((char *) zone->MR_zone_bottom),
+        NORMAL_PROT);
+    if (res < 0) {
 		char buf[2560];
-		sprintf(buf, "unable to reset %s#%d normal area\n"
-			"base=%p, redzone=%p",
-			zone->name, zone->id, zone->bottom, zone->redzone);
+        sprintf(buf, "unable to reset %s#%d normal area\nbase=%p, redzone=%p",
+            zone->MR_zone_name, zone->MR_zone_id,
+            zone->MR_zone_bottom, zone->MR_zone_redzone);
 		MR_fatal_error(buf);
 	}
 	/* protect the redzone area */
-	if (MR_protect_pages((char *)zone->redzone,
-		((char *)zone->top) - ((char *) zone->redzone),
-		REDZONE_PROT) < 0)
-	{
+    res = MR_protect_pages((char *) zone->MR_zone_redzone,
+        ((char *) zone->MR_zone_top) - ((char *) zone->MR_zone_redzone),
+        REDZONE_PROT);
+    if (res < 0) {
 		char buf[2560];
-		sprintf(buf, "unable to reset %s#%d redzone\n"
-			"base=%p, redzone=%p",
-			zone->name, zone->id, zone->bottom, zone->redzone);
+        sprintf(buf, "unable to reset %s#%d redzone\nbase=%p, redzone=%p",
+            zone->MR_zone_name, zone->MR_zone_id,
+            zone->MR_zone_bottom, zone->MR_zone_redzone);
 		MR_fatal_error(buf);
 	}
 #endif	/* MR_CHECK_OVERFLOW_VIA_MPROTECT */
@@ -469,52 +664,74 @@
 MR_bool
 MR_in_zone(const MR_Word *ptr, const MR_MemoryZone *zone)
 {
-	return (zone->bottom <= ptr && ptr < zone->top);
+    return (zone->MR_zone_bottom <= ptr && ptr < zone->MR_zone_top);
 }
 
 void
-MR_debug_memory(void)
+MR_debug_memory(FILE *fp)
 {
 	MR_MemoryZone	*zone;
 
-	fprintf(stderr, "\n");
-	fprintf(stderr, "pcache_size  = %lu (0x%lx)\n",
+    fprintf(fp, "\n");
+    fprintf(fp, "pcache_size  = %lu (0x%lx)\n",
 		(unsigned long) MR_pcache_size, (unsigned long) MR_pcache_size);
-	fprintf(stderr, "page_size    = %lu (0x%lx)\n",
+    fprintf(fp, "page_size    = %lu (0x%lx)\n",
 		(unsigned long) MR_page_size, (unsigned long) MR_page_size);
-	fprintf(stderr, "unit         = %lu (0x%lx)\n",
+    fprintf(fp, "unit         = %lu (0x%lx)\n",
 		(unsigned long) MR_unit, (unsigned long) MR_unit);
 
-	fprintf(stderr, "\n");
-	fprintf(stderr, "fake_reg       = %p (offset %ld)\n",
+    fprintf(fp, "\n");
+    fprintf(fp, "fake_reg       = %p (offset %ld)\n",
 		(void *) MR_fake_reg, (long) MR_fake_reg & (MR_unit-1));
-	fprintf(stderr, "\n");
+    fprintf(fp, "\n");
 
-	for (zone = used_memory_zones; zone; zone = zone->next)
-	{
-		fprintf(stderr, "%-16s#%d-base	= %p\n",
-			zone->name, zone->id, (void *) zone->bottom);
-		fprintf(stderr, "%-16s#%d-min		= %p\n",
-			zone->name, zone->id, (void *) zone->min);
-		fprintf(stderr, "%-16s#%d-top		= %p\n",
-			zone->name, zone->id, (void *) zone->top);
+    for (zone = used_memory_zones; zone; zone = zone->MR_zone_next) {
+        MR_debug_memory_zone(fp, zone);
+    }
+}
+
+void
+MR_debug_memory_zone(FILE *fp, MR_MemoryZone *zone)
+{
+    fprintf(fp, "%-16s#%d-dessize   = %lu\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (unsigned long) zone->MR_zone_desired_size);
+    fprintf(fp, "%-16s#%d-base  = %p\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (void *) zone->MR_zone_bottom);
+    fprintf(fp, "%-16s#%d-min       = %p\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (void *) zone->MR_zone_min);
+    fprintf(fp, "%-16s#%d-top       = %p\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (void *) zone->MR_zone_top);
+    fprintf(fp, "%-16s#%d-end       = %p\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (void *) zone->MR_zone_end);
 #ifdef	MR_CHECK_OVERFLOW_VIA_MPROTECT
-		fprintf(stderr, "%-16s#%d-redzone	= %p\n",
-			zone->name, zone->id, (void *) zone->redzone);
-		fprintf(stderr, "%-16s#%d-redzone_base	= %p\n",
-			zone->name, zone->id, (void *) zone->redzone_base);
+    fprintf(fp, "%-16s#%d-redsize   = %lu\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (unsigned long) zone->MR_zone_redzone_size);
+    fprintf(fp, "%-16s#%d-redzone   = %p\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (void *) zone->MR_zone_redzone);
+    fprintf(fp, "%-16s#%d-redzone_base  = %p\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (void *) zone->MR_zone_redzone_base);
 #endif	/* MR_CHECK_OVERFLOW_VIA_MPROTECT */
 #ifdef	MR_PROTECTPAGE
-		fprintf(stderr, "%-16s#%d-hardmax		= %p\n",
-			zone->name, zone->id, (void *) zone->hardmax);
-		fprintf(stderr, "%-16s#%d-size		= %lu\n",
-			zone->name, zone->id, (unsigned long)
-			((char *)zone->hardmax - (char *)zone->min));
+    fprintf(fp, "%-16s#%d-hardmax       = %p\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (void *) zone->MR_zone_hardmax);
+    fprintf(fp, "%-16s#%d-size      = %lu\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (unsigned long) ((char *) zone->MR_zone_hardmax
+             - (char *) zone->MR_zone_min));
 #else
-		fprintf(stderr, "%-16s#%d-size		= %lu\n",
-			zone->name, zone->id, (unsigned long)
-			((char *)zone->top - (char *)zone->min));
+    fprintf(fp, "%-16s#%d-size      = %lu\n",
+        zone->MR_zone_name, zone->MR_zone_id,
+        (unsigned long) ((char *) zone->MR_zone_top
+             - (char *) zone->MR_zone_min));
 #endif	/* MR_PROTECTPAGE */
-		fprintf(stderr, "\n");
-	}
+    fprintf(fp, "\n");
 }
Index: runtime/mercury_memory_zones.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_memory_zones.h,v
retrieving revision 1.16
diff -u -b -r1.16 mercury_memory_zones.h
--- runtime/mercury_memory_zones.h	20 Jul 2004 04:41:22 -0000	1.16
+++ runtime/mercury_memory_zones.h	11 Sep 2005 02:47:25 -0000
@@ -5,10 +5,9 @@
 */
 
 /*
-** mercury_memory_zones.h - functions and data structures for handling
-** 			    memory zones.
+** mercury_memory_zones.h
 **
-** This defines a generic memory zone handler, which can be used for
+** This module defines a generic memory zone handler, which can be used for
 ** stacks and heaps in the Mercury runtime.  It provides functions for
 ** generating offsets so that different memory zones begin at different
 ** offsets (improves performance with direct mapped caches).  It also
@@ -20,108 +19,123 @@
 
 #include "mercury_regs.h"		/* for MR_NUM_REAL_R_REGS, etc */
 
+#include <stdio.h>			/* for FILE */
 #include <stdlib.h>			/* for size_t */
 
 #include "mercury_types.h"		/* for MR_Word */
 #include "mercury_std.h"		/* for MR_bool */
 
+typedef struct MR_MemoryZone_Struct	MR_MemoryZone;
+
+typedef MR_bool	MR_ZoneHandler(MR_Word *addr, MR_MemoryZone *zone,
+			void *context);
+
 /*
 ** The Mercury runtime uses a number of memory areas or *zones*. These
 ** hold the detstack, the nondetstack, the heap, and potentially other
 ** areas such as a trail, a "solutions"-heap, and so on.
-** These memory areas are each represented by a structure that contains
-** the following fields:
-**	name	- a string constant used to name the allocated area
-**	id	- an integer which together with the name should uniquely
+** These memory areas are each represented by an MR_MemoryZone structure
+** that contains the following fields:
+**
+** next		The memory zones are organized as a linked list of free zones
+**		and linked list of used zones. The next field, if not NULL,
+**		points to the next memory zone in the list.
+**
+** name		A string constant used to name the allocated area.
+**
+** id		An integer which together with the name should uniquely
 **		  identify the allocated area.
-**	bottom	- the address of the bottom of the allocated area
-**			(should be on a page boundary)
-**	top	- the address one word past the top of the allocated area
-**			(should be on a page boundary)
-**	min	- the address of the lowest part of the allocated that
+**
+** desired_size The desired size of the zone in kilobytes. The actual size
+** 		may be larger due to roundups.
+**
+** redzone_size The desired size of the redzone in kilobytes. The actual size
+** 		may be larger due to roundups.
+**
+** bottom	The address of the bottom of the allocated area
+**		(should be on a page boundary).
+**
+** top		The address one word past the top of the allocated area
+**		(should be on a page boundary).
+**
+** min		The address of the lowest part of the allocated that
 **			will be used. This may be different to `bottom'
 **			so that the use of different memory zones doesn't
 **			beat the cache.
-**	max	- the highest address in this memory area that has been
-**			used so far. This is only defined in debugging grades.
-**	hardmax	- the address of the bottom of the last page of the allocated
+**
+** max		The highest address in this memory area that has been
+**		used so far. This is only computed if MR_LOWLEVEL_DEBUG
+**		is enabled.
+**
+** hardmax	The address of the bottom of the last page of the allocated
 **			area. This is one higher than the highest address that
 **			can be used in this zone. We never unprotect the
 **			last page of a zone so that we retain protection
 **			against overrunning the end of the zone. This is
 **			obviously only available on platforms that have
-**			mprotect.
-**			(should be on a page boundary)
-**	redzone	- the address of the start of the region that has been
-**			mprotected as a redzone.  Redzone is only
-**			available on platforms where
-**			MR_CHECK_OVERFLOW_VIA_MPROTECT is defined.
-**			(should be on a page boundary)
-**	handler - the address of a function to handle accesses in the
+**		mprotect. (Should be on a page boundary.)
+**
+** redzone	The address of the start of the region that has been
+**		mprotected as a redzone.  Redzone is only available on
+**		platforms where MR_CHECK_OVERFLOW_VIA_MPROTECT is defined.
+**		(Should be on a page boundary.)
+**
+** redzone_base The original redzone.
+**
+** handler	The address of a function to handle accesses in the
 **			redzone of this allocated area. This is only
 **			available with MR_CHECK_OVERFLOW_VIA_MPROTECT.
+**
+** gc_threshold	This field, which is only used for heap zones, points to
+** 		MR_heap_margin_size bytes before MR_zone_end (which is defined
+** 		as one the fields above by the macros below). It is used to
+** 		decide when to do garbage collection without incurrent the
+** 		expense of a subtraction on every allocation.
 */
 
-typedef struct MR_MemoryZone_Struct	MR_MemoryZone;
-
-typedef MR_bool	MR_ZoneHandler(MR_Word *addr, MR_MemoryZone *zone,
-			void *context);
-
 struct MR_MemoryZone_Struct {
-	MR_MemoryZone *next;
-				  /* the memory zones are organized as a
-				  ** linked list of free zones and linked
-				  ** list of used zones. The next field
-				  ** is NULL or a pointer to the next memory
-				  ** zone in the list.
-				  */
-	const char *name;	/* name identifier */
-	int	id;		/* number */
-	MR_Word	*bottom;	/* beginning of the allocated area */
-	MR_Word	*top;		/* end of the allocated area */
-	MR_Word	*min;		/* lowest word of the area to be used */
-	MR_Word	*max;		/* highest word of the area to be used;
-				   computed only if MR_LOWLEVEL_DEBUG is
-				   enabled */
+	MR_MemoryZone		*MR_zone_next;
+	const char		*MR_zone_name;
+	int			MR_zone_id;
+	size_t			MR_zone_desired_size;
+	size_t			MR_zone_redzone_size;
+	MR_Word			*MR_zone_bottom;
+	MR_Word			*MR_zone_top;
+	MR_Word			*MR_zone_min;
+	MR_Word			*MR_zone_max;
 #ifdef MR_PROTECTPAGE
-	MR_Word	*hardmax;	/* last page of the zone which can't be
-				   unprotected */
+	MR_Word			*MR_zone_hardmax;
 #endif	/* MR_PROTECTPAGE */
+
 #ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
-	MR_Word	*redzone_base;	/* beginning of the original redzone */
-	MR_Word	*redzone;	/* beginning of the current redzone */
-	MR_ZoneHandler *handler;   /* handler for page faults in the redzone */
+	MR_Word			*MR_zone_redzone_base;
+	MR_Word			*MR_zone_redzone;
+	MR_ZoneHandler		*MR_zone_handler;
 #endif /* MR_CHECK_OVERFLOW_VIA_MPROTECT */
 
+#if defined(MR_NATIVE_GC) && defined(MR_HIGHLEVEL_CODE)
+	char			*MR_zone_gc_threshold;
+				/* == MR_zone_end - MR_heap_margin_size */
+#endif
+};
+
 	/*
-	** MR_zone_end specifies the end of the 
-	** area accessible without a page fault.
-	** It is used by MR_clear_zone_for_GC().
+	** MR_zone_end specifies the end of the area accessible without
+	** a page fault. It is used by MR_clear_zone_for_GC().
 	*/
 #ifdef MR_CHECK_OVERFLOW_VIA_MPROTECT
-	#define MR_zone_end	redzone
+	#define MR_zone_end	MR_zone_redzone
 #elif defined(MR_PROTECTPAGE)
-	#define MR_zone_end	hardmax
+	#define MR_zone_end	MR_zone_hardmax
 #else
-	#define MR_zone_end	top
-#endif
-
-#if defined(MR_NATIVE_GC) && defined(MR_HIGHLEVEL_CODE)
-	/*
-	** This field, which is only used for heap zones,
-	** points to MR_heap_margin_size bytes before MR_zone_end.
-	** It is used to decide when to do garbage collection.
-	*/
-	char *gc_threshold;	/* == MR_zone_end - MR_heap_margin_size */
+	#define MR_zone_end	MR_zone_top
 #endif
-};
 
 /*
 ** MR_clear_zone_for_GC(MR_MemoryZone *zone, void *start_address):
-**	Zero out the (hopefully unused) portion of the zone
-**	from the specified `start_address' to the end of the zone.
-**	This is used to avoid unwanted memory retention due to 
-**	false hits in the conservative garbage collector.
+** Zero out the (hopefully unused) portion of the zone from the specified
+** `start_address' to the end of the zone. This is used to avoid unwanted
+** memory retention due to false hits in the conservative garbage collector.
 */
 #define MR_clear_zone_for_GC(zone, start_address) \
 	((void) memset((start_address), 0, \
@@ -146,6 +160,7 @@
   #endif
 
 int MR_protect_pages(void *addr, size_t size, int prot_flags);
+
 #endif
 
 /*
@@ -178,13 +193,13 @@
 ** MR_construct_zone(Name, Id, Base, Size, Offset, RedZoneSize, FaultHandler)
 ** has the same behaviour as MR_create_zone, except instead of allocating
 ** the memory, it takes a pointer to a region of memory that must be at
-** least Size + unit[*] bytes, or if MR_PROTECTPAGE is defined, then it
+** least Size + MR_unit[*] bytes, or if MR_PROTECTPAGE is defined, then it
 ** must be at least Size + 2 * unit[*] bytes.
 ** If it fails to protect the redzone then it exits.
 ** If MR_CHECK_OVERFLOW_VIA_MPROTECT is unavailable, then the last two
 ** arguments are ignored.
 **
-** [*] unit is a global variable containing the page size in bytes
+** [*] MR_unit is a global variable containing the page size in bytes
 */
 
 extern	MR_MemoryZone	*MR_construct_zone(const char *name, int Id,
@@ -192,10 +207,18 @@
 				size_t redsize, MR_ZoneHandler *handler);
 
 /*
+** MR_extend_zone(Zone, NewSize) extends Zone to increase its size to NewSize,
+** and returns the difference between the new address of the memory area of
+** the zone and the old.
+*/
+
+extern	MR_Integer	MR_extend_zone(MR_MemoryZone *zone,
+				size_t new_size);
+
+/*
 ** MR_reset_redzone(Zone) resets the redzone on the given MR_MemoryZone to the
 ** original zone specified in the call to {create,construct}_zone() if
-** MR_CHECK_OVERFLOW_VIA_MPROTECT is defined.  Otherwise it does
-** nothing.
+** MR_CHECK_OVERFLOW_VIA_MPROTECT is defined.  Otherwise it does nothing.
 */
 
 extern	void		MR_reset_redzone(MR_MemoryZone *zone);
@@ -215,11 +238,18 @@
 				const MR_MemoryZone *zone);
 
 /*
-** MR_debug_memory() prints out debugging information about the current
-** memory zones.
+** MR_debug_memory(fp) prints out debugging information about the current
+** memory zones to fp.
+*/
+
+extern	void		MR_debug_memory(FILE *fp);
+
+/*
+** MR_debug_memory_zone(fp, zone) prints out debugging information about zone
+** to fp.
 */
 
-extern	void		MR_debug_memory(void);
+extern	void		MR_debug_memory_zone(FILE *fp, MR_MemoryZone *zone);
 
 /*
 ** MR_next_offset() returns sucessive offsets across the primary cache. Useful
Index: runtime/mercury_overflow.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_overflow.h,v
retrieving revision 1.7
diff -u -b -r1.7 mercury_overflow.h
--- runtime/mercury_overflow.h	31 May 2001 06:00:14 -0000	1.7
+++ runtime/mercury_overflow.h	11 Sep 2005 02:47:25 -0000
@@ -9,8 +9,6 @@
 #ifndef MERCURY_OVERFLOW_H
 #define MERCURY_OVERFLOW_H
 
-#define MR_IF(cond, val) ((cond) ? ((val), (void)0) : (void)0)
-
 #ifndef MR_CHECK_FOR_OVERFLOW
 
 #define	MR_heap_overflow_check()	((void)0)
Index: runtime/mercury_stacks.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stacks.c,v
retrieving revision 1.15
diff -u -b -r1.15 mercury_stacks.c
--- runtime/mercury_stacks.c	20 Jul 2004 04:41:24 -0000	1.15
+++ runtime/mercury_stacks.c	11 Sep 2005 02:41:03 -0000
@@ -114,6 +114,86 @@
 
 /***************************************************************************/
 
+#ifdef	MR_EXTEND_STACKS_WHEN_NEEDED
+
+static	void	MR_debug_zone_extend(FILE *fp, const char *when,
+			const char *stackname, MR_MemoryZone *zone);
+
+void
+MR_extend_detstack(void)
+{
+	MR_MemoryZone	*zone;
+	MR_Unsigned	old_size;
+	MR_Unsigned	new_size;
+	FILE		*debug_fp;
+
+	zone = MR_CONTEXT(MR_ctxt_detstack_zone);
+	old_size = zone->MR_zone_desired_size;
+	new_size = old_size * 2;
+
+	debug_fp = NULL;
+#ifdef	MR_STACK_EXTEND_DEBUG
+	if (MR_stack_extend_debug) {
+		debug_fp = fopen(".extend_stacks", "a");
+	}
+#endif
+
+	if (debug_fp != NULL) {
+		MR_debug_zone_extend(debug_fp, "before", "detstack", zone);
+	}
+
+	(void) MR_extend_zone(zone, new_size);
+
+	if (debug_fp != NULL) {
+		MR_debug_zone_extend(debug_fp, "after", "detstack", zone);
+	}
+}
+
+void
+MR_extend_nondetstack(void)
+{
+	MR_MemoryZone	*zone;
+	MR_Unsigned	old_size;
+	MR_Unsigned	new_size;
+	MR_Integer	base_incr;
+	FILE		*debug_fp;
+
+	zone = MR_CONTEXT(MR_ctxt_nondetstack_zone);
+	old_size = zone->MR_zone_desired_size;
+	new_size = old_size * 2;
+
+	debug_fp = NULL;
+#ifdef	MR_STACK_EXTEND_DEBUG
+	if (MR_stack_extend_debug) {
+		debug_fp = fopen(".extend_stacks", "a");
+	}
+#endif
+
+	if (debug_fp != NULL) {
+		MR_debug_zone_extend(debug_fp, "before", "nondetstack", zone);
+	}
+
+	base_incr = MR_extend_zone(zone, new_size);
+	/* XXX add code to adjust all the links in the nondet stack */
+
+	if (debug_fp != NULL) {
+		MR_debug_zone_extend(debug_fp, "after", "nondetstack", zone);
+	}
+}
+
+static void
+MR_debug_zone_extend(FILE *fp, const char *when, const char *stackname,
+	MR_MemoryZone *zone)
+{
+	fprintf(fp, "----------------\n");
+	fprintf(fp, "%s extending %s\n\n", when, stackname);
+	MR_debug_memory_zone(fp, zone);
+}
+
+#endif
+
+/***************************************************************************/
+
 #undef MR_TABLE_DEBUG
 
 #ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
Index: runtime/mercury_stacks.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_stacks.h,v
retrieving revision 1.50
diff -u -b -r1.50 mercury_stacks.h
--- runtime/mercury_stacks.h	17 May 2005 04:19:25 -0000	1.50
+++ runtime/mercury_stacks.h	13 Sep 2005 07:53:04 -0000
@@ -1,4 +1,7 @@
 /*
+** vim: ts=4 sw=4 expandtab
+*/
+/*
 ** Copyright (C) 1995-2005 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.
@@ -45,8 +48,7 @@
 
   #define MR_collect_det_frame_stats(size)				\
 	(								\
-		MR_increment_dword_tmp(MR_det_frame_count, 		\
-			1, MR_old_low_tmp),				\
+        MR_increment_dword_tmp(MR_det_frame_count, 1, MR_old_low_tmp),        \
 		MR_increment_dword_tmp(MR_det_frame_total_size,		\
 			(size), MR_old_low_tmp),			\
 		((MR_sp > MR_det_frame_max) ?				\
@@ -54,10 +56,9 @@
 	)
   #define MR_collect_non_frame_stats(slots)				\
 	(								\
-		MR_increment_dword_tmp(MR_non_frame_count,		\
-			1, MR_old_low_tmp),				\
+        MR_increment_dword_tmp(MR_non_frame_count, 1, MR_old_low_tmp),        \
 		MR_increment_dword_tmp(MR_non_frame_total_size, 	\
-			(slots) + MR_NONDET_FIXED_SIZE, MR_old_low_tmp),\
+            (slots) + MR_NONDET_FIXED_SIZE, MR_old_low_tmp),                  \
 		((MR_maxfr > MR_non_frame_max) ?			\
 		 	(MR_non_frame_max = MR_maxfr) : (void) 0)	\
 	)
@@ -71,6 +72,29 @@
 
 /*---------------------------------------------------------------------------*/
 
+#ifdef  MR_EXTEND_STACKS_WHEN_NEEDED
+
+  #define MR_detstack_extend_check()                                          \
+    MR_IF (MR_sp >= MR_CONTEXT(MR_ctxt_detstack_zone)->MR_zone_end, (         \
+        MR_extend_detstack()                                                  \
+    ))
+  #define MR_nondetstack_extend_check()                                       \
+    MR_IF (MR_maxfr >= MR_CONTEXT(MR_ctxt_nondetstack_zone)->MR_zone_end, (   \
+        MR_extend_nondetstack()                                               \
+    ))
+
+  extern    void            MR_extend_detstack(void);
+  extern    void            MR_extend_nondetstack(void);
+
+#else   /* MR_EXTEND_STACKS_WHEN_NEEDED */
+
+  #define MR_detstack_extend_check()            ((void) 0)
+  #define MR_nondetstack_extend_check()         ((void) 0)
+
+#endif  /* MR_EXTEND_STACKS_WHEN_NEEDED */
+
+/*---------------------------------------------------------------------------*/
+
 /* DEFINITIONS FOR MANIPULATING THE DET STACK */
 
 /*
@@ -91,6 +115,7 @@
 #define	MR_incr_sp(n)	(					\
 				MR_debugincrsp(n, MR_sp),	\
 				MR_sp_word = (MR_Word) (MR_sp + (n)),	\
+                MR_detstack_extend_check(),                                   \
 				MR_detstack_overflow_check(),	\
 				MR_collect_det_frame_stats(n),	\
 				(void) 0			\
@@ -181,6 +206,7 @@
 
 #define	MR_based_framevar_addr(fr, n) \
 				(&(((MR_Word *) (fr))[MR_SAVEVAL + 1 - (n)]))
+
 #define	MR_based_framevar(fr, n) (((MR_Word *) (fr))[MR_SAVEVAL + 1 - (n)])
 #define	MR_framevar(n)		MR_based_framevar(MR_curfr, n)
 #define	MR_fv(n)		MR_framevar(n)
@@ -189,11 +215,38 @@
 
 /* DEFINITIONS FOR MANIPULATING THE NONDET STACK */
 
+#define MR_nondet_zone_min  (MR_CONTEXT(MR_ctxt_nondetstack_zone)->MR_zone_min)
+
+#ifdef  MR_EXTEND_STACKS_WHEN_NEEDED
+
+  #define   MR_save_maxfr(lval)                                               \
+            do {                                                              \
+                lval = (MR_Word) (MR_maxfr - MR_nondet_zone_min);             \
+            } while (0)
+
+  #define   MR_restore_maxfr(lval)                                            \
+            do {                                                              \
+                MR_maxfr_word = (MR_Word)                                     \
+                    (((MR_Word *) lval) + MR_nondet_zone_min);                \
+            } while (0)
+
+#else
+
+  #define   MR_save_maxfr(lval)                                               \
+            do {                                                              \
+                lval = (MR_Word) MR_maxfr;                                    \
+            } while (0)
+  #define   MR_restore_maxfr(lval)                                            \
+            do {                                                              \
+                MR_maxfr_word = (MR_Word) lval;                               \
+            } while (0)
+
+#endif
+
 #ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY_EXTRA_SLOT
   #define	MR_maybe_fill_table_detfr_slot()			\
 			do {						\
-				MR_table_detfr_slot_word(MR_curfr) =	\
-					MR_sp_word;			\
+                MR_table_detfr_slot_word(MR_curfr) = MR_sp_word;              \
 			} while (0)
 #else
   #define	MR_maybe_fill_table_detfr_slot()			\
@@ -209,6 +262,7 @@
 		succfr = MR_curfr;					\
 		MR_maxfr_word = (MR_Word)				\
 			(MR_maxfr + (MR_NONDET_FIXED_SIZE + (numslots))); \
+        MR_nondetstack_extend_check(),                                        \
 		MR_curfr_word = MR_maxfr_word;				\
 		MR_prevfr_slot_word(MR_curfr) = (MR_Word) prevfr;	\
 		MR_succip_slot_word(MR_curfr) = (MR_Word) MR_succip;	\
@@ -296,7 +350,6 @@
 		MR_GOTO(MR_succip_slot(childfr));			\
 	} while (0)
 
-
 #define	MR_fail()							\
 	do {								\
 		MR_debugfail();						\
@@ -306,7 +359,6 @@
 		MR_GOTO(MR_redoip_slot(MR_maxfr));			\
 	} while (0)
 
-
 #define	MR_redo()							\
 	do {								\
 		MR_debugredo();						\
@@ -336,19 +388,18 @@
 */
 enum MR_HandlerCodeModel {
 	/* 
-	** For these three values, the exception handler is a Mercury closure
-	** with the specified determinism.  If an exception occurs, then
-	** after the Mercury stacks have been unwound, the closure will
-	** be called.
+    ** For these three values, the exception handler is a Mercury closure with
+    ** the specified determinism. If an exception occurs, then after the
+    ** Mercury stacks have been unwound, the closure will be called.
 	*/
 	MR_MODEL_DET_HANDLER,
 	MR_MODEL_SEMI_HANDLER,
 	MR_MODEL_NON_HANDLER,
 	/*
 	** For this value, the exception will be handled by C code using
-	** setjmp/longjmp.  If an exception occurs, then after the Mercury
-	** stacks have been unwound, `MR_longjmp(MR_ENGINE(MR_eng_jmp_buf))'
-	** will be called.
+    ** setjmp/longjmp. If an exception occurs, then after the Mercury stacks
+    ** have been unwound, `MR_longjmp(MR_ENGINE(MR_eng_jmp_buf))' will be
+    ** called.
 	*/
 	MR_C_LONGJMP_HANDLER
 };
@@ -362,18 +413,18 @@
 */
 typedef struct MR_Exception_Handler_Frame_struct {
 	/*
-	** The `code_model' field is used to identify what kind of
-	** handler it is. It holds values of type MR_HandlerCodeModel
-	** (see above), but it is declared to have type `MR_Word' to ensure
-	** that everything remains word-aligned.
+    ** The `code_model' field is used to identify what kind of handler it is.
+    ** It holds values of type MR_HandlerCodeModel (see above), but it is
+    ** declared to have type `MR_Word' to ensure that everything remains
+    ** word-aligned.
 	*/
 	MR_Word MR_excp_code_model;
 
 	/*
-	** If code_model is MR_MODEL_*_HANDLER, then
-	** the `handler' field holds the Mercury closure for the handler,
-	** which will be a closure of the specified determinism.
-	** If code_model is MR_C_LONGJMP, then this field is unused.
+    ** If code_model is MR_MODEL_*_HANDLER, then the `handler' field holds the
+    ** Mercury closure for the handler, which will be a closure of the
+    ** specified determinism. If code_model is MR_C_LONGJMP, then this field
+    ** is unused.
 	*/
 	MR_Word MR_excp_handler;
 
@@ -389,16 +440,16 @@
 	** to unwind the Mercury stacks.
 	*/
 
-	/* the det stack pointer */
+    /* The det stack pointer. */
 	MR_Word *MR_excp_stack_ptr;
 
-	/* the trail state */
+    /* The trail state. */
 	MR_IF_USE_TRAIL(
 		MR_Word MR_excp_trail_ptr;
 		MR_Word MR_excp_ticket_counter;
 	)
 
-	/* the heap state */
+    /* The heap state. */
 	MR_IF_NOT_CONSERVATIVE_GC(
 		MR_Word *MR_excp_heap_ptr;
 		MR_Word *MR_excp_solns_heap_ptr;
@@ -430,60 +481,50 @@
 		handler_code_model, handler_closure, redoip)		      \
 	do {								      \
 		/*							      \
-		** Create a handler on the stack with the special redoip      \
-		** of `MR_exception_handler_do_fail' (we'll look for this     \
-		** redoip when unwinding the nondet stack in		      \
-		** builtin_throw/1), and save the stuff we will		      \
-		** need if an exception is thrown.			      \
+        ** Create a handler on the stack with the special redoip of           \
+        ** `MR_exception_handler_do_fail' (we'll look for this redoip when    \
+        ** unwinding the nondet stack in builtin_throw/1), and save the stuff \
+        ** we will need if an exception is thrown.                            \
 		*/							      \
 		MR_mkpragmaframe((name), MR_EXCEPTION_FRAMEVARS,	      \
 			MR_Exception_Handler_Frame_struct,		      \
 			MR_ENTRY(MR_exception_handler_do_fail));	      \
-		/* record the handler's code model */			      \
-		MR_EXCEPTION_STRUCT->MR_excp_code_model =		      \
-			(handler_code_model);				      \
-		/* save the handler's closure */			      \
+        /* Record the handler's code model. */                                \
+        MR_EXCEPTION_STRUCT->MR_excp_code_model = (handler_code_model);       \
+        /* Save the handler's closure. */                                     \
 		MR_EXCEPTION_STRUCT->MR_excp_handler = (handler_closure);     \
-		/* save the full tracing flag */			      \
-		MR_EXCEPTION_STRUCT->MR_excp_full_trace =		      \
-			(MR_Word) MR_trace_from_full;			      \
-		/* save the det stack pointer */			      \
+        /* Save the full tracing flag. */                                     \
+        MR_EXCEPTION_STRUCT->MR_excp_full_trace = (MR_Word) MR_trace_from_full;\
+        /* Save the det stack pointer. */                                     \
 		MR_EXCEPTION_STRUCT->MR_excp_stack_ptr = MR_sp;		      \
 		MR_IF_NOT_CONSERVATIVE_GC(				      \
-			/* save the heap and solutions heap pointers */	      \
+            /* Save the heap and solutions heap pointers. */                  \
 			MR_EXCEPTION_STRUCT->MR_excp_heap_ptr = MR_hp;        \
-			MR_EXCEPTION_STRUCT->MR_excp_solns_heap_ptr =         \
-				MR_sol_hp;				      \
+            MR_EXCEPTION_STRUCT->MR_excp_solns_heap_ptr = MR_sol_hp;          \
 			MR_EXCEPTION_STRUCT->MR_excp_heap_zone =	      \
 				MR_ENGINE(MR_eng_heap_zone);		      \
 		)							      \
 		MR_IF_USE_TRAIL(					      \
-			/* save the trail state */			      \
-			MR_mark_ticket_stack(MR_EXCEPTION_STRUCT->	      \
-				MR_excp_ticket_counter);		      \
-			MR_store_ticket(MR_EXCEPTION_STRUCT->		      \
-				MR_excp_trail_ptr);			      \
+            /* Save the trail state. */                                       \
+            MR_mark_ticket_stack(MR_EXCEPTION_STRUCT->MR_excp_ticket_counter);\
+            MR_store_ticket(MR_EXCEPTION_STRUCT->MR_excp_trail_ptr);          \
 		)							      \
 									      \
 		/*							      \
-		** Now we need to create another frame.			      \
-		** This is so that we can be sure that no-one will hijack     \
-		** the redoip of the special frame we created above.	      \
-		** (The compiler sometimes generates ``hijacking'' code       \
-		** that saves the topmost redoip on the stack, and	      \
-		** temporarily replaces it with a new redoip that will	      \
-		** do some processing on failure before restoring the	      \
-		** original redoip.  This would cause problems when	      \
-		** doing stack unwinding in builtin_throw/1, because	      \
-		** we wouldn't be able to find the special redoip.	      \
-		** But code will only ever hijack the topmost frame,	      \
-		** so we can avoid this by creating a second frame	      \
-		** above the special frame.)				      \
+        ** Now we need to create another frame. This is so that we can be sure\
+        ** that no-one will hijack the redoip of the special frame we created \
+        ** above. (The compiler sometimes generates ``hijacking'' code that   \
+        ** saves the topmost redoip on the stack, and temporarily replaces it \
+        ** with a new redoip that will do some processing on failure before   \
+        ** restoring the original redoip. This would cause problems when doing\
+        ** stack unwinding in builtin_throw/1, because we wouldn't be able to \
+        ** find the special redoip. But code will only ever hijack the topmost\
+        ** frame, so we can avoid this by creating a second frame above the   \
+        ** special frame.)                                                    \
 		*/							      \
 		MR_mktempframe(redoip);				      	      \
 	} while (0)
 
-
 /*---------------------------------------------------------------------------*/
 
 #ifdef	MR_USE_MINIMAL_MODEL_STACK_COPY
Index: runtime/mercury_std.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_std.h,v
retrieving revision 1.30
diff -u -b -r1.30 mercury_std.h
--- runtime/mercury_std.h	11 Aug 2005 01:12:51 -0000	1.30
+++ runtime/mercury_std.h	11 Sep 2005 02:47:25 -0000
@@ -290,4 +290,13 @@
 
 /*---------------------------------------------------------------------------*/
 
+/*
+** MR_IF is for writing if-then-elses that must expand to expressions, not
+** statements.
+*/
+
+#define MR_IF(cond, val) ((cond) ? ((val), (void)0) : (void)0)
+
+/*---------------------------------------------------------------------------*/
+
 #endif /* not MERCURY_STD_H */
Index: runtime/mercury_wrapper.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_wrapper.c,v
retrieving revision 1.152
diff -u -b -r1.152 mercury_wrapper.c
--- runtime/mercury_wrapper.c	1 Sep 2005 12:04:35 -0000	1.152
+++ runtime/mercury_wrapper.c	11 Sep 2005 02:41:03 -0000
@@ -572,7 +572,7 @@
 #endif /* ! MR_HIGHLEVEL_CODE */
 
 	if (MR_memdebug) {
-		MR_debug_memory();
+		MR_debug_memory(stderr);
 	}
 
 	/* initialize profiling */
@@ -684,7 +684,7 @@
   #else /* MR_BOEHM_GC */
 
 	/*
-	** sometimes mercury apps fail the GC_is_visible() test.
+	** Sometimes Mercury apps fail the GC_is_visible() test.
 	** dyn_load.c traverses the entire address space and registers
 	** all segments that could possibly have been written to, which
 	** makes us suspect that &MR_runqueue_head is not in the registered
Index: runtime/mercury_wrapper.h
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/runtime/mercury_wrapper.h,v
retrieving revision 1.69
diff -u -b -r1.69 mercury_wrapper.h
--- runtime/mercury_wrapper.h	29 Aug 2005 03:22:30 -0000	1.69
+++ runtime/mercury_wrapper.h	11 Sep 2005 02:47:25 -0000
@@ -28,18 +28,21 @@
 ** and the Mercury engine's data areas, and then calls io__init_state/2
 ** in the Mercury library to initialize the io__state.
 */
+
 extern	void	mercury_runtime_init(int argc, char **argv);
 
 /*
 ** mercury_runtime_main() basically just calls main/2,
 ** with a bit of debugging scaffolding around it.
 */
+
 extern	void	mercury_runtime_main(void);
 
 /*
 ** mercury_runtime_terminate() does any necessary cleanup,
 ** and then returns mercury_exit_status.
 */
+
 extern	int	mercury_runtime_terminate(void);
 
 /*
@@ -53,6 +56,7 @@
 ** We use MR_Box here rather than the actual argument types to
 ** avoid dependencies on the Aditi headers.
 */
+
 extern	MR_Box	MR_load_aditi_rl_code(MR_Box connection, MR_Box transaction);
 
 /*
@@ -61,6 +65,7 @@
 ** or the MPS (Memory Pool System) kit collector.  This function is normally
 ** called from mercury_runtime_init().
 */
+
 #ifdef MR_CONSERVATIVE_GC
   extern void	MR_init_conservative_GC(void);
 #endif
@@ -169,6 +174,7 @@
 ** MR_address_of_trace_interrupt_handler points to
 ** MR_trace_interrupt_handler, otherwise it is NULL.
 */
+
 extern	void		(*MR_address_of_trace_interrupt_handler)(void);
 
 /*
@@ -176,6 +182,7 @@
 ** MR_register_module_layout points to MR_register_module_layout_real,
 ** otherwise it is NULL.
 */
+
 extern	void		(*MR_register_module_layout)(const MR_Module_Layout *);
 
 /*
cvs diff: Diffing runtime/GETOPT
cvs diff: Diffing runtime/machdeps
cvs diff: Diffing samples
cvs diff: Diffing samples/c_interface
cvs diff: Diffing samples/c_interface/c_calls_mercury
cvs diff: Diffing samples/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/c_interface/mercury_calls_c
cvs diff: Diffing samples/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/diff
cvs diff: Diffing samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
Index: scripts/canonical_grade.sh-subr
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/canonical_grade.sh-subr,v
retrieving revision 1.13
diff -u -b -r1.13 canonical_grade.sh-subr
--- scripts/canonical_grade.sh-subr	15 Feb 2005 04:45:03 -0000	1.13
+++ scripts/canonical_grade.sh-subr	3 Jun 2005 05:03:46 -0000
@@ -149,3 +149,8 @@
 			exit 1
 			;;
 esac
+
+case $extend_stacks in
+	true)		GRADE="$GRADE.exts" ;;
+	*)		;;
+esac
Index: scripts/init_grade_options.sh-subr
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/init_grade_options.sh-subr,v
retrieving revision 1.24
diff -u -b -r1.24 init_grade_options.sh-subr
--- scripts/init_grade_options.sh-subr	20 Jul 2004 04:41:31 -0000	1.24
+++ scripts/init_grade_options.sh-subr	3 Jun 2005 04:48:13 -0000
@@ -47,6 +47,7 @@
 	--no-stack-trace
 	--debug
 	--decl-debug
+	--extend-stacks-when-needed
 		See the documentation in the \"Invocation\" section
 		of the Mercury User's Guide."
 
@@ -78,6 +79,7 @@
 pic_reg=false
 debug=false
 decl_debug=false
+extend_stacks=false
 
 case $# in
 	0) set - --grade "$DEFAULT_GRADE" ;;
Index: scripts/mgnuc.in
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/mgnuc.in,v
retrieving revision 1.109
diff -u -b -r1.109 mgnuc.in
--- scripts/mgnuc.in	18 Aug 2005 05:18:28 -0000	1.109
+++ scripts/mgnuc.in	18 Aug 2005 08:06:59 -0000
@@ -441,6 +441,11 @@
 	false)		DECL_DEBUG_OPTS="" ;;
 esac
 
+case $extend_stacks in
+	true)		EXTEND_STACKS_OPTS="-DMR_EXTEND_STACKS_WHEN_NEEDED" ;;
+	false)		EXTEND_STACKS_OPTS="" ;;
+esac
+
 GCC_OPTS="$NEST_OPTS $ASM_OPTS $GOTO_OPTS $REG_OPTS"
 
 # check that special grades are only used with gcc
@@ -628,6 +633,7 @@
 	$STACK_TRACE_OPTS\
 	$TRACE_OPTS\
 	$DECL_DEBUG_OPTS\
+	$EXTEND_STACKS_OPTS\
 	$LLDEBUG_OPTS\
 	$C_DEBUG_OPTS\
 	$PROF_TIME_OPTS\
Index: scripts/parse_grade_options.sh-subr
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/scripts/parse_grade_options.sh-subr,v
retrieving revision 1.30
diff -u -b -r1.30 parse_grade_options.sh-subr
--- scripts/parse_grade_options.sh-subr	20 Jul 2004 04:41:31 -0000	1.30
+++ scripts/parse_grade_options.sh-subr	3 Jun 2005 04:49:34 -0000
@@ -178,6 +178,11 @@
 	--no-decl-debug)
 		decl_debug=false ;;
 
+	--extend-stacks-when-needed)
+		extend_stacks=true ;;
+	--no-extend-stacks-when-needed)
+		extend_stacks=false ;;
+
 	-s|--grade)
 		shift
 		grade="$1";
@@ -211,6 +216,7 @@
 		pic_reg=false
 		debug=false
 		decl_debug=false
+		extend_stacks=false
 
 		grade_pieces=`echo $grade | tr '.' ' '`
 		for grade_piece in $grade_pieces
@@ -442,6 +448,10 @@
 
 				decldebug)
 					decl_debug=true
+					;;
+
+				exts)
+					extend_stacks=true
 					;;
 
 				*)
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/recompilation
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
Index: tools/bootcheck
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/tools/bootcheck,v
retrieving revision 1.175
diff -u -b -r1.175 bootcheck
--- tools/bootcheck	29 Aug 2005 15:44:32 -0000	1.175
+++ tools/bootcheck	11 Sep 2005 02:41:23 -0000
@@ -65,6 +65,8 @@
         Otherwise, we use the stage 1 runtime, library etc,
         and trust that these are compatible with the given grade.
         Implies -r -g.
+    --mercury-options <options-string>
+        Set MERCURY_OPTIONS to the given string when doing the bootcheck.
     -g, --copy-boehm-gc
         Copy the boehm_gc directory instead of linking it.
         This is necessary if one wants to bootcheck a grade
@@ -296,6 +298,9 @@
 
     --test-grade)
         test_grade="$2"; shift ;;
+
+    --mercury-options)
+        MERCURY_OPTIONS="$2"; export MERCURY_OPTIONS; shift ;;
 
     --test-split-library)
         test_split_library=true ;;
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:  mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the reviews mailing list