[m-rev.] Retry added in ssdb

Peter Wang novalazy at gmail.com
Fri Nov 9 11:34:22 AEDT 2007


On 2007-11-08, Olivier Annet <oan at missioncriticalit.com> wrote:
> Hi,
> 
> could someone review my code before commiting please.
> 
> Olivier.
> 
> ===================================================================
> 
> 
> Estimated hours taken: 24
> Branches: main
> 
> Modification of the source-to-source debugger to manage the retry command.

Implement the retry command in the source-to-source debugger.

> 
> compiler/ssdebug.m:
> 	Create an output variable and modify each call to the handle_event 
> 	function at exit and fail port to support the retry command. Create 
> 	the switch at exit and fail port in the source-to-source code.

Make the transformed code switch on the variable at exit and fail ports,
retrying the procedure call as the user wishes.

> 
> ssdb/ssdb.m:
> 	Somme modifications have been added to support the retry at exit and
> 	fail port.

Some

> 	A new type ssdb_retry has been added. It is used to set the output 
> 	variable Retry used for the switch in the source-to-source code at
> 	exit and fail port.
> 


> Index: compiler/ssdebug.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/ssdebug.m,v
> retrieving revision 1.9
> diff -u -r1.9 ssdebug.m
> --- compiler/ssdebug.m	1 Nov 2007 06:23:22 -0000	1.9
> +++ compiler/ssdebug.m	8 Nov 2007 02:15:02 -0000
> @@ -266,35 +256,41 @@
> -        %
> -        % Generate the call to handle_event_exit(ProcId, VarList).
> -        %
> -        make_handle_event("exit", [ProcIdVar, ExitArgListVar], 
> -            HandleEventExitGoal, !ModuleInfo, !Varset, !Vartypes),
> +        % Create DoRetry output variable

Full stop.

> +        make_retry_var("", RetryVar, !Varset, !Vartypes),

See later.

>  
> +        % Generate the call to handle_event_exit(ProcId, VarList, DoRetry).
> +        make_handle_event("exit", [ProcIdVar, ExitArgListVar, RetryVar], 
> +            HandleEventExitGoal, !ModuleInfo, !Varset, !Vartypes),
>  
> -        %
> +        % Generate the recursive call in the case of a retry
> +        make_recursive_call(!.PredInfo, !.ModuleInfo, PredId, ProcId, HeadVars, 
> +            HeadGoal),

Rename HeadGoal.

