[m-dev.] for review: the new debugger command set

Zoltan Somogyi zs at cs.mu.OZ.AU
Thu Sep 17 10:22:22 AEST 1998


>> When generating the set of live variables at internal ports,
>> the variables that are in the pre-death set of the goal into which
>> we are entering may not be available. However, the variables in the
>> pre-death set that are also in the resume vars set will be available,
>> so now include info about them in the layout structure for the event.
>> Since with tracing the non-clobbered input args are in all resume vars
>> sets, this ensures that these input args will be available from all
>> internal events.
> 
> If the cost of keeping those variables live is not infinitesimal, maybe
> it would be nice to make that information optional (since it can be
> reconstructed within my debugger and switch on and off dynamicly).

I'll keep that in mind for a future modification.

>> runtime/mercury_trace.[ch]:
>> If MR_TRACE_HISTOGRAM is defined, record a count of the number of
>> events at each depth. This information can help us evaluate space-time
>> tradeoffs.
> 
> Sorry it is totaly out of purpose but I can't help with showing you how
> simply (and funny ;-) this can be done in Opium...

I knew it could be done simply in Opium, but it just so happens that
the amount of code required is about the same in C. Since it uses direct
array update, the C code executes in bounded time, whereas the Opium
version requires at least logarithmic time, and your code requires time
proportional to depth. Since I have seen the depth exceed 15000, this
can be somewhat important.

>> + at item nondet procedures
>> +a call event, zero or more repeats of (exit event, redo event), and a fail event
>> + at item multi procedures
>> +a call event, one or more repeats of (exit event, redo event), and a fail event
> 
> For multi procedures I would say:
> a call event, zero or more repeats of (exit event, redo event), and a
> exit event

That would not be correct. If a multi procedure gets a redo event after
it has produced its last solution, it *will* fail.

> > +Mercury debugging works by embedding calls to the debugging system
> > +into the executable code of Mercury procedures,
> > +at the execution points that represent trace events.
> 
> I suggest:
> 
> Trace extraction is performed by embedding calls to the debugging system
> into the executable code of Mercury procedures; each such call generate
> a
> trace event.

I dislike passive verbs. Who is performing the trace extraction?

However, my wording does not answer this question either, so I will try again.

> > + at item forward [-NSans]
> > +Continues the program until the program resumes forward execution,
> 
> I feel like a word is missing:
> "Continues the program execution until [...]" ?

OK.

> > +i.e. until it reaches a non-final port inside any predicate. Reports
> 
> don't you mean a final port here ?
> 
> > +an error if the current event refers to a non-final port.
> 
> don't you mean a final port again ???

Thanks for spotting this.

The implementation continues execution until it reaches a final port,
as you say. It does not check what port you are at when you give the command,
so the documentation above is doubly wrong.

However, I don't think the current implementation does what it was intended
to do, which is allowing the user to skip past large numbers of nearly
identical events. These can happen at least four ways:

	depth event

1	100	EXIT
	 99	EXIT
	 98	EXIT
	 97	EXIT
	 96	EXIT
	 ..	....
	 51	EXIT
	 50	<non-EXIT>	want to stop here

2	100	FAIL
	 99	FAIL
	 98	FAIL
	 ..	....
	 51	FAIL
	 50	<non-FAIL>	want to stop here

3	100	FAIL
	 99	REDO
	 99	FAIL
	 98	REDO
	 98	FAIL
	 ..	....
	 51	REDO
	 51	FAIL
	 50	REDO
	 50	<non-FAIL>	want to stop here

4	 50	REDO
	 51	REDO
	 98	REDO
	 99	REDO
	 99	REDO
	 ..	....
	100	REDO
	100	<non-REDO>	want to stop here

(The second sequence is the same as the third, except that it is from
a program which was compiled witht --no-trace-redo.)

The name "forward" is an appropriate name for a command that implements
the last three sequences. It should stop whenever it finds an event which
is not REDO or FAIL.

Maybe we need a new command for implementing the first, which should stop
whenever it finds an event which is not EXIT. Any suggestions?

Actually, it may be useful to have two variants of each command,
one that pays attention only to the event type and one which also
stops if the procedure involved in the event changes.

> > + at sp 1
> > +The debugger can perform a retry only from an exit or fail port;
> > +only at these ports does the debugger have enough information
> > +to figure out how to reset the stacks.
> > +If the debugger is not at such a port when a retry command is given,
> > +the debugger will continue forward execution
> > +until it reaches an exit or fail port of the call to be retries
> > +before it performs the retry.
> > +This may require a noticeable amount of time.
> > + at c XXX not yet
> > + at c and may result in the execution of I/O and/or other side-effects.
> 
> oh ? I thougth Mercury was side-effect free ;-)
> Shouldn't you forbid retry command when the current procedure performs
> I/O ?
> or at least warn the user that a retry command may not be safe in those
> cases
> (and possibly prompt for a confirmation ?).

The current implementation does not allow you to retry a call that does I/O;
that is why the last couple of lines are commented out. However, even if the
procedure does not have I/O states, a retry may cause user-written pragma C
code to be executed again. Such pragma C code *may* have side effects,
even though it shouldn't.

Allowing retry of a call that does I/O may not be pure, but it is frequently
useful. Implementing it properly is somewhat difficult, however, which is why
it is not in this change.

> > + at item stack
> > +Prints the names of the ancestors of the call specified by the
> > +current event. If two or more ancestor calls are for the same
> > +predicate, the procedure identification will be printed once
> > +with the appropriate multiplicity annotation.
> > + at sp 1
> > +This command will report an error if there is no stack trace
> > +information available about any ancestor.
> 
> Did you chose to report an error in that case because it was difficult to
> implement or because you thougth that printing such a stack traces has
> no sense
> if one of the ancestors is missing ?

The absence of stack trace information about a stack frame means that
continuing the trace is, by the definition of "stack trace info", impossible.

If the user wants stack traces to be always complete, they can use a grade
in which this info is guaranteed to be available.

This should be explained in the overview sections above.

> > + at sp 1
> > + at node Experimental commands
> > + at subsection Experimental commands
> > + at sp 1
> > + at table @code
> *****
> > + at item histogram_all @var{filename}
> > +Prints (to file @var{filename})
> > +a histogram that counts all events at various depths
> > +since the start of the program.
> > +This histogram is available
> > +only in some experimental versions of the Mercury runtime system.
> > + at sp 1
> *****
> > + at item histogram_exp @var{filename}
> > +Prints (to file @var{filename})
> > +a histogram that counts all events at various depths
> > +since the start of the program or since the histogram was last cleared.
> > +This histogram is available
> > +only in some experimental versions of the Mercury runtime system.
> > + at sp 1
> *****
> copy-paste-paste error here.

No, it isn't. The implementation keep *two* histograms. The one reported by
histogram_all is never cleared; the one reported by histogram_exp can be
cleared by the clear_histogram command.

Zoltan.



More information about the developers mailing list