[m-dev.] for review: delaying death

Zoltan Somogyi zs at cs.mu.OZ.AU
Fri Jan 5 15:14:42 AEDT 2001


For review by anyone.

Estimated hours taken: 8

If the trace level is `deep' or some level (e.g. `decl') whose functionality
includes the functionality of `deep', then by default delay the deaths of
named variables until as late as possible, in order to make their values
accessible in the debugger at as many events as possible. Add an option,
--no-delay-death, to preserve the old behavior.

This change increases the runtime of a compiler compiled in the debugging grade
by about 2.3%, and increases its size by 20.5%, from 27.2 to 32.7 Mb. The size
increase is mostly to read-only data increasing from 10.2 to 15.5 Mb, though
the code size also increases a bit, from 16.8 to 17.5 Mb, due to the larger
number of stores onto the stack.

I expect that the space penalty will be substantially reduced when I move
variable type information from label layouts to procedure layouts, since
at present the type of a variable that is live at many labels is recorded
many times.

compiler/liveness.m:
	Add an optional pass after the initial computation of deadness to
	delays deaths as late as possible.

compiler/trace_params.m:
	Add a predicate to test whether delaying deaths make sense.

compiler/options.m:
doc_/user_guide.texi:
	Add the new option.

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 compiler
Index: compiler/liveness.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/liveness.m,v
retrieving revision 1.114
diff -u -b -r1.114 liveness.m
--- compiler/liveness.m	2000/11/23 04:32:38	1.114
+++ compiler/liveness.m	2001/01/05 03:25:33
@@ -28,7 +28,7 @@
 % as late as possible (but before the first possible use), and the
 % death should be as early as possible (but after the last possible use).
 %
-% We compute liveness related information in three distinct passes.
+% We compute liveness related information in four distinct passes.
 %
 % The first pass, detect_liveness_in_goal, finds the first value-giving
 % occurrence of each variable on each computation path. Goals containing
@@ -46,7 +46,18 @@
 % used at all include a pre-death set listing the variables that
 % have died in parallel branches.
 %
-% The third pass, detect_resume_points_in_goal, finds goals that
+% The third pass is optional: it delays the deaths of named variables until
+% the last possible moment. This can be useful if debugging is enabled, as it
+% allows the programmer to look at the values of such variables at as many
+% trace events as possible. If debugging is not enabled, this pass is a pure
+% pessimization (it increases stack slot pressure and thus probably increases
+% the size of the procedure's stack frame), and therefore should not be
+% enabled.
+%
+% The second and third passes cannot be combined, because the second pass
+% traverses goals backwards while the third pass traverses goals forwards.
+%
+% The fourth pass, detect_resume_points_in_goal, finds goals that
 % establish resume points and attaches to them a resume_point
 % annotation listing the variables that may be referenced by the
 % code at that resume point as well as the nature of the required
@@ -180,13 +191,13 @@
 	requantify_proc(ProcInfo0, ProcInfo1),
 
 	proc_info_goal(ProcInfo1, Goal0),
-	proc_info_varset(ProcInfo1, Varset),
+	proc_info_varset(ProcInfo1, VarSet),
 	proc_info_vartypes(ProcInfo1, VarTypes),
 	proc_info_typeinfo_varmap(ProcInfo1, TVarMap),
 	module_info_globals(ModuleInfo, Globals),
 	module_info_pred_info(ModuleInfo, PredId, PredInfo),
 	body_should_use_typeinfo_liveness(PredInfo, Globals, TypeInfoLiveness),
-	live_info_init(ModuleInfo, TypeInfoLiveness, VarTypes, TVarMap, Varset,
+	live_info_init(ModuleInfo, TypeInfoLiveness, VarTypes, TVarMap, VarSet,
 		LiveInfo),
 
 	initial_liveness(ProcInfo1, PredId, ModuleInfo, Liveness0),
@@ -196,13 +207,25 @@
 	initial_deadness(ProcInfo1, LiveInfo, ModuleInfo, Deadness0),
 	detect_deadness_in_goal(Goal1, Deadness0, LiveInfo, _, Goal2),
 
+	(
+		globals__get_trace_level(Globals, TraceLevel),
+		AllowDelayDeath = trace_level_allows_delay_death(TraceLevel),
+		AllowDelayDeath = yes,
+		globals__lookup_bool_option(Globals, delay_death, DelayDeath),
+		DelayDeath = yes
+	->
+		delay_death_proc_body(Goal2, VarSet, Liveness0, Goal3)
+	;
+		Goal3 = Goal2
+	),
+
 	globals__get_trace_level(Globals, TraceLevel),
 	( trace_level_is_none(TraceLevel) = no ->
 		trace__fail_vars(ModuleInfo, ProcInfo0, ResumeVars0)
 	;
 		set__init(ResumeVars0)
 	),
-	detect_resume_points_in_goal(Goal2, Liveness0, LiveInfo,
+	detect_resume_points_in_goal(Goal3, Liveness0, LiveInfo,
 		ResumeVars0, Goal, _),
 
 	proc_info_set_goal(ProcInfo1, Goal, ProcInfo2),
@@ -645,6 +668,288 @@
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
 
+% The delay_death pass works by maintaining a set of variables (all named)
+% that, according to the deadness pass should have died by now, but which
+% are being kept alive so that their values are accessible to the debugger.
+% Variables in this DelayedDead set are finally killed when we come to the end
+% of the goal in which they were born. This is because if a variable is born in
+% one arm of a branched control structure (e.g. a switch), it cannot live
+% beyond the control structure, because it is not given a value in other
+% branches.
+%
+% The correctness of this pass with typeinfo_liveness depends on the fact that
+% typeinfo and typeclass_info variables are all named. If they weren't, then it
+% would be possible for a (named) variable to have its death delayed without
+% the type(class)info variable describing part of its type having its death
+% delayed as well. In fact, its delay will be delayed by at least as much,
+% since a variable cannot be live on entry to a branched control structure
+% without the type(class)info variables describing its type being live there as
+% well.
+
+:- pred delay_death_proc_body(hlds_goal::in, prog_varset::in, set(prog_var)::in,
+	hlds_goal::out) is det.
+
+delay_death_proc_body(Goal0, VarSet, BornVars0, Goal) :-
+	delay_death_goal(Goal0, BornVars0, set__init, VarSet,
+		Goal1, _, DelayedDead),
+	Goal1 = GoalExpr - GoalInfo1,
+	goal_info_get_post_deaths(GoalInfo1, PostDeaths1),
+	set__union(PostDeaths1, DelayedDead, PostDeaths),
+	goal_info_set_post_deaths(GoalInfo1, PostDeaths, GoalInfo),
+	Goal = GoalExpr - GoalInfo.
+
+:- pred delay_death_goal(hlds_goal::in, set(prog_var)::in, set(prog_var)::in,
+	prog_varset::in,
+	hlds_goal::out, set(prog_var)::out, set(prog_var)::out) is det.
+
+delay_death_goal(GoalExpr0 - GoalInfo0, BornVars0, DelayedDead0, VarSet,
+		GoalExpr - GoalInfo, BornVars, DelayedDead) :-
+	goal_info_get_pre_births(GoalInfo0, PreBirths),
+	goal_info_get_pre_deaths(GoalInfo0, PreDeaths0),
+
+	set__union(BornVars0, PreBirths, BornVars1),
+	set__divide(var_is_named(VarSet), PreDeaths0,
+		PreDelayedDead, UnnamedPreDeaths),
+	set__union(DelayedDead0, PreDelayedDead, DelayedDead1),
+	goal_info_set_pre_deaths(GoalInfo0, UnnamedPreDeaths, GoalInfo1),
+
+	delay_death_goal_expr(GoalExpr0, GoalInfo1, BornVars1, DelayedDead1,
+		VarSet, GoalExpr, GoalInfo2, BornVars2, DelayedDead2),
+
+	goal_info_get_post_births(GoalInfo2, PostBirths),
+	goal_info_get_post_deaths(GoalInfo2, PostDeaths2),
+
+	set__union(BornVars2, PostBirths, BornVars),
+	set__divide(var_is_named(VarSet), PostDeaths2,
+		PostDelayedDead, UnnamedPostDeaths),
+	set__union(DelayedDead2, PostDelayedDead, DelayedDead3),
+	set__divide(set__contains(BornVars0), DelayedDead3,
+		DelayedDead, ToBeKilled),
+	set__union(UnnamedPostDeaths, ToBeKilled, PostDeaths),
+	goal_info_set_post_deaths(GoalInfo2, PostDeaths, GoalInfo).
+
+:- pred var_is_named(prog_varset::in, prog_var::in) is semidet.
+
+var_is_named(VarSet, Var) :-
+	varset__search_name(VarSet, Var, _).
+
+:- pred delay_death_goal_expr(hlds_goal_expr::in, hlds_goal_info::in,
+	set(prog_var)::in, set(prog_var)::in, prog_varset::in,
+	hlds_goal_expr::out, hlds_goal_info::out,
+	set(prog_var)::out, set(prog_var)::out) is det.
+
+delay_death_goal_expr(GoalExpr0, GoalInfo0, BornVars0, DelayedDead0, VarSet,
+		GoalExpr, GoalInfo, BornVars, DelayedDead) :-
+	(
+		GoalExpr0 = call(_, _, _, _, _, _),
+		GoalExpr = GoalExpr0,
+		GoalInfo = GoalInfo0,
+		BornVars = BornVars0,
+		DelayedDead = DelayedDead0
+	;
+		GoalExpr0 = generic_call(_, _, _, _),
+		GoalExpr = GoalExpr0,
+		GoalInfo = GoalInfo0,
+		BornVars = BornVars0,
+		DelayedDead = DelayedDead0
+	;
+		GoalExpr0 = unify(_, _, _, _, _),
+		GoalExpr = GoalExpr0,
+		GoalInfo = GoalInfo0,
+		BornVars = BornVars0,
+		DelayedDead = DelayedDead0
+	;
+		GoalExpr0 = pragma_foreign_code(_, _, _, _, _, _, _),
+		GoalExpr = GoalExpr0,
+		GoalInfo = GoalInfo0,
+		BornVars = BornVars0,
+		DelayedDead = DelayedDead0
+	;
+		GoalExpr0 = conj(Goals0),
+		delay_death_conj(Goals0, BornVars0, DelayedDead0, VarSet,
+			Goals, BornVars, DelayedDead),
+		GoalExpr = conj(Goals),
+		GoalInfo = GoalInfo0
+	;
+		GoalExpr0 = par_conj(Goals0, SM),
+		delay_death_conj(Goals0, BornVars0, DelayedDead0, VarSet,
+			Goals, BornVars, DelayedDead),
+		GoalExpr = par_conj(Goals, SM),
+		GoalInfo = GoalInfo0
+	;
+		GoalExpr0 = disj(Goals0, SM),
+		delay_death_disj(Goals0, BornVars0, DelayedDead0, VarSet,
+			GoalDeaths, MaybeBornVarsDelayedDead),
+		(
+			MaybeBornVarsDelayedDead = yes(BornVars - DelayedDead),
+			Goals = list__map(
+				kill_excess_delayed_dead_goal(DelayedDead),
+				GoalDeaths),
+			GoalExpr = disj(Goals, SM),
+			GoalInfo = GoalInfo0
+		;
+			MaybeBornVarsDelayedDead = no,
+			% Empty disjunctions represent the goal `fail',
+			% so we process them as if they were primitive goals.
+			GoalExpr = GoalExpr0,
+			GoalInfo = GoalInfo0,
+			BornVars = BornVars0,
+			DelayedDead = DelayedDead0
+		)
+	;
+		GoalExpr0 = switch(Var, CanFail, Cases0, SM),
+		delay_death_cases(Cases0, BornVars0, DelayedDead0, VarSet,
+			CaseDeaths, MaybeBornVarsDelayedDead),
+		(
+			MaybeBornVarsDelayedDead = yes(BornVars - DelayedDead),
+			Cases = list__map(
+				kill_excess_delayed_dead_case(DelayedDead),
+				CaseDeaths),
+			GoalExpr = switch(Var, CanFail, Cases, SM),
+			GoalInfo = GoalInfo0
+		;
+			MaybeBornVarsDelayedDead = no,
+			error("delay_death_goal_expr: empty switch")
+		)
+	;
+		GoalExpr0 = not(Goal0),
+		delay_death_goal(Goal0, BornVars0, DelayedDead0, VarSet,
+			Goal, _BornVars, DelayedDead),
+		GoalExpr = not(Goal),
+		GoalInfo = GoalInfo0,
+		BornVars = BornVars0
+	;
+		GoalExpr0 = if_then_else(QuantVars, Cond0, Then0, Else0, SM),
+		delay_death_goal(Cond0, BornVars0, DelayedDead0, VarSet,
+			Cond, BornVarsCond, DelayedDeadCond),
+		delay_death_goal(Then0, BornVarsCond, DelayedDeadCond, VarSet,
+			Then1, BornVarsThen, DelayedDeadThen),
+		delay_death_goal(Else0, BornVars0, DelayedDead0, VarSet,
+			Else1, BornVarsElse, DelayedDeadElse),
+		set__intersect(BornVarsThen, BornVarsElse, BornVars),
+		set__intersect(DelayedDeadThen, DelayedDeadElse, DelayedDead),
+		Then = kill_excess_delayed_dead_goal(DelayedDead,
+			Then1 - DelayedDeadThen),
+		Else = kill_excess_delayed_dead_goal(DelayedDead,
+			Else1 - DelayedDeadElse),
+		GoalExpr = if_then_else(QuantVars, Cond, Then, Else, SM),
+		GoalInfo = GoalInfo0
+	;
+		GoalExpr0 = some(QuantVars, CanRemove, Goal0),
+		delay_death_goal(Goal0, BornVars0, DelayedDead0, VarSet,
+			Goal, _BornVars, DelayedDead),
+		GoalExpr = some(QuantVars, CanRemove, Goal),
+		GoalInfo = GoalInfo0,
+		BornVars = BornVars0
+	;
+		GoalExpr0 = bi_implication(_, _),
+		error("delay_death_goal_expr: bi_implication")
+	).
+
+:- pred delay_death_conj(list(hlds_goal)::in,
+	set(prog_var)::in, set(prog_var)::in, prog_varset::in,
+	list(hlds_goal)::out, set(prog_var)::out, set(prog_var)::out) is det.
+
+delay_death_conj([], BornVars, DelayedDead, _, [], BornVars, DelayedDead).
+delay_death_conj([Goal0 | Goals0], BornVars0, DelayedDead0, VarSet,
+		[Goal | Goals], BornVars, DelayedDead) :-
+	delay_death_goal(Goal0, BornVars0, DelayedDead0, VarSet,
+		Goal, BornVars1, DelayedDead1),
+	delay_death_conj(Goals0, BornVars1, DelayedDead1, VarSet,
+		Goals, BornVars, DelayedDead).
+
+:- pred delay_death_par_conj(list(hlds_goal)::in,
+	set(prog_var)::in, set(prog_var)::in, prog_varset::in,
+	list(hlds_goal)::out, set(prog_var)::out, set(prog_var)::out) is det.
+
+delay_death_par_conj([], BornVars, DelayedDead, _, [], BornVars, DelayedDead).
+delay_death_par_conj([Goal0 | Goals0], BornVars0, DelayedDead0, VarSet,
+		[Goal | Goals], BornVars, DelayedDead) :-
+	delay_death_goal(Goal0, BornVars0, DelayedDead0, VarSet,
+		Goal, BornVarsGoal, DelayedDeadGoal),
+	delay_death_par_conj(Goals0, BornVars0, DelayedDead0, VarSet,
+		Goals, BornVarsGoals, DelayedDeadGoals),
+	set__union(BornVarsGoal, BornVarsGoals, BornVars),
+	set__union(DelayedDeadGoal, DelayedDeadGoals, DelayedDead).
+
+:- pred delay_death_disj(list(hlds_goal)::in,
+	set(prog_var)::in, set(prog_var)::in, prog_varset::in,
+	assoc_list(hlds_goal, set(prog_var))::out,
+	maybe(pair(set(prog_var)))::out) is det.
+
+delay_death_disj([], _, _, _, [], no).
+delay_death_disj([Goal0 | Goals0], BornVars0, DelayedDead0, VarSet,
+		[Goal - DelayedDeadGoal | Goals],
+		yes(BornVars - DelayedDead)) :-
+	delay_death_goal(Goal0, BornVars0, DelayedDead0, VarSet,
+		Goal, BornVarsGoal, DelayedDeadGoal),
+	delay_death_disj(Goals0, BornVars0, DelayedDead0, VarSet,
+		Goals, MaybeBornVarsDelayedDead),
+	(
+		MaybeBornVarsDelayedDead =
+			yes(BornVarsGoals - DelayedDeadGoals),
+		set__intersect(BornVarsGoal, BornVarsGoals, BornVars),
+		set__intersect(DelayedDeadGoal, DelayedDeadGoals, DelayedDead)
+	;
+		MaybeBornVarsDelayedDead = no,
+		BornVars = BornVarsGoal,
+		DelayedDead = DelayedDeadGoal
+	).
+
+:- pred delay_death_cases(list(case)::in,
+	set(prog_var)::in, set(prog_var)::in, prog_varset::in,
+	assoc_list(case, set(prog_var))::out, maybe(pair(set(prog_var)))::out)
+	is det.
+
+delay_death_cases([], _, _, _, [], no).
+delay_death_cases([case(ConsId, Goal0) | Cases0], BornVars0, DelayedDead0,
+		VarSet, [case(ConsId, Goal) - DelayedDeadGoal | Cases],
+		yes(BornVars - DelayedDead)) :-
+	delay_death_goal(Goal0, BornVars0, DelayedDead0, VarSet,
+		Goal, BornVarsGoal, DelayedDeadGoal),
+	delay_death_cases(Cases0, BornVars0, DelayedDead0, VarSet,
+		Cases, MaybeBornVarsDelayedDead),
+	(
+		MaybeBornVarsDelayedDead =
+			yes(BornVarsCases - DelayedDeadCases),
+		set__intersect(BornVarsGoal, BornVarsCases, BornVars),
+		set__intersect(DelayedDeadGoal, DelayedDeadCases, DelayedDead)
+	;
+		MaybeBornVarsDelayedDead = no,
+		BornVars = BornVarsGoal,
+		DelayedDead = DelayedDeadGoal
+	).
+
+% The kill_excess_delayed_dead_* functions are called on each branch of a
+% branched control structure to make sure that all branches kill the same
+% set of variables.
+
+:- func kill_excess_delayed_dead_goal(set(prog_var),
+	pair(hlds_goal, set(prog_var))) = hlds_goal.
+
+kill_excess_delayed_dead_goal(FinalDelayedDead, Goal0 - DelayedDead0) = Goal :-
+	set__difference(DelayedDead0, FinalDelayedDead, ToBeKilled),
+	Goal0 = GoalExpr - GoalInfo0,
+	goal_info_get_post_deaths(GoalInfo0, PostDeath0),
+	set__union(PostDeath0, ToBeKilled, PostDeath),
+	goal_info_set_post_deaths(GoalInfo0, PostDeath, GoalInfo),
+	Goal = GoalExpr - GoalInfo.
+
+:- func kill_excess_delayed_dead_case(set(prog_var),
+	pair(case, set(prog_var))) = case.
+
+kill_excess_delayed_dead_case(FinalDelayedDead,
+		case(ConsId, Goal0) - DelayedDead0) = case(ConsId, Goal) :-
+	set__difference(DelayedDead0, FinalDelayedDead, ToBeKilled),
+	Goal0 = GoalExpr - GoalInfo0,
+	goal_info_get_post_deaths(GoalInfo0, PostDeath0),
+	set__union(PostDeath0, ToBeKilled, PostDeath),
+	goal_info_set_post_deaths(GoalInfo0, PostDeath, GoalInfo),
+	Goal = GoalExpr - GoalInfo.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
 :- pred detect_resume_points_in_goal(hlds_goal, set(prog_var), live_info,
 		set(prog_var), hlds_goal, set(prog_var)).
 :- mode detect_resume_points_in_goal(in, in, in, in, out, out) is det.