> +        
>          % Organize the order of the generated code.
>          % XXX Need optimization in list append.
>          goal_to_conj_list(BodyGoal1, BodyGoalList),
> -        ConjGoals = ProcIdGoals ++ CallArgListGoals ++ 
> -            [HandleEventCallGoal] ++ BodyGoalList ++ ExitArgListGoals ++ 
> -            [HandleEventExitGoal | RenamingGoals],
> -
>          % Set the determinism.
>          Determinism = detism_det,
>          goal_info_init(GoalInfo0),
>          goal_info_set_determinism(Determinism, GoalInfo0, GoalInfo),
> -        
> +
> +        conj_list_to_goal(RenamingGoals, GoalInfo, RenamingGoal),
> +        % Create the switch on Retry at exit port.
> +        make_switch_call(RetryVar, HeadGoal, RenamingGoal, GoalInfo, 
> +            SwitchGoal),
> +
> +        ConjGoals = ProcIdGoals ++ CallArgListGoals ++ 
> +            [HandleEventCallGoal | BodyGoalList] ++ ExitArgListGoals ++ 
> +            [HandleEventExitGoal, SwitchGoal],
> + 
>          conj_list_to_goal(ConjGoals, GoalInfo, GoalWithoutPurity),
>  
>          % Add the purity scope.
> @@ -364,46 +348,61 @@
> +        % Create DoRetryA output variable
> +        make_retry_var("A", RetryAVar, !Varset, !Vartypes),
>  
> -        %
> -        % Generate the call to handle_event_exit(ProcId, VarList).
> -        %
> -        make_handle_event("exit", [ProcIdVar, ExitArgListVar], 
> +        % Generate the call to handle_event_exit(ProcId, VarList, DoRetryA).
> +        make_handle_event("exit", [ProcIdVar, ExitArgListVar, RetryAVar], 
>              HandleEventExitGoal, !ModuleInfo, !Varset, !Vartypes),
>  
> +        % Generate the recursive call in the case of a retry
> +        make_recursive_call(!.PredInfo, !.ModuleInfo, PredId, ProcId, HeadVars, 
> +            HeadGoal),
>  
> -        %
>          % Generate the list of arguments at the fail port.
> -        %
>          make_arg_list(0, InitInstMap, [], Renaming, FailArgListVar, 
>              FailArgListGoals, !ModuleInfo, !ProcInfo, !PredInfo, !Varset, 
>              !Vartypes, BoundVarDescsAtCall, _BoundVarDescsAtFail),
>  
> -        %
> -        % Generate the call to handle_event_fail(ProcId, VarList).
> -        %
> -        make_handle_event("fail", [ProcIdVar, FailArgListVar], 
> +        % Create DoRetryA output variable
> +        make_retry_var("B", RetryBVar, !Varset, !Vartypes),
> +
> +        % Generate the call to handle_event_fail(ProcId, VarList, DoRetryB).
> +        make_handle_event("fail", [ProcIdVar, FailArgListVar, RetryBVar], 
>              HandleEventFailGoal, !ModuleInfo, !Varset, !Vartypes),
>  
>          make_fail_call(FailGoal, !.ModuleInfo),
>          
> -        %
>          % Organize the order of the generated code.
>          % XXX Need optimization in list append.
>  
>          % Get a flattened goal to avoid nested conjuction.
>          goal_to_conj_list(BodyGoal1, BodyGoalList),
>          GoalsCond   = BodyGoalList,
> -        GoalsThen   = ExitArgListGoals ++ [HandleEventExitGoal| RenamingGoals],
> -        GoalsElse   = FailArgListGoals ++ [HandleEventFailGoal, FailGoal],
> +        
> +        % Create the switch on DoRetryA at exit port.
> +        Determinism = detism_det,
> +        goal_info_init(GoalInfo1),
> +        goal_info_set_determinism(Determinism, GoalInfo1, GoalInfo),
> +        conj_list_to_goal(RenamingGoals, GoalInfo, RenamingGoal),
> +        make_switch_call(RetryAVar, HeadGoal, RenamingGoal, GoalInfo, 
> +            SwitchExitPortGoal),
> +        
> +        % Create the switch on DoRetryB at fail port.
> +        make_switch_call(RetryBVar, HeadGoal, FailGoal, GoalInfo, 
> +            SwitchFailPortGoal),
> +
> +        GoalsThen   = ExitArgListGoals ++ 
> +            [HandleEventExitGoal, SwitchExitPortGoal],
> +        GoalsElse   = FailArgListGoals ++ 
> +            [HandleEventFailGoal, SwitchFailPortGoal],
>  
>          goal_info_init(GoalInfo0),
>          goal_list_determinism(GoalsCond, Detism),
> @@ -426,10 +425,6 @@
>          GoalWithoutPurity = hlds_goal(conj(plain_conj, ConjGoal), 
>              GoalInfoCond),
>          
> -        Determinism = detism_det,
> -        goal_info_init(GoalInfo1),
> -        goal_info_set_determinism(Determinism, GoalInfo1, GoalInfo),
> -
>          % Add the purity scope.
>          Purity = goal_info_get_purity(BodyGoalInfo0),        
>          wrap_with_purity_scope(Purity, GoalInfo, GoalWithoutPurity, Goal),
> @@ -497,43 +480,38 @@
> +        
> +        % Create DoRetryA output variable
> +        make_retry_var("A", RetryAVar, !Varset, !Vartypes),
>  
> -        %
> -        % Generate the call to handle_event_exit(ProcId, VarList).
> -        %
> -        make_handle_event("exit", [ProcIdVar, ExitArgListVar], 
> +        % Generate the call to handle_event_exit(ProcId, VarList, DoRetryA).
> +        make_handle_event("exit", [ProcIdVar, ExitArgListVar, RetryAVar], 
>              HandleEventExitGoal, !ModuleInfo, !Varset, !Vartypes),
>          
> -        %
>          % Generate the call to handle_event_redo(ProcId, VarList).
> -        %
>          make_handle_event("redo", [ProcIdVar, ExitArgListVar], 
>              HandleEventRedoGoal, !ModuleInfo, !Varset, !Vartypes),
>  
> -        %
>          % Generate the list of argument at the fail port.
> -        %
>          make_arg_list(0, InitInstMap, [], Renaming, FailArgListVar, 
>              FailArgListGoals, !ModuleInfo, !ProcInfo, !PredInfo, !Varset, 
>              !Vartypes, BoundVarDescsAtCall, _BoundVarDescsAtFail),
>  
> -        %
> -        % Generate the call to handle_event_fail(ProcId, VarList).
> -        %
> -        make_handle_event("fail", [ProcIdVar, FailArgListVar], 
> +        % Create DoRetryB output variable
> +        make_retry_var("B", RetryBVar, !Varset, !Vartypes),
> +
> +        % Generate the call to handle_event_fail(ProcId, VarList, DoRetryB).
> +        make_handle_event("fail", [ProcIdVar, FailArgListVar, RetryBVar], 
>              HandleEventFailGoal, !ModuleInfo, !Varset, !Vartypes),
>  
>          make_fail_call(FailGoal, !.ModuleInfo),
>  
> @@ -541,29 +519,45 @@
>          goal_to_conj_list(BodyGoal1, BodyGoalList1),
>          CallVarGoal0 = CallArgListGoals ++ 
>              [HandleEventCallGoal | BodyGoalList1] ++ ExitArgListGoals,
> -        goal_info_init(GoalInfo),
> -        conj_list_to_goal(CallVarGoal0, GoalInfo, CallVarGoal1),
> +        goal_info_init(GoalInfo0),
> +        conj_list_to_goal(CallVarGoal0, GoalInfo0, CallVarGoal1),
>          goal_to_conj_list(CallVarGoal1, CallVarGoal),
>          
> +        % Generate the recursive call in the case of a retry
> +        make_recursive_call(!.PredInfo, !.ModuleInfo, PredId, ProcId, HeadVars, 
> +            HeadGoal),
> +
> +        % Create the switch on DoRetryA at exit port.
> +        Determinism = detism_det,
> +        goal_info_set_determinism(Determinism, GoalInfo0, GoalInfo),
> +        conj_list_to_goal(RenamingGoals, GoalInfo, RenamingGoal),
> +        make_switch_call(RetryAVar, HeadGoal, RenamingGoal, GoalInfo, 
> +            SwitchExitPortGoal),
> +        
> +        % Create the switch on DoRetryB at fail port.
> +        make_switch_call(RetryBVar, HeadGoal, FailGoal, GoalInfo, 
> +            SwitchFailPortGoal),
> +
>          ConjGoal11 = hlds_goal(conj(plain_conj, 
> -            [HandleEventExitGoal| RenamingGoals]), GoalInfo),
> +            [HandleEventExitGoal, SwitchExitPortGoal]), GoalInfo0),
>          ConjGoal120 = hlds_goal(conj(plain_conj, 
> -            [HandleEventRedoGoal, FailGoal]), GoalInfo),
> +            [HandleEventRedoGoal, FailGoal]), GoalInfo0),
>          goal_add_feature(feature_preserve_backtrack_into, ConjGoal120, 
>              ConjGoal12),
> -        DisjGoal1 = hlds_goal(disj([ConjGoal11, ConjGoal12]), GoalInfo),
> +        DisjGoal1 = hlds_goal(disj([ConjGoal11, ConjGoal12]), GoalInfo0),
>  
>          ConjGoal21 = hlds_goal(conj(plain_conj, 
> -            CallVarGoal ++ [DisjGoal1]), GoalInfo),
> +            CallVarGoal ++ [DisjGoal1]), GoalInfo0),
>          ConjGoal220 = hlds_goal(conj(plain_conj, 
> -            FailArgListGoals ++ [HandleEventFailGoal, FailGoal]), GoalInfo), 
> +            FailArgListGoals ++ [HandleEventFailGoal, SwitchFailPortGoal]), 
> +            GoalInfo0), 
>          goal_add_feature(feature_preserve_backtrack_into, ConjGoal220, 
>              ConjGoal22),
>          DisjGoal2 = hlds_goal(disj([ConjGoal21, ConjGoal22]), 
> -            GoalInfo),
> +            GoalInfo0),
>  
>          GoalWithoutPurity = hlds_goal(conj(plain_conj, 
> -            ProcIdGoals ++ [DisjGoal2]), GoalInfo),
> +            ProcIdGoals ++ [DisjGoal2]), GoalInfo0),
>  
>          % Add the purity scope.
>          Purity = goal_info_get_purity(BodyGoalInfo0),
> @@ -572,9 +566,64 @@
>          commit_goal_changes(Goal, PredId, ProcId, !.PredInfo, !ProcInfo,
>              !ModuleInfo, !.Varset, !.Vartypes)
>      ).
> -        
>  
> +
> +    %
> +    % Create the output variable DoRetry.
>      %
> +:- pred make_retry_var(string::in, prog_var::out, 
> +    prog_varset::in, prog_varset::out, vartypes::in, vartypes::out) is det.
> +
> +make_retry_var(String, RetryVar, !VarSet, !VarTypes) :-
> +    SSDBModule = mercury_ssdb_builtin_module,
> +    TypeCtor = type_ctor(qualified(SSDBModule, "ssdb_retry"), 0),
> +    construct_type(TypeCtor, [], RetryType),
> +    Name = "DoRetry" ++ String,

