for revew: fix bugs in the handling of temporaries

Zoltan Somogyi zs at cs.mu.OZ.AU
Mon Nov 2 18:36:35 AEDT 1998


For review by Tom or Fergus.

This change has been tested and found to work on mercury/extras/trailed/update
as well as the clpr directory.

Estimated hours taken: 10

Fix bugs in the handling of temporaries.

compiler/code_info.m:
	Reorganize the way temporary slots are handled. Create a stack slot
	to slot_contents map that is part of the permanent state, so each
	slot can be used for only one purpose within a procedure; this is
	to make garbage collection of these slots possible. Make the set
	of temporary slots in use be part of the location dependent state.

	At the ends of branched control structures, consider a temp slot
	in use if it was in use at the end of any branch. (Previously,
	we considered it live after the control structure if it was live
	at the end of the last branch. We got that right for branched
	structures that manipulate temp slots, i.e. disjunctions and
	if-then-elses, but we got it wrong for switches.

	Rename some predicates to get rid of the double meaning of the word
	"discard" as applied to a temporary, which used to mean either
	"release the slot" or "execute the discard_ticket operation".
	It now means only the latter; the word "release" refers to the former.

compiler/disj_gen.m:
compiler/ite_gen.m:
	Conform to the new method of handling temporary slots.

tests/valid/complex_failure.m:
tests/valid/semi_fail_in_non_ite.m:
	Copies of the test cases from tests/general.

tests/valid/Mmakefile:
	Enable the new test cases, running them with --use-trail.

	Unfortunately, we cannot just specify --use-trail for them
	in tests/general, since that would cause a link error in the usual
	case that the runtime being linked with is not in a trailing grade.

Zoltan.

cvs diff: Diffing .
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/include
cvs diff: Diffing boehm_gc/include/private
cvs diff: Diffing browser
cvs diff: Diffing bytecode
cvs diff: Diffing bytecode/test
cvs diff: Diffing compiler
Index: compiler/code_info.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/code_info.m,v
retrieving revision 1.230
diff -u -u -r1.230 code_info.m
--- code_info.m	1998/10/23 00:39:56	1.230
+++ code_info.m	1998/11/02 04:42:39
@@ -153,12 +153,10 @@
 :- pred code_info__set_exprn_info(exprn_info, code_info, code_info).
 :- mode code_info__set_exprn_info(in, in, out) is det.
 
-:- pred code_info__get_temps_in_use(map(lval, slot_contents),
-	code_info, code_info).
+:- pred code_info__get_temps_in_use(set(lval), code_info, code_info).
 :- mode code_info__get_temps_in_use(out, in, out) is det.
 
-:- pred code_info__set_temps_in_use(map(lval, slot_contents),
-	code_info, code_info).
+:- pred code_info__set_temps_in_use(set(lval), code_info, code_info).
 :- mode code_info__set_temps_in_use(in, in, out) is det.
 
 :- pred code_info__get_fail_info(fail_info, code_info, code_info).
@@ -189,11 +187,13 @@
 :- pred code_info__set_max_temp_slot_count(int, code_info, code_info).
 :- mode code_info__set_max_temp_slot_count(in, in, out) is det.
 
-:- pred code_info__get_avail_temp_slots(set(lval), code_info, code_info).
-:- mode code_info__get_avail_temp_slots(out, in, out) is det.
+:- pred code_info__get_temp_content_map(map(lval, slot_contents),
+	code_info, code_info).
+:- mode code_info__get_temp_content_map(out, in, out) is det.
 
-:- pred code_info__set_avail_temp_slots(set(lval), code_info, code_info).
-:- mode code_info__set_avail_temp_slots(in, in, out) is det.
+:- pred code_info__set_temp_content_map(map(lval, slot_contents),
+	code_info, code_info).
+:- mode code_info__set_temp_content_map(in, in, out) is det.
 
 %---------------------------------------------------------------------------%
 
@@ -242,9 +242,12 @@
 		exprn_info,	% A map storing the information about
 				% the status of each known variable.
 				% (Known vars = forward live vars + zombies)
-		map(lval, slot_contents),
-				% The temp locations in use on the stack
-				% and what they contain (for gc).
+		set(lval),	% The set of temporary locations currently in
+				% use. These lvals must be all be keys in the
+				% map of temporary locations ever used, which
+				% is one of the persistent fields below. Any
+				% keys in that map which are not in this set
+				% are free for reuse.
 		fail_info,	% Information about how to manage failures.
 
 		% PERSISTENT fields
@@ -259,9 +262,17 @@
 		int,		% The maximum number of extra
 				% temporary stackslots that have been
 				% used during the procedure.
-		set(lval)	% Stack variables that have been used
-				% for temporaries and are now again
-				% available for reuse.
+		map(lval, slot_contents)
+				% The temporary locations that have ever been
+				% used on the stack, and what they contain.
+				% Once we have used a stack slot to store
+				% e.g. a ticket, we never reuse that slot
+				% to hold something else, e.g. a saved hp.
+				% This policy prevents us from making such
+				% conflicting choices in parallel branches,
+				% which would make it impossible to describe
+				% to gc what the slot contains after the end
+				% of the branched control structure.
 	).
 
 %---------------------------------------------------------------------------%
