[m-rev.] for review: cleanup mercury_trace_declarative.c
Ian MacLarty
maclarty at cs.mu.OZ.AU
Sun Apr 10 13:55:20 AEST 2005
In this diff I have also included compiler generated unifications in the
annotated trace. The declarative debugger wont ask questions about these
because they are automatically trusted, but they are needed in case a subterm
needs to be tracked though a complicated unification.
I was unable, however to create a test case that caused a __Unify__ predicate
to be generated which produced output. Are all compiler generated unifications
just test unifications? If not could someone give me an example of a
complicated unification which produces output and for which the compiler
generates a seperate procedure? All the complicated unifications in the
tests directories seem to be test-unifications (i.e. unifications that produce
no output).
Cheers,
Ian.
Estimated hours taken: 5
Branches: main
Clean up trace/mercury_trace_declarative.c by breaking MR_trace_decl_debug into
several functions. This function was getting very big and difficult to
maintain.
trace/mercury_trace_declarative.c:
Break MR_trace_decl_debug into MR_trace_edt_build_sanity_check, which
checks that we haven't passed the last event for the portion of the
trace being constructed; MR_trace_include_event, which decides if an
event should be included in the annotated trace and resets the depth
if the event is at the top of an area to be materialized;
MR_trace_calculate_event_depth, which calculates the depth in the EDT
of the current event and sets the global MR_edt_depth appropriately;
And MR_trace_construct_node, which constructs a node in the annotated
trace.
Uncomment the code that includes compiler generated unifications in the
annotated trace.
Index: trace/mercury_trace_declarative.c
===================================================================
RCS file: /home/mercury1/repository/mercury/trace/mercury_trace_declarative.c,v
retrieving revision 1.84
diff -u -r1.84 mercury_trace_declarative.c
--- trace/mercury_trace_declarative.c 6 Apr 2005 01:11:32 -0000 1.84
+++ trace/mercury_trace_declarative.c 10 Apr 2005 03:50:08 -0000
@@ -212,7 +212,9 @@
** was safe to do the first retry across untabled IO. If they said this was
** okay then there's no point asking them again for the second retry.
*/
+
static MR_bool MR_edt_unsafe_retry_already_asked;
+
/*
** This is used as the abstract map from node identifiers to nodes
** in the data structure passed to the front end. It should be
@@ -313,10 +315,6 @@
MR_Trace_Cmd_Info *cmd,
MR_Event_Info *event_info,
MR_Event_Details *event_details);
- /*
- ** Retry max_distance if there are that many ancestors, otherwise
- ** retry as far as possible.
- */
static MR_Code *MR_trace_decl_retry_supertree(
MR_Unsigned max_distance,
MR_Event_Info *event_info,
@@ -331,6 +329,15 @@
MR_Event_Info *event_info);
static void MR_decl_checkpoint_loc(const char *str,
MR_Trace_Node node);
+static void MR_trace_edt_build_sanity_check(
+ MR_Event_Info *event_info,
+ const MR_Proc_Layout *entry);
+static MR_bool MR_trace_include_event(const MR_Proc_Layout *entry,
+ MR_Event_Info *event_info,
+ MR_Code **jumpaddr);
+static MR_Unsigned MR_trace_calculate_event_depth(
+ MR_Event_Info *event_info);
+static void MR_trace_construct_node(MR_Event_Info *event_info);
MR_bool MR_trace_decl_assume_all_io_is_tabled = MR_FALSE;
@@ -339,6 +346,23 @@
MR_bool MR_trace_decl_in_dd_dd_mode = MR_FALSE;
/*
+** We filter out events which are deeper than a certain
+** limit given by MR_edt_max_depth. These events are
+** implicitly represented in the structure being built.
+** Adding 1 to the depth limit ensures we get all the
+** interface events inside a call at the depth limit.
+** We need these to build the correct contour.
+** Note that interface events captured at max-depth + 1
+** will have their at-depth-limit flag set to no. This
+** is not a problem, since the parent's flag will be yes,
+** so there is no chance that the analyser could ask for the
+** children of an interface event captured at max-depth + 1,
+** without the annotated trace being rebuilt from the parent
+** first.
+*/
+#define MR_TRACE_EVENT_TOO_DEEP(depth) depth > MR_edt_max_depth + 1
+
+/*
** This function is called for every traced event when building the
** annotated trace. It must decide which events are included in the
** annotated trace.
@@ -348,48 +372,104 @@
{
const MR_Proc_Layout *entry;
MR_Unsigned depth;
- MR_Trace_Node trace;
MR_Event_Details event_details;
MR_Integer trace_suppress;
- MR_Unsigned depth_check_adjustment = 0;
+ MR_Unsigned event_depth;
+ MR_Code *jumpaddr;
entry = event_info->MR_event_sll->MR_sll_entry;
- depth = event_info->MR_call_depth;
+ MR_trace_edt_build_sanity_check(event_info, entry);
+
+ if (! MR_trace_include_event(entry, event_info, &jumpaddr)) {
+ return jumpaddr;
+ }
+
+ event_depth = MR_trace_calculate_event_depth(event_info);
+
+ if (MR_TRACE_EVENT_TOO_DEEP(event_depth)) {
+ return NULL;
+ }
+
+ trace_suppress = entry->MR_sle_module_layout->MR_ml_suppressed_events;
+ if (trace_suppress != 0) {
+ /*
+ ** We ignore events from modules that were not compiled
+ ** with the necessary information. Procedures in those
+ ** modules are effectively assumed correct, so we give
+ ** the user a warning.
+ */
+ MR_edt_compiler_flag_warning = MR_TRUE;
+ return NULL;
+ }
+
+ MR_trace_construct_node(event_info);
+
+ if (event_info->MR_call_seqno == MR_edt_start_seqno &&
+ MR_port_is_final(event_info->MR_trace_port))
+ {
+ MR_edt_return_node = MR_trace_current_node;
+ }
+
+ if ((!MR_edt_building_supertree &&
+ MR_trace_event_number == MR_edt_last_event)
+ || (MR_edt_building_supertree && event_depth == 0
+ && MR_port_is_final(event_info->MR_trace_port)))
+ {
+ /*
+ ** Call the front end.
+ */
+ event_details.MR_call_seqno = MR_trace_call_seqno;
+ event_details.MR_call_depth = MR_trace_call_depth;
+ event_details.MR_event_number = MR_trace_event_number;
+ return MR_decl_diagnosis(MR_edt_return_node, cmd,
+ event_info, &event_details, MR_TRUE);
+ }
+
+ return NULL;
+}
+
+static void
+MR_trace_edt_build_sanity_check(MR_Event_Info *event_info,
+ const MR_Proc_Layout *entry)
+{
if (event_info->MR_event_number > MR_edt_last_event
- && !MR_edt_building_supertree) {
+ && !MR_edt_building_supertree)
+ {
/* This shouldn't ever be reached. */
- fprintf(MR_mdb_err, "Warning: missed final event.\n");
+ fprintf(MR_mdb_err, "Error: missed final event.\n");
fprintf(MR_mdb_err, "event %lu\nlast event %lu\n",
(unsigned long) event_info->MR_event_number,
(unsigned long) MR_edt_last_event);
- MR_trace_decl_mode = MR_TRACE_INTERACTIVE;
- return MR_trace_event_internal(cmd, MR_TRUE, NULL, event_info);
+ fflush(NULL);
+ MR_fatal_error("Aborting.");
}
if (!MR_PROC_LAYOUT_HAS_EXEC_TRACE(entry)) {
/* XXX this should be handled better. */
MR_fatal_error("layout has no execution tracing");
}
+}
+static MR_bool
+MR_trace_include_event(const MR_Proc_Layout *entry,
+ MR_Event_Info *event_info, MR_Code **jumpaddr)
+{
/*
** Filter out events for compiler generated procedures.
- ** XXX Compiler generated unify procedures should be included
+ ** Compiler generated unify procedures should be included
** in the annotated trace so that sub-term dependencies can be
- ** tracked through them. The commented code below should be
- ** uncommented to include unifications in the annotated trace.
+ ** tracked through them.
+ ** XXX doing a string comparison to find out if this is a unification
+ ** predicate seems like overkill, but I don't know how else to
+ ** identify unifications - maclarty.
*/
- if (MR_PROC_LAYOUT_IS_UCI(entry)) {
- /* && !MR_streq("__Unify__",
+ if (MR_PROC_LAYOUT_IS_UCI(entry) && !MR_streq("__Unify__",
entry->MR_sle_proc_id.MR_proc_uci.MR_uci_pred_name)) {
- */
- return NULL;
+ *jumpaddr = NULL;
+ return MR_FALSE;
}
- event_details.MR_call_seqno = MR_trace_call_seqno;
- event_details.MR_call_depth = MR_trace_call_depth;
- event_details.MR_event_number = MR_trace_event_number;
-
/*
** Decide if we are inside or outside the subtree or supertree that
** needs to be materialized, ignoring for now any depth limit.
@@ -409,11 +489,13 @@
** MR_edt_start_seqno.
*/
MR_edt_inside = MR_TRUE;
+ return MR_TRUE;
} else if (event_info->MR_call_seqno ==
MR_edt_start_seqno && MR_port_is_entry(
event_info->MR_trace_port))
{
- MR_Code *jumpaddr;
+ MR_Event_Details event_details;
+
/*
** We are entering the top of the currently
** materialized portion of the annotated trace.
@@ -423,7 +505,7 @@
** trace from there.
*/
MR_edt_inside = MR_TRUE;
- jumpaddr = MR_trace_decl_retry_supertree(
+ *jumpaddr = MR_trace_decl_retry_supertree(
MR_edt_max_depth,
event_info, &event_details);
/*
@@ -440,13 +522,14 @@
** set it to 0.
*/
MR_edt_depth = -1;
- return jumpaddr;
+ return MR_FALSE;
} else {
/*
** We are in an existing explicit subtree.
*/
MR_decl_checkpoint_filter(event_info);
- return NULL;
+ *jumpaddr = NULL;
+ return MR_FALSE;
}
} else {
if (event_info->MR_call_seqno == MR_edt_start_seqno) {
@@ -455,9 +538,10 @@
** we are leaving the supertree and entering
** the existing explicit subtree.
** We must still however add this node to the
- ** generated EDT, so we don't return here.
+ ** generated EDT.
*/
MR_edt_inside = MR_FALSE;
+ return MR_TRUE;
}
}
} else {
@@ -469,6 +553,7 @@
** We are leaving the topmost call.
*/
MR_edt_inside = MR_FALSE;
+ return MR_TRUE;
}
} else {
if (event_info->MR_call_seqno == MR_edt_start_seqno) {
@@ -487,79 +572,54 @@
MR_io_tabling_counter;
}
MR_edt_depth = -1;
+ return MR_TRUE;
} else {
/*
** Ignore this event---it is outside the
** topmost call.
*/
MR_decl_checkpoint_filter(event_info);
- return NULL;
+ *jumpaddr = NULL;
+ return MR_FALSE;
}
}
}
-
- /*
- ** If the current event is an interface event then increase or decrease
- ** the EDT depth appropriately. Note that we must be inside the
- ** portion of the trace being materialized (ignoring the depth limit)
- ** when we reach this point.
- */
+ return MR_TRUE;
+}
+
+static MR_Unsigned
+MR_trace_calculate_event_depth(MR_Event_Info *event_info)
+{
if (event_info->MR_trace_port == MR_PORT_CALL
|| event_info->MR_trace_port == MR_PORT_REDO) {
- MR_edt_depth++;
- depth_check_adjustment = 0;
+ return ++MR_edt_depth;
}
if (MR_port_is_final(event_info->MR_trace_port)) {
/*
** The depth of the EXIT, FAIL or EXCP event is
- ** actually MR_edt_depth (not MR_edt_depth-1), however
- ** we need to adjust the depth here for future events.
- ** This inconsistency is neutralised by adjusting the
- ** depth limit check by setting depth_check_adjustment.
+ ** MR_edt_depth (not MR_edt_depth-1), however
+ ** we need to adjust MR_edt_depth here for future events.
*/
- MR_edt_depth--;
- depth_check_adjustment = 1;
- }
-
- if (MR_edt_depth + depth_check_adjustment > MR_edt_max_depth + 1) {
- /*
- ** We filter out events which are deeper than a certain
- ** limit given by MR_edt_max_depth. These events are
- ** implicitly represented in the structure being built.
- ** Adding 1 to the depth limit ensures we get all the
- ** interface events inside a call at the depth limit.
- ** We need these to build the correct contour.
- ** Note that interface events captured at max-depth + 1
- ** will have their at-depth-limit flag set to no. This
- ** is not a problem, since the parent's flag will be yes,
- ** so there is no chance that the analyser could ask for the
- ** children of an interface event captured at max-depth + 1,
- ** without the annotated trace being rebuilt from the parent
- ** first.
- ** Adding depth_check_adjustment (which will be 1 for EXIT,
- ** FAIL and EXCP events and 0 otherwise) ensures that EXIT,
- ** FAIL and EXCP events have the same depth as their
- ** corresponding CALL or REDO events.
- */
- return NULL;
+ return MR_edt_depth--;
}
+ return MR_edt_depth;
+}
- trace_suppress = entry->MR_sle_module_layout->MR_ml_suppressed_events;
- if (trace_suppress != 0) {
- /*
- ** We ignore events from modules that were not compiled
- ** with the necessary information. Procedures in those
- ** modules are effectively assumed correct, so we give
- ** the user a warning.
- */
- MR_edt_compiler_flag_warning = MR_TRUE;
- return NULL;
- }
+static void
+MR_trace_construct_node(MR_Event_Info *event_info)
+{
+ MR_Trace_Node trace;
+ MR_Event_Details event_details;
+
+ event_details.MR_call_seqno = MR_trace_call_seqno;
+ event_details.MR_call_depth = MR_trace_call_depth;
+ event_details.MR_event_number = MR_trace_event_number;
+ trace = MR_trace_current_node;
MR_debug_enabled = MR_FALSE;
MR_update_trace_func_enabled();
+
MR_decl_checkpoint_event(event_info);
- trace = MR_trace_current_node;
switch (event_info->MR_trace_port) {
case MR_PORT_CALL:
trace = MR_trace_decl_call(event_info, trace);
@@ -599,47 +659,32 @@
break;
case MR_PORT_PRAGMA_FIRST:
case MR_PORT_PRAGMA_LATER:
- MR_fatal_error("MR_trace_decl_debug: "
+ MR_fatal_error("MR_trace_construct_node: "
"foreign language code is not handled (yet)");
case MR_PORT_EXCEPTION:
trace = MR_trace_decl_excp(event_info, trace);
break;
default:
- MR_fatal_error("MR_trace_decl_debug: unknown port");
+ MR_fatal_error("MR_trace_construct_node: unknown port");
}
MR_decl_checkpoint_alloc(trace);
- MR_trace_current_node = trace;
+ MR_debug_enabled = MR_TRUE;
+ MR_update_trace_func_enabled();
+
/*
** Restore globals from the saved copies.
*/
MR_trace_call_seqno = event_details.MR_call_seqno;
MR_trace_call_depth = event_details.MR_call_depth;
MR_trace_event_number = event_details.MR_event_number;
-
- if (event_info->MR_call_seqno == MR_edt_start_seqno &&
- MR_port_is_final(event_info->MR_trace_port))
- {
- MR_edt_return_node = MR_trace_current_node;
- }
-
- if ((!MR_edt_building_supertree &&
- MR_trace_event_number == MR_edt_last_event)
- || (MR_edt_building_supertree &&
- MR_edt_depth + depth_check_adjustment == 0
- && MR_port_is_final(event_info->MR_trace_port))) {
- /*
- ** Call the front end.
- */
- return MR_decl_diagnosis(MR_edt_return_node, cmd,
- event_info, &event_details, MR_TRUE);
- }
-
- MR_debug_enabled = MR_TRUE;
- MR_update_trace_func_enabled();
- return NULL;
+ MR_trace_current_node = trace;
}
+/*
+** Retry max_distance if there are that many ancestors, otherwise
+** retry as far as possible.
+*/
static MR_Code *
MR_trace_decl_retry_supertree(MR_Unsigned max_distance,
MR_Event_Info *event_info, MR_Event_Details *event_details)
@@ -1676,7 +1721,7 @@
static MR_Code *
MR_decl_diagnosis(MR_Trace_Node root, MR_Trace_Cmd_Info *cmd,
- MR_Event_Info *event_info, MR_Event_Details *event_details,
+ MR_Event_Info *event_info, MR_Event_Details *event_details,
MR_bool new_tree)
{
MR_Word response;
@@ -1746,6 +1791,9 @@
MR_io_action_map_cache_end = io_end;
}
+ MR_debug_enabled = MR_FALSE;
+ MR_update_trace_func_enabled();
+
MR_TRACE_CALL_MERCURY(
if (new_tree == MR_TRUE) {
MR_DD_decl_diagnosis_new_tree(MR_trace_node_store,
@@ -1782,6 +1830,9 @@
(MR_Integer *) &topmost_seqno);
);
+ MR_debug_enabled = MR_TRUE;
+ MR_update_trace_func_enabled();
+
/*
** Turn off interactive debugging after the diagnosis in case a new
** explicit subtree or supertree needs to be constructed.
@@ -1843,7 +1894,11 @@
MR_Event_Info *event_info, MR_Event_Details *event_details)
{
const char *problem;
- MR_Retry_Result retry_result;
+ /*
+ ** Initialise this to avoid warnings that it might be used
+ ** uninitialised.
+ */
+ MR_Retry_Result retry_result = MR_RETRY_OK_DIRECT;
MR_Code *jumpaddr;
int ancestor_level;
MR_bool unsafe_retry;
--------------------------------------------------------------------------
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