Pass the full variable name to this predicate.

> +    svvarset.new_named_var(Name, RetryVar, !VarSet),
> +    svmap.det_insert(RetryVar, RetryType, !VarTypes).
> +
> +
> +    %
> +    % Create the goal for recursive call in the case of a retry.
> +    %
> +:- pred make_recursive_call(pred_info::in, module_info::in, pred_id::in, 
> +    proc_id::in, list(prog_var)::in, hlds_goal::out) is det.
> +
> +make_recursive_call(PredInfo, ModuleInfo, PredId, ProcId, HeadVars, 
> +    Goal) :-

Indent.

> +    PredName = pred_info_name(PredInfo),
> +    ModuleName = pred_info_module(PredInfo),
> +    SymName = qualified(ModuleName, PredName),
> +    BuiltIn = builtin_state(ModuleInfo, PredId, PredId, ProcId),
> +    GoalExpr = plain_call(PredId, ProcId, HeadVars, BuiltIn, no, 
> +        SymName),
> +    goal_info_init(GoalInfoHG),
> +    Goal = hlds_goal(GoalExpr, GoalInfoHG).
> +
> +
> +    %
> +    % make_switch_call(SwitchVar, SwitchCase1, SwitchCase2, GoalInfo, Goal).
> +    %
> +    % Create the switch Goal.
> +    %
> +:- pred make_switch_call(prog_var::in, hlds_goal::in, hlds_goal::in, 
> +    hlds_goal_info::in, hlds_goal::out) is det.