@@ -288,8 +299,8 @@
 	),
 	DummyFailInfo = fail_info(ResumePoints, resume_point_unknown,
 		may_be_different, not_inside_non_condition, Hijack),
-	set__init(AvailSlots),
-	map__init(TempsInUse),
+	map__init(TempContentMap),
+	set__init(TempsInUse),
 	set__init(Zombies),
 	map__init(LayoutMap),
 	code_info__max_var_slot(StackSlots, VarSlotMax),
@@ -317,7 +328,7 @@
 		SaveSuccip,
 		LayoutMap,
 		0,
-		AvailSlots
+		TempContentMap
 	),
 	code_info__init_maybe_trace_info(Globals, ModuleInfo, ProcInfo,
 		MaybeFailVars, MaybeFromFullSlot, CodeInfo0, CodeInfo1),
@@ -419,7 +430,7 @@
 	CI  = code_info(_, _, _, _, _, _, _, _,
 		_, _, _, _, _, _, _, _, _, _, PE, _).
 
-code_info__get_avail_temp_slots(PF, CI, CI) :-
+code_info__get_temp_content_map(PF, CI, CI) :-
 	CI  = code_info(_, _, _, _, _, _, _, _,
 		_, _, _, _, _, _, _, _, _, _, _, PF).
 
@@ -497,7 +508,7 @@
 	CI  = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
 		LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, PF).
 
-code_info__set_avail_temp_slots(PF, CI0, CI) :-
+code_info__set_temp_content_map(PF, CI0, CI) :-
 	CI0 = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
 		LA, LB, LC, LD, LE, LF, PA, PB, PC, PD, PE, _ ),
 	CI  = code_info(SA, SB, SC, SD, SE, SF, SG, SH,
@@ -934,7 +945,16 @@
 			"some but not all branches inside a non condition"),
 		FailInfo = fail_info(R, ResumeKnown, CurfrMaxfr,
 			CondEnv0, Hijack),
-		code_info__set_fail_info(FailInfo, EndCodeInfo1, EndCodeInfo)
+		code_info__set_fail_info(FailInfo, EndCodeInfo1, EndCodeInfoA),
+
+			% Make sure we "temps in use" set at the end the
+			% branched control structure includes every slot
+			% in use at the end of any branch.
+		code_info__get_temps_in_use(TempsInUse0, EndCodeInfo0, _),
+		code_info__get_temps_in_use(TempsInUse1, EndCodeInfo1, _),
+		set__union(TempsInUse0, TempsInUse1, TempsInUse),
+		code_info__set_temps_in_use(TempsInUse, EndCodeInfoA,
+			EndCodeInfo)
 	},
 	{ MaybeEnd = yes(branch_end_info(EndCodeInfo)) }.
 
@@ -2581,12 +2601,12 @@
 :- pred code_info__restore_hp(lval, code_tree, code_info, code_info).
 :- mode code_info__restore_hp(in, out, in, out) is det.
 
-:- pred code_info__restore_and_discard_hp(lval, code_tree,
-	code_info, code_info).
-:- mode code_info__restore_and_discard_hp(in, out, in, out) is det.
+:- pred code_info__release_hp(lval, code_info, code_info).
+:- mode code_info__release_hp(in, in, out) is det.
 
-:- pred code_info__discard_hp(lval, code_info, code_info).
-:- mode code_info__discard_hp(in, in, out) is det.
+:- pred code_info__restore_and_release_hp(lval, code_tree,
+	code_info, code_info).
+:- mode code_info__restore_and_release_hp(in, out, in, out) is det.
 
 :- pred code_info__maybe_save_hp(bool, code_tree, maybe(lval),
 	code_info, code_info).
@@ -2596,12 +2616,12 @@
 	code_info, code_info).
 :- mode code_info__maybe_restore_hp(in, out, in, out) is det.
 
-:- pred code_info__maybe_restore_and_discard_hp(maybe(lval), code_tree,
-	code_info, code_info).
-:- mode code_info__maybe_restore_and_discard_hp(in, out, in, out) is det.
+:- pred code_info__maybe_release_hp(maybe(lval), code_info, code_info).
+:- mode code_info__maybe_release_hp(in, in, out) is det.
 
-:- pred code_info__maybe_discard_hp(maybe(lval), code_info, code_info).
-:- mode code_info__maybe_discard_hp(in, in, out) is det.
+:- pred code_info__maybe_restore_and_release_hp(maybe(lval), code_tree,
+	code_info, code_info).
+:- mode code_info__maybe_restore_and_release_hp(in, out, in, out) is det.
 
 :- pred code_info__save_ticket(code_tree, lval, code_info, code_info).
 :- mode code_info__save_ticket(out, out, in, out) is det.
@@ -2610,19 +2630,17 @@
 	code_info, code_info).
 :- mode code_info__reset_ticket(in, in, out, in, out) is det.
 
