[m-dev.] for review: delaying death

Mark Anthony BROWN dougl at cs.mu.OZ.AU
Tue Jan 9 06:10:43 AEDT 2001


Zoltan Somogyi writes:
> 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:

s/doc_/doc/

> 	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,

s/its delay/its death/

> +% 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'.",

Someone reading this may miss the qualification "when the trace level is
`deep'" because it is right at the end.  I would change that to something
like:

	When the trace level is `deep', the compiler normally preserves ...

Also, the second occurrence of "normally" might be a bit confusing.  Perhaps
you could say "the point where they would die if the trace level was `none'"?

> +		"\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.

See above.

>  
>  @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
> --------------------------------------------------------------------------
> 

--------------------------------------------------------------------------
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