Rename this predicate and improve the comment.

> +
> +make_switch_call(SwitchVar, DoRetryGoal, DoNotRetryGoal, GoalInfo, 
> +    SwitchGoal) :-

Indent.


> Index: ssdb/ssdb.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/ssdb/ssdb.m,v
> retrieving revision 1.9
> diff -u -r1.9 ssdb.m
> --- ssdb/ssdb.m	1 Nov 2007 06:23:22 -0000	1.9
> +++ ssdb/ssdb.m	8 Nov 2007 02:15:02 -0000
> @@ -35,6 +35,13 @@
>      ;       ssdb_fail
>      .
>  
> +
> +:- type ssdb_retry
> +    --->    do_retry
> +    ;       do_not_retry
> +    .
> +
> +
>      %
>      % The list of all variables in use in a procedure.
>      %
> @@ -68,12 +75,14 @@
>      %
>      % This routine is called at each exit event that occurs.
>      %
> -:- impure pred handle_event_exit(ssdb_proc_id::in, list_var_value::in) is det.
> +:- impure pred handle_event_exit(ssdb_proc_id::in, list_var_value::in, 
> +    ssdb_retry::out) is det.
>  
>      %
>      % This routine is called at each fail event that occurs.
>      %
> -:- impure pred handle_event_fail(ssdb_proc_id::in, list_var_value::in) is det.
> +:- impure pred handle_event_fail(ssdb_proc_id::in, list_var_value::in, 
> +    ssdb_retry::out) is det.
>  
>      %
>      % This routine is called at each redo event that occurs.
> @@ -136,7 +146,14 @@
>      --->    wn_step
>      ;       wn_next
>      ;       wn_continue
> -    ;       wn_finish(int).
> +    ;       wn_finish(int)
> +    ;       wn_retry(int).
> +
> +:- inst what_next_no_retry
> +    --->    wn_step
> +    ;       wn_next
> +    ;       wn_continue
> +    ;       wn_finish(ground).
>  
>  
>      %
> @@ -147,7 +164,7 @@
>      --->    ns_step
>      ;       ns_next(int)
>      ;       ns_continue
> -    ;       ns_final_port(int).
> +    ;       ns_final_port(int, ssdb_retry).

Explain what the arguments are.