-:- pred code_info__reset_and_discard_ticket(lval, reset_trail_reason, code_tree,
-	code_info, code_info).
-:- mode code_info__reset_and_discard_ticket(in, in, out, in, out) is det.
+:- pred code_info__release_ticket(lval, code_info, code_info).
+:- mode code_info__release_ticket(in, in, out) is det.
 
-	% Same as reset_and_discard_ticket, but don't release the temp slot.
-	% Used for cases where the temp slot might still be needed again
-	% on backtracking and thus can't be reused in the code that follows.
-:- pred code_info__reset_and_pop_ticket(lval, reset_trail_reason,
+:- pred code_info__reset_and_discard_ticket(lval, reset_trail_reason,
 	code_tree, code_info, code_info).
-:- mode code_info__reset_and_pop_ticket(in, in, out, in, out) is det.
+:- mode code_info__reset_and_discard_ticket(in, in, out, in, out) is det.
 
-:- pred code_info__discard_ticket(lval, code_tree, code_info, code_info).
-:- mode code_info__discard_ticket(in, out, in, out) is det.
+:- pred code_info__reset_discard_and_release_ticket(lval, reset_trail_reason,
+	code_tree, code_info, code_info).
+:- mode code_info__reset_discard_and_release_ticket(in, in, out, in, out)
+	is det.
 
 :- pred code_info__maybe_save_ticket(bool, code_tree, maybe(lval),
 	code_info, code_info).
@@ -2632,20 +2650,17 @@
 	code_tree, code_info, code_info).
 :- mode code_info__maybe_reset_ticket(in, in, out, in, out) is det.
 
+:- pred code_info__maybe_release_ticket(maybe(lval), code_info, code_info).
+:- mode code_info__maybe_release_ticket(in, in, out) is det.
+
 :- pred code_info__maybe_reset_and_discard_ticket(maybe(lval),
 	reset_trail_reason, code_tree, code_info, code_info).
 :- mode code_info__maybe_reset_and_discard_ticket(in, in, out, in, out) is det.
 
-:- pred code_info__maybe_reset_and_pop_ticket(maybe(lval),
+:- pred code_info__maybe_reset_discard_and_release_ticket(maybe(lval),
 	reset_trail_reason, code_tree, code_info, code_info).
-:- mode code_info__maybe_reset_and_pop_ticket(in, in, out, in, out) is det.
-
-:- pred code_info__maybe_discard_ticket(maybe(lval), code_tree,
-	code_info, code_info).
-:- mode code_info__maybe_discard_ticket(in, out, in, out) is det.
-
-:- pred code_info__save_maxfr(lval, code_tree, code_info, code_info).
-:- mode code_info__save_maxfr(out, out, in, out) is det.
+:- mode code_info__maybe_reset_discard_and_release_ticket(in, in, out, in, out)
+	is det.
 
 %---------------------------------------------------------------------------%
 
@@ -2653,17 +2668,25 @@
 
 code_info__save_hp(Code, HpSlot) -->
 	code_info__acquire_temp_slot(lval(hp), HpSlot),
-	{ Code = node([mark_hp(HpSlot) - "Save heap pointer"]) }.
+	{ Code = node([
+		mark_hp(HpSlot) - "Save heap pointer"
+	]) }.
 
 code_info__restore_hp(HpSlot, Code) -->
-	{ Code = node([restore_hp(lval(HpSlot)) - "Restore heap pointer"]) }.
+	{ Code = node([
+		restore_hp(lval(HpSlot)) - "Restore heap pointer"
+	]) }.
 
-code_info__discard_hp(HpSlot) -->
+code_info__release_hp(HpSlot) -->
 	code_info__release_temp_slot(HpSlot).
 
-code_info__restore_and_discard_hp(HpSlot, Code) -->
-	{ Code = node([restore_hp(lval(HpSlot)) - "Restore heap pointer"]) },
-	code_info__discard_hp(HpSlot).
+code_info__restore_and_release_hp(HpSlot, Code) -->
+	{ Code = node([
+		restore_hp(lval(HpSlot)) - "Release heap pointer"
+	]) },
+	code_info__release_hp(HpSlot).
+
+%---------------------------------------------------------------------------%
 
 code_info__maybe_save_hp(Maybe, Code, MaybeHpSlot) -->
 	( { Maybe = yes } ->
@@ -2681,44 +2704,50 @@
 		{ Code = empty }
 	).
 
-code_info__maybe_restore_and_discard_hp(MaybeHpSlot, Code) -->
+code_info__maybe_release_hp(MaybeHpSlot) -->
 	( { MaybeHpSlot = yes(HpSlot) } ->
-		code_info__restore_and_discard_hp(HpSlot, Code)
+		code_info__release_hp(HpSlot)
 	;
-		{ Code = empty }
+		[]
 	).
 
-code_info__maybe_discard_hp(MaybeHpSlot) -->
+code_info__maybe_restore_and_release_hp(MaybeHpSlot, Code) -->
 	( { MaybeHpSlot = yes(HpSlot) } ->
-		code_info__discard_hp(HpSlot)
+		code_info__restore_and_release_hp(HpSlot, Code)
 	;
-		[]
+		{ Code = empty }
 	).
 
+%---------------------------------------------------------------------------%
+
 code_info__save_ticket(Code, TicketSlot) -->
 	code_info__acquire_temp_slot(ticket, TicketSlot),
-	{ Code = node([store_ticket(TicketSlot) - "Save trail state"]) }.
+	{ Code = node([
+		store_ticket(TicketSlot) - "Save trail state"
+	]) }.
 
 code_info__reset_ticket(TicketSlot, Reason, Code) -->
-	{ Code = node([reset_ticket(lval(TicketSlot), Reason) - "Reset trail"]) }.
+	{ Code = node([
+		reset_ticket(lval(TicketSlot), Reason) - "Reset trail"
+	]) }.
+
+code_info__release_ticket(TicketSlot) -->
+	code_info__release_temp_slot(TicketSlot).
 
 code_info__reset_and_discard_ticket(TicketSlot, Reason, Code) -->
-	code_info__release_temp_slot(TicketSlot),
 	{ Code = node([
 		reset_ticket(lval(TicketSlot), Reason) - "Restore trail",
 		discard_ticket - "Pop ticket stack"
 	]) }.
 
-code_info__reset_and_pop_ticket(TicketSlot, Reason, Code) -->
+code_info__reset_discard_and_release_ticket(TicketSlot, Reason, Code) -->
 	{ Code = node([
-		reset_ticket(lval(TicketSlot), Reason) -
-			"Restore trail (but don't release this stack slot)",
+		reset_ticket(lval(TicketSlot), Reason) - "Release trail",
 		discard_ticket - "Pop ticket stack"
-	]) }.
+	]) },
+	code_info__release_temp_slot(TicketSlot).
 
