[m-rev.] for review: add --resume dd option
Julien Fischer
juliensf at cs.mu.OZ.AU
Thu Feb 24 16:32:37 AEDT 2005
On Thu, 24 Feb 2005, Ian MacLarty wrote:
> For review by anyone.
>
> Estimated hours taken: 25
> Branches: main
>
> Add --resume option to `dd' command. This resumes the previous declarative
> debugging session and allows the user to switch between the procedural and
> declarative debuggers freely.
>
> browser/declarative_analyser.m
> Add analysis_type type which is used to tell the analyser whether
> it must start a new session or resume a previous session.
>
> browser/declarative_debugger.m
> Add two versions of the exported diagnosis predicate: one to
> resume a previous session and one to start a new session.
>
> browser/declarative_user.m
> Print usage message to the correct output stream.
>
> runtime/mercury_stack_trace.c
> runtime/mercury_stack_trace.h
> Add a function to find the first call on the stack whose event
> number is less than or equal to a given event number or whose
> call sequence number is less than or equal to a given call sequence
> number.
>
> Since this new function uses some code very similar to existing
> code in the function that prints the stack, seperate this code into
> a new function called MR_call_details_are_valid.
>
> trace/mercury_trace_declarative.c
> trace/mercury_trace_declarative.h
> Previously it could be safely assumed that the current event would
> be somewhere inside the materialized portion of the annotated trace,
> so it was sufficient to record the topmost node of the annotated
> trace and retry to there whenever we needed to build a new subtree
> (and to the topmost node plus some extra for a supertree).
>
> Now, however, the user may go to any event in the program before
> resuming the previous dd session. We could just retry to the call
> event for main/2, but this would be far from optimal, especially if the
> user is debugging code deep down in the program's call tree.
>
> Instead we retry to the first call on the stack whose event number
> is less than or equal to the call event number of the node we
> want to build a subtree for and then start forward execution from
> there. When building a supertree we retry to the first call on the
> stack whose event number is less than or equal to the event number of
> the call at the top of the currently materialized portion of the
> annotated trace. Then when we get to the call at the top of the
> currently materialized portion of the annotated trace through forward
> execution, we do a retry to the desired depth and start building the
> new supertree.
>
> Desribe the function of some of the global variables in more detail.
>
> Remove the global MR_edt_topmost_call_depth since it is no longer
> needed.
>
> Fix an inconsistency where the depth limit was being set to
> MR_edt_depth_step_size when starting a dd session, but to
> MR_edt_depth_step_size + 1 when building an additional portion of the
> annotated trace.
>
> tests/debugger/declarative/Mmakefile
> tests/debugger/declarative/resume.exp
> tests/debugger/declarative/resume.inp
> tests/debugger/declarative/resume.m
> Test the --resume option. Specifically test the creation of a
> supertree and subtree from a resumed session where the user
> has gone to an event before and after the materialized portion
> of the annotated trace.
>
> trace/mercury_trace_internal.c
> Handle the --resume option.
>
Do you need to update the user guide as well?
...
> @@ -557,10 +558,10 @@
> :- pragma export(mdb.declarative_debugger.divide_and_query_search_mode = out,
> "MR_DD_decl_divide_and_query_search_mode").
>
> - % Export a monomorphic version of diagnosis/10, to make it
> - % easier to call from C code.
> + % Export a monomorphic version of diagnosis/10 that passes a newly
> + % materialized tree for use with the C backend code.
> %
> -:- pred diagnosis_store(trace_node_store::in, trace_node_id::in,
> +:- pred diagnosis_new_tree(trace_node_store::in, trace_node_id::in,
> int::in, int::in, int::in, diagnoser_response(trace_node_id)::out,
> diagnoser_state(trace_node_id)::in,
> diagnoser_state(trace_node_id)::out,
> @@ -568,13 +569,32 @@
> browser_info.browser_persistent_state::out, io::di, io::uo)
> is cc_multi.
>
> -:- pragma export(diagnosis_store(in, in, in, in, in, out, in, out, in, out,
> - di, uo), "MR_DD_decl_diagnosis").
> +:- pragma export(diagnosis_new_tree(in, in, in, in, in, out, in, out, in, out,
> + di, uo), "MR_DD_decl_diagnosis_new_tree").
> +
> +diagnosis_new_tree(Store, Node, UseOldIoActionMap, IoActionStart, IoActionEnd,
> + Response, !State, !Browser, !IO) :-
> + diagnosis(Store, new_tree(dynamic(Node)), UseOldIoActionMap,
> + IoActionStart, IoActionEnd, Response, !State, !Browser, !IO).
> +
> + % Export a monomorphic version of diagnosis/10 that requests the
> + % continuance of a previously suspended declarative debugging session.
s/continuance/continuation/
...
> Index: runtime/mercury_stack_trace.h
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/runtime/mercury_stack_trace.h,v
> retrieving revision 1.36
> diff -u -r1.36 mercury_stack_trace.h
> --- runtime/mercury_stack_trace.h 17 Jan 2005 05:58:06 -0000 1.36
> +++ runtime/mercury_stack_trace.h 22 Feb 2005 22:25:10 -0000
> @@ -297,4 +297,25 @@
> const char *filename, int linenumber,
> const char *goal_path, MR_bool context_mismatch);
>
> +/*
> +** Find the first call event in the stack whose event number or sequence number
s/in the stack/on the stack/
> +** is less than or equal to the given event number or sequence number. The
> +** level of the call in the stack is returned. This can then be passed to
> +** MR_trace_retry as the ancestor_level. If no such call is found then -1 is
> +** returned and problem is set to the reason why the call could not be
> +** found.
> +*/
> +
...
> @@ -104,18 +104,29 @@
> ** MR_trace_start_decl_debug when the back end is started. They
> ** are used by MR_trace_decl_debug to decide what action to
> ** take for a particular trace event.
> -**
> -** Events that are deeper than the maximum depth, or which are
> -** outside the top call being debugged, are ignored. Events which
> -** are beyond the given last event cause the internal debugger to
> -** be switched back into interactive mode.
> */
>
> -static MR_Unsigned MR_edt_max_depth;
> +/*
> +** If we are building a subtree then reaching this event will cause the
> +** declarative debugger to continue its analysis. Reaching this event means
> +** generation of the desired subtree is complete. This variable is not used
> +** when building a new explicit supertree (a supertree is a tree above the
> +** currently materialized portion of the annotated trace).
> +*/
> +
> static MR_Unsigned MR_edt_last_event;
> +
> +/*
> +** If we are materializing a new subtree then MR_edt_start_seqno is the
> +** call sequence number of the call at the top the the subtree we want to
s/the the/of the/
...
> @@ -1284,7 +1363,7 @@
>
> MR_bool
> MR_trace_start_decl_debug(MR_Trace_Mode trace_mode, const char *outfile,
> - MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
> + MR_bool new_session, MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info,
> MR_Event_Details *event_details, MR_Code **jumpaddr)
> {
> MR_Retry_Result result;
> @@ -1293,10 +1372,25 @@
> MR_Unsigned edt_depth_limit;
> const char *message;
> MR_Trace_Level trace_level;
> + static MR_bool first_time = MR_TRUE;
>
> - MR_edt_return_node = (MR_Trace_Node) NULL;
> + MR_edt_initial_event = event_info->MR_event_number;
> +
> + /*
> + ** If it was requested that the previous session be resumed and
> + ** there was a previous dd session, then there is no need to
> + ** build a new annotated trace. Just call the front end, passing
> + ** NULL as the root node to let it know it must resume the
> + ** previous session.
> + */
> + if (!new_session && !first_time) {
> + MR_trace_decl_mode = trace_mode;
> + *jumpaddr = MR_decl_diagnosis((MR_Trace_Node) NULL, cmd,
> + event_info, event_details);
> + return MR_TRUE;
> + }
>
> - MR_edt_initial_event = event_details->MR_event_number;
> + MR_edt_return_node = (MR_Trace_Node) NULL;
>
> if (!MR_port_is_final(event_info->MR_trace_port)) {
> fflush(MR_mdb_out);
> @@ -1435,28 +1517,58 @@
>
> static const char *
> MR_trace_start_collecting(MR_Unsigned event, MR_Unsigned seqno,
> - MR_Unsigned maxdepth, MR_Unsigned topmost_call_depth,
> - MR_bool create_supertree, MR_Trace_Cmd_Info *cmd, MR_Event_Info
> - *event_info, MR_Event_Details *event_details, MR_Code **jumpaddr)
> + MR_Unsigned maxdepth, MR_bool create_supertree, MR_Trace_Cmd_Info *cmd,
> + MR_Event_Info *event_info, MR_Event_Details *event_details,
> + MR_Code **jumpaddr)
> {
> const char *problem;
> MR_Retry_Result retry_result;
> - MR_Unsigned retry_levels;
> + int retry_distance;
>
> - /*
> - ** Go back to an event before the topmost call.
> + /*
> + ** We need to do a retry if the current event is greater than the
> + ** call event number corresponding to seqno. Since we don't have the
> + ** call event number for seqno (`event' is the final event number,
> + ** not the call event number), we do a retry if:
> + ** a) The call sequence number of the current call is greater than
> + ** or equal to seqno, or
> + ** b) The current event number is greater than the final event
> + ** for seqno.
> + **
> + ** Case b) covers the situation where the current event is after the
> + ** final event for seqno and case a) covers the case where the current
> + ** event is greater than or equal to the call event for seqno and less
> + ** than or equal to the final event for seqno. This means we will do
> + ** a retry if the call event for seqno is equal to the current event
> + ** but thats not a problem since the retry will be a no-op.
s/thats/that's/
...
> @@ -1666,38 +1788,71 @@
> const char *problem;
> MR_Retry_Result retry_result;
> MR_Code *jumpaddr;
> + int ancestor_level;
>
> /*
> - ** Perform a retry to get to somewhere before the
> - ** bug event. Then set the command to go to the bug
> - ** event and return to interactive mode.
> - */
> + ** We only need to do a retry if the event number we want to be at is
> + ** less than or equal to the current event number (we need to do a
> + ** retry if the event numbers are equal, because MR_trace_real will
> + ** increment the current event number, so the next event displayed by
> + ** mdb will be the current event + 1.
> + */
> + if (event <= event_info->MR_event_number) {
> + ancestor_level = MR_find_first_call_less_eq_seq_or_event(
> + MR_FIND_FIRST_CALL_BEFORE_EVENT, event,
> + event_info->MR_event_sll,
> + MR_saved_sp(event_info->MR_saved_regs),
> + MR_saved_curfr(event_info->MR_saved_regs), &problem);
> +
> + if (ancestor_level >= 0) {
> + /*
> + ** Perform a retry to get to somewhere before the
"somewhere" is a bit imprecise.
> + ** given event. Then set the command to go to the
> + ** given event and return to interactive mode.
> + */
> #ifdef MR_DEBUG_RETRY
> - MR_print_stack_regs(stdout, event_info->MR_saved_regs);
> - MR_print_succip_reg(stdout, event_info->MR_saved_regs);
Julien.
--------------------------------------------------------------------------
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