@@ -976,12 +1281,12 @@
 	->
 		true
 	;
-		Varset = LiveInfo^varset,
+		VarSet = LiveInfo ^ varset,
 		set__to_sorted_list(LivenessFirst, FirstVarsList),
 		set__to_sorted_list(LivenessRest, RestVarsList),
-		list__map(varset__lookup_name(Varset),
+		list__map(varset__lookup_name(VarSet),
 			FirstVarsList, FirstVarNames),
-		list__map(varset__lookup_name(Varset),
+		list__map(varset__lookup_name(VarSet),
 			RestVarsList, RestVarNames),
 		Pad = lambda([S0::in, S::out] is det,
 			string__append(S0, " ", S)),
@@ -1071,7 +1376,7 @@
 		% typeinfos need to be added to these.
 	proc_info_typeinfo_varmap(ProcInfo, TVarMap),
 	proc_info_maybe_complete_with_typeinfo_vars(Deadness2,
-		LiveInfo^typeinfo_liveness, VarTypes, TVarMap, Deadness).
+		LiveInfo ^ typeinfo_liveness, VarTypes, TVarMap, Deadness).
 
 :- pred initial_deadness_2(list(prog_var), list(mode), list(type),
 		module_info, set(prog_var), set(prog_var)).
@@ -1126,11 +1431,11 @@
 find_value_giving_occurrences([], _, _, ValueVars, ValueVars).
 find_value_giving_occurrences([Var | Vars], LiveInfo, InstMapDelta,
 		ValueVars0, ValueVars) :-
-	VarTypes = LiveInfo^vartypes,
+	VarTypes = LiveInfo ^ vartypes,
 	map__lookup(VarTypes, Var, Type),
 	(
 		instmap_delta_search_var(InstMapDelta, Var, Inst),
-		ModuleInfo = LiveInfo^module_info,
+		ModuleInfo = LiveInfo ^ module_info,
 		mode_to_arg_mode(ModuleInfo, (free -> Inst), Type, top_out)
 	->
 		set__insert(ValueVars0, Var, ValueVars1)
@@ -1160,8 +1465,8 @@
 
 liveness__maybe_complete_with_typeinfos(LiveInfo, Vars0, Vars) :-
 	proc_info_maybe_complete_with_typeinfo_vars(Vars0,
-		LiveInfo^typeinfo_liveness, LiveInfo^vartypes,
-		LiveInfo^type_info_varmap, Vars).
+		LiveInfo ^ typeinfo_liveness, LiveInfo ^ vartypes,
+		LiveInfo ^ type_info_varmap, Vars).
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -1178,7 +1483,7 @@
 :- pred live_info_init(module_info::in, bool::in, vartypes::in,
 	type_info_varmap::in, prog_varset::in, live_info::out) is det.
 
-live_info_init(ModuleInfo, ProcInfo, TypeInfoLiveness, VarTypes, Varset,
-	live_info(ModuleInfo, ProcInfo, TypeInfoLiveness, VarTypes, Varset)).
+live_info_init(ModuleInfo, ProcInfo, TypeInfoLiveness, VarTypes, VarSet,
+	live_info(ModuleInfo, ProcInfo, TypeInfoLiveness, VarTypes, VarSet)).
 
 %-----------------------------------------------------------------------------%
Index: compiler/options.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/options.m,v
retrieving revision 1.304
diff -u -b -r1.304 options.m
--- compiler/options.m	2000/12/10 07:39:40	1.304
+++ compiler/options.m	2001/01/05 03:05:09
@@ -99,6 +99,7 @@
 		;	trace_optimized
 		;	trace_table_io
 		;	trace_table_io_states
+		;	delay_death
 		;	suppress_trace
 		;	stack_trace_higher_order
 		;	generate_bytecode
@@ -504,6 +505,7 @@
 	trace_table_io		-	bool(no),
 	trace_table_io_states	-	bool(no),
 	suppress_trace		-	string(""),
+	delay_death		-	bool(yes),
 	stack_trace_higher_order -	bool(no),
 	generate_bytecode	-	bool(no),
 	generate_prolog		-	bool(no),
@@ -903,6 +905,7 @@
 long_option("trace-table-io",		trace_table_io).
 long_option("trace-table-io-states",	trace_table_io_states).
 long_option("suppress-trace",		suppress_trace).
+long_option("delay-death",		delay_death).
 long_option("stack-trace-higher-order",	stack_trace_higher_order).
 long_option("generate-bytecode",	generate_bytecode).
 long_option("generate-prolog",		generate_prolog).
@@ -1719,6 +1722,12 @@
 %		"\tWhen tabling I/O actions, table the io__state arguments",
 %		"\ttogether with the others. This should be required iff",
 %		"\tvalues of type io__state actually contain information.",
+		"--no-delay-death",
+		"\tNormally, the compiler preserves the values of variables",
+		"\tas long as possible, even beyond the point where they would",
+		"\tnormally die, in order to make them accessible from as many",
+		"\tdebugger events as possible, when the trace level is `deep'.",
+		"\tHowever, it will not do this if this option is given.",
 		"--stack-trace-higher-order",
 		"\tEnable stack traces through predicates and functions with",
 		"\thigher-order arguments, even if stack tracing is not",
Index: compiler/trace_params.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/trace_params.m,v
retrieving revision 1.3
diff -u -b -r1.3 trace_params.m
--- compiler/trace_params.m	2000/11/10 01:00:56	1.3
+++ compiler/trace_params.m	2001/01/05 03:29:47
@@ -34,6 +34,7 @@
 :- func trace_level_needs_fixed_slots(trace_level) = bool.
 :- func trace_level_needs_from_full_slot(trace_level) = bool.
 :- func trace_level_needs_decl_debug_slots(trace_level) = bool.
+:- func trace_level_allows_delay_death(trace_level) = bool.
 :- func trace_needs_return_info(trace_level, trace_suppress_items) = bool.
 :- func trace_needs_all_var_names(trace_level, trace_suppress_items) = bool.
 :- func trace_needs_proc_body_reps(trace_level, trace_suppress_items) = bool.
@@ -97,6 +98,12 @@
 trace_level_needs_decl_debug_slots(deep) = no.
 trace_level_needs_decl_debug_slots(decl) = yes.
 trace_level_needs_decl_debug_slots(decl_rep) = yes.
+
+trace_level_allows_delay_death(none) = no.
+trace_level_allows_delay_death(shallow) = no.
+trace_level_allows_delay_death(deep) = yes.
+trace_level_allows_delay_death(decl) = yes.
+trace_level_allows_delay_death(decl_rep) = yes.
 
 trace_needs_return_info(TraceLevel, TraceSuppressItems) = Need :-
 	(
cvs diff: Diffing compiler/notes
cvs diff: Diffing debian
cvs diff: Diffing doc
Index: doc/user_guide.texi
===================================================================
RCS file: /home/mercury1/repository/mercury/doc/user_guide.texi,v
retrieving revision 1.229
diff -u -b -r1.229 user_guide.texi
--- doc/user_guide.texi	2001/01/01 04:03:41	1.229
+++ doc/user_guide.texi	2001/01/05 03:05:39
@@ -3140,10 +3140,12 @@
 @item --trace-optimized
 Do not disable optimizations that can change the trace.
 
- at c --trace-decl is commented out in the absence of runtime support
- at c @item --trace-decl
- at c Make the generated tracing code include support
- at c for an experimental declarative debugger.
+ at item --no-delay-death
+Normally, the compiler preserves the values of variables
+as long as possible, even beyond the point where they would
+normally die, in order to make them accessible from as many
+debugger events as possible, when the trace level is @samp{deep}.
+However, it will not do this if this option is given.
 
 @item --stack-trace-higher-order
 Enable stack traces through predicates and functions with
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/curses
cvs diff: Diffing extras/curses/sample
cvs diff: Diffing extras/dynamic_linking
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/lazy_evaluation
cvs diff: Diffing extras/logged_output
cvs diff: Diffing extras/moose
cvs diff: Diffing extras/moose/samples
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/references
cvs diff: Diffing extras/references/samples
cvs diff: Diffing extras/references/tests
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 library
cvs diff: Diffing profiler
cvs diff: Diffing robdd
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 samples/muz
cvs diff: Diffing samples/rot13
cvs diff: Diffing samples/solutions
cvs diff: Diffing samples/tests
cvs diff: Diffing samples/tests/c_interface
cvs diff: Diffing samples/tests/c_interface/c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/cplusplus_calls_mercury
cvs diff: Diffing samples/tests/c_interface/mercury_calls_c
cvs diff: Diffing samples/tests/c_interface/mercury_calls_cplusplus
cvs diff: Diffing samples/tests/c_interface/mercury_calls_fortran
cvs diff: Diffing samples/tests/c_interface/simpler_c_calls_mercury
cvs diff: Diffing samples/tests/c_interface/simpler_cplusplus_calls_mercury
cvs diff: Diffing samples/tests/diff
cvs diff: Diffing samples/tests/muz
cvs diff: Diffing samples/tests/rot13
cvs diff: Diffing samples/tests/solutions
cvs diff: Diffing samples/tests/toplevel
cvs diff: Diffing scripts
cvs diff: Diffing 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/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/tabling
cvs diff: Diffing tests/term
cvs diff: Diffing tests/valid
cvs diff: Diffing tests/warnings
cvs diff: Diffing tools
cvs diff: Diffing trace
cvs diff: Diffing trial
cvs diff: Diffing util
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list