for review: new method of handling failures, part 4b of 6

Zoltan Somogyi zs at cs.mu.OZ.AU
Thu Jul 2 16:32:13 AEST 1998


 %---------------------------------------------------------------------------%
 
-code_info__failure_is_direct_branch(CodeAddr) -->
-	code_info__top_failure_cont(FailureCont),
-	{ FailureCont = failure_cont(ContInfo, FailureMap) },
-	{ code_info__fail_cont_is_known(ContInfo) },
-	code_info__pick_matching_resume_addr(FailureMap, CodeAddr).
-
 code_info__generate_failure(Code) -->
-	code_info__top_failure_cont(FailureCont),
-	{ FailureCont = failure_cont(ContInfo, FailureMap) },
+	code_info__get_fail_info(FailInfo),
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _) },
 	(
-		{ code_info__fail_cont_is_known(ContInfo) }
-	->
+		{ ResumeKnown = resume_point_known },
+		{ stack__top_det(ResumePoints, TopResumePoint) },
 		(
-			code_info__pick_matching_resume_addr(FailureMap,
+			code_info__pick_matching_resume_addr(TopResumePoint,
 				FailureAddress0)
 		->
 			{ FailureAddress = FailureAddress0 },
 			{ PlaceCode = empty }
 		;
-			{ code_info__pick_first_resume_point(FailureMap,
+			{ code_info__pick_first_resume_point(TopResumePoint,
 				Map, FailureAddress) },
 			{ map__to_assoc_list(Map, AssocList) },
-			code_info__grab_code_info(CodeInfo),
+			code_info__remember_position(CurPos),
 			code_info__place_vars(AssocList, PlaceCode),
-			code_info__slap_code_info(CodeInfo)
+			code_info__reset_to_position(CurPos)
 		),
 		{ BranchCode = node([goto(FailureAddress) - "fail"]) },
 		{ Code = tree(PlaceCode, BranchCode) }
 	;
+		{ ResumeKnown = resume_point_unknown },
 		{ Code = node([goto(do_redo) - "fail"]) }
 	).
 
 code_info__fail_if_rval_is_false(Rval0, Code) -->
-	code_info__top_failure_cont(FailureCont),
-	{ FailureCont = failure_cont(ContInfo, FailureMap) },
+	code_info__get_fail_info(FailInfo),
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _) },
 	(
-		{ code_info__fail_cont_is_known(ContInfo) }
-	->
+		{ ResumeKnown = resume_point_known },
+		{ stack__top_det(ResumePoints, TopResumePoint) },
 		(
-			code_info__pick_matching_resume_addr(FailureMap,
+			code_info__pick_matching_resume_addr(TopResumePoint,
 				FailureAddress0)
 		->
 				% We branch away if the test *fails*
@@ -1689,19 +1494,19 @@
 					"Test for failure"
 			]) }
 		;
-			{ code_info__pick_first_resume_point(FailureMap,
+			{ code_info__pick_first_resume_point(TopResumePoint,
 				Map, FailureAddress) },
 			{ map__to_assoc_list(Map, AssocList) },
 			code_info__get_next_label(SuccessLabel),
-			code_info__grab_code_info(CodeInfo),
+			code_info__remember_position(CurPos),
 			code_info__place_vars(AssocList, PlaceCode),
-			code_info__slap_code_info(CodeInfo),
+			code_info__reset_to_position(CurPos),
 			{ SuccessAddress = label(SuccessLabel) },
 				% We branch away if the test *fails*,
-				% therefore we branch around the code
-				% that moves variables to their failure
-				% locations and branches away
-				% if the test succeeds
+				% therefore if the test succeeds, we branch
+				% around the code that moves variables to
+				% their failure locations and branches away
+				% to the failure continuation
 			{ TestCode = node([
 				if_val(Rval0, SuccessAddress) -
 					"Test for failure"
@@ -1715,213 +1520,600 @@
 			{ Code = tree(TestCode, tree(PlaceCode, TailCode)) }
 		)
 	;
-		{ FailureAddress = do_redo },
-			% We branch away if the test *fails*
-		{ code_util__neg_rval(Rval0, Rval) },
-		{ Code = node([
-			if_val(Rval, FailureAddress) -
-				"Test for failure"
-		]) }
+		{ ResumeKnown = resume_point_unknown },
+			% We branch away if the test *fails*
+		{ code_util__neg_rval(Rval0, Rval) },
+		{ Code = node([
+			if_val(Rval, do_redo) -
+				"Test for failure"
+		]) }
+	).
+
+%---------------------------------------------------------------------------%
+
+code_info__failure_is_direct_branch(CodeAddr) -->
+	code_info__get_fail_info(FailInfo),
+	{ FailInfo = fail_info(ResumePoints, resume_point_known, _) },
+	{ stack__top(ResumePoints, TopResumePoint) },
+	code_info__pick_matching_resume_addr(TopResumePoint, CodeAddr).
+
+code_info__may_use_nondet_tailcall(MayTailCall) -->
+	code_info__get_fail_info(FailInfo),
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, _) },
+	(
+		{ ResumeKnown = resume_point_known },
+		{ stack__top_det(ResumePoints, TopResumePoint) },
+		{ TopResumePoint = stack_only(_, do_fail) }
+	->
+		{ MayTailCall = yes }
+	;
+		{ MayTailCall = no }
+	).
+
+%---------------------------------------------------------------------------%
+
+	% See whether the current locations of variables match the locations
+	% associated with any of the options in the given failure map.
+	% If yes, return the code_addr of that option.
+
+:- pred code_info__pick_matching_resume_addr(resume_point_info::in,
+	code_addr::out, code_info::in, code_info::out) is semidet.
+
+code_info__pick_matching_resume_addr(ResumeMaps, Addr) -->
+	code_info__variable_locations(Locations),
+	{
+		ResumeMaps = orig_only(Map1, Addr1),
+		( code_info__match_resume_loc(Map1, Locations) ->
+			Addr = Addr1
+		;
+			fail
+		)
+	;
+		ResumeMaps = stack_only(Map1, Addr1),
+		( code_info__match_resume_loc(Map1, Locations) ->
+			Addr = Addr1
+		;
+			fail
+		)
+	;
+		ResumeMaps = orig_and_stack(Map1, Addr1, Map2, Addr2),
+		( code_info__match_resume_loc(Map1, Locations) ->
+			Addr = Addr1
+		; code_info__match_resume_loc(Map2, Locations) ->
+			Addr = Addr2
+		;
+			fail
+		)
+	;
+		ResumeMaps = stack_and_orig(Map1, Addr1, Map2, Addr2),
+		( code_info__match_resume_loc(Map1, Locations) ->
+			Addr = Addr1
+		; code_info__match_resume_loc(Map2, Locations) ->
+			Addr = Addr2
+		;
+			fail
+		)
+	}.
+
+:- pred code_info__match_resume_loc(resume_map::in, resume_map::in) is semidet.
+
+code_info__match_resume_loc(Map, Locations0) :-
+	map__keys(Map, KeyList),
+	set__list_to_set(KeyList, Keys),
+	map__select(Locations0, Keys, Locations),
+	map__to_assoc_list(Locations, List),
+	\+ (
+		list__member(Thingy, List),
+		\+ (
+			Thingy = Var - Actual,
+			map__search(Map, Var, Rvals),
+			set__subset(Rvals, Actual)
+		)
+	).
+
+:- pred code_info__pick_first_resume_point(resume_point_info::in,
+	resume_map::out, code_addr::out) is det.
+
+code_info__pick_first_resume_point(orig_only(Map, Addr), Map, Addr).
+code_info__pick_first_resume_point(stack_only(Map, Addr), Map, Addr).
+code_info__pick_first_resume_point(orig_and_stack(Map, Addr, _, _), Map, Addr).
+code_info__pick_first_resume_point(stack_and_orig(Map, Addr, _, _), Map, Addr).
+
+:- pred code_info__pick_stack_resume_point(resume_point_info::in,
+	resume_map::out, code_addr::out) is det.
+
+code_info__pick_stack_resume_point(ResumePoint, Map, Addr) :-
+	( code_info__maybe_pick_stack_resume_point(ResumePoint, Map1, Addr1) ->
+		Map = Map1,
+		Addr = Addr1
+	;
+		error("no stack resume point")
+	).
+
+:- pred code_info__maybe_pick_stack_resume_point(resume_point_info::in,
+	resume_map::out, code_addr::out) is semidet.
+
+code_info__maybe_pick_stack_resume_point(stack_only(Map, Addr), Map, Addr).
+code_info__maybe_pick_stack_resume_point(orig_and_stack(_, _, Map, Addr),
+	Map, Addr).
+code_info__maybe_pick_stack_resume_point(stack_and_orig(Map, Addr, _, _),
+	Map, Addr).
+
+%---------------------------------------------------------------------------%
+
+code_info__produce_vars(Vars, Map, Code) -->
+	{ set__to_sorted_list(Vars, VarList) },
+	code_info__produce_vars_2(VarList, Map, Code).
+
+:- pred code_info__produce_vars_2(list(var)::in,
+	map(var, set(rval))::out,
+	code_tree::out, code_info::in, code_info::out) is det.
+
+code_info__produce_vars_2([], Map, empty) -->
+	{ map__init(Map) }.
+code_info__produce_vars_2([V | Vs], Map, Code) -->
+	code_info__produce_vars_2(Vs, Map0, Code0),
+	code_info__produce_variable_in_reg_or_stack(V, Code1, Rval),
+	{ set__singleton_set(Rvals, Rval) },
+	{ map__set(Map0, V, Rvals, Map) },
+	{ Code = tree(Code0, Code1) }.
+
+code_info__flush_resume_vars_to_stack(Code) -->
+	code_info__get_fail_info(FailInfo),
+	{ FailInfo = fail_info(ResumePointStack, _, _) },
+	{ stack__top_det(ResumePointStack, ResumePoint) },
+	{ code_info__pick_stack_resume_point(ResumePoint, StackMap, _) },
+	{ map__to_assoc_list(StackMap, StackLocs) },
+	code_info__place_vars(StackLocs, Code).
+
+%---------------------------------------------------------------------------%
+
+:- pred code_info__init_fail_info(code_model::in, maybe(set(var))::in,
+	resume_point_info::out, code_info::in, code_info::out) is det.
+
+code_info__init_fail_info(CodeModel, MaybeFailVars, ResumePoint) -->
+	(
+		{ CodeModel = model_det },
+		code_info__get_next_label(ResumeLabel),
+		{ ResumeAddress = label(ResumeLabel) },
+		{ ResumeKnown = resume_point_unknown },
+		{ CurfrMaxfr = may_be_different }
+	;
+		{ CodeModel = model_semi },
+			% The resume point for this label
+			% will be part of the procedure epilog.
+		code_info__get_next_label(ResumeLabel),
+		{ ResumeAddress = label(ResumeLabel) },
+		{ ResumeKnown = resume_point_known },
+		{ CurfrMaxfr = may_be_different }
+	;
+		{ CodeModel = model_non },
+		( { MaybeFailVars = yes(_) } ->
+			code_info__get_next_label(ResumeLabel),
+			{ ResumeAddress = label(ResumeLabel) }
+		;
+			{ ResumeAddress = do_fail }
+		),
+		{ ResumeKnown = resume_point_known },
+		{ CurfrMaxfr = must_be_equal }
+	),
+	( { MaybeFailVars = yes(FailVars) } ->
+		code_info__get_stack_slots(StackSlots),
+		{ map__select(StackSlots, FailVars, StackMap0) },
+		{ map__to_assoc_list(StackMap0, StackList0) },
+		{ code_info__make_singleton_sets(StackList0, StackList) },
+		{ map__from_assoc_list(StackList, StackMap) }
+	;
+		{ map__init(StackMap) }
+	),
+	{ ResumePoint = stack_only(StackMap, ResumeAddress) },
+	{ stack__init(ResumeStack0) },
+	{ stack__push(ResumeStack0, ResumePoint, ResumeStack) },
+	{ FailInfo = fail_info(ResumeStack, ResumeKnown, CurfrMaxfr) },
+	code_info__set_fail_info(FailInfo).
+
+%---------------------------------------------------------------------------%
+
+code_info__make_resume_point(ResumeVars, ResumeLocs, FullMap, ResumePoint) -->
+	code_info__get_stack_slots(StackSlots),
+	{ map__select(FullMap, ResumeVars, OrigMap) },
+	(
+		{ ResumeLocs = orig_only },
+		code_info__get_next_label(OrigLabel),
+		{ OrigAddr = label(OrigLabel) },
+		{ ResumePoint = orig_only(OrigMap, OrigAddr) }
+	;
+		{ ResumeLocs = stack_only },
+		{ map__select(StackSlots, ResumeVars, StackMap0) },
+		{ map__to_assoc_list(StackMap0, StackList0) },
+		{ code_info__make_singleton_sets(StackList0, StackList) },
+		{ map__from_assoc_list(StackList, StackMap) },
+		code_info__get_next_label(StackLabel),
+		{ StackAddr = label(StackLabel) },
+		{ ResumePoint = stack_only(StackMap, StackAddr) }
+	;
+		{ ResumeLocs = orig_and_stack },
+		{ map__select(StackSlots, ResumeVars, StackMap0) },
+		{ map__to_assoc_list(StackMap0, StackList0) },
+		{ code_info__make_singleton_sets(StackList0, StackList) },
+		{ map__from_assoc_list(StackList, StackMap) },
+		code_info__get_next_label(OrigLabel),
+		{ OrigAddr = label(OrigLabel) },
+		code_info__get_next_label(StackLabel),
+		{ StackAddr = label(StackLabel) },
+		{ ResumePoint = orig_and_stack(OrigMap, OrigAddr,
+			StackMap, StackAddr) }
+	;
+		{ ResumeLocs = stack_and_orig },
+		{ map__select(StackSlots, ResumeVars, StackMap0) },
+		{ map__to_assoc_list(StackMap0, StackList0) },
+		{ code_info__make_singleton_sets(StackList0, StackList) },
+		{ map__from_assoc_list(StackList, StackMap) },
+		code_info__get_next_label(StackLabel),
+		{ StackAddr = label(StackLabel) },
+		code_info__get_next_label(OrigLabel),
+		{ OrigAddr = label(OrigLabel) },
+		{ ResumePoint = stack_and_orig(StackMap, StackAddr,
+			OrigMap, OrigAddr) }
+	).
+
+:- pred code_info__make_singleton_sets(assoc_list(var, lval)::in,
+	assoc_list(var, set(rval))::out) is det.
+
+code_info__make_singleton_sets([], []).
+code_info__make_singleton_sets([V - L | Rest0], [V - Rs | Rest]) :-
+	set__singleton_set(Rs, lval(L)),
+	code_info__make_singleton_sets(Rest0, Rest).
+
+%---------------------------------------------------------------------------%
+
+	% The code we generate for a resumption point looks like this:
+	%
+	% label(StackLabel)
+	% <assume variables are where StackMap says they are>
+	% <copy variables to their locations according to OrigMap>
+	% label(OrigLabel)
+	% <assume variables are where OrigMap says they are>
+	%
+	% Failures at different points may cause control to arrive at
+	% the resumption point via either label, which is why the last
+	% line is necessary.
+	%
+	% The idea is that failures from other procedures will go to
+	% StackLabel, and that failures from this procedure while
+	% everything is in its original place will go to OrigLabel.
+	% Failures from this procedure where not everything is in its
+	% original place can go to either, after moving the resume variables
+	% to the places where the label expects them.
+	%
+	% The above layout (stack, then orig) is the most common. However,
+	% liveness.m may decide that one or other of the two labels will
+	% never be referred to (e.g. because there are no calls inside
+	% the range of effect of the resumption point or because a call
+	% follows immediately after the establishment of the resumption
+	% point), or that it would be more efficient to put the two labels
+	% in the other order (e.g. because the code after the resumption point
+	% needs most of the variables in their stack slots).
+
+code_info__generate_resume_point(ResumePoint, Code) -->
+	(
+		{ ResumePoint = orig_only(Map1, Addr1) },
+		{ extract_label_from_code_addr(Addr1, Label1) },
+		{ Code = node([
+			label(Label1) -
+				"orig only failure continuation"
+		]) },
+		code_info__set_var_locations(Map1)
+	;
+		{ ResumePoint = stack_only(Map1, Addr1) },
+		{ extract_label_from_code_addr(Addr1, Label1) },
+		{ Code = node([
+			label(Label1) -
+				"stack only failure continuation"
+		]) },
+		code_info__set_var_locations(Map1)
+	;
+		{ ResumePoint = stack_and_orig(Map1, Addr1, Map2, Addr2) },
+		{ extract_label_from_code_addr(Addr1, Label1) },
+		{ extract_label_from_code_addr(Addr2, Label2) },
+		{ Label1Code = node([
+			label(Label1) -
+				"stack failure continuation before orig"
+		]) },
+		code_info__set_var_locations(Map1),
+		{ map__to_assoc_list(Map2, AssocList2) },
+		code_info__place_resume_vars(AssocList2, PlaceCode),
+		{ Label2Code = node([
+			label(Label2) -
+				"orig failure continuation after stack"
+		]) },
+		code_info__set_var_locations(Map2),
+		{ Code = tree(Label1Code, tree(PlaceCode, Label2Code)) }
+	;
+		{ ResumePoint = orig_and_stack(Map1, Addr1, Map2, Addr2) },
+		{ extract_label_from_code_addr(Addr1, Label1) },
+		{ extract_label_from_code_addr(Addr2, Label2) },
+		{ Label1Code = node([
+			label(Label1) -
+				"orig failure continuation before stack"
+		]) },
+		code_info__set_var_locations(Map1),
+		{ map__to_assoc_list(Map2, AssocList2) },
+		code_info__place_resume_vars(AssocList2, PlaceCode),
+		{ Label2Code = node([
+			label(Label2) -
+				"stack failure continuation after orig"
+		]) },
+		code_info__set_var_locations(Map2),
+		{ Code = tree(Label1Code, tree(PlaceCode, Label2Code)) }
+	).
+
+:- pred extract_label_from_code_addr(code_addr::in, label::out) is det.
+
+extract_label_from_code_addr(CodeAddr, Label) :-
+	( CodeAddr = label(Label0) ->
+		Label = Label0
+	;
+		error("code_info__generate_resume_setup: non-label!")
 	).
 
-%---------------------------------------------------------------------------%
+:- pred code_info__place_resume_vars(assoc_list(var, set(rval))::in,
+	code_tree::out, code_info::in, code_info::out) is det.
 
-	% See whether the current locations of variables match the locations
-	% associated with any of the options in the given failure map.
-	% If yes, return the code_addr of that option.
+code_info__place_resume_vars([], empty) --> [].
+code_info__place_resume_vars([Var - TargetSet | Rest], Code) -->
+	{ set__to_sorted_list(TargetSet, Targets) },
+	code_info__place_resume_var(Var, Targets, FirstCode),
+	{ Code = tree(FirstCode, RestCode) },
+	code_info__place_resume_vars(Rest, RestCode).
 
-:- pred code_info__pick_matching_resume_addr(resume_maps, code_addr,
-	code_info, code_info).
-:- mode code_info__pick_matching_resume_addr(in, out, in, out) is semidet.
+:- pred code_info__place_resume_var(var::in, list(rval)::in, code_tree::out,
+	code_info::in, code_info::out) is det.
 
-code_info__pick_matching_resume_addr(ResumeMaps, Addr) -->
-	code_info__variable_locations(Locations),
-	{
-		ResumeMaps = orig_only(Map1, Addr1),
-		( code_info__match_resume_loc(Map1, Locations) ->
-			Addr = Addr1
-		;
-			fail
-		)
-	;
-		ResumeMaps = stack_only(Map1, Addr1),
-		( code_info__match_resume_loc(Map1, Locations) ->
-			Addr = Addr1
-		;
-			fail
-		)
-	;
-		ResumeMaps = orig_and_stack(Map1, Addr1, Map2, Addr2),
-		( code_info__match_resume_loc(Map1, Locations) ->
-			Addr = Addr1
-		; code_info__match_resume_loc(Map2, Locations) ->
-			Addr = Addr2
-		;
-			fail
-		)
+code_info__place_resume_var(_Var, [], empty) --> [].
+code_info__place_resume_var(Var, [Target | Targets], Code) -->
+	( { Target = lval(TargetLval) } ->
+		code_info__place_var(Var, TargetLval, FirstCode)
 	;
-		ResumeMaps = stack_and_orig(Map1, Addr1, Map2, Addr2),
-		( code_info__match_resume_loc(Map1, Locations) ->
-			Addr = Addr1
-		; code_info__match_resume_loc(Map2, Locations) ->
-			Addr = Addr2
-		;
-			fail
-		)
-	}.
+		{ error("code_info__place_resume_var: not lval") }
+	),
+	{ Code = tree(FirstCode, RestCode) },
+	code_info__place_resume_var(Var, Targets, RestCode).
 
-:- pred code_info__match_resume_loc(resume_map, resume_map).
-:- mode code_info__match_resume_loc(in, in) is semidet.
+	% Reset the code generator's database of what is where.
+	% Remember that the variables in the map are available in their
+	% associated rvals; forget about all other variables.
 
-code_info__match_resume_loc(Map, Locations0) :-
-	map__keys(Map, KeyList),
-	set__list_to_set(KeyList, Keys),
-	map__select(Locations0, Keys, Locations),
-	map__to_assoc_list(Locations, List),
-	\+ (
-		list__member(Thingy, List),
-		\+ (
-			Thingy = Var - Actual,
-			map__search(Map, Var, Rvals),
-			set__subset(Rvals, Actual)
-		)
-	).
+:- pred code_info__set_var_locations(resume_map::in,
+	code_info::in, code_info::out) is det.
 
-	% Find the first label that will be generated for the
-	% given failure continuation based on the scheme used by
-	% code_info__generate_failure_cont.
+code_info__set_var_locations(Map) -->
+	{ map__to_assoc_list(Map, List0) },
+	{ code_info__flatten_varlval_list(List0, List) },
+	code_info__get_exprn_info(Exprn0),
+	{ code_exprn__reinit_state(List, Exprn0, Exprn) },
+	code_info__set_exprn_info(Exprn).
 
-:- pred code_info__find_first_resume_label(failure_cont, code_addr).
-:- mode code_info__find_first_resume_label(in, out) is det.
+:- pred code_info__flatten_varlval_list(assoc_list(var, set(rval))::in,
+	assoc_list(var, rval)::out) is det.
 
-code_info__find_first_resume_label(FailureCont, Address) :-
-	FailureCont = failure_cont(ContInfo, FailMap),
-	(
-		ContInfo = nondet(_, MaybeRedoLabel),
-		MaybeRedoLabel = yes(RedoLabel)
-	->
-		Address = label(RedoLabel)
-	;
-		code_info__pick_first_resume_point(FailMap, _, Address)
-	).
+code_info__flatten_varlval_list([], []).
+code_info__flatten_varlval_list([V - Rvals | Rest0], All) :-
+	code_info__flatten_varlval_list(Rest0, Rest),
+	set__to_sorted_list(Rvals, RvalList),
+	code_info__flatten_varlval_list_2(RvalList, V, Rest1),
+	list__append(Rest1, Rest, All).
 
-:- pred code_info__pick_first_resume_point(resume_maps, resume_map, code_addr).
-:- mode code_info__pick_first_resume_point(in, out, out) is det.
+:- pred code_info__flatten_varlval_list_2(list(rval)::in, var::in,
+	assoc_list(var, rval)::out) is det.
 
-code_info__pick_first_resume_point(orig_only(Map, Addr), Map, Addr).
-code_info__pick_first_resume_point(stack_only(Map, Addr), Map, Addr).
-code_info__pick_first_resume_point(orig_and_stack(Map, Addr, _, _), Map, Addr).
-code_info__pick_first_resume_point(stack_and_orig(Map, Addr, _, _), Map, Addr).
+code_info__flatten_varlval_list_2([], _V, []).
+code_info__flatten_varlval_list_2([R | Rs], V, [V - R | Rest]) :-
+	code_info__flatten_varlval_list_2(Rs, V, Rest).
 
-:- pred code_info__pick_last_resume_point(resume_maps, resume_map, code_addr).
-:- mode code_info__pick_last_resume_point(in, out, out) is det.
+code_info__resume_point_vars(ResumePoint, Vars) :-
+	code_info__pick_first_resume_point(ResumePoint, ResumeMap, _),
+	map__keys(ResumeMap, Vars).
 
-code_info__pick_last_resume_point(orig_only(Map, Addr), Map, Addr).
-code_info__pick_last_resume_point(stack_only(Map, Addr), Map, Addr).
-code_info__pick_last_resume_point(orig_and_stack( _, _, Map, Addr), Map, Addr).
-code_info__pick_last_resume_point(stack_and_orig( _, _, Map, Addr), Map, Addr).
-
-:- pred code_info__pick_stack_resume_point(resume_maps, resume_map, code_addr).
-:- mode code_info__pick_stack_resume_point(in, out, out) is det.
-
-code_info__pick_stack_resume_point(orig_only(_, _), _, _) :-
-	error("no stack resume point").
-code_info__pick_stack_resume_point(stack_only(Map, Addr), Map, Addr).
-code_info__pick_stack_resume_point(orig_and_stack(_, _, Map, Addr), Map, Addr).
-code_info__pick_stack_resume_point(stack_and_orig(Map, Addr, _, _), Map, Addr).
+code_info__resume_point_stack_addr(ResumePoint, StackAddr) :-
+	code_info__pick_stack_resume_point(ResumePoint, _, StackAddr).
 
 %---------------------------------------------------------------------------%
 
-code_info__unset_failure_cont(Code) -->
-	code_info__flush_resume_vars_to_stack(Code),
-	code_info__top_failure_cont(FailureCont0),
-	{ FailureCont0 = failure_cont(ContInfo0, FailureMap) },
-	code_info__pop_failure_cont,
-	{
-		ContInfo0 = semidet,
-		error("unset of semidet failure cont")
-	;
-		ContInfo0 = nondet(_, MaybeRedoLabel),
-		ContInfo = nondet(unknown, MaybeRedoLabel)
-	},
-	{ FailureCont = failure_cont(ContInfo, FailureMap) },
-	code_info__push_failure_cont(FailureCont).
+:- type det_commit_info
+	--->	det_commit_info(
+			maybe(lval),		% location of saved maxfr
+			maybe(pair(lval))	% location of saved ticket
+						% counter and trail pointer
+		).
 
-code_info__flush_resume_vars_to_stack(Code) -->
-	code_info__top_failure_cont(FailureCont0),
-	{ FailureCont0 = failure_cont(_, FailureMap) },
-	{ code_info__pick_stack_resume_point(FailureMap, StackMap, _) },
-	{ map__to_assoc_list(StackMap, StackLocs) },
-	code_info__place_resume_vars(StackLocs, Code).
+code_info__generate_det_pre_commit(DetCommitInfo, Code) -->
+	code_info__get_fail_info(FailInfo0),
+	{ FailInfo0 = fail_info(_, _, CurfrMaxfr) },
+	(
+		{ CurfrMaxfr = may_be_different },
+		code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
+		{ SaveMaxfrCode = node([
+			assign(MaxfrSlot, lval(maxfr))
+				- "save the value of maxfr"
+		]) },
+		{ MaybeMaxfrSlot = yes(MaxfrSlot) }
+	;
+		{ CurfrMaxfr = must_be_equal },
+		{ SaveMaxfrCode = empty },
+		{ MaybeMaxfrSlot = no }
+	),
+	code_info__maybe_save_trail_info(MaybeTrailSlots, SaveTrailCode),
+	{ DetCommitInfo = det_commit_info(MaybeMaxfrSlot, MaybeTrailSlots) },
+	{ Code = tree(SaveMaxfrCode, SaveTrailCode) }.
 
-code_info__may_use_nondet_tailcall(MayTailCall) -->
-	code_info__top_failure_cont(FailureCont),
-	{ FailureCont = failure_cont(ContInfo, FailureMap) },
+code_info__generate_det_commit(DetCommitInfo, Code) -->
+	{ DetCommitInfo = det_commit_info(MaybeMaxfrSlot, MaybeTrailSlots) },
 	(
-		{ code_info__fail_cont_is_known(ContInfo) },
-		{ FailureMap = stack_only(_, do_fail) }
-	->
-		{ MayTailCall = yes }
+		{ MaybeMaxfrSlot = yes(MaxfrSlot) },
+		{ RestoreMaxfrCode = node([
+			assign(maxfr, lval(MaxfrSlot))
+				- "restore the value of maxfr - perform commit"
+		]) },
+		code_info__release_temp_slot(MaxfrSlot)
 	;
-		{ MayTailCall = no }
-	).
+		{ MaybeMaxfrSlot = no },
+		{ RestoreMaxfrCode = node([
+			assign(maxfr, lval(curfr))
+				- "restore the value of maxfr - perform commit"
+		]) }
+	),
+	code_info__maybe_restore_trail_info(MaybeTrailSlots,
+		CommitTrailCode, _),
+	{ Code = tree(RestoreMaxfrCode, CommitTrailCode) }.
 
 %---------------------------------------------------------------------------%
 
-code_info__do_soft_cut(TheFrame, Code, ContCode) -->
-	code_info__top_failure_cont(FailureCont),
-	{ FailureCont = failure_cont(ContInfo, _) },
+:- type semi_commit_info
+	--->	semi_commit_info(
+			fail_info,		% fail_info on entry
+			resume_point_info,
+			commit_hijack_info,
+			maybe(pair(lval))	% location of saved ticket
+						% counter and trail pointer
+		).
+
+:- type commit_hijack_info
+	--->	commit_quarter_hijack
+	;	commit_half_hijack(
+			lval		% the stack slot in which we saved
+					% the value of the hijacked redoip
+		)
+	;	commit_full_hijack(
+			lval,		% the stack slot in which we saved
+					% the value of the hijacked redoip
+			lval,		% the stack slot in which we saved
+					% the value of the hijacked redofr
+			lval		% the stack slot in which we saved
+					% the value of maxfr
+		).
+
+code_info__generate_semi_pre_commit(SemiCommitInfo, Code) -->
+	code_info__get_fail_info(FailInfo0),
+	{ FailInfo0 = fail_info(ResumePoints0, ResumeKnown, CurfrMaxfr) },
+	{ stack__top_det(ResumePoints0, TopResumePoint) },
+	code_info__clone_resume_point(TopResumePoint, NewResumePoint),
+	{ stack__push(ResumePoints0, NewResumePoint, ResumePoints) },
+	{ FailInfo = fail_info(ResumePoints, ResumeKnown, CurfrMaxfr) },
+	code_info__set_fail_info(FailInfo),
+
+	{ code_info__pick_stack_resume_point(NewResumePoint, _, StackLabel) },
+	{ StackLabelConst = const(code_addr_const(StackLabel)) },
 	(
-		{ code_info__fail_cont_is_known(ContInfo) }
-	->
-		{ code_info__find_first_resume_label(FailureCont, Address) }
+		{ CurfrMaxfr = may_be_different },
+		code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
+			RedoipSlot),
+		code_info__acquire_temp_slot(lval(redofr(lval(maxfr))),
+			RedofrSlot),
+		code_info__acquire_temp_slot(lval(maxfr),
+			MaxfrSlot),
+		{ HijackInfo = commit_full_hijack(RedoipSlot, RedofrSlot,
+			MaxfrSlot) },
+		{ HijackCode = node([
+			assign(RedoipSlot, lval(redoip(lval(maxfr))))
+				- "prepare for full commit hijack",
+			assign(RedofrSlot, lval(redofr(lval(maxfr))))
+				- "prepare for full commit hijack",
+			assign(MaxfrSlot, lval(maxfr))
+				- "prepare for full commit hijack",
+			assign(redofr(lval(maxfr)), lval(curfr))
+				- "hijack the redofr slot",
+			assign(redoip(lval(maxfr)), StackLabelConst)
+				- "hijack the redoip slot"
+		]) }
 	;
-			% If the newly uncovered cont is unknown then
-			% we must have created a new frame before the
-			% condition which we no longer need, so we
-			% set its redoip to do_fail.
-		{ Address = do_fail }
+		{ CurfrMaxfr = must_be_equal },
+		(
+			{ ResumeKnown = resume_point_unknown },
+			code_info__acquire_temp_slot(lval(redoip(lval(curfr))),
+				RedoipSlot),
+			{ HijackInfo = commit_half_hijack(RedoipSlot) },
+			{ HijackCode = node([
+				assign(RedoipSlot, lval(redoip(lval(curfr))))
+					- "prepare for half commit hijack",
+				assign(redoip(lval(curfr)), StackLabelConst)
+					- "hijack the redofr slot"
+			]) }
+		;
+			{ ResumeKnown = resume_point_known },
+			{ HijackInfo = commit_quarter_hijack },
+			{ HijackCode = node([
+				assign(redoip(lval(curfr)), StackLabelConst)
+					- "hijack the redofr slot"
+			]) }
+		)
 	),
