[m-dev.] For review: implementation of collect for Opium-M
Fergus Henderson
fjh at cs.mu.OZ.AU
Tue Nov 2 11:15:12 AEDT 1999
On 01-Nov-1999, Erwan Jahier <Erwan.Jahier at irisa.fr> wrote:
> This change implements the `collect/2' command for opium-M. `collect/2'
> collects runtime information from Mercury program executions. It is intended to
> let users easily implement their own monitors with acceptable performances. It
> looks like the `fold/4' meta-predicate, except:
>
> (1) It operates on-the fly on a sequence of events rather than on a
> list.
> (2) The accumulator is initialized and updated via Mercury predicates
> whose implementation is in a file pass down as the first argument
> of `collect/2'.
s/pass/passed/
(Another difference with foldl/4 is that it stops when the filter returns `no'.
In fact it's a bit more like `std_util__do_while', the only difference is that
it operators on a sequence of debugger events rather than a sequence of solutions.
Or is that going to be committed as a separate change?)
> browser/collect_lib.m:
> New module that defines link_collect/7 that is used during a `collect'
> request: it performs the dynamic linking between collect.so and the
> current execution.
>
> Also defines ML_display_close_result() which display the result of
> ML_DL__close() function.
s/ML_DL__close/ML_DL_close/
> browser/debugger_interface.m:
...
> Define a new function get_collecting_variable_type/2 that retrieves
> the type of a variable. This type is needed in MR_trace_event_external()
> to be able to call MR_make_permanent() on MR_collecting_variable; we
> need to do that to ensure that the memory allocated for it won't be
> deallocated on backtracking.
I think that function should not be needed anymore.
> browser/dl.m:
> Move the type definition of the type `handle' to be able to use it in
> the collect_lib module.
Is that still needed?
Now that you're calling dl__close, rather than calling dlclose() directly,
I think you should not need to export that type.
> trace/mercury_trace_external.c:
> Add support to handle the requests `link_collect', `collect' and
> `current_grade'.
>
> Replace the global variable `searching' that was equal to TRUE when
> searching for a forward matching event and FALSE when reading a request,
> by a enum that is equal to `searching' when searching for a forward
> matching event, `reading_request' when reading a request and `collecting'
> when processing a `collect' request.
You should add `MR_' prefixes here in the log message.
> +++ collect_lib.m Tue Nov 2 04:14:40 1999
...
> +% To use it, users just need to define 4 things in a file, using the
> +% Mercury syntax:
> +% 1) a `collected_type' which is the type of the collecting
> +% variable that will contain the result of the monitoring
> +% activity.
> +% 2) The predicate initialize/1 which initializes this
> +% collecting variable. initialize/1 should have the
> +% following declarations:
> +% :- pred initialize(collected_type).
> +% :- mode initialize(out) is det.
> +% 3) the predicate filter/3 which updates this collecting
> +% variable at each execution event. filter/3 should have the
> +% following declarations:
> +% :- pred filter(event, collected_type, collected_type).
> +% :- mode filter(in, di, uo) is det.
> +% 4) and eventually the mode definition of the second and the
> +% third arguments of filter/3: `acc_in' and `acc_out'. Those
> +% mode have `di' and `uo' respectively as default values.
> +%
> +% Then, this file is used to generate the Mercury module `collect.m',
> +% which is compiled and dynamically linked with the current execution.
> +% When a `collect' request is made from the external debugger, a variable
> +% of type collected_type is first initialized (with initialize/1) and
> +% then updated (with filter/3) for all the events of the remaining
> +% execution. When the end of the execution is reached, the last value of
> +% the collecting variable is send to the debugger.
The documentation here will need to be modified for the extra bool argument.
> +:- module collect_lib.
...
> +% We need Handle to be able to close the shared object (dlclose) later on.
> +% When the link failed, we output NULL pointers instead of maybe pointers
> +% for performance reasons; indeed, filter will be called at every events
s/events/event/
> Index: browser/debugger_interface.m
...
> + % responses to collect
> + %; collected(collected_type)
I think you should have a comment here explaining why that is commented out.
> +:- pragma export(close(in, out, di, uo), "ML_DL__close").
s/DL__close/DL_close/
> +/*
> +** Variable generated during the dynamic linking that is needed to close
> +** this linking properly.
> +*/
> +
> +static Word *handle = NULL;
I think `collect_lib_handle' would be a better name for that variable.
Why is this declared to have type `Word *' rather than `Word'?
Why is it initialized to NULL?
> + Word *close_result;
> +
> + switch(external_debugger_mode) {
> + case MR_searching:
> + MR_send_message_to_socket("forward_move_match_not_found");
> + break;
> +
> + case MR_collecting:
> + (*send_collect_result_ptr)(
> + (Word) MR_collecting_variable,
That cast to (Word) should not be needed.
> + (Word) &MR_debugger_socket_out);
> + #if defined(HAVE_DLFCN_H) && defined(HAVE_DLCLOSE)
> + ML_DL__close((Word) handle,
> + (Word *) &close_result);
> + ML_display_close_result((Word) close_result);
> + #endif
> + break;
s/DL__close/DL_close/
Declare `close_result' to have type `Word', rather than `Word *',
and then those last two casts won't be needed.
The `(Word) handle' cast also looks a bit odd.
Why is handle declared to have type `Word *' rather than `Word'?
Don't those calls need to be inside MR_TRACE_CALL_MERCURY()?
> Code *
> MR_trace_event_external(MR_Trace_Cmd_Info *cmd, MR_Event_Info *event_info)
> {
> - static bool searching = FALSE;
> static Word search_data;
> + static void (*initialize_ptr)(Word *) = NULL;
> + static void (*filter_ptr)(Integer, Integer, Integer, MR_Trace_Port,
> + MR_PredFunc, String, String, String, Integer,
> + Integer, Integer, String, Word, Word *) = NULL;
Why are these pointers initialized to NULL?
The argument types here need to be Word rather than MR_*,
as discussed in my previous review.
> + case MR_REQUEST_LINK_COLLECT:
> + {
> + Char result;
> + Word MR_collecting_variable_type;
> +
> + if (MR_debug_socket) {
> + fprintf(stderr, "\nMercury runtime: "
> + "REQUEST_LINK_COLLECT\n");
> + }
> + MR_get_object_file_name(debugger_request,
> + &MR_object_file_name);
> + MR_TRACE_CALL_MERCURY(
> + ML_DI_link_collect(
> + MR_object_file_name,
> + (void *) &filter_ptr,
> + (void *) &initialize_ptr,
> + (void *) &send_collect_result_ptr,
> + (void *) &get_collect_var_type_ptr,
Those should be cast to (Word *) rather than (void *).
> + (Word *) &handle,
That cast should be unnecessary; instead you should change the
type of `handle'.
collect.in:
> :- type declarated_module_name == string.
s/declarated/declared/
I'd like to see another diff for this -- preferably in both
relative diff and full diff forms.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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