-code_info__discard_ticket(TicketSlot, Code) -->
-	code_info__release_temp_slot(TicketSlot),
-	{ Code = node([discard_ticket - "Pop ticket stack"]) }.
+%---------------------------------------------------------------------------%
 
 code_info__maybe_save_ticket(Maybe, Code, MaybeTicketSlot) -->
 	( { Maybe = yes } ->
@@ -2736,31 +2765,29 @@
 		{ Code = empty }
 	).
 
-code_info__maybe_reset_and_discard_ticket(MaybeTicketSlot, Reason, Code) -->
+code_info__maybe_release_ticket(MaybeTicketSlot) -->
 	( { MaybeTicketSlot = yes(TicketSlot) } ->
-		code_info__reset_and_discard_ticket(TicketSlot, Reason, Code)
+		code_info__release_ticket(TicketSlot)
 	;
-		{ Code = empty }
+		[]
 	).
 
-code_info__maybe_reset_and_pop_ticket(MaybeTicketSlot, Reason, Code) -->
+code_info__maybe_reset_and_discard_ticket(MaybeTicketSlot, Reason, Code) -->
 	( { MaybeTicketSlot = yes(TicketSlot) } ->
-		code_info__reset_and_pop_ticket(TicketSlot, Reason, Code)
+		code_info__reset_and_discard_ticket(TicketSlot, Reason, Code)
 	;
 		{ Code = empty }
 	).
 
-code_info__maybe_discard_ticket(MaybeTicketSlot, Code) -->
+code_info__maybe_reset_discard_and_release_ticket(MaybeTicketSlot, Reason,
+		Code) -->
 	( { MaybeTicketSlot = yes(TicketSlot) } ->
-		code_info__discard_ticket(TicketSlot, Code)
+		code_info__reset_discard_and_release_ticket(TicketSlot, Reason,
+			Code)
 	;
 		{ Code = empty }
 	).
 
-code_info__save_maxfr(MaxfrSlot, Code) -->
-	code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
-	{ Code = node([assign(MaxfrSlot, lval(maxfr)) - "Save maxfr"]) }.
-
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
 
@@ -3063,8 +3090,10 @@
 	{ set__to_sorted_list(Vars, VarList) },
 	{ set__init(LiveVals0) },
 	code_info__generate_var_livevals(VarList, LiveVals0, LiveVals1),