-	code_info__get_globals(Globals),
-	{ globals__lookup_bool_option(Globals, use_trail, UseTrail) },
-	( { UseTrail = yes } ->
-		code_info__get_next_label(ContLabel),
-		{ ContAddress = label(ContLabel) },
-		{ ContCode = node([
-			label(ContLabel) - "soft cut failure cont entry point",
-			discard_ticket - "pop ticket stack",
-			goto(Address) - "branch to prev failure continuation"
+	code_info__maybe_save_trail_info(MaybeTrailSlots, SaveTrailCode),
+	{ SemiCommitInfo = semi_commit_info(FailInfo0, NewResumePoint,
+		HijackInfo, MaybeTrailSlots) },
+	{ Code = tree(HijackCode, SaveTrailCode) }.
+
+code_info__generate_semi_commit(SemiCommitInfo, Code) -->
+	{ SemiCommitInfo = semi_commit_info(FailInfo, ResumePoint,
+		HijackInfo, MaybeTrailSlots) },
+
+	code_info__set_fail_info(FailInfo),
+	(
+		{ HijackInfo = commit_full_hijack(RedoipSlot, RedofrSlot,
+			MaxfrSlot) },
+		{ SuccessUndoCode = node([
+			assign(maxfr, lval(MaxfrSlot))
+				- "restore maxfr for full commit hijack",
+			assign(redoip(lval(maxfr)), lval(RedoipSlot))
+				- "restore redoip for full commit hijack",
+			assign(redofr(lval(maxfr)), lval(RedofrSlot))
+				- "restore redofr for full commit hijack"
+		]) },
+		{ FailureUndoCode = node([
+			assign(redoip(lval(maxfr)), lval(RedoipSlot))
+				- "restore redoip for full commit hijack",
+			assign(redofr(lval(maxfr)), lval(RedofrSlot))
+				- "restore redofr for full commit hijack"
+		]) }
+	;
+		{ HijackInfo = commit_half_hijack(RedoipSlot) },
+		{ SuccessUndoCode = node([
+			assign(maxfr, lval(curfr))
+				- "restore maxfr for half commit hijack",
+			assign(redoip(lval(maxfr)), lval(RedoipSlot))
+				- "restore redoip for half commit hijack"
+		]) },
+		{ FailureUndoCode = node([
+			assign(redoip(lval(maxfr)), lval(RedoipSlot))
+				- "restore redoip for half commit hijack"
 		]) }
 	;
-		{ ContAddress = Address },
-		{ ContCode = empty }
+		{ HijackInfo = commit_quarter_hijack },
+		{ FailInfo = fail_info(ResumePoints, _, _) },
+		{ stack__top_det(ResumePoints, TopResumePoint) },
+		{ code_info__pick_stack_resume_point(TopResumePoint,
+			_, StackLabel) },
+		{ StackLabelConst = const(code_addr_const(StackLabel)) },
+		{ SuccessUndoCode = node([
+			assign(maxfr, lval(curfr))
+				- "restore maxfr for quarter commit hijack",
+			assign(redoip(lval(maxfr)), StackLabelConst)
+				- "restore redoip for quarter commit hijack"
+		]) },
+		{ FailureUndoCode = node([
+			assign(redoip(lval(maxfr)), StackLabelConst)
+				- "restore redoip for quarter commit hijack"
+		]) }
 	),
-	{ Code = node([
-		assign(redoip(lval(TheFrame)),
-			const(code_addr_const(ContAddress)))
-		- "prune away the `else' case of the if-then-else"
-	]) }.
 
-%---------------------------------------------------------------------------%
+	code_info__remember_position(AfterCommit),
+	code_info__generate_resume_point(ResumePoint, ResumePointCode),
+	code_info__generate_failure(FailCode),
+	code_info__reset_to_position(AfterCommit),
 
-code_info__generate_semi_pre_commit(RedoLabel, Slots, PreCommit) -->
-	code_info__generate_pre_commit_saves(Slots, SaveCode),
-	code_info__get_next_label(ResumeLabel),
-	code_info__top_failure_cont(FailureCont0),
-	{ FailureCont0 = failure_cont(_, FailureMap0) },
-	{ code_info__pick_stack_resume_point(FailureMap0, StackMap, _) },
-	{ FailureCont = failure_cont(nondet(known, no),
-		stack_only(StackMap, label(ResumeLabel))) },
-	code_info__push_failure_cont(FailureCont),
-	code_info__get_next_label(RedoLabel),
-	{ HijackCode = node([
-		assign(redoip(lval(maxfr)),
-			const(code_addr_const(label(RedoLabel)))) -
-			"Hijack the failure cont"
-	]) },
-	{ PreCommit = tree(SaveCode, HijackCode) }.
+	code_info__maybe_restore_trail_info(MaybeTrailSlots,
+		CommitTrailCode, RestoreTrailCode),
 
-code_info__generate_semi_commit(RedoLabel, Slots, Commit) -->
 	code_info__get_next_label(SuccLabel),
 	{ GotoSuccLabel = node([
 		goto(label(SuccLabel)) - "Jump to success continuation"
@@ -1929,240 +2121,104 @@
 	{ SuccLabelCode = node([
 		label(SuccLabel) - "Success continuation"
 	]) },
-	{ RedoLabelCode = node([
-		label(RedoLabel) - "Failure (redo) continuation"
-	]) },
-
-	code_info__grab_code_info(CodeInfo0),
-	code_info__top_failure_cont(FailureCont),
-	{ FailureCont = failure_cont(_, FailureMaps) },
-	code_info__generate_resume_setup(FailureMaps, FailureContCode),
-	code_info__pop_failure_cont,
-	code_info__generate_failure(Fail),
-	code_info__slap_code_info(CodeInfo0),
-	code_info__pop_failure_cont,
-
-	code_info__undo_pre_commit_saves(Slots, RestoreMaxfr, RestoreRedoip,
-		RestoreCurfr, SuccPopCode, FailPopCode),
-
 	{ SuccessCode =
-		tree(RestoreMaxfr,
-		tree(RestoreRedoip,
-		tree(RestoreCurfr,
-		     SuccPopCode)))
+		tree(SuccessUndoCode,
+		     CommitTrailCode)
 	},
-	{ FailCode =
-		tree(RedoLabelCode,
-		tree(RestoreCurfr,
-		tree(FailureContCode,
-		tree(RestoreRedoip,
-		tree(FailPopCode,
-		     Fail)))))
+	{ FailureCode =
+		tree(ResumePointCode,
+		tree(FailureUndoCode,
+		tree(RestoreTrailCode,
+		     FailCode)))
 	},
-	{ Commit =
+	{ Code =
 		tree(SuccessCode,
 		tree(GotoSuccLabel,
-		tree(FailCode,
+		tree(FailureCode,
 		     SuccLabelCode)))
 	}.
 
 %---------------------------------------------------------------------------%
 
-code_info__generate_det_pre_commit(Slots, PreCommit) -->
-	code_info__generate_pre_commit_saves(Slots, PreCommit),
-	% Since the code we are cutting is model_non, it will call
-	% unset_failure_cont. If the current top entry on the failure stack
-	% at the time is semidet, this would cause unset_failure_cont to abort.
-	% We therefore push a dummy nondet failure continuation onto the
-	% failure stack. Since the code we are cutting across is multi,
-	% the failure continuation will never actually be used.
-	code_info__top_failure_cont(FailureCont0),
-	{ FailureCont0 = failure_cont(_, FailureMap) },
-	{ code_info__pick_stack_resume_point(FailureMap, StackMap, _) },
-	{ FailureCont = failure_cont(nondet(known, no),
-		stack_only(StackMap, do_fail)) },
-	code_info__push_failure_cont(FailureCont).
-
-code_info__generate_det_commit(Slots, Commit) -->
-	% Remove the dummy failure continuation pushed by det_pre_commit.
-	code_info__pop_failure_cont,
-	code_info__undo_pre_commit_saves(Slots, RestoreMaxfr, RestoreRedoip,
-		RestoreCurfr, SuccPopCode, _FailPopCode),
-	{ Commit = tree(RestoreMaxfr,
-		   tree(RestoreRedoip,
-		   tree(RestoreCurfr,
-		        SuccPopCode)))
-	}.
-
-%---------------------------------------------------------------------------%
-
-:- pred code_info__generate_pre_commit_saves(commit_slots, code_tree,
-	code_info, code_info).
-:- mode code_info__generate_pre_commit_saves(out, out, in, out) is det.
+:- pred code_info__maybe_save_trail_info(maybe(pair(lval))::out,
+	code_tree::out, code_info::in, code_info::out) is det.
 
-code_info__generate_pre_commit_saves(Slots, Code) -->
+code_info__maybe_save_trail_info(MaybeTrailSlots, SaveTrailCode) -->
 	code_info__get_globals(Globals),
 	{ globals__lookup_bool_option(Globals, use_trail, UseTrail) },
 	( { UseTrail = yes } ->
-		{ NumSlots = 5 },
-		{ SaveMessage =
-	"push space for curfr, maxfr, redoip, ticket_counter and trail_ptr" }
+		code_info__acquire_temp_slot(ticket_counter, CounterSlot),
+		code_info__acquire_temp_slot(ticket, TrailPtrSlot),
+		{ MaybeTrailSlots = yes(CounterSlot - TrailPtrSlot) },
+		{ SaveTrailCode = node([
+			mark_ticket_stack(CounterSlot)
+				- "save the ticket counter",
+			store_ticket(TrailPtrSlot)
+				- "save the trail pointer"
+		]) }
 	;
-		{ NumSlots = 3 },
-		{ SaveMessage = "push space for curfr, maxfr, and redoip" }
-	),
-	code_info__get_proc_model(CodeModel),
-	( { CodeModel = model_non } ->
-		% the pushes and pops on the det stack below will cause
-		% problems for accurate garbage collection. Hence we
-		% make sure the commit vals are made live, so gc
-		% can figure out what is going on later.
-		code_info__get_module_info(ModuleInfo),
-		code_info__get_pred_id(PredId),
-		{ predicate_module(ModuleInfo, PredId, ModuleName) },
-		{ predicate_name(ModuleInfo, PredId, PredName) },
-		{ prog_out__sym_name_to_string(ModuleName, ModuleNameString) },
-		{ string__append_list(["commit in ",
-			ModuleNameString, ":", PredName], Message) },
-		{ PushCode = node([
-			incr_sp(NumSlots, Message) - SaveMessage
+		{ MaybeTrailSlots = no },
+		{ SaveTrailCode = empty }
+	).
+
+:- pred code_info__maybe_restore_trail_info(maybe(pair(lval))::in,
+	code_tree::out, code_tree::out, code_info::in, code_info::out) is det.
+
+code_info__maybe_restore_trail_info(MaybeTrailSlots,
+		CommitCode, RestoreCode) -->
+	(
+		{ MaybeTrailSlots = no },
+		{ CommitCode = empty },
+		{ RestoreCode = empty }
+	;
+		{ MaybeTrailSlots = yes(CounterSlot - TrailPtrSlot) },
+		{ CommitTrailCode = node([
+			reset_ticket(lval(TrailPtrSlot), commit)
+				- "discard trail entries and restore trail ptr"
 		]) },
-		{ CurfrSlot = stackvar(1) },
-		{ MaxfrSlot = stackvar(2) },
-		{ RedoipSlot = stackvar(3) },
-		( { UseTrail = yes } ->
-			{ TicketCounterSlot = stackvar(4) },
-			{ TrailPtrSlot = stackvar(5) },
-			{ MaybeTrailSlots = yes(TicketCounterSlot -
-						TrailPtrSlot) }
-		;
-			{ MaybeTrailSlots = no }
-		),
-		{ Slots = commit_slots(CurfrSlot, MaxfrSlot, RedoipSlot,
-			MaybeTrailSlots) },
-		code_info__add_commit_triple
-	;
-		{ PushCode = empty },
-		code_info__acquire_temp_slot(lval(curfr), CurfrSlot),
-		code_info__acquire_temp_slot(lval(maxfr), MaxfrSlot),
-		code_info__acquire_temp_slot(lval(redoip(lval(maxfr))),
-			RedoipSlot),
-		( { UseTrail = yes } ->
-			code_info__acquire_temp_slot(ticket_counter,
-						TicketCounterSlot),
-			code_info__acquire_temp_slot(ticket, TrailPtrSlot),
-			{ MaybeTrailSlots = yes(TicketCounterSlot -
-						TrailPtrSlot) }
-		;
-			{ MaybeTrailSlots = no }
-		),
-		{ Slots = commit_slots(CurfrSlot, MaxfrSlot, RedoipSlot,
-			MaybeTrailSlots) }
-	),
-	{ SaveCode = node([
-		assign(CurfrSlot, lval(curfr)) -
-				"Save current nondet frame pointer",
-		assign(MaxfrSlot, lval(maxfr)) -
-				"Save top of nondet stack",
-		assign(RedoipSlot, lval(redoip(lval(maxfr)))) -
-				"Save the top redoip"
-	]) },
-	{ MaybeTrailSlots = yes(TheTicketCounterSlot - TheTrailPtrSlot) ->
-		MaybeSaveTrailCode = node([
-			mark_ticket_stack(TheTicketCounterSlot) -
-				"Save the ticket counter",
-			store_ticket(TheTrailPtrSlot) -
-				"Save the trail pointer"
-		])
-	;
-		MaybeSaveTrailCode = empty
-	},
-	{ Code = tree(PushCode, tree(SaveCode, MaybeSaveTrailCode)) }.
+		{ RestoreTrailCode = node([
+			reset_ticket(lval(TrailPtrSlot), undo)
+				- "apply trail entries and restore trail ptr"
+		]) },
+		{ RestoreCounterCode = node([
+			discard_tickets_to(lval(CounterSlot))
+				- "restore the ticket counter"
+		]) },
+		code_info__release_temp_slot(CounterSlot),
+		code_info__release_temp_slot(TrailPtrSlot),
+		{ CommitCode = tree(CommitTrailCode, RestoreCounterCode) },
+		{ RestoreCode = tree(RestoreTrailCode, RestoreCounterCode) }
+	).
 
-:- pred code_info__undo_pre_commit_saves(commit_slots, code_tree, code_tree,
-	code_tree, code_tree, code_tree, code_info, code_info).
-:- mode code_info__undo_pre_commit_saves(in, out, out, out, out, out, in, out)
-	is det.
+%---------------------------------------------------------------------------%
 
-code_info__undo_pre_commit_saves(Slots, RestoreMaxfr, RestoreRedoip,
-		RestoreCurfr, SuccPopCode, FailPopCode) -->
-	{ Slots = commit_slots(CurfrSlot, MaxfrSlot, RedoipSlot,
-		MaybeTrailSlots) },
-	{ RestoreMaxfr = node([
-		assign(maxfr, lval(MaxfrSlot)) -
-			"Prune away unwanted choice-points"
-	]) },
-	{ RestoreRedoip = node([
-		assign(redoip(lval(maxfr)), lval(RedoipSlot)) -
-			"Restore the top redoip"
-	]) },
-	{ RestoreCurfr = node([
-		assign(curfr, lval(CurfrSlot)) -
-			"Restore nondet frame pointer"
-	]) },
-	code_info__get_proc_model(CodeModel),
-	( { CodeModel = model_non } ->
-		code_info__rem_commit_triple,
-		( { MaybeTrailSlots = yes(TicketCounterSlot - TrailPtrSlot) } ->
-			{ CommitTrail = node([
-				reset_ticket(lval(TrailPtrSlot), commit) -
-				"discard trail entries and restore trail ptr"
-			]) },
-			{ RestoreTrail = node([
-				reset_ticket(lval(TrailPtrSlot), undo) -
-				"apply trail entries and restore trail ptr"
-			]) },
-			{ RestoreTicketCounter = node([
-				discard_tickets_to(lval(TicketCounterSlot)) -
-				"restore the ticket counter"
-			]) },
-			{ NumSlots = 5 },
-			{ PopMessage =
-		     "pop curfr, maxfr, redoip, ticket_counter and trail_ptr" }
-		;
-			{ CommitTrail = empty },
-			{ RestoreTrail = empty },
-			{ RestoreTicketCounter = empty },
-			{ NumSlots = 3 },
-			{ PopMessage = "pop curfr, maxfr, and redoip" }
-		),
-		{ MainPopCode = node([
-			decr_sp(NumSlots) - PopMessage
-		]) }
+:- pred code_info__clone_resume_point(resume_point_info::in,
+	resume_point_info::out, code_info::in, code_info::out) is det.
+
+code_info__clone_resume_point(ResumePoint0, ResumePoint) -->
+	(
+		{ ResumePoint0 = orig_only(_, _) },
+		{ error("cloning orig_only resume point") }
 	;
-		code_info__release_temp_slot(CurfrSlot),
-		code_info__release_temp_slot(MaxfrSlot),
-		code_info__release_temp_slot(RedoipSlot),
-		( { MaybeTrailSlots = yes(TicketCounterSlot - TrailPtrSlot) } ->
-			{ CommitTrail = node([
-				reset_ticket(lval(TrailPtrSlot), commit) -
-				"discard trail entries and restore trail ptr"
-			]) },
-			{ RestoreTrail = node([
-				reset_ticket(lval(TrailPtrSlot), undo) -
-				"apply trail entries and restore trail ptr"
-			]) },
-			{ RestoreTicketCounter = node([
-				discard_tickets_to(lval(TicketCounterSlot)) -
-				"restore the ticket counter"
-			]) },
-			code_info__release_temp_slot(TicketCounterSlot),
-			code_info__release_temp_slot(TrailPtrSlot)
-		;
-			{ CommitTrail = empty },
-			{ RestoreTrail = empty },
-			{ RestoreTicketCounter = empty }
-		),
-		{ MainPopCode = empty }
-	),
-	{ SuccPopCode =
-		tree(CommitTrail,
-		tree(RestoreTicketCounter,
-		     MainPopCode)) },
-	{ FailPopCode =
-		tree(RestoreTrail,
-		tree(RestoreTicketCounter,
-		     MainPopCode)) }.
+		{ ResumePoint0 = stack_only(Map1, _) },
+		code_info__get_next_label(Label1),
+		{ Addr1 = label(Label1) },
+		{ ResumePoint = stack_only(Map1, Addr1) }
+	;
+		{ ResumePoint0 = stack_and_orig(Map1, _, Map2, _) },
+		code_info__get_next_label(Label1),
+		{ Addr1 = label(Label1) },
+		code_info__get_next_label(Label2),
+		{ Addr2 = label(Label2) },
+		{ ResumePoint = stack_and_orig(Map1, Addr1, Map2, Addr2) }
+	;
+		{ ResumePoint0 = orig_and_stack(Map1, _, Map2, _) },
+		code_info__get_next_label(Label2),
+		{ Addr2 = label(Label2) },
+		code_info__get_next_label(Label1),
+		{ Addr1 = label(Label1) },
+		{ ResumePoint = stack_and_orig(Map2, Addr2, Map1, Addr1) }
+	).
 
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
@@ -2330,7 +2386,7 @@
 	% 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,
-					code_tree, code_info, code_info).
+	code_tree, code_info, code_info).
 :- mode code_info__reset_and_pop_ticket(in, in, out, in, out) is det.
 
 :- pred code_info__discard_ticket(lval, code_tree, code_info, code_info).
@@ -2350,8 +2406,7 @@
 
 :- pred code_info__maybe_reset_and_pop_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.
+:- 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).
@@ -2456,11 +2511,9 @@
 		{ Code = empty }
 	).
 
-code_info__maybe_reset_and_pop_ticket(MaybeTicketSlot, Reason, Code)
-		-->
+code_info__maybe_reset_and_pop_ticket(MaybeTicketSlot, Reason, Code) -->
 	( { MaybeTicketSlot = yes(TicketSlot) } ->
-		code_info__reset_and_pop_ticket(TicketSlot, Reason,
-			Code)
+		code_info__reset_and_pop_ticket(TicketSlot, Reason, Code)
 	;
 		{ Code = empty }
 	).
@@ -2530,20 +2583,6 @@
 :- pred code_info__clear_r1(code_tree, code_info, code_info).
 :- mode code_info__clear_r1(out, in, out) is det.
 
-:- pred code_info__generate_branch_end(code_model, store_map, code_tree,
-	code_info, code_info).
-:- mode code_info__generate_branch_end(in, in, out, in, out) is det.
-
-	% code_info__remake_with_store_map throws away the exprn_info data
-	% structure, forgetting the current locations of all variables,
-	% and rebuilds it from scratch based on the given store map.
-	% The new exprn_info will know about only the variables present
-	% in the store map, and will believe they are where the store map
-	% says they are.
-
-:- pred code_info__remake_with_store_map(store_map, code_info, code_info).
-:- mode code_info__remake_with_store_map(in, in, out) is det.
-
 :- type call_direction ---> caller ; callee.
 
 	% Generate code to either setup the input arguments for a call
@@ -2681,34 +2720,6 @@
 
 %---------------------------------------------------------------------------%
 
-code_info__generate_branch_end(CodeModel, StoreMap, Code) -->
-	code_info__get_exprn_info(Exprn0),
-	{ map__to_assoc_list(StoreMap, VarLocs) },
-	{ code_exprn__place_vars(VarLocs, PlaceCode, Exprn0, Exprn) },
-	code_info__set_exprn_info(Exprn),
-	( { CodeModel = model_non } ->
-		code_info__unset_failure_cont(FlushCode),
-		{ Code = tree(PlaceCode, FlushCode) }
-	;
-		{ Code = PlaceCode }
-	).
-
-code_info__remake_with_store_map(StoreMap) -->
-	{ map__to_assoc_list(StoreMap, VarLvals) },
-	{ code_info__fixup_lvallist(VarLvals, VarRvals) },
-	code_info__get_exprn_info(Exprn0),
-	{ code_exprn__reinit_state(VarRvals, Exprn0, Exprn) },
-	code_info__set_exprn_info(Exprn).
-
-:- pred code_info__fixup_lvallist(assoc_list(var, lval), assoc_list(var, rval)).
-:- mode code_info__fixup_lvallist(in, out) is det.
-
-code_info__fixup_lvallist([], []).
-code_info__fixup_lvallist([V - L | Ls], [V - lval(L) | Rs]) :-
-	code_info__fixup_lvallist(Ls, Rs).
-
-%---------------------------------------------------------------------------%
-
 code_info__setup_call([], _Direction, empty) --> [].
 code_info__setup_call([V - arg_info(Loc, Mode) | Rest], Direction, Code) -->
 	(
@@ -2804,7 +2815,7 @@
 	code_info, code_info).
 :- mode code_info__generate_stack_livevals(in, out, in, out) is det.
 
-:- pred code_info__generate_stack_livelvals(set(var), instmap, 
+:- pred code_info__generate_stack_livelvals(set(var), instmap,
 	list(liveinfo), code_info, code_info).
 :- mode code_info__generate_stack_livelvals(in, in, out, in, out) is det.
 
@@ -2821,9 +2832,7 @@
 	code_info__generate_var_livevals(VarList, LiveVals0, LiveVals1),
 	code_info__get_temps_in_use(TempsSet),
 	{ map__to_assoc_list(TempsSet, Temps) },
-	{ code_info__generate_temp_livevals(Temps, LiveVals1, LiveVals2) },
-	code_info__get_commit_triple_count(Triples),
-	{ code_info__generate_commit_livevals(Triples, LiveVals2, LiveVals) }.
+	{ code_info__generate_temp_livevals(Temps, LiveVals1, LiveVals) }.
 
 :- pred code_info__generate_var_livevals(list(var), set(lval), set(lval),
 	code_info, code_info).
@@ -2844,26 +2853,6 @@
 	set__insert(Vals0, Slot, Vals1),
 	code_info__generate_temp_livevals(Slots, Vals1, Vals).
 
-:- pred code_info__generate_commit_livevals(int, set(lval), set(lval)).
-:- mode code_info__generate_commit_livevals(in, in, out) is det.
-
-code_info__generate_commit_livevals(Triples0, Vals0, Vals) :-
-	( Triples0 = 0 ->
-		Vals = Vals0
-	;
-		CurfrSlot is (Triples0 - 1) * 3 + 1,
-		MaxfrSlot is (Triples0 - 1) * 3 + 2,
-		RedoipSlot is (Triples0 - 1) * 3 + 3,
-		CurfrVar = stackvar(CurfrSlot),
-		MaxfrVar = stackvar(MaxfrSlot),
-		RedoipVar = stackvar(RedoipSlot),
-		set__insert(Vals0, CurfrVar, Vals1),
-		set__insert(Vals1, MaxfrVar, Vals2),
-		set__insert(Vals2, RedoipVar, Vals3),
-		Triples1 is Triples0 - 1,
-		code_info__generate_commit_livevals(Triples1, Vals3, Vals)
-	).
-
 %---------------------------------------------------------------------------%
 
 code_info__generate_stack_livelvals(Args, AfterCallInstMap, LiveVals) -->
@@ -2890,9 +2879,7 @@
 		AfterCallInstMap, LiveVals3),
 	code_info__get_temps_in_use(TempsSet),
 	{ map__to_assoc_list(TempsSet, Temps) },
-	{ code_info__generate_temp_livelvals(Temps, LiveVals3, LiveVals4) },
-	code_info__get_commit_triple_count(Triples),
-	{ code_info__generate_commit_livelvals(Triples, LiveVals4, LiveVals) }.
+	{ code_info__generate_temp_livelvals(Temps, LiveVals3, LiveVals) }.
 
 :- pred code_info__generate_var_livelvals(list(var),
 	set(pair(lval, var)), set(pair(lval, var)), code_info, code_info).
@@ -2914,35 +2901,6 @@
 	code_info__get_live_value_type(StoredLval, LiveValueType),
 	code_info__generate_temp_livelvals(Slots, LiveInfo0, LiveInfo1).
 
-:- pred code_info__generate_commit_livelvals(int,
-	list(liveinfo), list(liveinfo)).
-:- mode code_info__generate_commit_livelvals(in, in, out) is det.
-
-code_info__generate_commit_livelvals(Triples0, LiveInfo0, LiveInfo) :-
-	( Triples0 = 0 ->
-		LiveInfo = LiveInfo0
-	;
-		Triples1 is Triples0 - 1,
-		code_info__generate_commit_livelvals(Triples1,
-			LiveInfo0, LiveInfo1),
-		CurfrSlot is (Triples0 - 1) * 3 + 1,
-		MaxfrSlot is (Triples0 - 1) * 3 + 2,
-		RedoipSlot is (Triples0 - 1) * 3 + 3,
-		CurfrVar = stackvar(CurfrSlot),
-		MaxfrVar = stackvar(MaxfrSlot),
-		RedoipVar = stackvar(RedoipSlot),
-		code_info__get_live_value_type(lval(curfr), CurfrValueType),
-		code_info__get_live_value_type(lval(maxfr), MaxfrValueType),
-		code_info__get_live_value_type(lval(redoip(lval(maxfr))),
-			RedoipValueType),
-		LiveInfo2 = [live_lvalue(CurfrVar, CurfrValueType, "", []) | 
-				LiveInfo1],
-		LiveInfo3 = [live_lvalue(MaxfrVar, MaxfrValueType, "", []) |
-				LiveInfo2],
-		LiveInfo  = [live_lvalue(RedoipVar, RedoipValueType, "", []) |
-				LiveInfo3]
-	).
-
 :- pred code_info__livevals_to_livelvals(assoc_list(lval, var), bool,
 	instmap, list(liveinfo), code_info, code_info).
 :- mode code_info__livevals_to_livelvals(in, in, in, out, in, out) is det.
@@ -2977,6 +2935,7 @@
 code_info__get_live_value_type(lval(curfr), curfr).
 code_info__get_live_value_type(lval(succfr(_)), unwanted).
 code_info__get_live_value_type(lval(prevfr(_)), unwanted).
+code_info__get_live_value_type(lval(redofr(_)), unwanted).
 code_info__get_live_value_type(lval(redoip(_)), unwanted).
 code_info__get_live_value_type(lval(succip(_)), unwanted).
 code_info__get_live_value_type(lval(sp), unwanted).



More information about the developers mailing list