[m-rev.] optimize MLDS heap reclamation code
Fergus Henderson
fjh at cs.mu.OZ.AU
Wed Nov 28 02:14:46 AEDT 2001
Estimated hours taken: 2
Branches: main
compiler/add_heap_ops.m:
Avoid saving and restoring the heap pointer across goals which
are known not to allocate any heap space.
Workspace: /home/earth/fjh/ws-earth4/mercury
Index: compiler/add_heap_ops.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/add_heap_ops.m,v
retrieving revision 1.1
diff -u -d -r1.1 add_heap_ops.m
--- compiler/add_heap_ops.m 26 Nov 2001 09:30:55 -0000 1.1
+++ compiler/add_heap_ops.m 27 Nov 2001 13:06:16 -0000
@@ -40,7 +40,7 @@
:- import_module prog_data, prog_util, (inst).
:- import_module hlds_goal, hlds_data.
:- import_module goal_util, quantification, modules, type_util.
-:- import_module instmap.
+:- import_module instmap, code_model, code_util.
:- import_module bool, string.
:- import_module assoc_list, list, map, set, varset, std_util, require, term.
@@ -100,18 +100,34 @@
goal_expr_add_heap_ops(disj([], B), GI, disj([], B) - GI) --> [].
goal_expr_add_heap_ops(disj(Goals0, B), GoalInfo, Goal - GoalInfo) -->
- { Goals0 = [_|_] },
+ { Goals0 = [FirstDisjunct | _] },
{ goal_info_get_context(GoalInfo, Context) },
+ { goal_info_get_code_model(GoalInfo, CodeModel) },
%
- % Save the heap pointer so that we can
+ % If necessary, save the heap pointer so that we can
% restore it on back-tracking.
+ % We don't need to do this here if it is a model_det or model_semi
+ % disjunction and the first disjunct won't allocate any heap --
+ % in that case, we delay saving the heap pointer until just before
+ % the first disjunct that might allocate heap.
%
- new_saved_hp_var(SavedHeapPointerVar),
- gen_mark_hp(SavedHeapPointerVar, Context, MarkHeapPointerGoal),
- disj_add_heap_ops(Goals0, yes, SavedHeapPointerVar, Goals),
- { Goal = conj([MarkHeapPointerGoal, disj(Goals, B) - GoalInfo]) }.
+ (
+ { CodeModel = model_non
+ ; code_util__goal_may_allocate_heap(FirstDisjunct)
+ }
+ ->
+ new_saved_hp_var(SavedHeapPointerVar),
+ gen_mark_hp(SavedHeapPointerVar, Context, MarkHeapPointerGoal),
+ disj_add_heap_ops(Goals0, yes, yes(SavedHeapPointerVar),
+ GoalInfo, Goals),
+ { Goal = conj([MarkHeapPointerGoal, disj(Goals, B) -
+ GoalInfo]) }
+ ;
+ disj_add_heap_ops(Goals0, yes, no, GoalInfo, Goals),
+ { Goal = disj(Goals, B) }
+ ).
goal_expr_add_heap_ops(switch(A, B, Cases0, D), GI,
switch(A, B, Cases, D) - GI) -->
@@ -154,21 +170,29 @@
goal_add_heap_ops(Then0, Then),
goal_add_heap_ops(Else0, Else1),
%
- % Save the heap pointer so that we can
+ % If the condition can allocate heap space,
+ % save the heap pointer so that we can
% restore it if the condition fails.
%
- new_saved_hp_var(SavedHeapPointerVar),
- { goal_info_get_context(GoalInfo, Context) },
- gen_mark_hp(SavedHeapPointerVar, Context, MarkHeapPointerGoal),
- %
- % Generate code to restore the heap pointer,
- % and insert that code at the start of the Else branch.
- %
- gen_restore_hp(SavedHeapPointerVar, Context, RestoreHeapPointerGoal),
- { Else1 = _ - Else1GoalInfo },
- { Else = conj([RestoreHeapPointerGoal, Else1]) - Else1GoalInfo },
- { IfThenElse = if_then_else(A, Cond, Then, Else, E) - GoalInfo },
- { Goal = conj([MarkHeapPointerGoal, IfThenElse]) }.
+ ( { code_util__goal_may_allocate_heap(Cond0) } ->
+ new_saved_hp_var(SavedHeapPointerVar),
+ { goal_info_get_context(GoalInfo, Context) },
+ gen_mark_hp(SavedHeapPointerVar, Context, MarkHeapPointerGoal),
+ %
+ % Generate code to restore the heap pointer,
+ % and insert that code at the start of the Else branch.
+ %
+ gen_restore_hp(SavedHeapPointerVar, Context,
+ RestoreHeapPointerGoal),
+ { Else1 = _ - Else1GoalInfo },
+ { Else = conj([RestoreHeapPointerGoal, Else1]) -
+ Else1GoalInfo },
+ { IfThenElse = if_then_else(A, Cond, Then, Else, E) -
+ GoalInfo },
+ { Goal = conj([MarkHeapPointerGoal, IfThenElse]) }
+ ;
+ { Goal = if_then_else(A, Cond, Then, Else1, E) }
+ ).
goal_expr_add_heap_ops(call(A,B,C,D,E,F), GI, call(A,B,C,D,E,F) - GI) --> [].
@@ -208,37 +232,59 @@
conj_add_heap_ops(Goals0, Goals) -->
list__map_foldl(goal_add_heap_ops, Goals0, Goals).
-:- pred disj_add_heap_ops(hlds_goals::in, bool::in, prog_var::in,
- hlds_goals::out, heap_ops_info::in, heap_ops_info::out) is det.
+:- pred disj_add_heap_ops(hlds_goals::in, bool::in, maybe(prog_var)::in,
+ hlds_goal_info::in, hlds_goals::out,
+ heap_ops_info::in, heap_ops_info::out) is det.
-disj_add_heap_ops([], _, _, []) --> [].
-disj_add_heap_ops([Goal0 | Goals0], IsFirstBranch,
- SavedHeapPointerVar, [Goal | Goals]) -->
- { Goal0 = _ - GoalInfo0 },
- { goal_info_get_context(GoalInfo0, Context) },
+disj_add_heap_ops([], _, _, _, []) --> [].
+disj_add_heap_ops([Goal0 | Goals0], IsFirstBranch, MaybeSavedHeapPointerVar,
+ DisjGoalInfo, DisjGoals) -->
+ goal_add_heap_ops(Goal0, Goal1),
+ { Goal1 = _ - GoalInfo },
+ { goal_info_get_context(GoalInfo, Context) },
%
- % First reset the heap pointer to
- % undo the effects of any earlier branches
+ % If needed, reset the heap pointer before executing the goal,
+ % to reclaim heap space allocated in earlier branches.
%
- ( { IsFirstBranch = yes } ->
- { UndoList = [] }
- ;
- gen_restore_hp(SavedHeapPointerVar, Context,
+ (
+ { IsFirstBranch = no },
+ { MaybeSavedHeapPointerVar = yes(SavedHeapPointerVar0) }
+ ->
+ gen_restore_hp(SavedHeapPointerVar0, Context,
RestoreHeapPointerGoal),
- { UndoList = [RestoreHeapPointerGoal] }
+ { conj_list_to_goal([RestoreHeapPointerGoal, Goal1], GoalInfo,
+ Goal) }
+ ;
+ { Goal = Goal1 }
),
+
%
- % Then execute the disjunct goal
- %
- goal_add_heap_ops(Goal0, Goal1),
- %
- % Package up the stuff we built earlier.
+ % Save the heap pointer, if we haven't already done so,
+ % and if this disjunct might allocate heap space.
%
- { Goal1 = _ - GoalInfo1 },
- { conj_list_to_goal(UndoList ++ [Goal1], GoalInfo1, Goal) },
-
- % Recursively handle the remaining disjuncts
- disj_add_heap_ops(Goals0, no, SavedHeapPointerVar, Goals).
+ (
+ { MaybeSavedHeapPointerVar = no },
+ { code_util__goal_may_allocate_heap(Goal) }
+ ->
+ % Generate code to save the heap pointer
+ new_saved_hp_var(SavedHeapPointerVar),
+ gen_mark_hp(SavedHeapPointerVar, Context, MarkHeapPointerGoal),
+ % Recursively handle the remaining disjuncts
+ disj_add_heap_ops(Goals0, no, yes(SavedHeapPointerVar),
+ DisjGoalInfo, Goals1),
+ % Put this disjunct and the remaining disjuncts in a
+ % nested disjunction, so that the heap pointer variable
+ % can scope over these disjuncts
+ { map__init(StoreMap) },
+ { Disj = disj([Goal | Goals1], StoreMap) - DisjGoalInfo },
+ { DisjGoals = [conj([MarkHeapPointerGoal, Disj]) -
+ DisjGoalInfo] }
+ ;
+ % Just recursively handle the remaining disjuncts
+ disj_add_heap_ops(Goals0, no, MaybeSavedHeapPointerVar,
+ DisjGoalInfo, Goals),
+ { DisjGoals = [Goal | Goals] }
+ ).
:- pred cases_add_heap_ops(list(case)::in, list(case)::out,
heap_ops_info::in, heap_ops_info::out) is det.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
The University of Melbourne | of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list