> @@ -260,11 +278,17 @@
>              print_event_info(Event, EventNum, ProcId, PrintDepth, CSN, !IO),  
>           
>              semipure get_shadow_stack(ShadowStack),
> -            impure prompt(Event, ShadowStack, 0, WhatNext, !IO),
> +            (
> +                AutoRetry = do_retry
> +            ->
> +                WhatNext = wn_retry(CSN)
> +            ;
> +                impure prompt(Event, ShadowStack, 0, WhatNext, !IO)
> +            ),

Use a switch.

> @@ -295,7 +320,7 @@
>   
>      CSN = StackFrame ^ se_initial_state ^ ssdb_csn,
>  
> -    set_stop(Event, CSN, State0, ProcId, Stop),
> +    set_stop(Event, CSN, State0, ProcId, Stop, AutoRetry),
>      (
>          Stop = yes,
>          some [!IO] 
> @@ -305,11 +330,17 @@
>              print_event_info(Event, EventNum, ProcId, PrintDepth, CSN, !IO),  
>           
>              semipure get_shadow_stack(ShadowStack),
> -            impure prompt(Event, ShadowStack, 0, WhatNext, !IO),
> +            (
> +                AutoRetry = do_retry
> +            ->
> +                WhatNext = wn_retry(CSN)
> +            ;
> +                impure prompt(Event, ShadowStack, 0, WhatNext, !IO)
> +            ),

Switch.

> @@ -490,17 +557,19 @@
>      % Set Stop, if Stop equals yes, we will call the prompt.
>      %
>  :- pred set_stop(ssdb_event_type::in, int::in, debugger_state::in, 
> -    ssdb_proc_id::in, bool::out) is det.
> +    ssdb_proc_id::in, bool::out, ssdb_retry::out) is det.
>  
> -set_stop(Event, CSN, State, ProcId, ShouldStopAtEvent) :-
> +set_stop(Event, CSN, State, ProcId, ShouldStopAtEvent, AutoRetry) :-

This predicate should be renamed.

> @@ -527,6 +597,58 @@
>      ).
>  
>  
> +    %
> +    % set_next_stop(CSN, WhatNext, ShadowStack, NextStop, Retry).
> +    %
> +    % Set the NextStop and the Retry variable according to the WhatNext value.
> +    % In the case where the WathNext is set for a retry, it modify the 
> +    % debugger_state at his old value which it had at the call point.
> +    %
> +:- impure pred set_next_stop(int::in, what_next::in, stack(stack_elem)::in, 
> +    next_stop::out, ssdb_retry::out) is det.
> +

Try to name that better.

> +set_next_stop(CSN, WhatNext, ShadowStack, NextStop, Retry) :-
> +    (
> +        WhatNext = wn_step,
> +        NextStop = ns_step,
> +        Retry = do_not_retry
> +    ;
> +        WhatNext = wn_next,
> +        NextStop = ns_next(CSN),
> +        Retry = do_not_retry
> +    ;
> +        WhatNext = wn_continue,
> +        NextStop = ns_continue,
> +        Retry = do_not_retry
> +    ;
> +        WhatNext = wn_finish(EndCSN),
> +        NextStop = ns_final_port(EndCSN, do_not_retry),
> +        Retry = do_not_retry
> +    ;
> +        WhatNext = wn_retry(RetryCSN),
> +        (
> +            RetryCSN = CSN
> +        ->
> +            NextStop = ns_step,
> +            Retry = do_retry,
> +            % Set the debugger state for the retry
> +            stack.top_det(ShadowStack, FrameStack),
> +            SetCSN0 = FrameStack ^ se_initial_state ^ ssdb_csn,
> +            SetEventNum0 = FrameStack ^ se_initial_state ^ ssdb_event_number,
> +            SetCSN = SetCSN0 - 1,
> +            SetEventNum = SetEventNum0 - 1,
> +            impure set_csn(SetCSN),
> +            impure set_event_num(SetEventNum)

You don't need those extra variables.

> @@ -697,6 +804,18 @@
>                  impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
>              )
>  
> +        ; Words = ["r"] ->
> +            (
> +                ( Event = ssdb_exit
> +                ; Event = ssdb_fail
> +                ) ->
> +                stack.top_det(ShadowStack, FrameStack),
> +                CSN = FrameStack ^ se_initial_state ^ ssdb_csn,
> +                WhatNext = wn_retry(CSN)        
> +            ;
> +                io.write_string("Impossible at call or redo port\n", !IO),
> +                impure prompt(Event, ShadowStack, Depth, WhatNext, !IO)
> +            )

Switch.

Peter

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list