-	code_info__get_temps_in_use(TempsSet),
-	{ map__to_assoc_list(TempsSet, Temps) },
+	code_info__get_temps_in_use(TempsInUse),
+	code_info__get_temp_content_map(TempContentMap),
+	{ map__select(TempContentMap, TempsInUse, TempsInUseContentMap) },
+	{ map__to_assoc_list(TempsInUseContentMap, Temps) },
 	{ code_info__generate_temp_livevals(Temps, LiveVals1, LiveVals) }.
 
 :- pred code_info__generate_var_livevals(list(var), set(lval), set(lval),
@@ -3100,8 +3129,10 @@
 	{ globals__want_return_layouts(Globals, WantReturnLayout) },
 	code_info__livevals_to_livelvals(LiveVals2, WantReturnLayout, 
 		AfterCallInstMap, LiveVals3),
-	code_info__get_temps_in_use(TempsSet),
-	{ map__to_assoc_list(TempsSet, Temps) },
+	code_info__get_temps_in_use(TempsInUse),
+	code_info__get_temp_content_map(TempContentMap),
+	{ map__select(TempContentMap, TempsInUse, TempsInUseContentMap) },
+	{ map__to_assoc_list(TempsInUseContentMap, Temps) },
 	{ code_info__generate_temp_livelvals(Temps, LiveVals3, LiveVals) }.
 
 :- pred code_info__generate_var_livelvals(list(var),
@@ -3250,28 +3281,36 @@
 :- implementation.
 
 code_info__acquire_temp_slot(Item, StackVar) -->
-	code_info__get_avail_temp_slots(AvailSlots0),
-	( { set__remove_least(AvailSlots0, StackVarPrime, AvailSlots) } ->
-		{ StackVar = StackVarPrime },
-		code_info__set_avail_temp_slots(AvailSlots)
+	code_info__get_temps_in_use(TempsInUse0),
+	{ IsTempUsable = lambda([TempContent::in, Lval::out] is semidet, (
+		TempContent = Lval - ContentType,
+		ContentType = Item,
+		\+ set__member(Lval, TempsInUse0)
+	)) },
+	code_info__get_temp_content_map(TempContentMap0),
+	{ map__to_assoc_list(TempContentMap0, TempContentList) },
+	{ list__filter_map(IsTempUsable, TempContentList, UsableLvals) },
+	(
+		{ UsableLvals = [UsableLval | _] },
+		{ StackVar = UsableLval }
 	;
+		{ UsableLvals = [] },
 		code_info__get_var_slot_count(VarSlots),
 		code_info__get_max_temp_slot_count(TempSlots0),
 		{ TempSlots is TempSlots0 + 1 },
 		{ Slot is VarSlots + TempSlots },
 		code_info__stack_variable(Slot, StackVar),
-		code_info__set_max_temp_slot_count(TempSlots)
+		code_info__set_max_temp_slot_count(TempSlots),
+		{ map__det_insert(TempContentMap0, StackVar, Item,
+			TempContentMap) },
+		code_info__set_temp_content_map(TempContentMap)
 	),
-	code_info__get_temps_in_use(TempsInUse0),
-	{ map__det_insert(TempsInUse0, StackVar, Item, TempsInUse) },
+	{ set__insert(TempsInUse0, StackVar, TempsInUse) },
 	code_info__set_temps_in_use(TempsInUse).
 
 code_info__release_temp_slot(StackVar) -->
-	code_info__get_avail_temp_slots(AvailSlots0),
-	{ set__insert(AvailSlots0, StackVar, AvailSlots) },
-	code_info__set_avail_temp_slots(AvailSlots),
 	code_info__get_temps_in_use(TempsInUse0),
-	{ map__delete(TempsInUse0, StackVar, TempsInUse) },
+	{ set__delete(TempsInUse0, StackVar, TempsInUse) },
 	code_info__set_temps_in_use(TempsInUse).
 
 %---------------------------------------------------------------------------%
Index: compiler/disj_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/disj_gen.m,v
retrieving revision 1.65
diff -u -u -r1.65 disj_gen.m
--- disj_gen.m	1998/07/20 10:00:36	1.65
+++ disj_gen.m	1998/11/02 04:23:24
@@ -120,7 +120,6 @@
 	;
 		[]
 	),
-		% XXX release any temp slots holding heap or trail pointers
 	{ Code =
 		tree(FlushCode,
 		tree(SaveTicketCode,
@@ -214,8 +213,15 @@
 			% so we make sure every variable in the resume set
 			% is in its stack slot.
 			code_info__flush_resume_vars_to_stack(ResumeVarsCode)
+
+			% We hang onto any temporary slots holding saved
+			% heap pointers and/or tickets, thus ensuring that
+			% they will still be reserved after the disjunction.
 		;
-			{ ResumeVarsCode = empty }
+			{ ResumeVarsCode = empty },
+
+			code_info__maybe_release_hp(MaybeHpSlot),
+			code_info__maybe_release_ticket(MaybeTicketSlot)
 		),
 
 			% Put every variable whose value is needed after
@@ -253,29 +259,10 @@
 
 			% Restore the heap pointer and solver state
 			% if necessary.
-		( { CodeModel = model_non } ->
-
-			% Note that we can't release the temps used for the
-			% heap pointer and ticket, because those values may be
-			% required again after backtracking after control
-			% leaves the disjunction. If we were to reuse either
-			% of their stack slots for something else when
-			% generating the code that follows this goal,
-			% then the values that earlier disjuncts need on
-			% backtracking would get clobbered.
-			% Thus we must not use the `_discard' versions
-			% of the two predicates below.
-
-			code_info__maybe_restore_hp(MaybeHpSlot0,
-				RestoreHpCode),
-			code_info__maybe_reset_and_pop_ticket(
-				MaybeTicketSlot, undo, RestoreTicketCode)
-		;
-			code_info__maybe_restore_and_discard_hp(MaybeHpSlot0,
-				RestoreHpCode),
-			code_info__maybe_reset_and_discard_ticket(
-				MaybeTicketSlot, undo, RestoreTicketCode)
-		),
+		code_info__maybe_restore_and_release_hp(MaybeHpSlot0,
+			RestoreHpCode),
+		code_info__maybe_reset_discard_and_release_ticket(
+			MaybeTicketSlot, undo, RestoreTicketCode),
 
 		code_info__undo_disj_hijack(HijackInfo, UndoCode),
 
Index: compiler/ite_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ite_gen.m,v
retrieving revision 1.59
diff -u -u -r1.59 ite_gen.m
--- ite_gen.m	1998/09/10 06:38:24	1.59
+++ ite_gen.m	1998/11/02 04:31:05
@@ -109,16 +109,21 @@
 	code_info__make_vars_forward_dead(Zombies),
 
 		% Discard hp and trail ticket if the condition succeeded
-		% XXX is this the right thing to do?
-	code_info__maybe_reset_and_discard_ticket(MaybeTicketSlot, commit,
-		DiscardTicketCode),
-	code_info__maybe_discard_hp(MaybeHpSlot),
-
-		% XXX release any temp slots holding heap or trail pointers
+	( { CondCodeModel = model_non } ->
+		% We cannot release the stack slots used for the heap pointer
+		% and the trail ticket if the condition can be backtracked
+		% into.
+		code_info__maybe_reset_and_discard_ticket(
+			MaybeTicketSlot, commit, DiscardTicketCode)
+	;
+		code_info__maybe_release_hp(MaybeHpSlot),
+		code_info__maybe_reset_discard_and_release_ticket(
+			MaybeTicketSlot, commit, DiscardTicketCode)
+	),
 
 	code_info__get_instmap(EndCondInstMap),
 	( { instmap__is_unreachable(EndCondInstMap) } ->
-		% If instmap indicates we cannot reach then part,
+		% If the instmap indicates we cannot reach the then part,
 		% do not attempt to generate it (may cause aborts).
 		{ ThenTraceCode = empty },
 		{ ThenCode = empty },
@@ -138,19 +143,10 @@
 	code_info__reset_to_position(BranchStart),
 	code_info__generate_resume_point(ResumePoint, ResumeCode),
 
-	( { CondCodeModel = model_non } ->
-			% We cannot release the stack slots used for
-			% the trail ticket and heap pointer if the
-			% condition can be backtracked into.
-		code_info__maybe_restore_hp(MaybeHpSlot, RestoreHpCode),
-		code_info__maybe_reset_and_pop_ticket(MaybeTicketSlot,
-			undo, RestoreTicketCode)
-	;
-		code_info__maybe_restore_and_discard_hp(MaybeHpSlot,
-			RestoreHpCode),
-		code_info__maybe_reset_and_discard_ticket(MaybeTicketSlot,
-			undo, RestoreTicketCode)
-	),
+		% Restore the heap pointer and solver state if necessary.
+	code_info__maybe_restore_and_release_hp(MaybeHpSlot, RestoreHpCode),
+	code_info__maybe_reset_discard_and_release_ticket(
+		MaybeTicketSlot, undo, RestoreTicketCode),
 
 		% Generate the else branch
 	trace__maybe_generate_internal_event_code(ElseGoal, ElseTraceCode),
@@ -310,8 +306,9 @@
 		code_info__remember_position(AfterNegatedGoal),
 		% The call to reset_ticket(..., commit) here is necessary
 		% in order to properly detect floundering.
-		code_info__maybe_reset_and_discard_ticket(MaybeTicketSlot,
-			commit, DiscardTicketCode),
+		code_info__maybe_release_hp(MaybeHpSlot),
+		code_info__maybe_reset_discard_and_release_ticket(
+			MaybeTicketSlot, commit, DiscardTicketCode),
 		code_info__generate_failure(FailCode),
 			% We want liveness after not(G) to be the same as
 			% after G. Information about what variables are where
@@ -324,9 +321,10 @@
 
 	code_info__set_forward_live_vars(LiveVars),
 
-	code_info__maybe_reset_and_discard_ticket(MaybeTicketSlot, undo,
-		RestoreTicketCode),
-	code_info__maybe_restore_and_discard_hp(MaybeHpSlot, RestoreHpCode),
+		% Restore the heap pointer and solver state if necessary.
+	code_info__maybe_restore_and_release_hp(MaybeHpSlot, RestoreHpCode),
+	code_info__maybe_reset_discard_and_release_ticket(
+		MaybeTicketSlot, undo, RestoreTicketCode),
 
 	{ Code =
 		tree(FlushCode,
cvs diff: Diffing compiler/notes
cvs diff: Diffing doc
cvs diff: Diffing extras
cvs diff: Diffing extras/cgi
cvs diff: Diffing extras/complex_numbers
cvs diff: Diffing extras/complex_numbers/samples
cvs diff: Diffing extras/complex_numbers/tests
cvs diff: Diffing extras/exceptions
cvs diff: Diffing extras/graphics
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/maze
cvs diff: Diffing extras/graphics/samples/pent
cvs diff: Diffing extras/odbc
cvs diff: Diffing extras/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
cvs diff: Diffing extras/trailed_update
cvs diff: Diffing extras/trailed_update/samples
cvs diff: Diffing extras/trailed_update/tests
cvs diff: Diffing library
cvs diff: Diffing lp_solve
cvs diff: Diffing lp_solve/lp_examples
cvs diff: Diffing profiler
cvs diff: Diffing runtime
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 scripts
cvs diff: Diffing tests
cvs diff: Diffing tests/benchmarks
cvs diff: Diffing tests/debugger
cvs diff: Diffing tests/general
cvs diff: Diffing tests/hard_coded
cvs diff: Diffing tests/hard_coded/typeclasses
cvs diff: Diffing tests/invalid
cvs diff: Diffing tests/misc_tests
cvs diff: Diffing tests/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
Index: tests/valid/Mmakefile
===================================================================
RCS file: /home/mercury1/repository/tests/valid/Mmakefile,v
retrieving revision 1.26
diff -u -u -r1.26 Mmakefile
--- Mmakefile	1998/10/28 01:52:01	1.26
+++ Mmakefile	1998/10/29 03:13:19
@@ -6,7 +6,7 @@
 
 #-----------------------------------------------------------------------------#
 
-# please keep this list sorted
+# please keep these lists sorted
 AGC_SOURCES= \
 	agc_graph.m \
 	agc_ho_pred.m \
@@ -22,6 +22,7 @@
 
 OTHER_SOURCES= \
 	compl_unify_bug.m \
+	complex_failure.m \
 	complicated_unify.m \
 	constructor_arg_names.m \
 	dcg_test.m \
@@ -81,6 +82,7 @@
 	pred_with_no_modes.m \
 	qualified_cons_id.m \
 	same_length_2.m \
+	semi_fail_in_non_ite.m \
 	semidet_disj.m \
 	shape_type.m \
 	simplify_bug.m \
@@ -88,16 +90,16 @@
 	some_switch.m \
 	stack_alloc.m \
 	subtype_switch.m \
-	switches.m \
 	switch_detection_bug.m \
 	switch_detection_bug2.m \
+	switches.m \
 	tricky_ite.m \
 	two_pragma_c_codes.m \
 	two_way_unif.m \
 	type_inf_ambig_test.m \
+	unbound_tvar_in_lambda.m \
 	undead_proc.m \
 	uniq_unify.m \
-	unbound_tvar_in_lambda.m \
 	unreachable_code.m \
 	unused_args_test2.m \
 	vn_float.m
@@ -140,6 +142,7 @@
 GRADEFLAGS-agc_unbound_typevars2 = --gc accurate
 GRADEFLAGS-agc_unused_in	= --gc accurate
 MCFLAGS-compl_unify_bug		= -O3
+MCFLAGS-complex_failure		= --use-trail
 MCFLAGS-double_vn		= -O4
 MCFLAGS-explicit_quant		= --halt-at-warn
 MCFLAGS-higher_order_implied_mode = -O-1
@@ -148,6 +151,7 @@
 MCFLAGS-middle_rec_labels	= --middle-rec --no-follow-vars 
 MCFLAGS-mostly_uniq_mode_inf	= --infer-all
 MCFLAGS-pred_with_no_modes	= --infer-all
+MCFLAGS-semi_fail_in_non_ite	= --use-trail
 MCFLAGS-simplify_bug		= -O-1
 MCFLAGS-two_way_unif		= -O-1
 MCFLAGS-type_inf_ambig_test	= --infer-all
Index: tests/valid/complex_failure.m
===================================================================
RCS file: complex_failure.m
diff -N complex_failure.m
--- /dev/null	Mon Nov  2 18:14:52 1998
+++ complex_failure.m	Tue Sep 29 19:43:34 1998
@@ -0,0 +1,128 @@
+% This test case is a copy of tests/general/complex_failure, and tests
+% whether this test case can be compiled with --use-trail; this caused
+% a compiler abort with the 21 September, 1998 version of the compiler.
+%
+% Unfortunately, we cannot just specify --use-trail for complex_failure
+% in tests/general, since that would cause a link error in the usual case
+% that the runtime being linked with is not in a trailing grade.
+
+:- module complex_failure.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module std_util, list, int.
+
+main -->
+	{ solutions(p1, Xs1) },
+	print_list(Xs1),
+	{ solutions(p2, Xs2) },
+	print_list(Xs2),
+	{ solutions(p3, Xs3) },
+	print_list(Xs3).
+
+:- pred p1(int::out) is nondet.
+
+p1(X) :-
+	p(1, X).
+
+:- pred p2(int::out) is nondet.
+
+p2(X) :-
+	p(2, X).
+
+:- pred p3(int::out) is nondet.
+
+p3(X) :-
+	p(3, X).
+
+:- pred p(int::in, int::out) is nondet.
+
+p(A, X) :-
+	% The first if-then-else can hijack the redoip/redofr slots
+	% of p's frame.
+	( if
+		some [B] ( q(A, B) ; r(A, B) )
+	then
+		C is B * 10
+		% s(B, C)
+	else
+		C is A * 10
+		% s(A, C)
+	),
+	% The second if-then-else cannot hijack the redoip/redofr slots
+	% of p's frame, since this may not be (and usually won't be)
+	% on top when execution gets here.
+	( if
+		some [D] ( q(C, D) ; r(C, D) )
+	then
+		s(D, X)
+	else
+		s(C, X)
+	).
+
+:- pred q(int::in, int::out) is nondet.
+
+q(1, 15).
+q(1, 16).
+q(2, 25).
+q(2, 26).
+q(3, 35).
+
+q(150, 660).
+q(161, 661).
+q(281, 662).
+
+:- pred r(int::in, int::out) is nondet.
+
+r(1, 18).
+r(1, 19).
+r(2, 28).
+r(2, 29).
+r(3, 38).
+r(260, 690).
+r(370, 698).
+
+:- pred s(int::in, int::out) is nondet.
+
+s(F, G) :-
+	F < 695,
+	(
+		G is 10 * F
+	;
+		G is 10 * F + 1
+	).
+
+:- pred print_list(list(int), io__state, io__state).
+:- mode print_list(in, di, uo) is det.
+
+print_list(Xs) -->
+	(
+		{ Xs = [] }
+	->
+		io__write_string("[]\n")
+	;
+		io__write_string("["),
+		print_list_2(Xs),
+		io__write_string("]\n")
+	).
+
+:- pred print_list_2(list(int), io__state, io__state).
+:- mode print_list_2(in, di, uo) is det.
+
+print_list_2([]) --> [].
+print_list_2([X|Xs]) --> 
+	io__write_int(X),
+	(
+		{ Xs = [] }
+	->
+		[]
+	;
+		io__write_string(", "),
+		print_list_2(Xs)
+	).
Index: tests/valid/semi_fail_in_non_ite.m
===================================================================
RCS file: semi_fail_in_non_ite.m
diff -N semi_fail_in_non_ite.m
--- /dev/null	Mon Nov  2 18:14:52 1998
+++ semi_fail_in_non_ite.m	Tue Sep 29 19:49:59 1998
@@ -0,0 +1,129 @@
+% This test case is a copy of tests/general/semi_fail_in_non_ite, and tests
+% whether this test case can be compiled with --use-trail; this caused
+% a compiler abort with the 21 September, 1998 version of the compiler.
+%
+% Unfortunately, we cannot just specify --use-trail for semi_fail_in_non_ite
+% in tests/general, since that would cause a link error in the usual case
+% that the runtime being linked with is not in a trailing grade.
+
+:- module semi_fail_in_non_ite.
+
+:- interface.
+
+:- import_module io.
+
+:- pred main(io__state::di, io__state::uo) is det.
+
+:- implementation.
+
+:- import_module std_util, list, int.
+
+main -->
+	{ solutions(p1, Xs1) },
+	print_list(Xs1).
+
+:- pred p1(int::out) is nondet.
+
+p1(X) :-
+	p(1, X).
+
+:- pred p2(int::out) is nondet.
+
+p2(X) :-
+	p(2, X).
+
+:- pred p3(int::out) is nondet.
+
+p3(X) :-
+	p(3, X).
+
+:- pred p(int::in, int::out) is nondet.
+
+p(A, X) :-
+	% The first if-then-else can hijack the redoip/redofr slots
+	% of p's frame.
+	( if
+		some [B] ( q(A, B) ; r(A, B) )
+	then
+		C is B * 10
+		% s(B, C)
+	else
+		C is A * 10
+		% s(A, C)
+	),
+	% The second if-then-else cannot hijack the redoip/redofr slots
+	% of p's frame, since this may not be (and usually won't be)
+	% on top when execution gets here.
+	( if
+		some [D] (
+			q(C, D)
+		;
+			C = 260,
+			D = 690
+		)
+	then
+		s(D, X)
+	else
+		s(C, X)
+	).
+
+:- pred q(int::in, int::out) is nondet.
+
+q(1, 15).
+q(1, 16).
+q(2, 25).
+q(2, 26).
+q(3, 35).
+
+q(150, 660).
+q(161, 661).
+q(281, 662).
+
+:- pred r(int::in, int::out) is nondet.
+
+r(1, 18).
+r(1, 19).
+r(2, 28).
+r(2, 29).
+r(3, 38).
+r(260, 690).
+r(370, 698).
+
+:- pred s(int::in, int::out) is nondet.
+
+s(F, G) :-
+	F < 695,
+	(
+		G is 10 * F
+	;
+		G is 10 * F + 1
+	).
+
+:- pred print_list(list(int), io__state, io__state).
+:- mode print_list(in, di, uo) is det.
+
+print_list(Xs) -->
+	(
+		{ Xs = [] }
+	->
+		io__write_string("[]\n")
+	;
+		io__write_string("["),
+		print_list_2(Xs),
+		io__write_string("]\n")
+	).
+
+:- pred print_list_2(list(int), io__state, io__state).
+:- mode print_list_2(in, di, uo) is det.
+
+print_list_2([]) --> [].
+print_list_2([X|Xs]) --> 
+	io__write_int(X),
+	(
+		{ Xs = [] }
+	->
+		[]
+	;
+		io__write_string(", "),
+		print_list_2(Xs)
+	).
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing trial
cvs diff: Diffing util



More information about the developers mailing list