[m-rev.] for review: support call sequence numbers in the deep profiler

Zoltan Somogyi zs at csse.unimelb.edu.au
Wed Oct 11 14:03:11 AEST 2006


For review by Julien.

Zoltan.

Include call sequence numbers in the pages generated by the deep profiler
(if the user's preferences ask for this).

deep_profiler/measurements.m:
	Standardize on one spelling of call sequence numbers (callseqs).

	Add some utility predicates for use in dump.m.

	Fix a bug in the calculation of the number of calls: redos enter
	procedure invocations, not leave them.

deep_profiler/profile.m:
	Fix a bug: the num_callseqs field was in the wrong place.

deep_profiler/html_format.m:
	When generating a line of the clique description, include call sequence
	number information if requested.

	Do likewise when generating other HTML fragments that have to match
	the contents of those lines (e.g. the table headers).

	Generate the links that allow the users to sort rows by call
	sequence numbers.

	Generate the links that allow the users to toggle the switches
	controlling the display of call sequence number information.

	Do not show the toggles relevant to the display of times if times are
	not being displayed.

deep_profiler/interface.m:
	Extend the preferences to allow requests for call sequence number
	information.

	Include the display of call sequence numbers in the default set of
	preferences. However, include the display of time information in the
	default only of the profiling run lasted long enough for this
	information to have some hope of being useful.

	Rename some function symbols to avoid ambiguities.

deep_profiler/query.m:
	Extend the menu to include links for the most expensive
	cliques/procedures as measured by call sequence numbers.

	Include the links for the most expensive cliques/procedures as
	measured by clock ticks in the menu only if the profiling run
	lasted long enough for this to be useful.

	Print out the total number of call sequence numbers with the other
	statistics.

	Use call sequence numbers instead of time to decide where the "action"
	begins, since this works even for short profiling runs.

deep_profiler/top_procs.m:
	Provide the capability of sorting on call sequence numbers.

deep_profiler/dump.m:
	Provide the capability to dump out several more fields of the top level
	structure (profile.deep), including the cliques, the reverse links and
	the propagated measurement information.

deep_profiler/startup.m:
	Dump out the cliques, the reverse links and the propagated measurement
	information when computed.

deep_profiler/mdprof_cgi.m:
	Add an option for setting the hostname in the generated links to
	"localhost". This is useful on laptops temporarily disconnected
	from the Domain Name System (e.g. my laptop).

	Set this option automatically if the name of the file in the initial
	query has a ".localhost" suffix added to it.

	Add some tracing hooks.

deep_profiler/mdprof_test.m:
	Add an option to specify what info to dump during startup.

deep_profiler/mdprof_dump.m:
	Switch to using the compiler's method of specifying what to dump,
	since this is more maintainable.

deep_profiler/exclude.m:
	Rename some function symbols to avoid ambiguities.

deep_profiler/timeout.m:
	Add conditionally compiled code to help debug lock management.

deep_profiler/callgraph.m:
deep_profiler/canonical.m:
deep_profiler/cliques.m:
deep_profiler/conf.m:
deep_profiler/read_profile.m:
	Minor cleanups.

cvs diff: Diffing .
Index: callgraph.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/callgraph.m,v
retrieving revision 1.9
diff -u -b -r1.9 callgraph.m
--- callgraph.m	29 Sep 2006 06:15:11 -0000	1.9
+++ callgraph.m	11 Oct 2006 03:49:04 -0000
@@ -46,19 +46,17 @@
 % :- import_module io.
 % :- import_module require.
 % :- import_module string.
-% :- import_module unsafe.
 
 %-----------------------------------------------------------------------------%
 
 find_cliques(InitDeep, BottomUpPDPtrCliqueList) :-
     make_graph(InitDeep, Graph),
     topological_sort(Graph, TopDownPDICliqueList),
-    %
+
     % Turn each of the sets of PDIs into a list of PDPtrs.  We use foldl here
     % because the list may be very long and map runs out of stack space, and
     % we want the final list in reverse order anyway because the propagation
     % algorithm works bottom up.
-    %
     list.foldl(accumulate_pdptr_lists, TopDownPDICliqueList,
         [], BottomUpPDPtrCliqueList).
 
@@ -133,10 +131,9 @@
 make_clique_indexes(NPDs, CliqueList, Cliques, CliqueIndex) :-
     Cliques = array(CliqueList),
     array.init(NPDs, clique_ptr(-1), CliqueIndex0),
-    %
+
     % For each clique, add entries to the CliqueIndex array, which maps every
     % proc_dynamic_ptr back to the clique to which it belongs.
-    %
     array_foldl_from_1(index_clique, Cliques, CliqueIndex0, CliqueIndex).
 
 :- pred index_clique(int::in, list(proc_dynamic_ptr)::in,
@@ -149,8 +146,6 @@
 :- pred index_clique_member(int::in, proc_dynamic_ptr::in,
     array(clique_ptr)::array_di, array(clique_ptr)::array_uo) is det.
 
-% :- pragma promise_pure(index_clique_member/4).
-
 index_clique_member(CliqueNum, PDPtr, !CliqueIndex) :-
     PDPtr = proc_dynamic_ptr(PDI),
     % impure unsafe_perform_io(write_pdi_cn(PDI, CliqueNum)),
Index: canonical.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/canonical.m,v
retrieving revision 1.12
diff -u -b -r1.12 canonical.m
--- canonical.m	5 Oct 2006 04:37:50 -0000	1.12
+++ canonical.m	11 Oct 2006 03:49:04 -0000
@@ -44,8 +44,6 @@
 
 %-----------------------------------------------------------------------------%
 
-% :- import_module unsafe.
-
 :- type merge_info
     --->    merge_info(
                 merge_clique_members :: array(list(proc_dynamic_ptr)),
Index: cliques.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/cliques.m,v
retrieving revision 1.7
diff -u -b -r1.7 cliques.m
--- cliques.m	9 Mar 2006 04:56:39 -0000	1.7
+++ cliques.m	11 Oct 2006 03:49:04 -0000
@@ -53,7 +53,6 @@
 
 % :- import_module io.
 % :- import_module string.
-% :- import_module unsafe.
 
 %-----------------------------------------------------------------------------%
 
@@ -103,8 +102,6 @@
         mklist(N - 1, Acc1, Acc)
     ).
 
-% :- pragma promise_pure(topological_sort/2).
-
 topological_sort(Graph, TSort) :-
     % impure unsafe_perform_io(io.nl),
     % impure unsafe_perform_io(io.write_string("the graph:\n")),
@@ -202,8 +199,6 @@
 :- pred dfs(list(int)::in, graph::in, visit::array_di, list(int)::in,
     visit::array_uo, list(int)::out) is det.
 
-% :- pragma promise_pure(dfs/6).
-
 dfs([], _Graph, Visit, Dfs, Visit, Dfs).
 dfs([Node | Nodes], Graph, Visit0, Dfs0, Visit, Dfs) :-
     ( dense_bitset.member(Node, Visit0) ->
Index: conf.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/conf.m,v
retrieving revision 1.8
diff -u -b -r1.8 conf.m
--- conf.m	9 Mar 2006 04:56:39 -0000	1.8
+++ conf.m	11 Oct 2006 03:49:04 -0000
@@ -62,10 +62,7 @@
             io.read_file_as_string(TmpStream, TmpReadRes, !IO),
             (
                 TmpReadRes = ok(ServerNameNl),
-                (
-                    string.remove_suffix(ServerNameNl,
-                        "\n", ServerNamePrime)
-                ->
+                ( string.remove_suffix(ServerNameNl, "\n", ServerNamePrime) ->
                     ServerName = ServerNamePrime
                 ;
                     error("malformed server name")
Index: dump.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/dump.m,v
retrieving revision 1.7
diff -u -b -r1.7 dump.m
--- dump.m	5 Oct 2006 04:37:50 -0000	1.7
+++ dump.m	11 Oct 2006 03:49:04 -0000
@@ -18,21 +18,31 @@
 :- import_module profile.
 
 :- import_module io.
-:- import_module bool.
+:- import_module list.
 
 %-----------------------------------------------------------------------------%
 
-    % dump_initial_deep(ProfStats, Restrict, DumpCSDs, DumpPDs,
-    %   DumpCSSs, DumpPSs, InitialDeep, !IO):
+    % dump_initial_deep(InitialDeep, DumpOptions, !IO):
+    %
     % Dump selected parts of InitialDeep to standard output. The array of call
     % site dynamics, proc dynamics, call site statics and proc statics is
-    % dumped if the corresponding Dump bool is "yes". If Restrict is "yes",
-    % then the only the elements of the static arrays that will be dumped are
-    % the ones that are referred to from the dynamic arrays. The statistics
-    % and the root node are dumped if ProfStats is "yes".
+    % dumped if DumpOptions contains "csd", "pd", "css" or "ps" respectively.
+    % If it contains "restrict", then the only the elements of the static
+    % arrays that will be dumped are the ones that are referred to from the
+    % dynamic arrays. The statistics and the root node are dumped if
+    % DumpOptions contains "stats".
+    %
+:- pred dump_initial_deep(initial_deep::in, list(string)::in, io::di, io::uo)
+    is det.
+
+    % dump_deep(Deep, DumpOptions, !IO):
+    %
+    % Dump selected parts of Deep to standard output. Information about cliques
+    % is output if DumpOptions contains "clique". The fields of Deep that
+    % contain reverse links are dumped if DumpOptions contains "rev".
+    % The propagated costs are dumped if DumpOptions contains "prop".
     %
-:- pred dump_initial_deep(bool::in, bool::in, bool::in, bool::in, bool::in,
-    bool::in, initial_deep::in, io::di, io::uo) is det.
+:- pred dump_deep(deep::in, list(string)::in, io::di, io::uo) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -43,7 +53,12 @@
 :- import_module measurements.
 
 :- import_module array.
-:- import_module list.
+:- import_module bool.
+:- import_module int.
+:- import_module map.
+:- import_module maybe.
+:- import_module pair.
+:- import_module require.
 :- import_module set.
 :- import_module std_util.
 :- import_module string.
@@ -51,47 +66,39 @@
 
 %----------------------------------------------------------------------------%
 
-dump_initial_deep(ProfStats, Restrict, DumpCSDs, DumpPDs, DumpCSSs, DumpPSs,
-        InitialDeep, !IO) :-
+dump_initial_deep(InitialDeep, DumpOptions, !IO) :-
     InitialDeep = initial_deep(Stats, InitRoot, CSDs, PDs, CSSs, PSs),
-    (
-        Restrict = yes,
+    ( should_dump(DumpOptions, "restrict") ->
         get_static_ptrs_from_dynamic_procs(PDs, PSs, UsedPSs, UsedCSSs),
         Restriction = these(UsedPSs, UsedCSSs)
     ;
-        Restrict = no,
         Restriction = none
     ),
-    (
-        ProfStats = yes,
+    ( should_dump(DumpOptions, "stat") ->
         dump_init_profile_stats(Stats, !IO),
         dump_init_root(InitRoot, !IO)
     ;
-        ProfStats = no
+        true
     ),
-    (
-        DumpCSDs= yes,
+    ( should_dump(DumpOptions, "csd") ->
         dump_init_call_site_dynamics(CSDs, !IO)
     ;
-        DumpCSDs = no
+        true
     ),
-    (
-        DumpPDs = yes,
+    ( should_dump(DumpOptions, "pd") ->
         dump_init_proc_dynamics(PDs, PSs, !IO)
     ;
-        DumpPDs = no
+        true
     ),
-    (
-        DumpCSSs = yes,
+    ( should_dump(DumpOptions, "css") ->
         dump_init_call_site_statics(Restriction, CSSs, !IO)
     ;
-        DumpCSSs = no
+        true
     ),
-    (
-        DumpPSs = yes,
+    ( should_dump(DumpOptions, "ps") ->
         dump_init_proc_statics(Restriction, PSs, !IO)
     ;
-        DumpPSs = no
+        true
     ).
 
 %----------------------------------------------------------------------------%
@@ -141,7 +148,7 @@
     io.format("\tticks_per_sec = %d\n", [i(TicksPerSec)], !IO),
     io.format("\tinstrument_quanta = %d\n", [i(InstrumentQuanta)], !IO),
     io.format("\tuser_quanta = %d\n", [i(UserQuanta)], !IO),
-    io.format("\tnum_call_seqs = %d\n", [i(NumCallSeqs)], !IO),
+    io.format("\tnum_callseqs = %d\n", [i(NumCallSeqs)], !IO),
     io.format("\tword_size   = %d\n", [i(WordSize)], !IO),
     io.write_string("\tcanonical = ", !IO),
     (
@@ -192,47 +199,75 @@
     ( Calls = 0 ->
         true
     ;
-        io.format("\tcalls:\t%d\n", [i(Calls)], !IO)
+        io.format("\tcalls:\t\t%d\n", [i(Calls)], !IO)
     ),
     ( Exits = 0 ->
         true
     ;
-        io.format("\texits:\t%d\n", [i(Exits)], !IO)
+        io.format("\texits:\t\t%d\n", [i(Exits)], !IO)
     ),
     ( Fails = 0 ->
         true
     ;
-        io.format("\tfails:\t%d\n", [i(Fails)], !IO)
+        io.format("\tfails:\t\t%d\n", [i(Fails)], !IO)
     ),
     ( Redos = 0 ->
         true
     ;
-        io.format("\tredos:\t%d\n", [i(Redos)], !IO)
+        io.format("\tredos:\t\t%d\n", [i(Redos)], !IO)
     ),
     ( Excps = 0 ->
         true
     ;
-        io.format("\texcps:\t%d\n", [i(Excps)], !IO)
+        io.format("\texcps:\t\t%d\n", [i(Excps)], !IO)
     ),
     ( Quanta = 0 ->
         true
     ;
-        io.format("\tquanta:\t%d\n", [i(Quanta)], !IO)
+        io.format("\tquanta:\t\t%d\n", [i(Quanta)], !IO)
     ),
     ( CallSeqs = 0 ->
         true
     ;
-        io.format("\tcall_seqs:\t%d\n", [i(CallSeqs)], !IO)
+        io.format("\tcallseqs:\t%d\n", [i(CallSeqs)], !IO)
     ),
     ( Allocs = 0 ->
         true
     ;
-        io.format("\tallocs:\t%d\n", [i(Allocs)], !IO)
+        io.format("\tallocs:\t\t%d\n", [i(Allocs)], !IO)
     ),
     ( Words = 0 ->
         true
     ;
-        io.format("\twords:\t%d\n", [i(Words)], !IO)
+        io.format("\twords:\t\t%d\n", [i(Words)], !IO)
+    ).
+
+:- pred dump_inherit_prof_info(inherit_prof_info::in, io::di, io::uo) is det.
+
+dump_inherit_prof_info(Inherit, !IO) :-
+    Quanta = inherit_quanta(Inherit),
+    CallSeqs = inherit_callseqs(Inherit),
+    Allocs = inherit_allocs(Inherit),
+    Words = inherit_words(Inherit),
+    ( Quanta = 0 ->
+        true
+    ;
+        io.format("\tquanta:\t\t%d\n", [i(Quanta)], !IO)
+    ),
+    ( CallSeqs = 0 ->
+        true
+    ;
+        io.format("\tcallseqs:\t%d\n", [i(CallSeqs)], !IO)
+    ),
+    ( Allocs = 0 ->
+        true
+    ;
+        io.format("\tallocs:\t\t%d\n", [i(Allocs)], !IO)
+    ),
+    ( Words = 0 ->
+        true
+    ;
+        io.format("\twords:\t\t%d\n", [i(Words)], !IO)
     ).
 
 %----------------------------------------------------------------------------%
@@ -257,8 +292,7 @@
         RefinedPSId = PS ^ ps_refined_id
     ),
     io.format("pd%d:\n", [i(Index)], !IO),
-    io.format("\tpd_proc_static = %d (%s)\n", [i(PSI), s(RefinedPSId)],
-        !IO),
+    io.format("\tpd_proc_static = %d (%s)\n", [i(PSI), s(RefinedPSId)], !IO),
     array_foldl_from_0(dump_call_site_array_slot, Sites, !IO),
     io.nl(!IO).
 
@@ -282,8 +316,7 @@
 
 dump_init_call_site_statics(Restriction, CallStatics, !IO) :-
     io.write_string("SECTION CALL SITE STATICS:\n\n", !IO),
-    array_foldl_from_1(dump_call_site_static(Restriction), CallStatics,
-        !IO).
+    array_foldl_from_1(dump_call_site_static(Restriction), CallStatics, !IO).
 
 :- pred dump_call_site_static(restriction::in, int::in, call_site_static::in,
     io::di, io::uo) is det.
@@ -294,8 +327,7 @@
             Restriction = none
         ;
             Restriction = these(_, UsedCallSiteStatics),
-            set.member(call_site_static_ptr(Index),
-                UsedCallSiteStatics)
+            set.member(call_site_static_ptr(Index), UsedCallSiteStatics)
         )
     ->
         CallSiteStatic = call_site_static(ContainerPSPtr, SlotNum,
@@ -348,8 +380,7 @@
             % redundant information.
             true
         ;
-            io.format("\tps_refined_id\t= %s\n",
-                [s(RefinedId)], !IO)
+            io.format("\tps_refined_id\t= %s\n", [s(RefinedId)], !IO)
         ),
         ( RefinedId \= RawId ->
             % The output is too big already; don't include
@@ -358,8 +389,7 @@
         ;
             io.format("\tps_raw_id\t= %s\n", [s(RawId)], !IO)
         ),
-        io.format("\tlocation\t= %s:%d\n",
-            [s(FileName), i(LineNumber)], !IO),
+        io.format("\tlocation\t= %s:%d\n", [s(FileName), i(LineNumber)], !IO),
         (
             InInterface = yes,
             io.write_string("\tin_interface\n", !IO)
@@ -419,5 +449,302 @@
     io.write_string("callback", !IO).
 
 %----------------------------------------------------------------------------%
+
+dump_deep(Deep, DumpOptions, !IO) :-
+    ( should_dump(DumpOptions, "clique") ->
+        dump_deep_cliques(Deep, !IO)
+    ;
+        true
+    ),
+    ( should_dump(DumpOptions, "rev") ->
+        dump_deep_rev_links(Deep, !IO)
+    ;
+        true
+    ),
+    ( should_dump(DumpOptions, "prop") ->
+        dump_deep_prop_measurements(Deep, !IO)
+    ;
+        true
+    ).
+
+%----------------------------------------------------------------------------%
+
+:- pred dump_deep_cliques(deep::in, io::di, io::uo) is det.
+
+dump_deep_cliques(Deep, !IO) :-
+    CliqueIndex = Deep ^ clique_index,
+    io.write_string("SECTION MAP FROM PROC DYNAMIC TO CLIQUE:\n\n", !IO),
+    array_foldl_from_1(dump_clique_index_entry, CliqueIndex, !IO),
+    io.nl(!IO),
+
+    CliqueMembers = Deep ^ clique_members,
+    io.write_string("SECTION MAP FROM CLIQUE TO PROC DYNAMICS:\n\n", !IO),
+    array_foldl_from_1(dump_clique_members, CliqueMembers, !IO),
+    io.nl(!IO),
+
+    CliqueParents = Deep ^ clique_parents,
+    io.write_string("SECTION MAP FROM CLIQUE TO PARENT CSD:\n\n", !IO),
+    array_foldl_from_1(dump_clique_parent, CliqueParents, !IO),
+    io.nl(!IO),
+
+    CliqueMaybeChild = Deep ^ clique_maybe_child,
+    io.write_string("SECTION MAP FROM CSD TO MAYBE CHILD CLIQUE:\n\n",
+        !IO),
+    array_foldl_from_1(dump_clique_maybe_child, CliqueMaybeChild, !IO),
+    io.nl(!IO).
+
+:- pred dump_clique_index_entry(int::in, clique_ptr::in,
+    io::di, io::uo) is det.
+
+dump_clique_index_entry(Index, CliquePtr, !IO) :-
+    CliquePtr = clique_ptr(CliqueNum),
+    io.format("pd%d is in clique%d\n", [i(Index), i(CliqueNum)], !IO).
+
+:- pred dump_clique_members(int::in, list(proc_dynamic_ptr)::in,
+    io::di, io::uo) is det.
+
+dump_clique_members(Index, CliqueMembers, !IO) :-
+    io.format("clique%d members:", [i(Index)], !IO),
+    list.foldl(dump_pd_in_clique, CliqueMembers, !IO),
+    io.nl(!IO).
+
+:- pred dump_pd_in_clique(proc_dynamic_ptr::in, io::di, io::uo) is det.
+
+dump_pd_in_clique(PDPtr, !IO) :-
+    PDPtr = proc_dynamic_ptr(PDNum),
+    io.write_string(" pd", !IO),
+    io.write_int(PDNum, !IO).
+
+:- pred dump_clique_parent(int::in, call_site_dynamic_ptr::in,
+    io::di, io::uo) is det.
+
+dump_clique_parent(Index, CSDPtr, !IO) :-
+    CSDPtr = call_site_dynamic_ptr(CSDNum),
+    io.format("clique%d parent: csd%d\n", [i(Index), i(CSDNum)], !IO).
+
+:- pred dump_clique_maybe_child(int::in, maybe(clique_ptr)::in,
+    io::di, io::uo) is det.
+
+dump_clique_maybe_child(Index, MaybeCliquePtr, !IO) :-
+    (
+        MaybeCliquePtr = no
+    ;
+        MaybeCliquePtr = yes(CliquePtr),
+        CliquePtr = clique_ptr(CliqueNum),
+        io.format("csd%d child: clique%d\n", [i(Index), i(CliqueNum)], !IO)
+    ).
+
+%----------------------------------------------------------------------------%
+
+:- pred dump_deep_rev_links(deep::in, io::di, io::uo) is det.
+
+dump_deep_rev_links(Deep, !IO) :-
+    ProcCallers = Deep ^ proc_callers,
+    io.write_string("SECTION MAP FROM PROC STATIC TO CALLER CSDs:\n\n", !IO),
+    array_foldl_from_1(dump_proc_static_caller_csds, ProcCallers, !IO),
+    io.nl(!IO),
+
+    CallSiteStaticMap = Deep ^ call_site_static_map,
+    io.write_string("SECTION MAP FROM CALL SITE DYNAMICS TO STATICS:\n\n", !IO),
+    array_foldl_from_1(dump_call_site_dynamic_to_static, CallSiteStaticMap,
+        !IO),
+    io.nl(!IO),
+
+    CallSiteCalls = Deep ^ call_site_calls,
+    io.write_string("SECTION MAP FROM CALL SITE STATICS TO CALLS:\n\n", !IO),
+    array_foldl_from_1(dump_call_site_calls, CallSiteCalls, !IO),
+    io.nl(!IO).
+
+:- pred dump_proc_static_caller_csds(int::in, list(call_site_dynamic_ptr)::in,
+    io::di, io::uo) is det.
+
+dump_proc_static_caller_csds(Index, CallerCSDs, !IO) :-
+    (
+        CallerCSDs = []
+    ;
+        CallerCSDs = [_ | _],
+        io.format("ps%d callers:", [i(Index)], !IO),
+        list.foldl(dump_space_csdptr, CallerCSDs, !IO),
+        io.nl(!IO)
+    ).
+
+:- pred dump_space_csdptr(call_site_dynamic_ptr::in, io::di, io::uo) is det.
+
+dump_space_csdptr(CSDPtr, !IO) :-
+    CSDPtr = call_site_dynamic_ptr(CSDNum),
+    io.write_string(" csd", !IO),
+    io.write_int(CSDNum, !IO).
+
+:- pred dump_call_site_dynamic_to_static(int::in, call_site_static_ptr::in,
+    io::di, io::uo) is det.
+
+dump_call_site_dynamic_to_static(Index, CSSPtr, !IO) :-
+    CSSPtr = call_site_static_ptr(CSSNum),
+    io.format("csd%d is at css%d\n", [i(Index), i(CSSNum)], !IO).
+
+:- pred dump_call_site_calls(int::in,
+    map(proc_static_ptr, list(call_site_dynamic_ptr))::in,
+    io::di, io::uo) is det.
+
+dump_call_site_calls(Index, CalleeMap, !IO) :-
+    CalleeList = map.to_assoc_list(CalleeMap),
+    (
+        CalleeList = []
+    ;
+        CalleeList = [OneCallee],
+        io.format("css%d calls one procedure: ", [i(Index)], !IO),
+        dump_call_site_calls_to_proc("", OneCallee, !IO)
+    ;
+        CalleeList = [_, _ | _],
+        io.format("css%d calls several procedures:\n", [i(Index)], !IO),
+        list.foldl(dump_call_site_calls_to_proc("\t"), CalleeList, !IO)
+    ).
+
+:- pred dump_call_site_calls_to_proc(string::in,
+    pair(proc_static_ptr, list(call_site_dynamic_ptr))::in,
+    io::di, io::uo) is det.
+
+dump_call_site_calls_to_proc(Prefix, PSPtr - CSDPtrs, !IO) :-
+    PSPtr = proc_static_ptr(PSNum),
+    io.format("%sps%d:", [s(Prefix), i(PSNum)], !IO),
+    list.foldl(dump_space_csdptr, CSDPtrs, !IO),
+    io.nl(!IO).
+
+%----------------------------------------------------------------------------%
+
+:- pred dump_deep_prop_measurements(deep::in, io::di, io::uo) is det.
+
+dump_deep_prop_measurements(Deep, !IO) :-
+    PDOwn = Deep ^ pd_own,
+    PDDesc = Deep ^ pd_desc,
+    PDOwnMax = array.max(PDOwn),
+    PDDescMax = array.max(PDDesc),
+    require(unify(PDOwnMax, PDDescMax),
+        "dump_deep: PDOwnMax != PDDescMax"),
+    io.write_string("SECTION PROC DYNAMIC MEASUREMENTS:\n\n", !IO),
+    dump_pd_measurements(1, PDOwnMax, PDOwn, PDDesc, !IO),
+
+    CSDs = Deep ^ call_site_dynamics,
+    CSDDesc = Deep ^ csd_desc,
+    CSDMax = array.max(CSDs),
+    CSDDescMax = array.max(CSDDesc),
+    require(unify(CSDMax, CSDDescMax),
+        "dump_deep: CSDMax != CSDDescMax"),
+    io.write_string("SECTION CALL SITE DYNAMIC MEASUREMENTS:\n\n", !IO),
+    dump_csd_measurements(1, CSDMax, CSDs, CSDDesc, !IO),
+
+    PSOwn = Deep ^ ps_own,
+    PSDesc = Deep ^ ps_desc,
+    PSOwnMax = array.max(PSOwn),
+    PSDescMax = array.max(PSDesc),
+    require(unify(PSOwnMax, PSDescMax),
+        "dump_deep: PSOwnMax != PSDescMax"),
+    io.write_string("SECTION PROC STATIC MEASUREMENTS:\n\n", !IO),
+    dump_ps_measurements(1, PSOwnMax, PSOwn, PSDesc, !IO),
+
+    CSSOwn = Deep ^ css_own,
+    CSSDesc = Deep ^ css_desc,
+    CSSOwnMax = array.max(CSSOwn),
+    CSSDescMax = array.max(CSSDesc),
+    require(unify(CSSOwnMax, CSSDescMax),
+        "dump_deep: CSSOwnMax != CSSDescMax"),
+    io.write_string("SECTION CALL SITE STATIC MEASUREMENTS:\n\n", !IO),
+    dump_css_measurements(1, CSSOwnMax, CSSOwn, CSSDesc, !IO).
+
+:- pred dump_pd_measurements(int::in, int::in,
+    array(own_prof_info)::in, array(inherit_prof_info)::in,
+    io::di, io::uo) is det.
+
+dump_pd_measurements(Cur, Max, PDOwn, PDDesc, !IO) :-
+    ( Cur =< Max ->
+        array.lookup(PDOwn, Cur, Own),
+        array.lookup(PDDesc, Cur, Desc),
+        dump_own_and_desc("pd", Cur, Own, Desc, !IO),
+        dump_pd_measurements(Cur + 1, Max, PDOwn, PDDesc, !IO)
+    ;
+        true
+    ).
+
+:- pred dump_csd_measurements(int::in, int::in,
+    array(call_site_dynamic)::in, array(inherit_prof_info)::in,
+    io::di, io::uo) is det.
+
+dump_csd_measurements(Cur, Max, CSDs, CSDDesc, !IO) :-
+    ( Cur =< Max ->
+        array.lookup(CSDs, Cur, CSD),
+        Own = CSD ^ csd_own_prof,
+        array.lookup(CSDDesc, Cur, Desc),
+        dump_own_and_desc("csd", Cur, Own, Desc, !IO),
+        dump_csd_measurements(Cur + 1, Max, CSDs, CSDDesc, !IO)
+    ;
+        true
+    ).
+
+:- pred dump_ps_measurements(int::in, int::in,
+    array(own_prof_info)::in, array(inherit_prof_info)::in,
+    io::di, io::uo) is det.
+
+dump_ps_measurements(Cur, Max, PSOwn, PSDesc, !IO) :-
+    ( Cur =< Max ->
+        array.lookup(PSOwn, Cur, Own),
+        array.lookup(PSDesc, Cur, Desc),
+        dump_own_and_desc("ps", Cur, Own, Desc, !IO),
+        dump_ps_measurements(Cur + 1, Max, PSOwn, PSDesc, !IO)
+    ;
+        true
+    ).
+
+:- pred dump_css_measurements(int::in, int::in,
+    array(own_prof_info)::in, array(inherit_prof_info)::in,
+    io::di, io::uo) is det.
+
+dump_css_measurements(Cur, Max, CSSOwn, CSSDesc, !IO) :-
+    ( Cur =< Max ->
+        array.lookup(CSSOwn, Cur, Own),
+        array.lookup(CSSDesc, Cur, Desc),
+        dump_own_and_desc("css", Cur, Own, Desc, !IO),
+        dump_css_measurements(Cur + 1, Max, CSSOwn, CSSDesc, !IO)
+    ;
+        true
+    ).
+
+:- pred dump_own_and_desc(string::in, int::in,
+    own_prof_info::in, inherit_prof_info::in, io::di, io::uo) is det.
+
+dump_own_and_desc(Prefix, Cur, Own, Desc, !IO) :-
+    ( is_zero_own_prof_info(Own) ->
+        PrintedOwn = no
+    ;
+        io.format("%s%d own:\n", [s(Prefix), i(Cur)], !IO),
+        dump_own_prof_info(Own, !IO),
+        PrintedOwn = yes
+    ),
+    ( is_zero_inherit_prof_info(Desc) ->
+        PrintedDesc = no
+    ;
+        io.format("%s%d inherit:\n", [s(Prefix), i(Cur)], !IO),
+        dump_inherit_prof_info(Desc, !IO),
+        PrintedDesc = yes
+    ),
+    (
+        ( PrintedOwn = yes
+        ; PrintedDesc = yes
+        )
+    ->
+        io.nl(!IO)
+    ;
+        true
+    ).
+
+%----------------------------------------------------------------------------%
+
+:- pred should_dump(list(string)::in, string::in) is semidet.
+
+should_dump(DumpOptions, What) :-
+    ( list.member(What, DumpOptions)
+    ; DumpOptions = []
+    ).
+
+%----------------------------------------------------------------------------%
 :- end_module dump.
 %----------------------------------------------------------------------------%
Index: exclude.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/exclude.m,v
retrieving revision 1.9
diff -u -b -r1.9 exclude.m
--- exclude.m	20 Sep 2006 09:42:23 -0000	1.9
+++ exclude.m	11 Oct 2006 03:49:04 -0000
@@ -83,12 +83,11 @@
            ).
 
 :- type exclusion_type
-    --->    all_procedures      % Exclude all procedures in the
-                                % named module.
-    ;       internal_procedures.    % Exclude all procedures in the
-                                    % named module, except those
-                                    % which are exported from the
-                                    % module.
+    --->    exclude_all_procedures
+            % Exclude all procedures in the named module.
+    ;       exclude_internal_procedures.
+            % Exclude all procedures in the named module, except those
+            % which are exported from the module.
 
 %-----------------------------------------------------------------------------%
 
@@ -129,18 +128,17 @@
             Words = [Scope, ModuleName],
             (
                 Scope = "all",
-                ExclType = all_procedures
+                ExclType = exclude_all_procedures
             ;
                 Scope = "internal",
-                ExclType = internal_procedures
+                ExclType = exclude_internal_procedures
             )
         ->
             Spec = exclude_spec(ModuleName, ExclType),
             RevSpecs1 = [Spec | RevSpecs0],
             read_exclude_lines(FileName, InputStream, RevSpecs1, Res, !IO)
         ;
-            Msg = string.format(
-                "file %s contains badly formatted line: %s",
+            Msg = string.format("file %s contains badly formatted line: %s",
                 [s(FileName), s(Line)]),
             Res = error(Msg)
         )
@@ -194,9 +192,9 @@
             set.member(ExclSpec, ExcludedSpecs),
             ExclSpec = exclude_spec(ModuleName, ExclType),
             (
-                ExclType = all_procedures
+                ExclType = exclude_all_procedures
             ;
-                ExclType = internal_procedures,
+                ExclType = exclude_internal_procedures,
                 PS ^ ps_in_interface = no
             )
         ->
Index: html_format.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/html_format.m,v
retrieving revision 1.14
diff -u -b -r1.14 html_format.m
--- html_format.m	4 Oct 2006 07:03:54 -0000	1.14
+++ html_format.m	11 Oct 2006 03:49:04 -0000
@@ -56,8 +56,10 @@
 :- func fields_header(preferences, id_fields, totals_disposition,
     header_wrap_func) = string.
 
-:- func header_row(string, preferences, id_fields, totals_disposition) = string.
-:- func separator_row(preferences, id_fields, totals_disposition) = string.
+:- func header_row(string, preferences, id_fields, totals_disposition)
+    = string.
+:- func separator_row(preferences, id_fields, totals_disposition)
+    = string.
 
 :- type sub_lines(T)
     ---> sub_lines(
@@ -165,45 +167,75 @@
 banner_style(Pref) = HTML :-
     Fields = Pref ^ pref_fields,
 
-    GroupNum0 = 0,
+    some [!GroupNum] (
+        !:GroupNum = 0,
     IdStyle = string.format("  TD.id     { %s }\n",
-        [s(select_colgroup_background(Pref, GroupNum0))]),
-    GroupNum1 = GroupNum0 + 1,
-    ( Fields ^ port_fields = no_port ->
-        PortStyle = "",
-        GroupNum2 = GroupNum1
+            [s(select_colgroup_background(Pref, !.GroupNum))]),
+        !:GroupNum = !.GroupNum + 1,
+        Fields = fields(PortFields, TimeFields, CallSeqsFields,
+            AllocFields, MemoryFields),
+        (
+            PortFields = no_port,
+            PortStyle = ""
     ;
+            PortFields = port,
         PortStyle = string.format("  TD.port   { %s }\n",
-            [s(select_colgroup_background(Pref, GroupNum1))]),
-        GroupNum2 = GroupNum1 + 1
+                [s(select_colgroup_background(Pref, !.GroupNum))]),
+            !:GroupNum = !.GroupNum + 1
     ),
-    ( Fields ^ time_fields = no_time ->
-        TimeStyle = "",
-        GroupNum3 = GroupNum2
+        (
+            TimeFields = no_time,
+            TimeStyle = ""
     ;
+            ( TimeFields = ticks
+            ; TimeFields = time
+            ; TimeFields = ticks_and_time
+            ; TimeFields = time_and_percall
+            ; TimeFields = ticks_and_time_and_percall
+            ),
         TimeStyle = string.format("  TD.time   { %s }\n",
-            [s(select_colgroup_background(Pref, GroupNum2))]),
-        GroupNum3 = GroupNum2 + 1
+                [s(select_colgroup_background(Pref, !.GroupNum))]),
+            !:GroupNum = !.GroupNum + 1
     ),
-    ( Fields ^ alloc_fields = no_alloc ->
-        AllocStyle = "",
-        GroupNum4 = GroupNum3
+        (
+            CallSeqsFields = no_callseqs,
+            CallSeqsStyle = ""
     ;
+            ( CallSeqsFields = callseqs
+            ; CallSeqsFields = callseqs_and_percall
+            ),
+            CallSeqsStyle = string.format("  TD.callseqs { %s }\n",
+                [s(select_colgroup_background(Pref, !.GroupNum))]),
+            !:GroupNum = !.GroupNum + 1
+        ),
+        (
+            AllocFields = no_alloc,
+            AllocStyle = ""
+        ;
+            ( AllocFields = alloc
+            ; AllocFields = alloc_and_percall
+            ),
         AllocStyle = string.format("  TD.alloc  { %s }\n",
-            [s(select_colgroup_background(Pref, GroupNum3))]),
-        GroupNum4 = GroupNum3 + 1
+                [s(select_colgroup_background(Pref, !.GroupNum))]),
+            !:GroupNum = !.GroupNum + 1
     ),
-    ( Fields ^ memory_fields = no_memory ->
+        (
+            MemoryFields = no_memory,
         MemoryStyle = ""
     ;
+            ( MemoryFields = memory(_)
+            ; MemoryFields = memory_and_percall(_)
+            ),
         MemoryStyle = string.format("  TD.memory { %s }\n",
-            [s(select_colgroup_background(Pref, GroupNum4))])
+                [s(select_colgroup_background(Pref, !.GroupNum))])
+        )
     ),
     HTML =
         "<STYLE TYPE=""text/css"">\n" ++
         IdStyle ++
         PortStyle ++
         TimeStyle ++
+        CallSeqsStyle ++
         AllocStyle ++
         MemoryStyle ++
         "</STYLE>\n".
@@ -212,7 +244,7 @@
 
 select_colgroup_background(Pref, N) = HTML :-
     (
-        Pref ^ pref_colour = column_groups,
+        Pref ^ pref_colour = colour_column_groups,
         ( N /\ 1 = 0 ->
             Background = even_background
         ;
@@ -220,7 +252,7 @@
         ),
         string.format("background: %s", [s(Background)], HTML)
     ;
-        Pref ^ pref_colour = none,
+        Pref ^ pref_colour = colour_none,
         HTML = ""
     ).
 
@@ -252,11 +284,11 @@
     footer_pref_toggles(Cmd, Pref, Deep) ++
     "<br>\n" ++
     string.format("<A HREF=""%s"">Menu</A>\n",
-        [s(deep_cmd_pref_to_url(Pref, Deep, menu))]) ++
+        [s(deep_cmd_pref_to_url(Pref, Deep, deep_cmd_menu))]) ++
     string.format("<A HREF=""%s"">Restart</A>\n",
-        [s(deep_cmd_pref_to_url(Pref, Deep, restart))]) ++
+        [s(deep_cmd_pref_to_url(Pref, Deep, deep_cmd_restart))]) ++
     string.format("<A HREF=""%s"">Quit</A>\n",
-        [s(deep_cmd_pref_to_url(Pref, Deep, quit))]) ++
+        [s(deep_cmd_pref_to_url(Pref, Deep, deep_cmd_quit))]) ++
     "</BODY>\n" ++
     "</HTML>\n".
 
@@ -346,34 +378,35 @@
 
 :- func command_relevant_toggles(cmd) = list(toggle_kind).
 
-command_relevant_toggles(quit) = [].
-command_relevant_toggles(restart) = [].
-command_relevant_toggles(timeout(_)) = [].
-command_relevant_toggles(menu) = [].
-command_relevant_toggles(root(_)) =
-    command_relevant_toggles(clique(1)). % The clique num doesn't matter.
-command_relevant_toggles(clique(_)) =
+command_relevant_toggles(deep_cmd_quit) = [].
+command_relevant_toggles(deep_cmd_restart) = [].
+command_relevant_toggles(deep_cmd_timeout(_)) = [].
+command_relevant_toggles(deep_cmd_menu) = [].
+command_relevant_toggles(deep_cmd_root(_)) =
+    % The clique num doesn't matter.
+    command_relevant_toggles(deep_cmd_clique(1)).
+command_relevant_toggles(deep_cmd_clique(_)) =
     [toggle_fields, toggle_box, toggle_colour, toggle_ancestor_limit,
     toggle_summarize, toggle_order_criteria, toggle_time_format].
-command_relevant_toggles(proc(_)) =
+command_relevant_toggles(deep_cmd_proc(_)) =
     [toggle_fields, toggle_box, toggle_colour, toggle_summarize,
     toggle_order_criteria, toggle_time_format].
-command_relevant_toggles(proc_callers(_, _, _)) =
+command_relevant_toggles(deep_cmd_proc_callers(_, _, _)) =
     [toggle_fields, toggle_box, toggle_colour, toggle_order_criteria,
     toggle_contour, toggle_time_format].
-command_relevant_toggles(modules) =
+command_relevant_toggles(deep_cmd_modules) =
     [toggle_fields, toggle_box, toggle_colour, toggle_order_criteria,
     toggle_time_format, toggle_inactive_modules].
-command_relevant_toggles(module(_)) =
+command_relevant_toggles(deep_cmd_module(_)) =
     [toggle_fields, toggle_box, toggle_colour, toggle_order_criteria,
     toggle_time_format, toggle_inactive_procs].
-command_relevant_toggles(top_procs(_, _, _, _)) =
+command_relevant_toggles(deep_cmd_top_procs(_, _, _, _)) =
     [toggle_fields, toggle_box, toggle_colour, toggle_time_format].
-command_relevant_toggles(proc_static(_)) = [].
-command_relevant_toggles(proc_dynamic(_)) = [].
-command_relevant_toggles(call_site_static(_)) = [].
-command_relevant_toggles(call_site_dynamic(_)) = [].
-command_relevant_toggles(raw_clique(_)) = [].
+command_relevant_toggles(deep_cmd_proc_static(_)) = [].
+command_relevant_toggles(deep_cmd_proc_dynamic(_)) = [].
+command_relevant_toggles(deep_cmd_call_site_static(_)) = [].
+command_relevant_toggles(deep_cmd_call_site_dynamic(_)) = [].
+command_relevant_toggles(deep_cmd_raw_clique(_)) = [].
 
 :- func footer_field_toggle(cmd, preferences, deep) = string.
 
@@ -424,7 +457,7 @@
         Time3Toggle = string.format("<A HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(Time3Pref, Deep, Cmd)), s(Time3Msg)])
     ),
-    ( Fields ^ time_fields = ticks_and_time ->
+    ( Fields ^ time_fields = ticks_and_time->
         Time4Toggle = ""
     ;
         Time4Fields = Fields ^ time_fields := ticks_and_time,
@@ -445,13 +478,42 @@
     ( Fields ^ time_fields = ticks_and_time_and_percall ->
         Time6Toggle = ""
     ;
-        Time6Fields = Fields ^ time_fields :=
-            ticks_and_time_and_percall,
+        Time6Fields = Fields ^ time_fields := ticks_and_time_and_percall,
         Time6Pref = Pref ^ pref_fields := Time6Fields,
         Time6Msg = "Ticks and times and per-call times",
         Time6Toggle = string.format("<A HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(Time6Pref, Deep, Cmd)), s(Time6Msg)])
     ),
+    ( Fields ^ callseqs_fields = no_callseqs ->
+        CallSeqs1Toggle = ""
+    ;
+        CallSeqs1Fields = Fields ^ callseqs_fields := no_callseqs,
+        CallSeqs1Pref = Pref ^ pref_fields := CallSeqs1Fields,
+        CallSeqs1Msg = "No call sequence number info",
+        CallSeqs1Toggle = string.format("<A HREF=""%s"">%s</A>\n",
+            [s(deep_cmd_pref_to_url(CallSeqs1Pref, Deep, Cmd)),
+                s(CallSeqs1Msg)])
+    ),
+    ( Fields ^ callseqs_fields = callseqs ->
+        CallSeqs2Toggle = ""
+    ;
+        CallSeqs2Fields = Fields ^ callseqs_fields := callseqs,
+        CallSeqs2Pref = Pref ^ pref_fields := CallSeqs2Fields,
+        CallSeqs2Msg = "Call sequence numbers",
+        CallSeqs2Toggle = string.format("<A HREF=""%s"">%s</A>\n",
+            [s(deep_cmd_pref_to_url(CallSeqs2Pref, Deep, Cmd)),
+                s(CallSeqs2Msg)])
+    ),
+    ( Fields ^ callseqs_fields = callseqs_and_percall ->
+        CallSeqs3Toggle = ""
+    ;
+        CallSeqs3Fields = Fields ^ callseqs_fields := callseqs_and_percall,
+        CallSeqs3Pref = Pref ^ pref_fields := CallSeqs3Fields,
+        CallSeqs3Msg = "Call sequence numbers including per-call",
+        CallSeqs3Toggle = string.format("<A HREF=""%s"">%s</A>\n",
+            [s(deep_cmd_pref_to_url(CallSeqs3Pref, Deep, Cmd)),
+                s(CallSeqs3Msg)])
+    ),
     ( Fields ^ alloc_fields = no_alloc ->
         Alloc1Toggle = ""
     ;
@@ -488,60 +550,64 @@
         Memory1Toggle = string.format("<A HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(Memory1Pref, Deep, Cmd)), s(Memory1Msg)])
     ),
-    ( Fields ^ memory_fields = memory(words) ->
+    ( Fields ^ memory_fields = memory(units_words) ->
         Memory2Toggle = ""
     ;
-        Memory2Fields = Fields ^ memory_fields := memory(words),
+        Memory2Fields = Fields ^ memory_fields := memory(units_words),
         Memory2Pref = Pref ^ pref_fields := Memory2Fields,
         Memory2Msg = "Words",
         Memory2Toggle = string.format("<A HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(Memory2Pref, Deep, Cmd)), s(Memory2Msg)])
     ),
-    ( Fields ^ memory_fields = memory(bytes) ->
+    ( Fields ^ memory_fields = memory(units_bytes) ->
         Memory3Toggle = ""
     ;
-        Memory3Fields = Fields ^ memory_fields := memory(bytes),
+        Memory3Fields = Fields ^ memory_fields := memory(units_bytes),
         Memory3Pref = Pref ^ pref_fields := Memory3Fields,
         Memory3Msg = "Bytes",
         Memory3Toggle = string.format("<A HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(Memory3Pref, Deep, Cmd)), s(Memory3Msg)])
     ),
-    ( Fields ^ memory_fields = memory_and_percall(words) ->
+    ( Fields ^ memory_fields = memory_and_percall(units_words) ->
         Memory4Toggle = ""
     ;
         Memory4Fields = Fields ^ memory_fields :=
-            memory_and_percall(words),
+            memory_and_percall(units_words),
         Memory4Pref = Pref ^ pref_fields := Memory4Fields,
         Memory4Msg = "Words and per-call words",
         Memory4Toggle = string.format("<A HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(Memory4Pref, Deep, Cmd)), s(Memory4Msg)])
     ),
-    ( Fields ^ memory_fields = memory_and_percall(bytes) ->
+    ( Fields ^ memory_fields = memory_and_percall(units_bytes) ->
         Memory5Toggle = ""
     ;
         Memory5Fields = Fields ^ memory_fields :=
-            memory_and_percall(bytes),
+            memory_and_percall(units_bytes),
         Memory5Pref = Pref ^ pref_fields := Memory5Fields,
         Memory5Msg = "Bytes and per-call bytes",
         Memory5Toggle = string.format("<A HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(Memory5Pref, Deep, Cmd)), s(Memory5Msg)])
     ),
-    ( Fields = default_fields ->
+    ( Fields = default_fields(Deep) ->
+        DefaultToggle = ""
+    ;
         DefaultMsg  = "Restore defaults",
-        DefaultPref = Pref ^ pref_fields := default_fields,
+        DefaultPref = Pref ^ pref_fields := default_fields(Deep),
         DefaultToggle = string.format("<A HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(DefaultPref, Deep, Cmd)), s(DefaultMsg)])
-    ;
-        DefaultToggle = ""
     ),
     HTML =
         "Toggle fields:\n" ++
         DefaultToggle ++
         Port1Toggle ++ Port2Toggle ++
+        "<br>\n" ++
         Time1Toggle ++ Time2Toggle ++ Time3Toggle ++
         Time4Toggle ++ Time5Toggle ++ Time6Toggle ++
         "<br>\n" ++
+        CallSeqs1Toggle ++ CallSeqs2Toggle ++ CallSeqs3Toggle ++
+        "<br>\n" ++
         Alloc1Toggle ++ Alloc2Toggle ++ Alloc3Toggle ++
+        "<br>\n" ++
         Memory1Toggle ++ Memory2Toggle ++ Memory3Toggle ++
         Memory4Toggle ++ Memory5Toggle ++
         "<br>\n".
@@ -633,12 +699,12 @@
 
 footer_colour_toggle(Cmd, Pref, Deep) = HTML :-
     (
-        Pref ^ pref_colour = none,
-        Pref1 = Pref ^ pref_colour := column_groups,
+        Pref ^ pref_colour = colour_none,
+        Pref1 = Pref ^ pref_colour := colour_column_groups,
         Msg1 = "Colour column groups"
     ;
-        Pref ^ pref_colour = column_groups,
-        Pref1 = Pref ^ pref_colour := none,
+        Pref ^ pref_colour = colour_column_groups,
+        Pref1 = Pref ^ pref_colour := colour_none,
         Msg1 = "Fade column groups"
     ),
     HTML = string.format("<A HREF=""%s"">%s</A>\n",
@@ -677,6 +743,25 @@
 :- func footer_time_format_toggle(cmd, preferences, deep) = string.
 
 footer_time_format_toggle(Cmd, Pref, Deep) = HTML :-
+    TimeFields = Pref ^ pref_fields ^ time_fields,
+    (
+        ( TimeFields = no_time
+        ; TimeFields = ticks
+        ),
+        ToggleTimeFormat = no
+    ;
+        ( TimeFields = time
+        ; TimeFields = ticks_and_time
+        ; TimeFields = time_and_percall
+        ; TimeFields = ticks_and_time_and_percall
+        ),
+        ToggleTimeFormat = yes
+    ),
+    (
+        ToggleTimeFormat = no,
+        HTML = ""
+    ;
+        ToggleTimeFormat = yes,
     (
         Pref ^ pref_time = no_scale,
         Pref1 = Pref ^ pref_time := scale_by_millions,
@@ -700,7 +785,8 @@
         string.format("<A HREF=""%s"">%s</A>\n",
             [s(deep_cmd_pref_to_url(Pref1, Deep, Cmd)), s(Msg1)]) ++
         string.format("<A HREF=""%s"">%s</A>\n",
-            [s(deep_cmd_pref_to_url(Pref2, Deep, Cmd)), s(Msg2)]).
+                [s(deep_cmd_pref_to_url(Pref2, Deep, Cmd)), s(Msg2)])
+    ).
 
 %-----------------------------------------------------------------------------%
 
@@ -752,10 +838,14 @@
         [s(UpdateCriteria(Criteria1)), s(Msg1)]),
     Toggle2 = string.format("<A HREF=""%s"">%s</A>\n",
         [s(UpdateCriteria(Criteria2)), s(Msg2)]),
-    ( Criteria = by_cost(CostKind, InclDesc, Scope) ->
+    (
+        Criteria = by_cost(CostKind, InclDesc, Scope),
         ToggleRest = toggle_cost_criteria(CostKind, InclDesc, Scope,
             UpdateCostCriteria)
     ;
+        ( Criteria = by_context
+        ; Criteria = by_name
+        ),
         ToggleRest = ""
     ),
     HTML = "Toggle ordering criteria:\n" ++ Toggle1 ++ Toggle2 ++ ToggleRest.
@@ -764,39 +854,89 @@
     update_cost_criteria_func) = string.
 
 toggle_cost_criteria(CostKind, InclDesc, Scope, UpdateCriteria) = Toggles :-
-    ( CostKind \= calls ->
+    (
+        ( CostKind = cost_redos
+        ; CostKind = cost_time
+        ; CostKind = cost_callseqs
+        ; CostKind = cost_allocs
+        ; CostKind = cost_words
+        ),
         MsgCalls = "Sort by calls",
         ToggleCalls = string.format("<A HREF=""%s"">%s</A>\n",
-            [s(UpdateCriteria(calls, InclDesc, Scope)), s(MsgCalls)])
+            [s(UpdateCriteria(cost_calls, InclDesc, Scope)), s(MsgCalls)])
     ;
+        CostKind = cost_calls,
         ToggleCalls = ""
     ),
-    ( CostKind \= redos ->
+    (
+        ( CostKind = cost_calls
+        ; CostKind = cost_time
+        ; CostKind = cost_callseqs
+        ; CostKind = cost_allocs
+        ; CostKind = cost_words
+        ),
         MsgRedos = "Sort by redos",
         ToggleRedos = string.format("<A HREF=""%s"">%s</A>\n",
-            [s(UpdateCriteria(redos, InclDesc, Scope)), s(MsgRedos)])
+            [s(UpdateCriteria(cost_redos, InclDesc, Scope)), s(MsgRedos)])
     ;
+        CostKind = cost_redos,
         ToggleRedos = ""
     ),
-    ( CostKind \= time ->
+    (
+        ( CostKind = cost_calls
+        ; CostKind = cost_redos
+        ; CostKind = cost_callseqs
+        ; CostKind = cost_allocs
+        ; CostKind = cost_words
+        ),
         MsgTime = "Sort by time",
         ToggleTime = string.format("<A HREF=""%s"">%s</A>\n",
-            [s(UpdateCriteria(time, InclDesc, Scope)), s(MsgTime)])
+            [s(UpdateCriteria(cost_time, InclDesc, Scope)), s(MsgTime)])
     ;
+        CostKind = cost_time,
         ToggleTime = ""
     ),
-    ( CostKind \= allocs ->
+    (
+        ( CostKind = cost_calls
+        ; CostKind = cost_redos
+        ; CostKind = cost_time
+        ; CostKind = cost_allocs
+        ; CostKind = cost_words
+        ),
+        MsgCallSeqs = "Sort by call sequence numbers",
+        ToggleCallSeqs = string.format("<A HREF=""%s"">%s</A>\n",
+            [s(UpdateCriteria(cost_callseqs, InclDesc, Scope)),
+                s(MsgCallSeqs)])
+    ;
+        CostKind = cost_callseqs,
+        ToggleCallSeqs = ""
+    ),
+    (
+        ( CostKind = cost_calls
+        ; CostKind = cost_redos
+        ; CostKind = cost_time
+        ; CostKind = cost_callseqs
+        ; CostKind = cost_words
+        ),
         MsgAllocs = "Sort by allocations",
         ToggleAllocs = string.format("<A HREF=""%s"">%s</A>\n",
-            [s(UpdateCriteria(allocs, InclDesc, Scope)), s(MsgAllocs)])
+            [s(UpdateCriteria(cost_allocs, InclDesc, Scope)), s(MsgAllocs)])
     ;
+        CostKind = cost_allocs,
         ToggleAllocs = ""
     ),
-    ( CostKind \= words ->
+    (
+        ( CostKind = cost_calls
+        ; CostKind = cost_redos
+        ; CostKind = cost_time
+        ; CostKind = cost_callseqs
+        ; CostKind = cost_allocs
+        ),
         MsgWords = "Sort by words",
         ToggleWords = string.format("<A HREF=""%s"">%s</A>\n",
-            [s(UpdateCriteria(words, InclDesc, Scope)), s(MsgWords)])
+            [s(UpdateCriteria(cost_words, InclDesc, Scope)), s(MsgWords)])
     ;
+        CostKind = cost_words,
         ToggleWords = ""
     ),
     (
@@ -821,8 +961,9 @@
         ToggleScope = string.format("<A HREF=""%s"">%s</A>\n",
             [s(UpdateCriteria(CostKind, InclDesc, per_call)), s(MsgScope)])
     ),
-    Toggles = ToggleCalls ++ ToggleRedos ++ ToggleTime ++ ToggleAllocs
-        ++ ToggleWords ++ ToggleDesc ++ ToggleScope.
+    Toggles = ToggleCalls ++ ToggleRedos ++ ToggleTime ++ ToggleCallSeqs ++
+        ToggleAllocs ++ ToggleWords ++
+        "\n<br>\n" ++ ToggleDesc ++ ToggleScope.
 
 %-----------------------------------------------------------------------------%
 %
@@ -834,13 +975,13 @@
 footer_inactive_modules_toggle(Cmd, Pref0, Deep) = HTML :-
     Pref0 ^ pref_inactive = inactive_items(Procs, Modules),
     (
-        Modules = show,
+        Modules = inactive_show,
         Msg  = "Hide inactive modules",
-        Pref = Pref0 ^ pref_inactive := inactive_items(Procs, hide)
+        Pref = Pref0 ^ pref_inactive := inactive_items(Procs, inactive_hide)
     ;
-        Modules = hide,
+        Modules = inactive_hide,
         Msg  = "Show inactive modules",
-        Pref = Pref0 ^ pref_inactive := inactive_items(Procs, show)
+        Pref = Pref0 ^ pref_inactive := inactive_items(Procs, inactive_show)
     ),
     HTML = string.format("<A HREF=""%s"">%s</A>\n",
         [s(deep_cmd_pref_to_url(Pref, Deep, Cmd)), s(Msg)]).
@@ -850,13 +991,13 @@
 footer_inactive_procs_toggle(Cmd, Pref0, Deep) = HTML :-
     Pref0 ^ pref_inactive = inactive_items(Procs, Modules),
     (
-        Procs = show,
+        Procs = inactive_show,
         Msg = "Hide inactive procedures",
-        Pref = Pref0 ^ pref_inactive := inactive_items(hide, Modules)
+        Pref = Pref0 ^ pref_inactive := inactive_items(inactive_hide, Modules)
     ;
-        Procs = hide,
+        Procs = inactive_hide,
         Msg = "Show inactive procedures",
-        Pref = Pref0 ^ pref_inactive := inactive_items(show, Modules)
+        Pref = Pref0 ^ pref_inactive := inactive_items(inactive_show, Modules)
     ),
     HTML = string.format("<A HREF=""%s"">%s</A>\n",
         [s(deep_cmd_pref_to_url(Pref, Deep, Cmd)), s(Msg)]).
@@ -883,7 +1024,7 @@
 
 update_cost_criteria_in_top_procs_cmd(Pref, Deep, Limit,
         CostKind, InclDesc, Scope) = HTML :-
-    Cmd = top_procs(Limit, CostKind, InclDesc, Scope),
+    Cmd = deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope),
     HTML = deep_cmd_pref_to_url(Pref, Deep, Cmd).
 
 %-----------------------------------------------------------------------------%
@@ -902,11 +1043,12 @@
 
 :- func cost_kind_to_description(cost_kind) = string.
 
-cost_kind_to_description(calls)  = "number of calls".
-cost_kind_to_description(redos)  = "number of redos".
-cost_kind_to_description(time)   = "time".
-cost_kind_to_description(allocs) = "memory allocations".
-cost_kind_to_description(words)  = "words allocated".
+cost_kind_to_description(cost_calls)    = "number of calls".
+cost_kind_to_description(cost_redos)    = "number of redos".
+cost_kind_to_description(cost_time)     = "time".
+cost_kind_to_description(cost_callseqs) = "call sequence numbers".
+cost_kind_to_description(cost_allocs)   = "memory allocations".
+cost_kind_to_description(cost_words)    = "words allocated".
 
 :- func incl_desc_to_description(include_descendants) = string.
 
@@ -920,98 +1062,115 @@
 
 %-----------------------------------------------------------------------------%
 
-% The predicates fields_header, table_width and own_and_desc_to_html all make
-% decisions about what columns each row in the table will have.  They
-% therefore have similar control structures, and a change in one may require
-% changes in the others as well.
+% The predicates banner_style, fields_header, table_width and
+% own_and_desc_to_html all make decisions about what columns each row
+% in the table will have.  They therefore have similar control structures,
+% and a change in one may require changes in the others as well.
 
 fields_header(Pref, IdFields, TotalsDisp, WrapFunc) = HTML :-
     Fields = Pref ^ pref_fields,
     ProcName = WrapFunc("Procedure", by_name),
     ModuleName = WrapFunc("Module", by_name),
+
+    some [!FirstRow, !SecondRow] (
     (
         IdFields = source_proc,
         Source = WrapFunc("Source", by_context),
-        FirstRow0 =
+            !:FirstRow =
             "<TR>\n" ++
             string.format("<TH ALIGN=LEFT ROWSPAN=2>%s\n", [s(Source)]) ++
             string.format("<TH ALIGN=LEFT ROWSPAN=2>%s\n", [s(ProcName)])
     ;
         IdFields = rank_proc,
-        FirstRow0 =
+            !:FirstRow =
             "<TR>\n" ++
             "<TH ALIGN=LEFT ROWSPAN=2>Rank\n" ++
             string.format("<TH ALIGN=LEFT ROWSPAN=2>%s\n", [s(ProcName)])
     ;
         IdFields = rank_module,
-        FirstRow0 =
+            !:FirstRow =
             "<TR>\n" ++
             "<TH ALIGN=LEFT ROWSPAN=2>Rank\n" ++
             string.format("<TH ALIGN=LEFT ROWSPAN=2>%s\n", [s(ModuleName)])
     ;
         IdFields = proc,
-        FirstRow0 =
+            !:FirstRow =
             "<TR>\n" ++
             string.format("<TH ALIGN=LEFT ROWSPAN=2>%s\n", [s(ProcName)])
     ),
-    SecondRow0 = "<TR>\n",
-    ( show_port_counts(Fields) = yes ->
-        Calls = WrapFunc("Calls", by_cost(calls, self, overall)),
-        Redos = WrapFunc("Redos", by_cost(redos, self, overall)),
-        FirstRow1 = FirstRow0 ++
+        !:SecondRow = "<TR>\n",
+
+        ShowPortCounts = show_port_counts(Fields),
+        (
+            ShowPortCounts = yes,
+            Calls = WrapFunc("Calls", by_cost(cost_calls, self, overall)),
+            Redos = WrapFunc("Redos", by_cost(cost_redos, self, overall)),
+            !:FirstRow = !.FirstRow ++
             "<TH COLSPAN=5>Port counts\n",
-        SecondRow1 = SecondRow0 ++
+            !:SecondRow = !.SecondRow ++
             string.format("<TH ALIGN=RIGHT>%s\n", [s(Calls)]) ++
             "<TH ALIGN=RIGHT>Exits\n" ++
             "<TH ALIGN=RIGHT>Fails\n" ++
             string.format("<TH ALIGN=RIGHT>%s\n", [s(Redos)]) ++
             "<TH ALIGN=RIGHT>Excps\n"
     ;
-        FirstRow1 = FirstRow0,
-        SecondRow1 = SecondRow0
+            ShowPortCounts = no
     ),
-    ( show_quanta(Fields) = yes ->
+
+        ShowQuanta = show_quanta(Fields),
+        (
+            ShowQuanta = yes,
         TicksSelfOverall = WrapFunc("Self",
-            by_cost(time, self, overall)),
+                by_cost(cost_time, self, overall)),
         TicksSelfHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(TicksSelfOverall)]),
         TicksSelfFields = 1
     ;
+            ShowQuanta = no,
         TicksSelfHeading = "",
         TicksSelfFields = 0
     ),
-    ( show_times(Fields) = yes ->
+        ShowTimes = show_times(Fields),
+        (
+            ShowTimes = yes,
         ( show_quanta(Fields) = yes ->
-            TimeSelfOverall = WrapFunc("Time", by_cost(time, self, overall))
+                TimeSelfOverall = WrapFunc("Time",
+                    by_cost(cost_time, self, overall))
         ;
-            TimeSelfOverall = WrapFunc("Self", by_cost(time, self, overall))
+                TimeSelfOverall = WrapFunc("Self",
+                    by_cost(cost_time, self, overall))
         ),
         TimeSelfHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(TimeSelfOverall)]),
         TimeSelfFields = 1
     ;
+            ShowTimes = no,
         TimeSelfHeading = "",
         TimeSelfFields = 0
     ),
-    ( ( show_quanta(Fields) = yes ; show_times(Fields) = yes ) ->
+        ( ( ShowQuanta = yes ; ShowTimes = yes ) ->
         TimeSelfPercentHeading = "<TH ALIGN=RIGHT>%\n",
         TimeSelfPercentFields = 1
     ;
         TimeSelfPercentHeading = "",
         TimeSelfPercentFields = 0
     ),
-    ( show_per_times(Fields) = yes ->
-        TimeSelfPerCall = WrapFunc("/call", by_cost(time, self, per_call)),
+        ShowTimesPerCall = show_times_per_call(Fields),
+        (
+            ShowTimesPerCall = yes,
+            TimeSelfPerCall = WrapFunc("/call",
+                by_cost(cost_time, self, per_call)),
         TimeSelfPerCallHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(TimeSelfPerCall)]),
         TimeSelfPerCallFields = 1
     ;
+            ShowTimesPerCall = no,
         TimeSelfPerCallHeading = "",
         TimeSelfPerCallFields = 0
     ),
-    ( TotalsDisp = totals_meaningful, show_quanta(Fields) = yes ->
+        ( TotalsDisp = totals_meaningful, ShowQuanta = yes ->
         TicksTotalOverall = WrapFunc("Total",
-            by_cost(time, self_and_desc, overall)),
+                by_cost(cost_time, self_and_desc, overall)),
         TicksTotalHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(TicksTotalOverall)]),
         TicksTotalFields = 1
@@ -1019,13 +1178,13 @@
         TicksTotalHeading = "",
         TicksTotalFields = 0
     ),
-    ( TotalsDisp = totals_meaningful, show_times(Fields) = yes ->
+        ( TotalsDisp = totals_meaningful, ShowTimes = yes ->
         ( show_quanta(Fields) = yes ->
             TimeTotalOverall = WrapFunc("Time",
-                by_cost(time, self_and_desc, overall))
+                    by_cost(cost_time, self_and_desc, overall))
         ;
             TimeTotalOverall = WrapFunc("Total",
-                by_cost(time, self_and_desc, overall))
+                    by_cost(cost_time, self_and_desc, overall))
         ),
         TimeTotalHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(TimeTotalOverall)]),
@@ -1036,7 +1195,7 @@
     ),
     (
         TotalsDisp = totals_meaningful,
-        ( show_quanta(Fields) = yes ; show_times(Fields) = yes )
+            ( ShowQuanta = yes ; ShowTimes = yes )
     ->
         TimeTotalPercentHeading = "<TH ALIGN=RIGHT>%\n",
         TimeTotalPercentFields = 1
@@ -1044,9 +1203,9 @@
         TimeTotalPercentHeading = "",
         TimeTotalPercentFields = 0
     ),
-    ( TotalsDisp = totals_meaningful, show_per_times(Fields) = yes ->
+        ( TotalsDisp = totals_meaningful, ShowTimesPerCall = yes ->
         TimeTotalPerCall = WrapFunc("/call",
-            by_cost(time, self_and_desc, per_call)),
+                by_cost(cost_time, self_and_desc, per_call)),
         TimeTotalPerCallHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(TimeTotalPerCall)]),
         TimeTotalPerCallFields = 1
@@ -1059,59 +1218,141 @@
         TimeSelfPercentFields + TimeSelfPerCallFields +
         TicksTotalFields + TimeTotalFields +
         TimeTotalPercentFields + TimeTotalPerCallFields,
-    SecondRow2 = SecondRow1 ++
+        !:SecondRow = !.SecondRow ++
         TicksSelfHeading ++ TimeSelfHeading ++
         TimeSelfPercentHeading ++ TimeSelfPerCallHeading ++
         TicksTotalHeading ++ TimeTotalHeading ++
         TimeTotalPercentHeading ++ TimeTotalPerCallHeading,
-    ( show_quanta(Fields) = yes, show_times(Fields) = yes ->
-        FirstRow2 = FirstRow1 ++
+        (
+            ShowQuanta = yes,
+            ShowTimes = yes,
+            !:FirstRow = !.FirstRow ++
             string.format("<TH COLSPAN=%d>Clock ticks and times\n",
                 [i(TimeFields)])
-    ; show_quanta(Fields) = yes ->
-        FirstRow2 = FirstRow1 ++
+        ;
+            ShowQuanta = yes,
+            ShowTimes = no,
+            !:FirstRow = !.FirstRow ++
             string.format("<TH COLSPAN=%d>Clock ticks\n", [i(TimeFields)])
-    ; show_times(Fields) = yes ->
-        FirstRow2 = FirstRow1 ++
+        ;
+            ShowQuanta = no,
+            ShowTimes = yes,
+            !:FirstRow = !.FirstRow ++
             string.format("<TH COLSPAN=%d>Time\n", [i(TimeFields)])
     ;
-        FirstRow2 = FirstRow1
+            ShowQuanta = no,
+            ShowTimes = no
+        ),
+
+        ShowCallSeqs = show_callseqs(Fields),
+        (
+            ShowCallSeqs = yes,
+            CallSeqsSelfOverall = WrapFunc("Self",
+                by_cost(cost_callseqs, self, overall)),
+            CallSeqsSelfHeading =
+                string.format("<TH ALIGN=RIGHT>%s\n",
+                    [s(CallSeqsSelfOverall)]) ++
+                "<TH ALIGN=RIGHT>%\n",
+            CallSeqsSelfFields = 2
+        ;
+            ShowCallSeqs = no,
+            CallSeqsSelfHeading = "",
+            CallSeqsSelfFields = 0
+        ),
+        ShowCallSeqsPerCall = show_callseqs_per_call(Fields),
+        (
+            ShowCallSeqsPerCall = yes,
+            CallSeqsSelfPerCall = WrapFunc("/call",
+                by_cost(cost_callseqs, self, per_call)),
+            CallSeqsSelfPerCallHeading =
+                string.format("<TH ALIGN=RIGHT>%s\n", [s(CallSeqsSelfPerCall)]),
+            CallSeqsSelfPerCallFields = 1
+        ;
+            ShowCallSeqsPerCall = no,
+            CallSeqsSelfPerCallHeading = "",
+            CallSeqsSelfPerCallFields = 0
+        ),
+        ( TotalsDisp = totals_meaningful, ShowCallSeqs = yes ->
+            CallSeqsTotalOverall = WrapFunc("Total",
+                by_cost(cost_callseqs, self_and_desc, overall)),
+            CallSeqsTotalHeading =
+                string.format("<TH ALIGN=RIGHT>%s\n",
+                    [s(CallSeqsTotalOverall)]) ++
+                "<TH ALIGN=RIGHT>%\n",
+            CallSeqsTotalFields = 2
+        ;
+            CallSeqsTotalHeading = "",
+            CallSeqsTotalFields = 0
+        ),
+        ( TotalsDisp = totals_meaningful, ShowCallSeqsPerCall = yes ->
+            CallSeqsTotalPerCall = WrapFunc("/call",
+                by_cost(cost_callseqs, self_and_desc, per_call)),
+            CallSeqsTotalPerCallHeading =
+                string.format("<TH ALIGN=RIGHT>%s\n",
+                    [s(CallSeqsTotalPerCall)]),
+            CallSeqsTotalPerCallFields = 1
+        ;
+            CallSeqsTotalPerCallHeading = "",
+            CallSeqsTotalPerCallFields = 0
+        ),
+        CallSeqsFields =
+            CallSeqsSelfFields + CallSeqsSelfPerCallFields +
+            CallSeqsTotalFields + CallSeqsTotalPerCallFields,
+        !:SecondRow = !.SecondRow ++
+            CallSeqsSelfHeading ++ CallSeqsSelfPerCallHeading ++
+            CallSeqsTotalHeading ++ CallSeqsTotalPerCallHeading,
+        (
+            ShowCallSeqs = yes,
+            !:FirstRow = !.FirstRow ++
+                string.format("<TH COLSPAN=%d>Call sequence numbers\n",
+                    [i(CallSeqsFields)])
+        ;
+            ShowCallSeqs = no
     ),
-    ( show_alloc(Fields) = yes ->
+
+        ShowAlloc = show_alloc(Fields),
+        (
+            ShowAlloc = yes,
         AllocsSelfOverall = WrapFunc("Self",
-            by_cost(allocs, self, overall)),
+                by_cost(cost_allocs, self, overall)),
         AllocsSelfHeading =
-            string.format("<TH ALIGN=RIGHT>%s\n", [s(AllocsSelfOverall)]) ++
+                string.format("<TH ALIGN=RIGHT>%s\n",
+                    [s(AllocsSelfOverall)]) ++
             "<TH ALIGN=RIGHT>%\n",
         AllocsSelfFields = 2
     ;
+            ShowAlloc = no,
         AllocsSelfHeading = "",
         AllocsSelfFields = 0
     ),
-    ( show_per_alloc(Fields) = yes ->
+        ShowAllocPerCall = show_alloc_per_call(Fields),
+        (
+            ShowAllocPerCall = yes,
         AllocsSelfPerCall = WrapFunc("/call",
-            by_cost(allocs, self, per_call)),
+                by_cost(cost_allocs, self, per_call)),
         AllocsSelfPerCallHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(AllocsSelfPerCall)]),
         AllocsSelfPerCallFields = 1
     ;
+            ShowAllocPerCall = no,
         AllocsSelfPerCallHeading = "",
         AllocsSelfPerCallFields = 0
     ),
-    ( TotalsDisp = totals_meaningful, show_alloc(Fields) = yes ->
+        ( TotalsDisp = totals_meaningful, ShowAlloc = yes ->
         AllocsTotalOverall = WrapFunc("Total",
-            by_cost(allocs, self_and_desc, overall)),
+                by_cost(cost_allocs, self_and_desc, overall)),
         AllocsTotalHeading =
-            string.format("<TH ALIGN=RIGHT>%s\n", [s(AllocsTotalOverall)]) ++
+                string.format("<TH ALIGN=RIGHT>%s\n",
+                    [s(AllocsTotalOverall)]) ++
             "<TH ALIGN=RIGHT>%\n",
         AllocsTotalFields = 2
     ;
         AllocsTotalHeading = "",
         AllocsTotalFields = 0
     ),
-    ( TotalsDisp = totals_meaningful, show_per_alloc(Fields) = yes ->
+        ( TotalsDisp = totals_meaningful, ShowAllocPerCall = yes ->
         AllocsTotalPerCall = WrapFunc("/call",
-            by_cost(allocs, self_and_desc, per_call)),
+                by_cost(cost_allocs, self_and_desc, per_call)),
         AllocsTotalPerCallHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(AllocsTotalPerCall)]),
         AllocsTotalPerCallFields = 1
@@ -1122,51 +1363,61 @@
     AllocsFields =
         AllocsSelfFields + AllocsSelfPerCallFields +
         AllocsTotalFields + AllocsTotalPerCallFields,
-    SecondRow3 = SecondRow2 ++
+        !:SecondRow = !.SecondRow ++
         AllocsSelfHeading ++ AllocsSelfPerCallHeading ++
         AllocsTotalHeading ++ AllocsTotalPerCallHeading,
-    ( show_alloc(Fields) = yes ->
-        FirstRow3 = FirstRow2 ++
+        (
+            ShowAlloc = yes,
+            !:FirstRow = !.FirstRow ++
             string.format("<TH COLSPAN=%d>Memory allocations\n",
                 [i(AllocsFields)])
     ;
-        FirstRow3 = FirstRow2
+            ShowAlloc = no
     ),
-    ( show_memory(Fields) = yes(_) ->
+
+        ShowMemory = show_memory(Fields),
+        (
+            ShowMemory = yes(_),
         MemorySelfOverall = WrapFunc("Self",
-            by_cost(words, self, overall)),
+                by_cost(cost_words, self, overall)),
         MemorySelfHeading =
-            string.format("<TH ALIGN=RIGHT>%s\n", [s(MemorySelfOverall)]) ++
+                string.format("<TH ALIGN=RIGHT>%s\n",
+                    [s(MemorySelfOverall)]) ++
             "<TH ALIGN=RIGHT>%\n",
         MemorySelfFields = 2
     ;
+            ShowMemory = no,
         MemorySelfHeading = "",
         MemorySelfFields = 0
     ),
-    ( show_per_memory(Fields) = yes(_) ->
+        ShowMemoryPerCall = show_memory_per_call(Fields),
+        (
+            ShowMemoryPerCall = yes(_),
         MemorySelfPerCall = WrapFunc("/call",
-            by_cost(words, self, per_call)),
+                by_cost(cost_words, self, per_call)),
         MemorySelfPerCallHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(MemorySelfPerCall)]),
         MemorySelfPerCallFields = 1
     ;
+            ShowMemoryPerCall = no,
         MemorySelfPerCallHeading = "",
         MemorySelfPerCallFields = 0
     ),
-    ( TotalsDisp = totals_meaningful, show_memory(Fields) = yes(_) ->
+        ( TotalsDisp = totals_meaningful, ShowMemory = yes(_) ->
         MemoryTotalOverall = WrapFunc("Total",
-            by_cost(words, self_and_desc, overall)),
+                by_cost(cost_words, self_and_desc, overall)),
         MemoryTotalHeading =
-            string.format("<TH ALIGN=RIGHT>%s\n", [s(MemoryTotalOverall)]) ++
+                string.format("<TH ALIGN=RIGHT>%s\n",
+                    [s(MemoryTotalOverall)]) ++
             "<TH ALIGN=RIGHT>%\n",
         MemoryTotalFields = 2
     ;
         MemoryTotalHeading = "",
         MemoryTotalFields = 0
     ),
-    ( TotalsDisp = totals_meaningful, show_per_memory(Fields) = yes(_) ->
+        ( TotalsDisp = totals_meaningful, ShowMemoryPerCall = yes(_) ->
         MemoryTotalPerCall = WrapFunc("/call",
-            by_cost(words, self_and_desc, per_call)),
+                by_cost(cost_words, self_and_desc, per_call)),
         MemoryTotalPerCallHeading =
             string.format("<TH ALIGN=RIGHT>%s\n", [s(MemoryTotalPerCall)]),
         MemoryTotalPerCallFields = 1
@@ -1177,30 +1428,32 @@
     MemoryFields =
         MemorySelfFields + MemorySelfPerCallFields +
         MemoryTotalFields + MemoryTotalPerCallFields,
-    SecondRow4 = SecondRow3 ++
+        !:SecondRow = !.SecondRow ++
         MemorySelfHeading ++ MemorySelfPerCallHeading ++
         MemoryTotalHeading ++ MemoryTotalPerCallHeading,
-    ( show_memory(Fields) = yes(Units) ->
         (
-            Units = words,
-            FirstRow4 = FirstRow3 ++
+            ShowMemory = yes(Units),
+            (
+                Units = units_words,
+                !:FirstRow = !.FirstRow ++
                 string.format("<TH COLSPAN=%d>Memory words\n",
                     [i(MemoryFields)])
         ;
-            Units = bytes,
-            FirstRow4 = FirstRow3 ++
+                Units = units_bytes,
+                !:FirstRow = !.FirstRow ++
                 string.format("<TH COLSPAN=%d>Memory bytes\n",
                     [i(MemoryFields)])
         )
     ;
-        FirstRow4 = FirstRow3
+            ShowMemory = no
     ),
     HTML =
         "<THEAD>\n" ++
-        FirstRow4 ++
-        SecondRow4 ++
+            !.FirstRow ++
+            !.SecondRow ++
         "<TBODY>\n" ++
-        separator_row(Pref, IdFields, TotalsDisp).
+            separator_row(Pref, IdFields, TotalsDisp)
+    ).
 
 %-----------------------------------------------------------------------------%
 
@@ -1241,46 +1494,56 @@
         Time = 0
     ;
         Fields ^ time_fields = ticks,
-        Time = 4
+        Time = 2
     ;
         Fields ^ time_fields = time,
-        Time = 4
+        Time = 2
     ;
         Fields ^ time_fields = ticks_and_time,
-        Time = 6
+        Time = 3
     ;
         Fields ^ time_fields = time_and_percall,
-        Time = 6
+        Time = 3
     ;
         Fields ^ time_fields = ticks_and_time_and_percall,
-        Time = 8
+        Time = 4
+    ),
+    (
+        Fields ^ callseqs_fields = no_callseqs,
+        CallSeqs = 0
+    ;
+        Fields ^ callseqs_fields = callseqs,
+        CallSeqs = 2
+    ;
+        Fields ^ callseqs_fields = callseqs_and_percall,
+        CallSeqs = 3
     ),
     (
         Fields ^ alloc_fields = no_alloc,
         Alloc = 0
     ;
         Fields ^ alloc_fields = alloc,
-        Alloc = 4
+        Alloc = 2
     ;
         Fields ^ alloc_fields = alloc_and_percall,
-        Alloc = 6
+        Alloc = 3
     ),
     (
         Fields ^ memory_fields = no_memory,
         Memory = 0
     ;
         Fields ^ memory_fields = memory(_),
-        Memory = 4
+        Memory = 2
     ;
         Fields ^ memory_fields = memory_and_percall(_),
-        Memory = 6
+        Memory = 3
     ),
     (
         TotalsDisp = totals_meaningful,
-        Width = Id + Port + Time + Alloc + Memory
+        Width = Id + Port + Time * 2 + CallSeqs * 2 + Alloc * 2 + Memory * 2
     ;
         TotalsDisp = totals_not_meaningful,
-        Width = Id + Port + Time // 2 + Alloc // 2 + Memory // 2
+        Width = Id + Port + Time + CallSeqs + Alloc + Memory
     ).
 
 %-----------------------------------------------------------------------------%
@@ -1380,6 +1643,12 @@
     OwnQuantaProp = percentage(OwnQuanta, RootQuanta),
     TotalQuantaProp = percentage(TotalQuanta, RootQuanta),
 
+    OwnCallSeqs = callseqs(Own),
+    TotalCallSeqs = inherit_callseqs(OwnPlusDesc),
+    RootCallSeqs = inherit_callseqs(Root),
+    OwnCallSeqsProp = percentage(OwnCallSeqs, RootCallSeqs),
+    TotalCallSeqsProp = percentage(TotalCallSeqs, RootCallSeqs),
+
     OwnAllocs = allocs(Own),
     TotalAllocs = inherit_allocs(OwnPlusDesc),
     RootAllocs = inherit_allocs(Root),
@@ -1392,25 +1661,11 @@
     OwnMemoryProp = percentage(OwnWords, RootWords),
     TotalMemoryProp = percentage(TotalWords, RootWords),
 
-    ( show_memory(Fields) = yes(Unit) ->
-        (
-            Unit = words,
-            OwnMemory = OwnWords,
-            TotalMemory = TotalWords
-        ;
-            Unit = bytes,
-            WordSize = Deep ^ profile_stats ^ word_size,
-            OwnMemory = OwnWords * WordSize,
-            TotalMemory = TotalWords * WordSize
-        )
-    ;
-        % These values won't be used.
-        OwnMemory = 0,
-        TotalMemory = 0
-    ),
-
     Fields = Pref ^ pref_fields,
-    ( show_port_counts(Fields) = yes ->
+
+    ShowPortCounts = show_port_counts(Fields),
+    (
+        ShowPortCounts = yes,
         PortHTML =
             string.format("<TD CLASS=port ALIGN=RIGHT>%s</TD>\n",
                 [s(commas(Calls))]) ++
@@ -1423,9 +1678,13 @@
             string.format("<TD CLASS=port ALIGN=RIGHT>%s</TD>\n",
                 [s(commas(Excps))])
     ;
+        ShowPortCounts = no,
         PortHTML = ""
     ),
-    ( show_quanta(Fields) = yes ->
+
+    ShowQuanta = show_quanta(Fields),
+    (
+        ShowQuanta = yes,
         QuantaSelfHTML =
             string.format("<TD CLASS=time ALIGN=RIGHT>%s</TD>\n",
                 [s(commas(OwnQuanta))]),
@@ -1433,10 +1692,13 @@
             string.format("<TD CLASS=time ALIGN=RIGHT>%s</TD>\n",
                 [s(commas(TotalQuanta))])
     ;
+        ShowQuanta = no,
         QuantaSelfHTML = "",
         QuantaTotalHTML = ""
     ),
-    ( show_times(Fields) = yes ->
+    ShowTimes = show_times(Fields),
+    (
+        ShowTimes = yes,
         TimeSelfHTML =
             string.format("<TD CLASS=time ALIGN=RIGHT>%s</TD>\n",
                 [s(overall_time(Pref, Deep, OwnQuanta))]),
@@ -1444,10 +1706,13 @@
             string.format("<TD CLASS=time ALIGN=RIGHT>%s</TD>\n",
                 [s(overall_time(Pref, Deep, TotalQuanta))])
     ;
+        ShowTimes = no,
         TimeSelfHTML = "",
         TimeTotalHTML = ""
     ),
-    ( ( show_quanta(Fields) = yes ; show_times(Fields) = yes ) ->
+    ShowTimeFraction = bool.or(ShowQuanta, ShowTimes),
+    (
+        ShowTimeFraction = yes,
         QuantaPropSelfHTML =
             string.format("<TD CLASS=time ALIGN=RIGHT>%s</TD>\n",
                 [s(OwnQuantaProp)]),
@@ -1455,23 +1720,72 @@
             string.format("<TD CLASS=time ALIGN=RIGHT>%s</TD>\n",
                 [s(TotalQuantaProp)])
     ;
+        ShowTimeFraction = no,
         QuantaPropSelfHTML = "",
         QuantaPropTotalHTML = ""
     ),
-    ( show_per_times(Fields) = yes ->
+    ShowTimesPerCall = show_times_per_call(Fields),
+    (
+        ShowTimesPerCall = yes,
         TimePerCallSelfHTML =
             string.format("<TD CLASS=time ALIGN=RIGHT>%s</TD>\n",
-                [s(per_call_time(Pref, Deep,
-                    OwnQuanta, Calls))]),
+                [s(per_call_time(Pref, Deep, OwnQuanta, Calls))]),
         TimePerCallTotalHTML =
             string.format("<TD CLASS=time ALIGN=RIGHT>%s</TD>\n",
-                [s(per_call_time(Pref, Deep,
-                    TotalQuanta, Calls))])
+                [s(per_call_time(Pref, Deep, TotalQuanta, Calls))])
     ;
+        ShowTimesPerCall = no,
         TimePerCallSelfHTML = "",
         TimePerCallTotalHTML = ""
     ),
-    ( show_alloc(Fields) = yes ->
+
+    ShowCallSeqs = show_callseqs(Fields),
+    (
+        ShowCallSeqs = yes,
+        CallSeqsSelfHTML =
+            string.format("<TD CLASS=callseqs ALIGN=RIGHT>%i</TD>\n",
+                [i(OwnCallSeqs)]),
+        CallSeqsTotalHTML =
+            string.format("<TD CLASS=callseqs ALIGN=RIGHT>%i</TD>\n",
+                [i(TotalCallSeqs)]),
+        CallSeqsPropSelfHTML =
+            string.format("<TD CLASS=callseqs ALIGN=RIGHT>%s</TD>\n",
+                [s(OwnCallSeqsProp)]),
+        CallSeqsPropTotalHTML =
+            string.format("<TD CLASS=callseqs ALIGN=RIGHT>%s</TD>\n",
+                [s(TotalCallSeqsProp)])
+    ;
+        ShowCallSeqs = no,
+        CallSeqsSelfHTML = "",
+        CallSeqsTotalHTML = "",
+        CallSeqsPropSelfHTML = "",
+        CallSeqsPropTotalHTML = ""
+    ),
+    ShowCallSeqsPerCall = show_callseqs_per_call(Fields),
+    (
+        ShowCallSeqsPerCall = yes,
+        ( Calls = 0 ->
+            OwnCallSeqsPerCall = 0.0,
+            TotalCallSeqsPerCall = 0.0
+        ;
+            OwnCallSeqsPerCall = float(OwnCallSeqs) / float(Calls),
+            TotalCallSeqsPerCall = float(TotalCallSeqs) / float(Calls)
+        ),
+        CallSeqsPerCallSelfHTML =
+            string.format("<TD CLASS=callseqs ALIGN=RIGHT>%.1f</TD>\n",
+                [f(OwnCallSeqsPerCall)]),
+        CallSeqsPerCallTotalHTML =
+            string.format("<TD CLASS=callseqs ALIGN=RIGHT>%.1f</TD>\n",
+                [f(TotalCallSeqsPerCall)])
+    ;
+        ShowCallSeqsPerCall = no,
+        CallSeqsPerCallSelfHTML = "",
+        CallSeqsPerCallTotalHTML = ""
+    ),
+
+    ShowAlloc = show_alloc(Fields),
+    (
+        ShowAlloc = yes,
         AllocSelfHTML =
             string.format("<TD CLASS=alloc ALIGN=RIGHT>%s</TD>\n",
                 [s(commas(OwnAllocs))]) ++
@@ -1483,10 +1797,13 @@
             string.format("<TD CLASS=alloc ALIGN=RIGHT>%s</TD>\n",
                 [s(TotalAllocProp)])
     ;
+        ShowAlloc = no,
         AllocSelfHTML = "",
         AllocTotalHTML = ""
     ),
-    ( show_per_alloc(Fields) = yes ->
+    ShowAllocPerCall = show_alloc_per_call(Fields),
+    (
+        ShowAllocPerCall = yes,
         AllocPerCallSelfHTML =
             string.format("<TD CLASS=alloc ALIGN=RIGHT>%s</TD>\n",
                 [s(count_per_call(OwnAllocs, Calls))]),
@@ -1494,10 +1811,32 @@
             string.format("<TD CLASS=alloc ALIGN=RIGHT>%s</TD>\n",
                 [s(count_per_call(TotalAllocs, Calls))])
     ;
+        ShowAllocPerCall = no,
         AllocPerCallSelfHTML = "",
         AllocPerCallTotalHTML = ""
     ),
-    ( show_memory(Fields) = yes(_) ->
+
+    ShowMemory = show_memory(Fields),
+    (
+        ShowMemory = yes(Unit),
+        (
+            Unit = units_words,
+            OwnMemory = OwnWords,
+            TotalMemory = TotalWords
+        ;
+            Unit = units_bytes,
+            WordSize = Deep ^ profile_stats ^ word_size,
+            OwnMemory = OwnWords * WordSize,
+            TotalMemory = TotalWords * WordSize
+        )
+    ;
+        ShowMemory = no,
+        % These values won't be used.
+        OwnMemory = 0,
+        TotalMemory = 0
+    ),
+    (
+        ShowMemory = yes(_),
         MemorySelfHTML =
             string.format("<TD CLASS=memory ALIGN=RIGHT>%s</TD>\n",
                 [s(commas(OwnMemory))]) ++
@@ -1509,10 +1848,13 @@
             string.format("<TD CLASS=memory ALIGN=RIGHT>%s</TD>\n",
                 [s(TotalMemoryProp)])
     ;
+        ShowMemory = no,
         MemorySelfHTML = "",
         MemoryTotalHTML = ""
     ),
-    ( show_per_memory(Fields) = yes(_) ->
+    ShowMemoryPerCall = show_memory_per_call(Fields),
+    (
+        ShowMemoryPerCall = yes(_),
         MemoryPerCallSelfHTML =
             string.format("<TD CLASS=memory ALIGN=RIGHT>%s</TD>\n",
                 [s(count_per_call(OwnMemory, Calls))]),
@@ -1520,9 +1862,11 @@
             string.format("<TD CLASS=memory ALIGN=RIGHT>%s</TD>\n",
                 [s(count_per_call(TotalMemory, Calls))])
     ;
+        ShowMemoryPerCall = no,
         MemoryPerCallSelfHTML = "",
         MemoryPerCallTotalHTML = ""
     ),
+
     (
         TotalsDisp = totals_meaningful,
         HTML =
@@ -1537,6 +1881,13 @@
             QuantaPropTotalHTML ++
             TimePerCallTotalHTML ++
 
+            CallSeqsSelfHTML ++
+            CallSeqsPropSelfHTML ++
+            CallSeqsPerCallSelfHTML ++
+            CallSeqsTotalHTML ++
+            CallSeqsPropTotalHTML ++
+            CallSeqsPerCallTotalHTML ++
+
             AllocSelfHTML ++
             AllocPerCallSelfHTML ++
             AllocTotalHTML ++
@@ -1556,6 +1907,10 @@
             QuantaPropSelfHTML ++
             TimePerCallSelfHTML ++
 
+            CallSeqsSelfHTML ++
+            CallSeqsPropSelfHTML ++
+            CallSeqsPerCallSelfHTML ++
+
             AllocSelfHTML ++
             AllocPerCallSelfHTML ++
 
@@ -1756,16 +2111,34 @@
     ; TimeFields = ticks_and_time_and_percall, ShowTimes = yes
     ).
 
-:- func show_per_times(fields) = bool.
+:- func show_times_per_call(fields) = bool.
 
-show_per_times(Fields) = ShowPerTimes :-
+show_times_per_call(Fields) = ShowTimesPerCall :-
     TimeFields = Fields ^ time_fields,
-    ( TimeFields = no_time, ShowPerTimes = no
-    ; TimeFields = ticks, ShowPerTimes = no
-    ; TimeFields = time, ShowPerTimes = no
-    ; TimeFields = ticks_and_time, ShowPerTimes = no
-    ; TimeFields = time_and_percall, ShowPerTimes = yes
-    ; TimeFields = ticks_and_time_and_percall, ShowPerTimes = yes
+    ( TimeFields = no_time, ShowTimesPerCall = no
+    ; TimeFields = ticks, ShowTimesPerCall = no
+    ; TimeFields = time, ShowTimesPerCall = no
+    ; TimeFields = ticks_and_time, ShowTimesPerCall = no
+    ; TimeFields = time_and_percall, ShowTimesPerCall = yes
+    ; TimeFields = ticks_and_time_and_percall, ShowTimesPerCall = yes
+    ).
+
+:- func show_callseqs(fields) = bool.
+
+show_callseqs(Fields) = ShowCallSeqs :-
+    CallSeqsField = Fields ^ callseqs_fields,
+    ( CallSeqsField = no_callseqs, ShowCallSeqs = no
+    ; CallSeqsField = callseqs, ShowCallSeqs = yes
+    ; CallSeqsField = callseqs_and_percall, ShowCallSeqs = yes
+    ).
+
+:- func show_callseqs_per_call(fields) = bool.
+
+show_callseqs_per_call(Fields) = ShowCallSeqsPerCall :-
+    CallSeqsField = Fields ^ callseqs_fields,
+    ( CallSeqsField = no_callseqs, ShowCallSeqsPerCall = no
+    ; CallSeqsField = callseqs, ShowCallSeqsPerCall = no
+    ; CallSeqsField = callseqs_and_percall, ShowCallSeqsPerCall = yes
     ).
 
 :- func show_alloc(fields) = bool.
@@ -1777,9 +2150,9 @@
     ; AllocFields = alloc_and_percall, ShowAlloc = yes
     ).
 
-:- func show_per_alloc(fields) = bool.
+:- func show_alloc_per_call(fields) = bool.
 
-show_per_alloc(Fields) = ShowPerAlloc :-
+show_alloc_per_call(Fields) = ShowPerAlloc :-
     AllocFields = Fields ^ alloc_fields,
     ( AllocFields = no_alloc, ShowPerAlloc = no
     ; AllocFields = alloc, ShowPerAlloc = no
@@ -1795,9 +2168,9 @@
     ; MemoryFields = memory_and_percall(Unit), ShowMemory = yes(Unit)
     ).
 
-:- func show_per_memory(fields) = maybe(memory_units).
+:- func show_memory_per_call(fields) = maybe(memory_units).
 
-show_per_memory(Fields) = ShowPerMemory :-
+show_memory_per_call(Fields) = ShowPerMemory :-
     MemoryFields = Fields ^ memory_fields,
     ( MemoryFields = no_memory, ShowPerMemory = no
     ; MemoryFields = memory(_Unit), ShowPerMemory = no
@@ -1855,20 +2228,20 @@
 
 proc_static_to_html_ref(Pref, Deep, PSPtr) = HTML :-
     PSPtr = proc_static_ptr(PSI),
-    URL = deep_cmd_pref_to_url(Pref, Deep, proc(PSI)),
+    URL = deep_cmd_pref_to_url(Pref, Deep, deep_cmd_proc(PSI)),
     deep_lookup_proc_statics(Deep, PSPtr, PS),
     ProcName = PS ^ ps_refined_id,
     HTML = string.format("<A HREF=""%s"">%s</A>",
         [s(URL), s(escape_html_string(ProcName))]).
 
 module_name_to_html_ref(Pref, Deep, ModuleName) = HTML :-
-    URL = deep_cmd_pref_to_url(Pref, Deep, module(ModuleName)),
+    URL = deep_cmd_pref_to_url(Pref, Deep, deep_cmd_module(ModuleName)),
     HTML = string.format("<A HREF=""%s"">%s</A>",
         [s(URL), s(escape_html_string(ModuleName))]).
 
 clique_ptr_to_html_ref(Pref, Deep, ProcName, CliquePtr) = HTML :-
     CliquePtr = clique_ptr(CliqueNum),
-    URL = deep_cmd_pref_to_url(Pref, Deep, clique(CliqueNum)),
+    URL = deep_cmd_pref_to_url(Pref, Deep, deep_cmd_clique(CliqueNum)),
     HTML = string.format("<A HREF=""%s"">%s</A>",
         [s(URL), s(escape_html_string(ProcName))]).
 
Index: interface.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/interface.m,v
retrieving revision 1.14
diff -u -b -r1.14 interface.m
--- interface.m	5 Oct 2006 04:49:29 -0000	1.14
+++ interface.m	11 Oct 2006 03:49:04 -0000
@@ -1,4 +1,4 @@
-%-----------------------------------------------------------------------------%
+%----------------------------------------------------------------------------%
 % vim: ft=mercury ts=4 sw=4 et
 %-----------------------------------------------------------------------------%
 % Copyright (C) 2001-2002, 2004-2006 The University of Melbourne.
@@ -49,6 +49,8 @@
 
 :- interface.
 
+:- import_module profile.
+
 :- import_module bool.
 :- import_module char.
 :- import_module io.
@@ -56,9 +58,9 @@
 
 %-----------------------------------------------------------------------------%
 
-    % These functions derive the names of auxiliary files (or parts
-    % thereof) from the name of the profiling data file being explored.
-    % The auxiliary files are:
+    % These functions derive the names of auxiliary files (or parts thereof)
+    % from the name of the profiling data file being explored. The auxiliary
+    % files are:
     %
     % - the name of the named pipe for transmitting queries to the server;
     % - the name of the named pipe for transmitting responses back to the
@@ -84,27 +86,29 @@
 :- func contour_file_name(string) = string.
 
     % send_term(ToFileName, Debug, Term):
+    %
     %   Write the term Term to ToFileName, making it is new contents.
-    %   If Debug is `yes', write it to the file `/tmp/.send_term'
-    %   as well.
+    % If Debug is `yes', write it to the file `/tmp/.send_term' as well.
     %
 :- pred send_term(string::in, bool::in, T::in, io::di, io::uo) is det.
 
     % send_string(ToFileName, Debug, Str):
+    %
     %   Write the string Str to ToFileName, making it is new contents.
-    %   If Debug is `yes', write it to the file `/tmp/.send_string'
-    %   as well.
+    % If Debug is `yes', write it to the file `/tmp/.send_string' as well.
     %
 :- pred send_string(string::in, bool::in, string::in, io::di, io::uo) is det.
 
     % recv_term(FromFileName, Debug, Term):
-    %   Read the contents of FromFileName, which should be a single
-    %   Mercury term. If Debug is `yes', write the result of the read
-    %   to the file `/tmp/.recv_term' as well.
+    %
+    % Read the contents of FromFileName, which should be a single Mercury term.
+    % If Debug is `yes', write the result of the read to the file
+    % `/tmp/.recv_term' as well.
     %
 :- pred recv_term(string::in, bool::in, T::out, io::di, io::uo) is det.
 
     % recv_string(FromFileName, Debug, Str):
+    %
     %   Read the contents of FromFileName, and return it as Str.
     %   If Debug is `yes', write the result of the read to the file
     %   `/tmp/.recv_string' as well.
@@ -117,29 +121,29 @@
     --->    html(string).
 
 :- type cmd_pref
-    --->    cmd_pref(cmd, preferences).
+    --->    cmd_pref(cmd, preferences_indication).
 
 :- type cmd
-    --->    quit
-    ;       restart
-    ;       timeout(int)
-    ;       menu
-    ;       root(maybe(int))
-    ;       clique(int)
-    ;       proc(int)
-    ;       proc_callers(int, caller_groups, int)
-    ;       modules
-    ;       module(string)
-    ;       top_procs(display_limit, cost_kind, include_descendants,
+    --->    deep_cmd_quit
+    ;       deep_cmd_restart
+    ;       deep_cmd_timeout(int)
+    ;       deep_cmd_menu
+    ;       deep_cmd_root(maybe(int))
+    ;       deep_cmd_clique(int)
+    ;       deep_cmd_proc(int)
+    ;       deep_cmd_proc_callers(int, caller_groups, int)
+    ;       deep_cmd_modules
+    ;       deep_cmd_module(string)
+    ;       deep_cmd_top_procs(display_limit, cost_kind, include_descendants,
                 measurement_scope)
     %
     % The following commands are for debugging.
     %
-    ;       proc_static(int)
-    ;       proc_dynamic(int)
-    ;       call_site_static(int)
-    ;       call_site_dynamic(int)
-    ;       raw_clique(int).
+    ;       deep_cmd_proc_static(int)
+    ;       deep_cmd_proc_dynamic(int)
+    ;       deep_cmd_call_site_static(int)
+    ;       deep_cmd_call_site_dynamic(int)
+    ;       deep_cmd_raw_clique(int).
 
 :- type caller_groups
     --->    group_by_call_site
@@ -148,11 +152,12 @@
     ;       group_by_clique.
 
 :- type cost_kind
-    --->    calls
-    ;       redos
-    ;       time
-    ;       allocs
-    ;       words.
+    --->    cost_calls
+    ;       cost_redos
+    ;       cost_time
+    ;       cost_callseqs
+    ;       cost_allocs
+    ;       cost_words.
 
 :- type include_descendants
     --->    self
@@ -160,40 +165,46 @@
 
 :- type display_limit
     --->    rank_range(int, int)
-                    % rank_range(M, N): display procedures
-                    % with rank M to N, both inclusive.
+            % rank_range(M, N): display procedures with rank M to N,
+            % both inclusive.
 
     ;       threshold(float).
-                    % threshold(Percent): display
-                    % procedures whose cost is at least
-                    % Fraction of the whole program's
-                    % cost.
+            % threshold(Percent): display procedures whose cost is at least
+            % Percent% of the whole program's cost.
+
+:- type preferences_indication
+    --->    given_pref(preferences)
+    ;       default_pref
+    ;       all_pref.
 
 :- type preferences
     ---> preferences(
+                % The set of fields to display.
             pref_fields :: fields,
-                    % set of fields to display
+
+                % Whether displays should be boxed.
             pref_box    :: box,
-                    % whether displays should be boxed
+
+                % What principle governs colours.
             pref_colour :: colour_scheme,
-                    % what principle governs colours
+
+                % The max number of ancestors to display.
             pref_anc    :: maybe(int),
-                    % max number of ancestors to display
+
+                % Whether pages should summarize at higher order call sites.
             pref_summarize  :: summarize,
-                    % whether pages should summarize
-                    % at higher order call sites
+
+                % The criteria for ordering lines in pages, if the command
+                % doesn't specify otherwise.
             pref_criteria   :: order_criteria,
-                    % the criteria for ordering lines in
-                    % pages, if the command doesn't specify
-                    % otherwise
+
+                % Whether contour exclusion should be applied.
             pref_contour :: contour,
-                    % whether contour exclusion should be
-                    % applied
+
             pref_time :: time_format,
 
+                % Whether we should show modules/procs that haven't been called.
             pref_inactive :: inactive_items
-                    % Whether we should show modules/procs
-                    % that haven't been called.
         ).
 
 :- type port_fields
@@ -208,6 +219,12 @@
     ;       time_and_percall
     ;       ticks_and_time_and_percall.
 
+
+:- type callseqs_fields
+    --->    no_callseqs
+    ;       callseqs
+    ;       callseqs_and_percall.
+
 :- type alloc_fields
     --->    no_alloc
     ;       alloc
@@ -219,13 +236,14 @@
     ;       memory_and_percall(memory_units).
 
 :- type memory_units
-    --->    words
-    ;       bytes.
+    --->    units_words
+    ;       units_bytes.
 
 :- type fields
     --->    fields(
                 port_fields   :: port_fields,
                 time_fields   :: time_fields,
+                callseqs_fields :: callseqs_fields,
                 alloc_fields  :: alloc_fields,
                 memory_fields :: memory_fields
             ).
@@ -235,8 +253,8 @@
     ;       nobox.
 
 :- type colour_scheme
-    --->    column_groups
-    ;       none.
+    --->    colour_column_groups
+    ;       colour_none.
 
 :- type summarize
     --->    summarize
@@ -264,7 +282,9 @@
     ;       scale_by_millions
     ;       scale_by_thousands.
 
-:- type inactive_status ---> hide ; show.
+:- type inactive_status
+    --->    inactive_hide
+    ;       inactive_show.
 
 :- type inactive_items
     --->    inactive_items(
@@ -274,9 +294,15 @@
 
 %-----------------------------------------------------------------------------%
 
-:- func default_preferences = preferences.
+    % Return "yes" if it is worth displaying times for this profile.
+    %
+:- func should_display_times(deep) = bool.
+
+:- func solidify_preference(deep, preferences_indication) = preferences.
 
-:- func default_fields = fields.
+:- func default_preferences(deep) = preferences.
+
+:- func default_fields(deep) = fields.
 :- func all_fields = fields.
 :- func default_box = box.
 :- func default_colour_scheme = colour_scheme.
@@ -305,6 +331,7 @@
 :- import_module conf.
 :- import_module util.
 
+:- import_module int.
 :- import_module list.
 :- import_module require.
 :- import_module set.
@@ -312,9 +339,34 @@
 
 %-----------------------------------------------------------------------------%
 
-default_preferences =
+    % Display times only if the profile was derived from a run that ran for
+    % at least this many quanta.
+    %
+:- func minimum_meaningful_quanta = int.
+
+minimum_meaningful_quanta = 10.
+
+should_display_times(Deep) =
+    ( Deep ^ profile_stats ^ user_quanta > minimum_meaningful_quanta ->
+        yes
+    ;
+        no
+    ).
+
+solidify_preference(Deep, PrefInd) = Pref :-
+    (
+        PrefInd = given_pref(Pref)
+    ;
+        PrefInd = default_pref,
+        Pref = default_preferences(Deep)
+    ;
+        PrefInd = all_pref,
+        Pref = default_preferences(Deep) ^ pref_fields := all_fields
+    ).
+
+default_preferences(Deep) =
     preferences(
-        default_fields,
+        default_fields(Deep),
         default_box,
         default_colour_scheme,
         default_ancestor_limit,
@@ -325,19 +377,29 @@
         default_inactive_items
     ).
 
-default_fields = fields(port, ticks, no_alloc, memory(words)).
-all_fields = fields(port, ticks_and_time_and_percall, alloc, memory(words)).
+default_fields(Deep) = Fields :-
+    ShouldDisplayTimes = should_display_times(Deep),
+    (
+        ShouldDisplayTimes = yes,
+        Time = ticks
+    ;
+        ShouldDisplayTimes = no,
+        Time = no_time
+    ),
+    Fields = fields(port, Time, callseqs, no_alloc, memory(units_words)).
+all_fields = fields(port, ticks_and_time_and_percall, callseqs_and_percall,
+    alloc, memory(units_words)).
 default_box = box.
-default_colour_scheme = column_groups.
+default_colour_scheme = colour_column_groups.
 default_ancestor_limit = yes(5).
 default_summarize = dont_summarize.
 default_order_criteria = by_context.
-default_cost_kind = time.
+default_cost_kind = cost_callseqs.
 default_incl_desc = self_and_desc.
 default_scope = overall.
 default_contour = no_contour.
 default_time_format = scale_by_thousands.
-default_inactive_items = inactive_items(hide, hide).
+default_inactive_items = inactive_items(inactive_hide, inactive_hide).
 
 %-----------------------------------------------------------------------------%
 
@@ -527,20 +589,20 @@
 
 cmd_to_string(Cmd) = CmdStr :-
     (
-        Cmd = quit,
+        Cmd = deep_cmd_quit,
         CmdStr = "quit"
     ;
-        Cmd = restart,
+        Cmd = deep_cmd_restart,
         CmdStr = "restart"
     ;
-        Cmd = timeout(Minutes),
+        Cmd = deep_cmd_timeout(Minutes),
         CmdStr = string.format("timeout%c%d",
             [c(cmd_separator_char), i(Minutes)])
     ;
-        Cmd = menu,
+        Cmd = deep_cmd_menu,
         CmdStr = "menu"
     ;
-        Cmd = root(MaybePercent),
+        Cmd = deep_cmd_root(MaybePercent),
         (
             MaybePercent = yes(Percent),
             CmdStr = string.format("root%c%d",
@@ -551,29 +613,29 @@
                 [c(cmd_separator_char), s("no")])
         )
     ;
-        Cmd = clique(CliqueNum),
+        Cmd = deep_cmd_clique(CliqueNum),
         CmdStr = string.format("clique%c%d",
             [c(cmd_separator_char), i(CliqueNum)])
     ;
-        Cmd = proc(ProcNum),
+        Cmd = deep_cmd_proc(ProcNum),
         CmdStr = string.format("proc%c%d",
             [c(cmd_separator_char), i(ProcNum)])
     ;
-        Cmd = proc_callers(ProcNum, GroupCallers, BunchNum),
+        Cmd = deep_cmd_proc_callers(ProcNum, GroupCallers, BunchNum),
         GroupCallersStr = caller_groups_to_string(GroupCallers),
         CmdStr = string.format("proc_callers%c%d%c%s%c%d",
             [c(cmd_separator_char), i(ProcNum),
             c(cmd_separator_char), s(GroupCallersStr),
             c(cmd_separator_char), i(BunchNum)])
     ;
-        Cmd = modules,
+        Cmd = deep_cmd_modules,
         CmdStr = "modules"
     ;
-        Cmd = module(ModuleName),
+        Cmd = deep_cmd_module(ModuleName),
         CmdStr = string.format("module%c%s",
             [c(cmd_separator_char), s(ModuleName)])
     ;
-        Cmd = top_procs(Limit, CostKind, InclDesc, Scope),
+        Cmd = deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope),
         LimitStr = limit_to_string(Limit),
         CostKindStr = cost_kind_to_string(CostKind),
         InclDescStr = incl_desc_to_string(InclDesc),
@@ -584,23 +646,23 @@
             c(cmd_separator_char), s(InclDescStr),
             c(cmd_separator_char), s(ScopeStr)])
     ;
-        Cmd = proc_static(PSI),
+        Cmd = deep_cmd_proc_static(PSI),
         CmdStr = string.format("proc_static%c%d",
             [c(cmd_separator_char), i(PSI)])
     ;
-        Cmd = proc_dynamic(PDI),
+        Cmd = deep_cmd_proc_dynamic(PDI),
         CmdStr = string.format("proc_dynamic%c%d",
             [c(cmd_separator_char), i(PDI)])
     ;
-        Cmd = call_site_static(CSSI),
+        Cmd = deep_cmd_call_site_static(CSSI),
         CmdStr = string.format("call_site_static%c%d",
             [c(cmd_separator_char), i(CSSI)])
     ;
-        Cmd = call_site_dynamic(CSDI),
+        Cmd = deep_cmd_call_site_dynamic(CSDI),
         CmdStr = string.format("call_site_dynamic%c%d",
             [c(cmd_separator_char), i(CSDI)])
     ;
-        Cmd = raw_clique(CI),
+        Cmd = deep_cmd_raw_clique(CI),
         CmdStr = string.format("raw_clique%c%d",
             [c(cmd_separator_char), i(CI)])
     ).
@@ -652,83 +714,82 @@
             fail
         )
     ->
-        MaybeCmd = yes(root(MaybePercent))
+        MaybeCmd = yes(deep_cmd_root(MaybePercent))
     ;
         Pieces = ["clique", CliqueNumStr],
         string.to_int(CliqueNumStr, CliqueNum)
     ->
-        MaybeCmd = yes(clique(CliqueNum))
+        MaybeCmd = yes(deep_cmd_clique(CliqueNum))
     ;
         Pieces = ["proc", PSIStr],
         string.to_int(PSIStr, PSI)
     ->
-        MaybeCmd = yes(proc(PSI))
+        MaybeCmd = yes(deep_cmd_proc(PSI))
     ;
         Pieces = ["proc_callers", PSIStr, GroupCallersStr, BunchNumStr],
         string.to_int(PSIStr, PSI),
         string.to_int(BunchNumStr, BunchNum),
         string_to_caller_groups(GroupCallersStr, GroupCallers)
     ->
-        MaybeCmd = yes(proc_callers(PSI, GroupCallers, BunchNum))
+        MaybeCmd = yes(deep_cmd_proc_callers(PSI, GroupCallers, BunchNum))
     ;
         Pieces = ["modules"]
     ->
-        MaybeCmd = yes(modules)
+        MaybeCmd = yes(deep_cmd_modules)
     ;
         Pieces = ["module", ModuleName]
     ->
-        MaybeCmd = yes(module(ModuleName))
+        MaybeCmd = yes(deep_cmd_module(ModuleName))
     ;
-        Pieces = ["top_procs", LimitStr,
-            CostKindStr, InclDescStr, ScopeStr],
+        Pieces = ["top_procs", LimitStr, CostKindStr, InclDescStr, ScopeStr],
         string_to_limit(LimitStr, Limit),
         string_to_cost_kind(CostKindStr, CostKind),
         string_to_incl_desc(InclDescStr, InclDesc),
         string_to_scope(ScopeStr, Scope)
     ->
-        MaybeCmd = yes(top_procs(Limit, CostKind, InclDesc, Scope))
+        MaybeCmd = yes(deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope))
     ;
         Pieces = ["menu"]
     ->
-        MaybeCmd = yes(menu)
+        MaybeCmd = yes(deep_cmd_menu)
     ;
         Pieces = ["proc_static", PSIStr],
         string.to_int(PSIStr, PSI)
     ->
-        MaybeCmd = yes(proc_static(PSI))
+        MaybeCmd = yes(deep_cmd_proc_static(PSI))
     ;
         Pieces = ["proc_dynamic", PDIStr],
         string.to_int(PDIStr, PDI)
     ->
-        MaybeCmd = yes(proc_dynamic(PDI))
+        MaybeCmd = yes(deep_cmd_proc_dynamic(PDI))
     ;
         Pieces = ["call_site_static", CSSIStr],
         string.to_int(CSSIStr, CSSI)
     ->
-        MaybeCmd = yes(call_site_static(CSSI))
+        MaybeCmd = yes(deep_cmd_call_site_static(CSSI))
     ;
         Pieces = ["call_site_dynamic", CSDIStr],
         string.to_int(CSDIStr, CSDI)
     ->
-        MaybeCmd = yes(call_site_dynamic(CSDI))
+        MaybeCmd = yes(deep_cmd_call_site_dynamic(CSDI))
     ;
         Pieces = ["raw_clique", CliqueNumStr],
         string.to_int(CliqueNumStr, CliqueNum)
     ->
-        MaybeCmd = yes(raw_clique(CliqueNum))
+        MaybeCmd = yes(deep_cmd_raw_clique(CliqueNum))
     ;
         Pieces = ["timeout", TimeOutStr],
         string.to_int(TimeOutStr, TimeOut)
     ->
-        MaybeCmd = yes(timeout(TimeOut))
+        MaybeCmd = yes(deep_cmd_timeout(TimeOut))
     ;
         Pieces = ["restart"]
     ->
-        MaybeCmd = yes(restart)
+        MaybeCmd = yes(deep_cmd_restart)
     ;
         Pieces = ["quit"]
     ->
-        MaybeCmd = yes(quit)
+        MaybeCmd = yes(deep_cmd_quit)
     ;
         MaybeCmd = no
     ).
@@ -755,9 +816,8 @@
         string_to_time_format(TimeStr, Time),
         string_to_inactive_items(InactiveItemsStr, InactiveItems)
     ->
-        Preferences = preferences(Fields, Box, Colour,
-            MaybeAncestorLimit, Summarize, Order, Contour, Time,
-            InactiveItems),
+        Preferences = preferences(Fields, Box, Colour, MaybeAncestorLimit,
+            Summarize, Order, Contour, Time, InactiveItems),
         MaybePreferences = yes(Preferences)
     ;
         MaybePreferences = no
@@ -793,6 +853,19 @@
 string_to_time_fields("tp",  time_and_percall).
 string_to_time_fields("qtp", ticks_and_time_and_percall).
 
+:- func callseqs_fields_to_string(callseqs_fields) = string.
+
+callseqs_fields_to_string(AllocFields) = String :-
+    string_to_callseqs_fields(String, AllocFields).
+
+:- pred string_to_callseqs_fields(string, callseqs_fields).
+:- mode string_to_callseqs_fields(in, out) is semidet.
+:- mode string_to_callseqs_fields(out, in) is det.
+
+string_to_callseqs_fields("_", no_callseqs).
+string_to_callseqs_fields("s", callseqs).
+string_to_callseqs_fields("S", callseqs_and_percall).
+
 :- func alloc_fields_to_string(alloc_fields) = string.
 
 alloc_fields_to_string(AllocFields) = String :-
@@ -804,7 +877,7 @@
 
 string_to_alloc_fields("_",  no_alloc).
 string_to_alloc_fields("a",  alloc).
-string_to_alloc_fields("ap", alloc_and_percall).
+string_to_alloc_fields("A", alloc_and_percall).
 
 :- func memory_fields_to_string(memory_fields) = string.
 
@@ -816,18 +889,20 @@
 :- mode string_to_memory_fields(out, in) is det.
 
 string_to_memory_fields("_",  no_memory).
-string_to_memory_fields("b",  memory(bytes)).
-string_to_memory_fields("w",  memory(words)).
-string_to_memory_fields("bp", memory_and_percall(bytes)).
-string_to_memory_fields("wp", memory_and_percall(words)).
+string_to_memory_fields("b", memory(units_bytes)).
+string_to_memory_fields("w", memory(units_words)).
+string_to_memory_fields("B", memory_and_percall(units_bytes)).
+string_to_memory_fields("W", memory_and_percall(units_words)).
 
 :- func fields_to_string(fields) = string.
 
-fields_to_string(fields(Port, Time, Allocs, Memory)) =
+fields_to_string(fields(Port, Time, CallSeqs, Allocs, Memory)) =
     port_fields_to_string(Port) ++
     string.char_to_string(field_separator_char) ++
     time_fields_to_string(Time) ++
     string.char_to_string(field_separator_char) ++
+    callseqs_fields_to_string(CallSeqs) ++
+    string.char_to_string(field_separator_char) ++
     alloc_fields_to_string(Allocs) ++
     string.char_to_string(field_separator_char) ++
     memory_fields_to_string(Memory).
@@ -837,13 +912,14 @@
 string_to_fields(FieldsStr, Fields) :-
     (
         split(FieldsStr, field_separator_char, Pieces),
-        Pieces = [PortStr, TimeStr, AllocStr, MemoryStr],
+        Pieces = [PortStr, TimeStr, CallSeqsStr, AllocStr, MemoryStr],
         string_to_port_fields(PortStr, Port),
         string_to_time_fields(TimeStr, Time),
+        string_to_callseqs_fields(CallSeqsStr, CallSeqs),
         string_to_alloc_fields(AllocStr, Alloc),
         string_to_memory_fields(MemoryStr, Memory)
     ->
-        Fields = fields(Port, Time, Alloc, Memory)
+        Fields = fields(Port, Time, CallSeqs, Alloc, Memory)
     ;
         fail
     ).
@@ -871,11 +947,12 @@
 :- mode string_to_cost_kind(in, out) is semidet.
 :- mode string_to_cost_kind(out, in) is det.
 
-string_to_cost_kind("calls",  calls).
-string_to_cost_kind("redos",  redos).
-string_to_cost_kind("time",   time).
-string_to_cost_kind("allocs", allocs).
-string_to_cost_kind("words",  words).
+string_to_cost_kind("calls",    cost_calls).
+string_to_cost_kind("redos",    cost_redos).
+string_to_cost_kind("time",     cost_time).
+string_to_cost_kind("callseqs", cost_callseqs).
+string_to_cost_kind("allocs",   cost_allocs).
+string_to_cost_kind("words",    cost_words).
 
 :- func incl_desc_to_string(include_descendants) = string.
 
@@ -894,7 +971,7 @@
 limit_to_string(rank_range(Lo, Hi)) =
     string.format("%d%c%d", [i(Lo), c(limit_separator_char), i(Hi)]).
 limit_to_string(threshold(Threshold)) =
-    string.format("%f", [f(Threshold)]).
+    string.format("%g", [f(Threshold)]).
 
 :- pred string_to_limit(string::in, display_limit::out) is semidet.
 
@@ -1007,10 +1084,10 @@
 :- mode string_to_inactive_items(in, out) is semidet.
 :- mode string_to_inactive_items(out, in) is det.
 
-string_to_inactive_items("hh", inactive_items(hide,  hide)).
-string_to_inactive_items("sh", inactive_items(show,  hide)).
-string_to_inactive_items("hs", inactive_items(hide,  show)).
-string_to_inactive_items("ss", inactive_items(show,  show)).
+string_to_inactive_items("hh", inactive_items(inactive_hide, inactive_hide)).
+string_to_inactive_items("sh", inactive_items(inactive_show, inactive_hide)).
+string_to_inactive_items("hs", inactive_items(inactive_hide, inactive_show)).
+string_to_inactive_items("ss", inactive_items(inactive_show, inactive_show)).
 
 :- func colour_scheme_to_string(colour_scheme) = string.
 
@@ -1021,8 +1098,8 @@
 :- mode string_to_colour_scheme(in, out) is semidet.
 :- mode string_to_colour_scheme(out, in) is det.
 
-string_to_colour_scheme("cols", column_groups).
-string_to_colour_scheme("none", none).
+string_to_colour_scheme("cols", colour_column_groups).
+string_to_colour_scheme("none", colour_none).
 
 :- func box_to_string(box) = string.
 
Index: mdprof_cgi.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_cgi.m,v
retrieving revision 1.15
diff -u -b -r1.15 mdprof_cgi.m
--- mdprof_cgi.m	8 Jun 2006 02:53:20 -0000	1.15
+++ mdprof_cgi.m	11 Oct 2006 03:53:40 -0000
@@ -74,13 +74,13 @@
         ),
         split(QueryString0, query_separator_char, Pieces),
         ( Pieces = [CmdStr, PrefStr, FileName] ->
-            Cmd = url_component_to_cmd(CmdStr, menu),
+            Cmd = url_component_to_cmd(CmdStr, deep_cmd_menu),
             process_query(Cmd, yes(PrefStr), FileName, Options, !IO)
         ; Pieces = [CmdStr, FileName] ->
-            Cmd = url_component_to_cmd(CmdStr, menu),
+            Cmd = url_component_to_cmd(CmdStr, deep_cmd_menu),
             process_query(Cmd, no, FileName, Options, !IO)
         ; Pieces = [FileName] ->
-            process_query(menu, no, FileName, Options, !IO)
+            process_query(deep_cmd_menu, no, FileName, Options, !IO)
         ;
             io.set_exit_status(1, !IO),
             % Give the simplest URL in the error message.
@@ -197,7 +197,7 @@
 :- pred process_query(cmd::in, maybe(string)::in, string::in,
     option_table::in, io::di, io::uo) is cc_multi.
 
-process_query(Cmd, MaybePrefStr, DataFileName, Options, !IO) :-
+process_query(Cmd, MaybePrefStr, DataFileName0, Options0, !IO) :-
     (
         MaybePrefStr = yes(PrefStr),
         MaybePref = url_component_to_maybe_pref(PrefStr)
@@ -206,10 +206,18 @@
         MaybePref = no
     ),
     (
-        MaybePref = yes(Pref)
+        MaybePref = yes(Pref),
+        PrefInd = given_pref(Pref)
     ;
         MaybePref = no,
-        Pref = default_preferences
+        PrefInd = default_pref
+    ),
+    ( string.remove_suffix(DataFileName0, ".localhost", DataFileNamePrime) ->
+        DataFileName = DataFileNamePrime,
+        map.det_update(Options0, localhost, bool(yes), Options)
+    ;
+        DataFileName = DataFileName0,
+        Options = Options0
     ),
     ToServerPipe = to_server_pipe_name(DataFileName),
     FromServerPipe = from_server_pipe_name(DataFileName),
@@ -229,13 +237,12 @@
     ),
     check_for_existing_fifos(ToServerPipe, FromServerPipe, FifoCount, !IO),
     ( FifoCount = 0 ->
-        handle_query_from_new_server(Cmd, Pref, DataFileName,
-            ToServerPipe, FromServerPipe, StartupFile,
-            MutexFile, WantFile, Options, !IO)
+        handle_query_from_new_server(Cmd, PrefInd, DataFileName,
+            ToServerPipe, FromServerPipe, StartupFile, MutexFile, WantFile,
+            Options, !IO)
     ; FifoCount = 2 ->
-        handle_query_from_existing_server(Cmd, Pref,
-            ToServerPipe, FromServerPipe,
-            MutexFile, WantFile, Options, !IO)
+        handle_query_from_existing_server(Cmd, PrefInd,
+            ToServerPipe, FromServerPipe, MutexFile, WantFile, Options, !IO)
     ;
         release_lock(Debug, MutexFile, !IO),
         remove_want_file(WantFile, !IO),
@@ -246,19 +253,43 @@
     % Handle the given query using the existing server. Delete the mutex and
     % want files when we get out of the critical region.
     %
-:- pred handle_query_from_existing_server(cmd::in, preferences::in,
+:- pred handle_query_from_existing_server(cmd::in, preferences_indication::in,
     string::in, string::in, string::in, string::in, option_table::in,
     io::di, io::uo) is det.
 
-handle_query_from_existing_server(Cmd, Pref, ToServerPipe, FromServerPipe,
+handle_query_from_existing_server(Cmd, PrefInd, ToServerPipe, FromServerPipe,
         MutexFile, WantFile, Options, !IO) :-
     lookup_bool_option(Options, debug, Debug),
-    send_term(ToServerPipe, Debug, cmd_pref(Cmd, Pref), !IO),
+    trace [compiletime(flag("debug_client_server")), io(!S)] (
+        io.open_append("/tmp/deep_debug", Res1, !S),
+        ( Res1 = ok(DebugStream1) ->
+            io.write_string(DebugStream1,
+                "sending query to existing server.\n", !S),
+            io.write(DebugStream1, cmd_pref(Cmd, PrefInd), !S),
+            io.close_output(DebugStream1, !S)
+        ;
+            true
+        )
+    ),
+    send_term(ToServerPipe, Debug, cmd_pref(Cmd, PrefInd), !IO),
     release_lock(Debug, MutexFile, !IO),
     remove_want_file(WantFile, !IO),
     recv_string(FromServerPipe, Debug, ResponseFileName, !IO),
     CatCmd = string.format("cat %s", [s(ResponseFileName)]),
     io.call_system(CatCmd, _, !IO),
+    trace [compiletime(flag("debug_client_server")), io(!T)] (
+        io.open_append("/tmp/deep_debug", Res2, !T),
+        ( Res2 = ok(DebugStream2) ->
+            io.write_string(DebugStream2,
+                "sending reply from existing server.\n", !T),
+            io.close_output(DebugStream2, !T),
+            DebugCatCmd = string.format("cat %s >> /tmp/deep_debug",
+                [s(ResponseFileName)]),
+            io.call_system(DebugCatCmd, _, !T)
+        ;
+            true
+        )
+    ),
     (
         Debug = yes
         % Leave the response file to be examined.
@@ -270,13 +301,21 @@
     % Handle the given query and then become the new server. Delete the mutex
     % and want files when we get out of the critical region.
     %
-:- pred handle_query_from_new_server(cmd::in, preferences::in, string::in,
-    string::in, string::in, string::in, string::in, string::in,
+:- pred handle_query_from_new_server(cmd::in, preferences_indication::in,
+    string::in, string::in, string::in, string::in, string::in, string::in,
     option_table::in, io::di, io::uo) is cc_multi.
 
-handle_query_from_new_server(Cmd, Pref, FileName, ToServerPipe, FromServerPipe,
-        StartupFile, MutexFile, WantFile, Options, !IO) :-
-    server_name(Machine, !IO),
+handle_query_from_new_server(Cmd, PrefInd, FileName,
+        ToServerPipe, FromServerPipe, StartupFile, MutexFile, WantFile,
+        Options, !IO) :-
+    lookup_bool_option(Options, localhost, LocalHost),
+    (
+        LocalHost = no,
+        server_name(Machine, !IO)
+    ;
+        LocalHost = yes,
+        Machine = "localhost"
+    ),
     lookup_bool_option(Options, canonical_clique, Canonical),
     lookup_bool_option(Options, server_process, ServerProcess),
     lookup_bool_option(Options, debug, Debug),
@@ -297,16 +336,16 @@
         MaybeStartupStream = no
     ),
     read_and_startup(Machine, [FileName], Canonical, MaybeStartupStream,
-        [], Res, !IO),
+        [], [], Res, !IO),
     (
         Res = ok(Deep),
+        Pref = solidify_preference(Deep, PrefInd),
         try_exec(Cmd, Pref, Deep, HTML, !IO),
         (
             MaybeStartupStream = yes(StartupStream1),
             io.format(StartupStream1, "query 0 output:\n%s\n", [s(HTML)], !IO),
-            % If we don't flush the output before the fork, it will
-            % be flushed twice, once by the parent process and
-            % once by the child process.
+            % If we don't flush the output before the fork, it will be flushed
+            % twice, once by the parent process and once by the child process.
             io.flush_output(StartupStream1, !IO)
         ;
             MaybeStartupStream = no
@@ -363,7 +402,8 @@
         DetachProcess = yes,
         detach_process(DetachRes, !IO)
     ),
-    ( DetachRes = in_child(ChildHasParent) ->
+    (
+        DetachRes = in_child(ChildHasParent),
         % We are in the child; start serving queries.
         (
             ChildHasParent = child_has_parent,
@@ -407,7 +447,8 @@
         lookup_bool_option(Options, canonical_clique, Canonical),
         server_loop(ToServerPipe, FromServerPipe, TimeOut,
             MaybeDebugStream, Debug, Canonical, 0, Deep, !IO)
-    ; DetachRes = in_parent ->
+    ;
+        DetachRes = in_parent,
         % We are in the parent after we spawned the child. We cause the process
         % to exit simply by not calling server_loop.
         %
@@ -416,6 +457,7 @@
         release_lock(Debug, MutexFile, !IO),
         remove_want_file(WantFile, !IO)
     ;
+        DetachRes = fork_failed,
         % We are in the parent because the fork failed. Again we cause
         % the process to exit simply by not calling server_loop, but we also
         % report the failure through the exit status. We don't report it
@@ -447,19 +489,21 @@
     ;
         MaybeStartupStream = no
     ),
-    CmdPref0 = cmd_pref(Cmd0, Pref0),
-    ( Cmd0 = restart ->
+    CmdPref0 = cmd_pref(Cmd0, PrefInd0),
+    Pref0 = solidify_preference(Deep, PrefInd0),
+
+    ( Cmd0 = deep_cmd_restart ->
         read_and_startup(Deep0 ^ server_name, [Deep0 ^ data_file_name],
-            Canonical, MaybeStartupStream, [], MaybeDeep, !IO),
+            Canonical, MaybeStartupStream, [], [], MaybeDeep, !IO),
         (
             MaybeDeep = ok(Deep),
             MaybeMsg = no,
-            Cmd = menu
+            Cmd = deep_cmd_menu
         ;
             MaybeDeep = error(ErrorMsg),
             MaybeMsg = yes(ErrorMsg),
             Deep = Deep0,
-            Cmd = quit
+            Cmd = deep_cmd_quit
         )
     ;
         Deep = Deep0,
@@ -495,13 +539,13 @@
         MaybeStartupStream = no
     ),
 
-    ( Cmd = quit ->
+    ( Cmd = deep_cmd_quit ->
         % The lack of a recursive call here shuts down the server.
         %
         % This deletes all the files created by the process, including
         % WantFile and MutexFile, with MutexFile being deleted last.
         delete_cleanup_files(!IO)
-    ; Cmd = timeout(TimeOut) ->
+    ; Cmd = deep_cmd_timeout(TimeOut) ->
         server_loop(ToServerPipe, FromServerPipe, TimeOut, MaybeStartupStream,
             Debug, Canonical, QueryNum, Deep, !IO)
     ;
@@ -654,6 +698,7 @@
     ;       debug
     ;       detach_process
     ;       help
+    ;       localhost
     ;       modules
     ;       proc
     ;       quit
@@ -665,7 +710,6 @@
     ;       version
     ;       write_query_string.
 
-:- type options ---> options.
 :- type option_table == (option_table(option)).
 
 :- pred short(char::in, option::out) is semidet.
@@ -688,6 +732,7 @@
 long("debug",               debug).
 long("detach-process",      detach_process).
 long("help",                help).
+long("localhost",           localhost).
 long("modules",             modules).
 long("proc",                proc).
 long("quit",                quit).
@@ -706,6 +751,7 @@
 defaults(debug,                 bool(no)).
 defaults(detach_process,        bool(yes)).
 defaults(help,                  bool(no)).
+defaults(localhost,             bool(no)).
 defaults(modules,               bool(no)).
 defaults(proc,                  int(0)).
 defaults(quit,                  bool(no)).
@@ -726,17 +772,17 @@
     lookup_int_option(Options, clique, CliqueNum),
     lookup_int_option(Options, proc, ProcNum),
     ( Root = yes ->
-        Cmd = root(no)
+        Cmd = deep_cmd_root(no)
     ; Modules = yes ->
-        Cmd = modules
+        Cmd = deep_cmd_modules
     ; CliqueNum > 0 ->
-        Cmd = clique(CliqueNum)
+        Cmd = deep_cmd_clique(CliqueNum)
     ; ProcNum > 0 ->
-        Cmd = proc(ProcNum)
+        Cmd = deep_cmd_proc(ProcNum)
     ; Quit = yes ->
-        Cmd = quit
+        Cmd = deep_cmd_quit
     ;
-        Cmd = menu
+        Cmd = deep_cmd_menu
     ).
 
 %-----------------------------------------------------------------------------%
Index: mdprof_dump.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_dump.m,v
retrieving revision 1.5
diff -u -b -r1.5 mdprof_dump.m
--- mdprof_dump.m	9 Oct 2006 08:09:04 -0000	1.5
+++ mdprof_dump.m	11 Oct 2006 03:49:04 -0000
@@ -79,37 +79,11 @@
 :- pred main_2(option_table(option)::in, string::in, io::di, io::uo) is det.
 
 main_2(Options, FileName, !IO) :-
-    getopt.lookup_bool_option(Options, restrict_statics, Restrict),
-    getopt.lookup_bool_option(Options, dump_prof_stats, ProfStats0),
-    getopt.lookup_bool_option(Options, dump_call_site_dynamics, DumpCSDs0),
-    getopt.lookup_bool_option(Options, dump_proc_dynamics, DumpPDs0),
-    getopt.lookup_bool_option(Options, dump_call_site_statics, DumpCSSs0),
-    getopt.lookup_bool_option(Options, dump_proc_statics, DumpPSs0),
-    % If the user doesn't say what he/she wants, they dump everything.
-    (
-        ProfStats0 = no,
-        DumpCSDs0 = no,
-        DumpPDs0 = no,
-        DumpCSSs0 = no,
-        DumpPSs0 = no
-    ->
-        ProfStats = yes,
-        DumpCSDs = yes,
-        DumpPDs = yes,
-        DumpCSSs = yes,
-        DumpPSs = yes
-    ;
-        ProfStats = ProfStats0,
-        DumpCSDs = DumpCSDs0,
-        DumpPDs = DumpPDs0,
-        DumpCSSs = DumpCSSs0,
-        DumpPSs = DumpPSs0
-    ),
+    getopt.lookup_accumulating_option(Options, dump_options, DumpOptions),
     read_call_graph(FileName, MaybeInitialDeep, !IO),
     (
         MaybeInitialDeep = ok(InitialDeep),
-        dump_initial_deep(ProfStats, Restrict, DumpCSDs, DumpPDs,
-            DumpCSSs, DumpPSs, InitialDeep, !IO)
+        dump_initial_deep(InitialDeep, DumpOptions, !IO)
     ;
         MaybeInitialDeep = error(Msg),
         io.format("Cannot read %s: %s\n", [s(Msg), s(FileName)], !IO)
@@ -122,42 +96,24 @@
 
 :- type option
     --->    help
-    ;       dump_prof_stats
-    ;       dump_call_site_dynamics
-    ;       dump_proc_dynamics
-    ;       dump_call_site_statics
-    ;       dump_proc_statics
-    ;       restrict_statics.
+    ;       dump_options.
 
 :- type option_table == (option_table(option)).
 
 :- pred short_option(char::in, option::out) is semidet.
 
 short_option('h', help).
+short_option('D', dump_options).
 
 :- pred long_option(string::in, option::out) is semidet.
 
 long_option("help", help).
-long_option("prof-stats", dump_prof_stats).
-long_option("call-site-dynamics", dump_call_site_dynamics).
-long_option("csd", dump_call_site_dynamics).
-long_option("proc-dynamics", dump_proc_dynamics).
-long_option("pd", dump_proc_dynamics).
-long_option("call-site-statics", dump_call_site_statics).
-long_option("css", dump_call_site_statics).
-long_option("proc-statics", dump_proc_statics).
-long_option("ps", dump_proc_statics).
-long_option("restrict-statics", restrict_statics).
+long_option("dump-options", dump_options).
 
 :- pred defaults(option::out, option_data::out) is multi.
 
 defaults(help, bool(no)).
-defaults(dump_prof_stats, bool(no)).
-defaults(dump_call_site_dynamics, bool(no)).
-defaults(dump_proc_dynamics, bool(no)).
-defaults(dump_call_site_statics, bool(no)).
-defaults(dump_proc_statics, bool(no)).
-defaults(restrict_statics, bool(no)).
+defaults(dump_options, accumulating([])).
 
 %----------------------------------------------------------------------------%
 
@@ -165,23 +121,33 @@
 
 usage(ProgName, !IO) :-
     io.stderr_stream(StdErr, !IO),
-    io.format(StdErr, "Usage: %s [<options>] [filename]\n", [s(ProgName)],
+    io.format(StdErr, "Usage: %s [-h] [-D what] [filename]\n", [s(ProgName)],
         !IO),
-    io.write_string(StdErr, "Options:\n", !IO),
-    io.write_string(StdErr, "\t-h, --help\n", !IO),
-    io.write_string(StdErr, "\t\tDisplay this message.\n", !IO),
-    io.write_string(StdErr, "\t--csd, --call-site-dynamics\n", !IO),
-    io.write_string(StdErr, "\t\tDump call-site dynamics.\n", !IO),
-    io.write_string(StdErr, "\t--pd, --proc-dynamics\n", !IO),
-    io.write_string(StdErr, "\t\tDump proc dynamics.\n", !IO),
-    io.write_string(StdErr, "\t--css, --call-site-statics\n", !IO),
-    io.write_string(StdErr, "\t\tDump call-site statics.\n", !IO),
-    io.write_string(StdErr, "\t--ps, --proc-statics\n", !IO),
-    io.write_string(StdErr, "\t\tDump proc statics.\n", !IO),
-    io.write_string(StdErr, "\t--restrict-statics\n", !IO),
-    io.write_string(StdErr, "\t\tOnly dump those proc and ", !IO),
-    io.write_string(StdErr, "call-site statics that are referenced ", !IO),
-    io.write_string(StdErr, "from the proc dynamics\n", !IO).
+    io.write_string(StdErr, options_description, !IO).
+
+:- func options_description = string.
+
+options_description =
+    "Options:\n" ++
+    "\t-h, --help\n" ++
+    "\t\tDisplay this message.\n" ++
+    "\t--D csd\n" ++
+    "\t\tDump call-site dynamics.\n" ++
+    "\t--D pd\n" ++
+    "\t\tDump proc dynamics.\n" ++
+    "\t--D css\n" ++
+    "\t\tDump call-site statics.\n" ++
+    "\t--D ps\n" ++
+    "\t\tDump proc statics.\n" ++
+    "\t--D restrict\n" ++
+    "\t\tDo not dump proc and call-site statics that are\n" ++
+    "\t\tnot referenced from the proc dynamics\n" ++
+    "\t--D clique\n" ++
+    "\t\tDump information about cliques.\n" ++
+    "\t--D rev\n" ++
+    "\t\tDump reverse links.\n" ++
+    "\t--D prop\n" ++
+    "\t\tDump propagated measurement information.\n".
 
 %----------------------------------------------------------------------------%
 :- end_module mdprof_dump.
Index: mdprof_test.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/mdprof_test.m,v
retrieving revision 1.11
diff -u -b -r1.11 mdprof_test.m
--- mdprof_test.m	29 Mar 2006 08:07:40 -0000	1.11
+++ mdprof_test.m	11 Oct 2006 03:49:04 -0000
@@ -102,6 +102,7 @@
         lookup_bool_option(Options, canonical_clique, Canonical),
         lookup_bool_option(Options, verbose, Verbose),
         lookup_accumulating_option(Options, dump, DumpStages),
+        lookup_accumulating_option(Options, dump_options, DumpOptions),
         server_name(Machine, !IO),
         (
             Verbose = no,
@@ -112,7 +113,7 @@
             MaybeOutput = yes(Stdout)
         ),
         read_and_startup(Machine, [FileName], Canonical, MaybeOutput,
-            DumpStages, Res, !IO),
+            DumpStages, DumpOptions, Res, !IO),
         (
             Res = ok(Deep),
             lookup_bool_option(Options, test, Test),
@@ -121,7 +122,7 @@
             ;
                 Test = yes,
                 lookup_string_option(Options, test_dir, TestDir),
-                test_server(TestDir, default_preferences, Deep, !IO)
+                test_server(TestDir, default_preferences(Deep), Deep, !IO)
             )
         ;
             Res = error(Error),
@@ -164,7 +165,7 @@
 verify_profile_2(ProgName, Options, FileName, !IO) :-
     lookup_bool_option(Options, canonical_clique, Canonical),
     Machine = "dummy_server",      % For verification this doesn't matter.
-    read_and_startup(Machine, [FileName], Canonical, no, [], Res, !IO),
+    read_and_startup(Machine, [FileName], Canonical, no, [], [], Res, !IO),
     (
         Res = ok(_Deep)
     ;
@@ -226,7 +227,7 @@
 
 test_cliques(Cur, Max, DirName, Pref, Deep, !IO) :-
     ( Cur =< Max ->
-        try_exec(clique(Cur), Pref, Deep, HTML, !IO),
+        try_exec(deep_cmd_clique(Cur), Pref, Deep, HTML, !IO),
         write_test_html(DirName, "clique", Cur, HTML, !IO),
         test_cliques(Cur + 1, Max, DirName, Pref, Deep, !IO)
     ;
@@ -238,7 +239,7 @@
 
 test_procs(Cur, Max, DirName, Pref, Deep, !IO) :-
     ( Cur =< Max ->
-        try_exec(proc(Cur), Pref, Deep, HTML, !IO),
+        try_exec(deep_cmd_proc(Cur), Pref, Deep, HTML, !IO),
         write_test_html(DirName, "proc", Cur, HTML, !IO),
         test_procs(Cur + 1, Max, DirName, Pref, Deep, !IO)
     ;
@@ -285,6 +286,7 @@
 :- type option
     --->    canonical_clique
     ;       dump
+    ;       dump_options
     ;       flat
     ;       help
     ;       test
@@ -300,14 +302,15 @@
 
 short('c',  canonical_clique).
 short('d',  dump).
-short('v',  verbose).
-short('D',  test_dir).
+short('D',  dump_options).
 short('T',  test).
+short('v',  verbose).
 
 :- pred long(string::in, option::out) is semidet.
 
 long("canonical-clique",    canonical_clique).
 long("dump",                dump).
+long("dump-options",        dump_options).
 long("help",                help).
 long("test",                test).
 long("test-dir",            test_dir).
@@ -319,6 +322,7 @@
 
 defaults(canonical_clique,  bool(no)).
 defaults(dump,              accumulating([])).
+defaults(dump_options,      accumulating([])).
 defaults(help,              bool(no)).
 defaults(test,              bool(no)).
 defaults(test_dir,          string("deep_test")).
Index: measurements.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/measurements.m,v
retrieving revision 1.11
diff -u -b -r1.11 measurements.m
--- measurements.m	4 Oct 2006 06:59:17 -0000	1.11
+++ measurements.m	11 Oct 2006 03:49:04 -0000
@@ -30,19 +30,23 @@
 :- func redos(own_prof_info) = int.
 :- func excps(own_prof_info) = int.
 :- func quanta(own_prof_info) = int.
-:- func call_seqs(own_prof_info) = int.
+:- func callseqs(own_prof_info) = int.
 :- func allocs(own_prof_info) = int.
 :- func words(own_prof_info) = int.
 
 :- func zero_own_prof_info = own_prof_info.
 
+:- pred is_zero_own_prof_info(own_prof_info::in) is semidet.
+
 :- func inherit_quanta(inherit_prof_info) = int.
-:- func inherit_call_seqs(inherit_prof_info) = int.
+:- func inherit_callseqs(inherit_prof_info) = int.
 :- func inherit_allocs(inherit_prof_info) = int.
 :- func inherit_words(inherit_prof_info) = int.
 
 :- func zero_inherit_prof_info = inherit_prof_info.
 
+:- pred is_zero_inherit_prof_info(inherit_prof_info::in) is semidet.
+
 :- func add_inherit_to_inherit(inherit_prof_info, inherit_prof_info)
     = inherit_prof_info.
 :- func add_own_to_inherit(own_prof_info, inherit_prof_info)
@@ -89,7 +93,7 @@
                 opa_redos       :: int,
                 opa_excps       :: int,
                 opa_quanta      :: int,
-                opa_call_seqs   :: int,
+                opa_callseqs            :: int,
                 opa_allocs      :: int,
                 opa_words       :: int
             )
@@ -98,7 +102,7 @@
     ;       own_prof_det(
                 opd_exits       :: int,
                 opd_quanta      :: int,
-                opd_call_seqs   :: int,
+                opd_callseqs            :: int,
                 opd_allocs      :: int,
                 opd_words       :: int
             )
@@ -107,7 +111,7 @@
 
     ;       own_prof_fast_det(
                 opfd_exits      :: int,
-                opfd_call_seqs  :: int,
+                opfd_callseqs           :: int,
                 opfd_allocs     :: int,
                 opfd_words      :: int
             )
@@ -118,7 +122,7 @@
     ;       own_prof_fast_nomem_semi(
                 opfns_exits     :: int,
                 opfns_fails     :: int,
-                opfns_call_seqs :: int
+                opfns_callseqs          :: int
             ).
             % implicit redos == excps == 0
             % implicit calls == exits + fails
@@ -128,7 +132,7 @@
 :- type inherit_prof_info
     --->    inherit_prof_info(
                 ipo_quanta      :: int,
-                ipo_call_seqs   :: int,
+                ipo_callseqs            :: int,
                 ipo_allocs      :: int,
                 ipo_words       :: int
             ).
@@ -138,7 +142,7 @@
 fails(own_prof_fast_nomem_semi(_, Fails, _)) = Fails.
 redos(own_prof_fast_nomem_semi(_, _, _)) = 0.
 excps(own_prof_fast_nomem_semi(_, _, _)) = 0.
-call_seqs(own_prof_fast_nomem_semi(_, _, CallSeqs)) = CallSeqs.
+callseqs(own_prof_fast_nomem_semi(_, _, CallSeqs)) = CallSeqs.
 quanta(own_prof_fast_nomem_semi(_, _, _)) = 0.
 allocs(own_prof_fast_nomem_semi(_, _, _)) = 0.
 words(own_prof_fast_nomem_semi(_, _, _)) = 0.
@@ -149,7 +153,7 @@
 redos(own_prof_fast_det(_, _, _, _)) = 0.
 excps(own_prof_fast_det(_, _, _, _)) = 0.
 quanta(own_prof_fast_det(_, _, _, _)) = 0.
-call_seqs(own_prof_fast_det(_, CallSeqs, _, _)) = CallSeqs.
+callseqs(own_prof_fast_det(_, CallSeqs, _, _)) = CallSeqs.
 allocs(own_prof_fast_det(_, _, Allocs, _)) = Allocs.
 words(own_prof_fast_det(_, _, _, Words)) = Words.
 
@@ -159,7 +163,7 @@
 redos(own_prof_det(_, _, _, _, _)) = 0.
 excps(own_prof_det(_, _, _, _, _)) = 0.
 quanta(own_prof_det(_, Quanta, _, _, _)) = Quanta.
-call_seqs(own_prof_det(_, _, CallSeqs, _, _)) = CallSeqs.
+callseqs(own_prof_det(_, _, CallSeqs, _, _)) = CallSeqs.
 allocs(own_prof_det(_, _, _, Allocs, _)) = Allocs.
 words(own_prof_det(_, _, _, _, Words)) = Words.
 
@@ -170,43 +174,50 @@
 redos(own_prof_all(_, _, Redos, _, _, _, _, _)) = Redos.
 excps(own_prof_all(_, _, _, Excps, _, _, _, _)) = Excps.
 quanta(own_prof_all(_, _, _, _, Quanta, _, _, _)) = Quanta.
-call_seqs(own_prof_all(_, _, _, _, CallSeqs, _, _, _)) = CallSeqs.
+callseqs(own_prof_all(_, _, _, _, _, CallSeqs, _, _)) = CallSeqs.
 allocs(own_prof_all(_, _, _, _, _, _, Allocs, _)) = Allocs.
 words(own_prof_all(_, _, _, _, _, _, _, Words)) = Words.
 
 zero_own_prof_info = own_prof_fast_nomem_semi(0, 0, 0).
 
+is_zero_own_prof_info(own_prof_all(0, 0, 0, 0, 0, 0, 0, 0)).
+is_zero_own_prof_info(own_prof_det(0, 0, 0, 0, 0)).
+is_zero_own_prof_info(own_prof_fast_det(0, 0, 0, 0)).
+is_zero_own_prof_info(own_prof_fast_nomem_semi(0, 0, 0)).
+
 inherit_quanta(inherit_prof_info(Quanta, _, _, _)) = Quanta.
-inherit_call_seqs(inherit_prof_info(_, CallSeqs, _, _)) = CallSeqs.
+inherit_callseqs(inherit_prof_info(_, CallSeqs, _, _)) = CallSeqs.
 inherit_allocs(inherit_prof_info(_, _, Allocs, _)) = Allocs.
 inherit_words(inherit_prof_info(_, _, _, Words)) = Words.
 
 zero_inherit_prof_info = inherit_prof_info(0, 0, 0, 0).
 
+is_zero_inherit_prof_info(inherit_prof_info(0, 0, 0, 0)).
+
 add_inherit_to_inherit(PI1, PI2) = SumPI :-
     Quanta = inherit_quanta(PI1) + inherit_quanta(PI2),
-    CallSeqs = inherit_call_seqs(PI1) + inherit_call_seqs(PI2),
+    CallSeqs = inherit_callseqs(PI1) + inherit_callseqs(PI2),
     Allocs = inherit_allocs(PI1) + inherit_allocs(PI2),
     Words = inherit_words(PI1) + inherit_words(PI2),
     SumPI = inherit_prof_info(Quanta, CallSeqs, Allocs, Words).
 
 add_own_to_inherit(PI1, PI2) = SumPI :-
     Quanta = quanta(PI1) + inherit_quanta(PI2),
-    CallSeqs = call_seqs(PI1) + inherit_call_seqs(PI2),
+    CallSeqs = callseqs(PI1) + inherit_callseqs(PI2),
     Allocs = allocs(PI1) + inherit_allocs(PI2),
     Words = words(PI1) + inherit_words(PI2),
     SumPI = inherit_prof_info(Quanta, CallSeqs, Allocs, Words).
 
 subtract_own_from_inherit(PI1, PI2) = SumPI :-
     Quanta = inherit_quanta(PI2) - quanta(PI1),
-    CallSeqs = inherit_call_seqs(PI2) - call_seqs(PI1),
+    CallSeqs = inherit_callseqs(PI2) - callseqs(PI1),
     Allocs = inherit_allocs(PI2) - allocs(PI1),
     Words = inherit_words(PI2) - words(PI1),
     SumPI = inherit_prof_info(Quanta, CallSeqs, Allocs, Words).
 
 subtract_inherit_from_inherit(PI1, PI2) = SumPI :-
     Quanta = inherit_quanta(PI2) - inherit_quanta(PI1),
-    CallSeqs = inherit_call_seqs(PI2) - inherit_call_seqs(PI1),
+    CallSeqs = inherit_callseqs(PI2) - inherit_callseqs(PI1),
     Allocs = inherit_allocs(PI2) - inherit_allocs(PI1),
     Words = inherit_words(PI2) - inherit_words(PI1),
     SumPI = inherit_prof_info(Quanta, CallSeqs, Allocs, Words).
@@ -217,11 +228,11 @@
     Redos = redos(PI2),
     Excps = excps(PI2),
     Quanta = inherit_quanta(PI1) + quanta(PI2),
-    CallSeqs = inherit_call_seqs(PI1) + call_seqs(PI2),
+    CallSeqs = inherit_callseqs(PI1) + callseqs(PI2),
     Allocs = inherit_allocs(PI1) + allocs(PI2),
     Words = inherit_words(PI1) + words(PI2),
-    SumPI = compress_profile(Exits, Fails, Redos, Excps, Quanta, CallSeqs,
-        Allocs, Words).
+    SumPI = compress_profile(Exits, Fails, Redos, Excps,
+        Quanta, CallSeqs, Allocs, Words).
 
 add_own_to_own(PI1, PI2) = SumPI :-
     Exits = exits(PI1) + exits(PI2),
@@ -229,11 +240,11 @@
     Redos = redos(PI1) + redos(PI2),
     Excps = excps(PI1) + excps(PI2),
     Quanta = quanta(PI1) + quanta(PI2),
-    CallSeqs = call_seqs(PI1) + call_seqs(PI2),
+    CallSeqs = callseqs(PI1) + callseqs(PI2),
     Allocs = allocs(PI1) + allocs(PI2),
     Words = words(PI1) + words(PI2),
-    SumPI = compress_profile(Exits, Fails, Redos, Excps, Quanta, CallSeqs,
-        Allocs, Words).
+    SumPI = compress_profile(Exits, Fails, Redos, Excps,
+        Quanta, CallSeqs, Allocs, Words).
 
 sum_own_infos(Owns) =
     list.foldl(add_own_to_own, Owns, zero_own_prof_info).
@@ -319,7 +330,7 @@
     (
         Own = own_prof_all(Exits, Fails, Redos, Excps, Quanta, CallSeqs,
             Allocs, Words),
-        Calls = Exits + Fails + Redos
+        Calls = Exits + Fails - Redos
     ;
         Own = own_prof_det(Exits, Quanta, CallSeqs, Allocs, Words),
         Calls = Exits,
Index: profile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/profile.m,v
retrieving revision 1.14
diff -u -b -r1.14 profile.m
--- profile.m	5 Oct 2006 04:37:51 -0000	1.14
+++ profile.m	11 Oct 2006 03:49:04 -0000
@@ -38,10 +38,10 @@
                 max_css                     :: int,
                 max_pd                      :: int,
                 max_ps                      :: int,
-                num_callseqs                :: int,
                 ticks_per_sec               :: int,
                 instrument_quanta           :: int,
                 user_quanta                 :: int,
+                num_callseqs            :: int,
                 word_size                   :: int,
                 canonical                   :: bool
             ).
@@ -85,8 +85,7 @@
                                             % index: call_site_dynamic_ptr int
 
                 % Reverse links.
-                proc_callers                :: array(
-                                                list(call_site_dynamic_ptr)),
+                proc_callers            :: array(list(call_site_dynamic_ptr)),
                                             % index: proc_static_ptr int
                 call_site_static_map        :: call_site_static_map,
                                             % index: call_site_dynamic_ptr int
@@ -94,7 +93,7 @@
                                                 list(call_site_dynamic_ptr))),
                                             % index: call_site_static_ptr int
 
-                % Propagated timing info.
+                % Propagated measurements.
                 pd_own                      :: array(own_prof_info),
                 pd_desc                     :: array(inherit_prof_info),
                 csd_desc                    :: array(inherit_prof_info),
Index: query.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/query.m,v
retrieving revision 1.13
diff -u -b -r1.13 query.m
--- query.m	29 Sep 2006 06:15:11 -0000	1.13
+++ query.m	11 Oct 2006 03:49:04 -0000
@@ -68,29 +68,27 @@
         ;
             Msg = "unknown exception"
         ),
-        HTML = string.format(
-                "<H3>AN EXCEPTION HAS OCCURRED: %s</H3>\n",
+        HTML = string.format("<H3>AN EXCEPTION HAS OCCURRED: %s</H3>\n",
                 [s(Msg)])
     ).
 
 :- pred exec(cmd::in, preferences::in, deep::in, string::out,
     io::di, io::uo) is det.
 
-exec(restart, _Pref, _Deep, _HTML, !IO) :-
+exec(deep_cmd_restart, _Pref, _Deep, _HTML, !IO) :-
     % Our caller is supposed to filter out restart commands.
     error("exec: found restart command").
-exec(quit, _Pref, Deep, HTML, !IO) :-
+exec(deep_cmd_quit, _Pref, Deep, HTML, !IO) :-
     HTML = string.format(
         "<H3>Shutting down deep profile server for %s.</H3>\n",
         [s(Deep ^ data_file_name)]).
-exec(timeout(TimeOut), _Pref, _Deep, HTML, !IO) :-
-    HTML = string.format("<H3>Timeout set to %d minutes</H3>\n",
-        [i(TimeOut)]).
+exec(deep_cmd_timeout(TimeOut), _Pref, _Deep, HTML, !IO) :-
+    HTML = string.format("<H3>Timeout set to %d minutes</H3>\n", [i(TimeOut)]).
 exec(Cmd, Pref, Deep, HTML, !IO) :-
-    Cmd = menu,
+    Cmd = deep_cmd_menu,
     HTML = generate_menu_page(Cmd, Pref, Deep).
 exec(Cmd, Pref, Deep, HTML, !IO) :-
-    Cmd = root(MaybePercent),
+    Cmd = deep_cmd_root(MaybePercent),
     deep_lookup_clique_index(Deep, Deep ^ root, RootCliquePtr),
     RootCliquePtr = clique_ptr(RootCliqueNum),
     (
@@ -101,7 +99,7 @@
         generate_clique_page(Cmd, RootCliqueNum, Pref, Deep, HTML, 100, _)
     ).
 exec(Cmd, Pref, Deep, HTML, !IO) :-
-    Cmd = clique(CliqueNum),
+    Cmd = deep_cmd_clique(CliqueNum),
     CliquePtr = clique_ptr(CliqueNum),
     ( valid_clique_ptr(Deep, CliquePtr) ->
         generate_clique_page(Cmd, CliqueNum, Pref, Deep, HTML, 100, _)
@@ -112,7 +110,7 @@
             page_footer(Cmd, Pref, Deep)
     ).
 exec(Cmd, Pref, Deep, HTML, !IO) :-
-    Cmd = proc(PSI),
+    Cmd = deep_cmd_proc(PSI),
     PSPtr = proc_static_ptr(PSI),
     ( valid_proc_static_ptr(Deep, PSPtr) ->
         HTML = generate_proc_page(Cmd, PSPtr, Pref, Deep)
@@ -123,7 +121,7 @@
             page_footer(Cmd, Pref, Deep)
     ).
 exec(Cmd, Pref, Deep, HTML, !IO) :-
-    Cmd = proc_callers(PSI, CallerGroups, BunchNum),
+    Cmd = deep_cmd_proc_callers(PSI, CallerGroups, BunchNum),
     PSPtr = proc_static_ptr(PSI),
     ( valid_proc_static_ptr(Deep, PSPtr) ->
         generate_proc_callers_page(Cmd, PSPtr, CallerGroups, BunchNum,
@@ -135,10 +133,10 @@
             page_footer(Cmd, Pref, Deep)
     ).
 exec(Cmd, Pref, Deep, HTML, !IO) :-
-    Cmd = modules,
+    Cmd = deep_cmd_modules,
     HTML = generate_modules_page(Cmd, Pref, Deep).
 exec(Cmd, Pref, Deep, HTML, !IO) :-
-    Cmd = module(ModuleName),
+    Cmd = deep_cmd_module(ModuleName),
     ( map.search(Deep ^ module_data, ModuleName, ModuleData) ->
         HTML = generate_module_page(Cmd, ModuleName, ModuleData, Pref, Deep)
     ;
@@ -148,18 +146,18 @@
             page_footer(Cmd, Pref, Deep)
     ).
 exec(Cmd, Pref, Deep, HTML, !IO) :-
-    Cmd = top_procs(Limit, CostKind, InclDesc, Scope),
+    Cmd = deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope),
     HTML = generate_top_procs_page(Cmd, Limit, CostKind, InclDesc, Scope,
         Pref, Deep).
-exec(proc_static(PSI), _Pref, Deep, HTML, !IO) :-
+exec(deep_cmd_proc_static(PSI), _Pref, Deep, HTML, !IO) :-
     HTML = generate_proc_static_debug_page(PSI, Deep).
-exec(proc_dynamic(PDI), _Pref, Deep, HTML, !IO) :-
+exec(deep_cmd_proc_dynamic(PDI), _Pref, Deep, HTML, !IO) :-
     HTML = generate_proc_dynamic_debug_page(PDI, Deep).
-exec(call_site_static(CSSI), _Pref, Deep, HTML, !IO) :-
+exec(deep_cmd_call_site_static(CSSI), _Pref, Deep, HTML, !IO) :-
     HTML = generate_call_site_static_debug_page(CSSI, Deep).
-exec(call_site_dynamic(CSDI), _Pref, Deep, HTML, !IO) :-
+exec(deep_cmd_call_site_dynamic(CSDI), _Pref, Deep, HTML, !IO) :-
     HTML = generate_call_site_dynamic_debug_page(CSDI, Deep).
-exec(raw_clique(CI), _Pref, Deep, HTML, !IO) :-
+exec(deep_cmd_raw_clique(CI), _Pref, Deep, HTML, !IO) :-
     HTML = generate_clique_debug_page(CI, Deep).
 
 %-----------------------------------------------------------------------------%
@@ -337,62 +335,86 @@
 :- func generate_menu_page(cmd, preferences, deep) = string.
 
 generate_menu_page(Cmd, Pref, Deep) = HTML :-
+    ShouldDisplayTimes = should_display_times(Deep),
     HTML =
         page_banner(Cmd, Pref) ++
         "<p>\n" ++
         menu_text ++
         "<ul>\n" ++
         "<li>\n" ++
-        menu_item(Deep, Pref, root(no),
+        menu_item(Deep, Pref, deep_cmd_root(no),
             "Exploring the call graph, starting at the root.") ++
         "<li>\n" ++
-        menu_item(Deep, Pref, root(yes(90)),
+        menu_item(Deep, Pref, deep_cmd_root(yes(90)),
             "Exploring the call graph, starting at the action.") ++
         "<li>\n" ++
-        menu_item(Deep, Pref, modules,
+        menu_item(Deep, Pref, deep_cmd_modules,
             "Exploring the program module by module.") ++
+        ( ShouldDisplayTimes = yes ->
         "<li>\n" ++
         menu_item(Deep, Pref,
-            top_procs(rank_range(1, 100), time,
+                deep_cmd_top_procs(rank_range(1, 100), cost_time,
                 self, overall),
             "Top 100 most expensive procedures: time, self.") ++
         "<li>\n" ++
         menu_item(Deep, Pref,
-            top_procs(rank_range(1, 100), time,
+                deep_cmd_top_procs(rank_range(1, 100), cost_time,
                 self_and_desc, overall),
             "Top 100 most expensive procedures: time, self+desc.")
-            ++
+        ;
+            ""
+        ) ++
         "<li>\n" ++
         menu_item(Deep, Pref,
-            top_procs(rank_range(1, 100), words,
+            deep_cmd_top_procs(rank_range(1, 100), cost_callseqs,
                 self, overall),
-            "Top 100 most expensive procedures: words, self.") ++
+            "Top 100 most expensive procedures: callseqs, self.") ++
         "<li>\n" ++
         menu_item(Deep, Pref,
-            top_procs(rank_range(1, 100), words,
+            deep_cmd_top_procs(rank_range(1, 100), cost_callseqs,
                 self_and_desc, overall),
+            "Top 100 most expensive procedures: callseqs, self+desc.") ++
+        "<li>\n" ++
+        menu_item(Deep, Pref,
+            deep_cmd_top_procs(rank_range(1, 100), cost_words, self, overall),
+            "Top 100 most expensive procedures: words, self.") ++
+        "<li>\n" ++
+        menu_item(Deep, Pref,
+            deep_cmd_top_procs(rank_range(1, 100), cost_words, self_and_desc,
+                overall),
             "Top 100 most expensive procedures: words, self+desc.")
             ++
+        ( ShouldDisplayTimes = yes ->
         "<li>\n" ++
         menu_item(Deep, Pref,
-            top_procs(threshold(0.1), time,
-                self, overall),
+                deep_cmd_top_procs(threshold(0.1), cost_time, self, overall),
             "Procedures above 0.1% threshold: time, self.") ++
         "<li>\n" ++
         menu_item(Deep, Pref,
-            top_procs(threshold(0.1), time,
-                self_and_desc, overall),
+                deep_cmd_top_procs(threshold(1.0), cost_time, self_and_desc,
+                    overall),
             "Procedures above 1% threshold: time, self+desc.")
+        ;
+            ""
+        ) ++
+        "<li>\n" ++
+        menu_item(Deep, Pref,
+            deep_cmd_top_procs(threshold(0.1), cost_callseqs, self, overall),
+            "Procedures above 0.1% threshold: callseqs, self.") ++
+        "<li>\n" ++
+        menu_item(Deep, Pref,
+            deep_cmd_top_procs(threshold(1.0), cost_callseqs, self_and_desc,
+                overall),
+            "Procedures above 1% threshold: callseqs, self+desc.")
             ++
         "<li>\n" ++
         menu_item(Deep, Pref,
-            top_procs(threshold(0.1), words,
-                self, overall),
+            deep_cmd_top_procs(threshold(0.1), cost_words, self, overall),
             "Procedures above 0.1% threshold: words, self.") ++
         "<li>\n" ++
         menu_item(Deep, Pref,
-            top_procs(threshold(0.1), words,
-                self_and_desc, overall),
+            deep_cmd_top_procs(threshold(1.0), cost_words, self_and_desc,
+                overall),
             "Procedures above 1% threshold: words, self+desc.")
             ++
         "</ul>\n" ++
@@ -434,6 +456,9 @@
         "<TR><TD ALIGN=left>Quanta in instrumentation:</TD>\n" ++
         string.format("<TD ALIGN=right>%d</TD></TR>\n",
             [i(Stats ^ instrument_quanta)]) ++
+        "<TR><TD ALIGN=left>Call sequence numbers:</TD>\n" ++
+        string.format("<TD ALIGN=right>%d</TD></TR>\n",
+            [i(Stats ^ num_callseqs)]) ++
         "<TR><TD ALIGN=left>CallSiteDynamic structures:</TD>\n" ++
         string.format("<TD ALIGN=right>%d</TD></TR>\n",
             [i(Stats ^ max_csd)]) ++
@@ -459,8 +484,7 @@
     generate_clique_page(Cmd, CliqueNum, Pref, Deep, HTML0,
         Percent, ActionPtrs),
     ( ActionPtrs = [clique_ptr(ActionCliqueNum)] ->
-        HTML = chase_the_action(Cmd, ActionCliqueNum,
-            Pref, Deep, Percent)
+        HTML = chase_the_action(Cmd, ActionCliqueNum, Pref, Deep, Percent)
     ;
         HTML = HTML0
     ).
@@ -470,18 +494,15 @@
 :- pred generate_clique_page(cmd::in, int::in, preferences::in, deep::in,
     string::out, int::in, list(clique_ptr)::out) is det.
 
-generate_clique_page(Cmd, CliqueNum, Pref, Deep, HTML,
-        Percent, ActionPtrs) :-
-    clique_to_html(Pref, Deep, clique_ptr(CliqueNum),
-        CliqueHTML, Percent, ActionPtrs),
+generate_clique_page(Cmd, CliqueNum, Pref, Deep, HTML, Percent, ActionPtrs) :-
+    clique_to_html(Pref, Deep, clique_ptr(CliqueNum), CliqueHTML, Percent,
+        ActionPtrs),
     HTML =
         page_banner(Cmd, Pref) ++
-        string.format("<H3>Clique %d:</H3>\n",
-            [i(CliqueNum)]) ++
+        string.format("<H3>Clique %d:</H3>\n", [i(CliqueNum)]) ++
         table_start(Pref) ++
         fields_header(Pref, source_proc, totals_meaningful,
-            wrap_clique_links(clique_ptr(CliqueNum),
-                Pref, Deep)) ++
+            wrap_clique_links(clique_ptr(CliqueNum), Pref, Deep)) ++
         CliqueHTML ++
         table_end(Pref) ++
         page_footer(Cmd, Pref, Deep).
@@ -519,10 +540,8 @@
                 ""
             ;
                 table_start(Pref) ++
-                fields_header(Pref, IdFields,
-                    totals_meaningful,
-                    wrap_proc_callers_links(PSPtr,
-                        CallerGroups, 1,
+                fields_header(Pref, IdFields, totals_meaningful,
+                    wrap_proc_callers_links(PSPtr, CallerGroups, 1,
                         Pref, Deep)) ++
                 CallersHTML ++
                 table_end(Pref) ++
@@ -571,8 +590,8 @@
 
 generate_top_procs_page(Cmd, Limit, CostKind, InclDesc0, Scope0, Pref, Deep)
         = HTML :-
-    ( CostKind = calls ->
-        % counting calls is incompatible both with self_and_desc
+    ( CostKind = cost_calls ->
+        % Counting calls is incompatible both with self_and_desc
         % and per_call.
         InclDesc = self,
         Scope = overall
@@ -595,7 +614,8 @@
         Desc = cost_criteria_to_description(CostKind, InclDesc, Scope),
         Heading = string.format("<H3>Top procedures %s</H3>\n",
             [s(Desc)]),
-        ( TopPSIs = [] ->
+        (
+            TopPSIs = [],
             HTML =
                 page_banner(Cmd, Pref) ++
                 Heading ++ "<p>\n" ++
@@ -605,22 +625,20 @@
                 ToggleCostHTML ++
                 page_footer(Cmd, Pref, Deep)
         ;
+            TopPSIs = [_ | _],
             TopProcs = list.filter_map(
                 lookup_proc_total_to_html(Pref, Deep, no, ""),
                 list.map(wrap_proc_static_ptr, TopPSIs)),
             RankedTopProcs = add_ranks(TopProcs),
             SummaryHTMLs = list.map(
-                two_id_line_to_html(Pref, Deep,
-                    totals_meaningful),
+                two_id_line_to_html(Pref, Deep, totals_meaningful),
                 RankedTopProcs),
             HTML =
                 page_banner(Cmd, Pref) ++
                 Heading ++ "<p>\n" ++
                 table_start(Pref) ++
-                fields_header(Pref, rank_proc,
-                    totals_meaningful,
-                    wrap_top_procs_links(Limit, Pref,
-                        Deep)) ++
+                fields_header(Pref, rank_proc, totals_meaningful,
+                    wrap_top_procs_links(Limit, Pref, Deep)) ++
                 string.append_list(SummaryHTMLs) ++
                 table_end(Pref) ++
                 "<p>\n" ++
@@ -660,11 +678,11 @@
 module_summary_to_html(Pref, Deep, ModuleName - ModuleData) = LineGroup :-
     ModuleData = module_data(Own, Desc, _),
     not (
-        Pref ^ pref_inactive ^ inactive_modules = hide,
+        Pref ^ pref_inactive ^ inactive_modules = inactive_hide,
         is_inactive(Own)
     ),
     HTML = string.format("<TD><A HREF=""%s"">%s</A></TD>\n",
-        [s(deep_cmd_pref_to_url(Pref, Deep, module(ModuleName))),
+        [s(deep_cmd_pref_to_url(Pref, Deep, deep_cmd_module(ModuleName))),
             s(ModuleName)]),
     LineGroup = line_group(ModuleName, 0, ModuleName, Own, Desc, HTML, unit).
 
@@ -675,8 +693,8 @@
 
 module_to_html(Pref, Deep, _ModuleName, ModuleData, IdHeaders, HTML) :-
     ModuleData = module_data(_Own, _Desc, PSPtrs),
-    ProcLines = list.filter_map(
-        lookup_proc_total_to_html(Pref, Deep, yes, ""), PSPtrs),
+    ProcLines = list.filter_map(lookup_proc_total_to_html(Pref, Deep, yes, ""),
+        PSPtrs),
     Criteria = Pref ^ pref_criteria,
     SortedProcLines = sort_line_groups(Criteria, ProcLines),
     ( Criteria = by_cost(_, _, _) ->
@@ -686,8 +704,7 @@
         IdHeaders = source_proc,
         RankedProcLines = list.map(add_self_context, SortedProcLines)
     ),
-    ProcHTMLs = list.map(
-        two_id_line_to_html(Pref, Deep, totals_meaningful),
+    ProcHTMLs = list.map(two_id_line_to_html(Pref, Deep, totals_meaningful),
         RankedProcLines),
     HTML =
         separator_row(Pref, IdHeaders, totals_meaningful) ++
@@ -742,8 +759,8 @@
         separator_row(Pref, source_proc, totals_meaningful) ++
         Ancestors ++
         separator_row(Pref, source_proc, totals_meaningful) ++
-        header_row("Procedures of the clique:",
-            Pref, source_proc, totals_meaningful) ++
+        header_row("Procedures of the clique:", Pref, source_proc,
+            totals_meaningful) ++
         separator_row(Pref, source_proc, totals_meaningful) ++
         ProcGroups.
 
@@ -763,7 +780,7 @@
         deep_lookup_call_site_dynamics(Deep, EntryCSDPtr, EntryCSD),
         EntryPDPtr = EntryCSD ^ csd_caller,
         ( EntryPDPtr = Deep ^ root ->
-            % we have reached the root
+            % We have reached the root.
             HTML = "",
             Cutoff = no
         ; RespectLimit = yes, AncestorLimit =< 0 ->
@@ -776,12 +793,11 @@
             ThisHTML = two_id_line_to_html(Pref, Deep, totals_meaningful,
                 ThisLine),
             clique_ancestors_to_html(Pref, Deep, AncestorLimit - 1,
-                RespectLimit, EntryCliquePtr,
-                AncestorHTML, Cutoff),
+                RespectLimit, EntryCliquePtr, AncestorHTML, Cutoff),
             HTML = AncestorHTML ++ ThisHTML
         )
     ;
-        % we have reached the parent of root
+        % We have reached the parent of root.
         HTML = "",
         Cutoff = no
     ).
@@ -819,24 +835,21 @@
         list.map(deep_lookup_pd_desc(Deep), PDPtrs, ProcDescs),
         ProcOwn = sum_own_infos(ProcOwns),
         ProcDesc = sum_inherit_infos(ProcDescs),
-        ProcTotal = proc_total_to_two_id_line(Pref, Deep,
-            yes, "summary ", PSPtr, ProcOwn, ProcDesc),
-        list.map2(
-            proc_in_clique_to_html(Pref, Deep, CliquePtr, Percent),
+        ProcTotal = proc_total_to_two_id_line(Pref, Deep, yes, "summary ",
+            PSPtr, ProcOwn, ProcDesc),
+        list.map2(proc_in_clique_to_html(Pref, Deep, CliquePtr, Percent),
             PDPtrs, ComponentHTMLs, ActionPtrLists),
         list.condense(ActionPtrLists, ActionPtrs),
         string.append_list(ComponentHTMLs, ComponentHTML),
         HTML =
             separator_row(Pref, source_proc, totals_meaningful) ++
-            two_id_line_to_html(Pref, Deep, totals_meaningful,
-                ProcTotal) ++
+            two_id_line_to_html(Pref, Deep, totals_meaningful, ProcTotal) ++
             separator_row(Pref, source_proc, totals_meaningful) ++
             ComponentHTML
     ).
 
 :- pred proc_in_clique_to_html(preferences::in, deep::in, clique_ptr::in,
-    int::in, proc_dynamic_ptr::in, string::out, list(clique_ptr)::out)
-    is det.
+    int::in, proc_dynamic_ptr::in, string::out, list(clique_ptr)::out) is det.
 
 proc_in_clique_to_html(Pref, Deep, CliquePtr, Percent, PDPtr,
         HTML, ActionPtrs) :-
@@ -845,36 +858,30 @@
         deep_lookup_pd_desc(Deep, PDPtr, ProcDesc),
         deep_lookup_proc_dynamics(Deep, PDPtr, PD),
         PSPtr = PD ^ pd_proc_static,
-        ProcTotal = proc_total_to_two_id_line(Pref, Deep,
-            yes, "", PSPtr, ProcOwn, ProcDesc),
+        ProcTotal = proc_total_to_two_id_line(Pref, Deep, yes, "",
+            PSPtr, ProcOwn, ProcDesc),
         child_call_sites(Deep ^ proc_dynamics, Deep ^ proc_statics,
             PDPtr, GroupPairs),
-        ( GroupPairs = [] ->
-            HTML =
-                separator_row(Pref, source_proc,
-                    totals_meaningful) ++
-                two_id_line_to_html(Pref, Deep,
-                    totals_meaningful,ProcTotal),
+        ProcHTML =
+            separator_row(Pref, source_proc, totals_meaningful) ++
+            two_id_line_to_html(Pref, Deep, totals_meaningful, ProcTotal),
+        (
+            GroupPairs = [],
+            HTML = ProcHTML,
             ActionPtrs = []
         ;
-            list.map2(call_site_clique_to_html(Pref, Deep,
-                CliquePtr, Percent),
+            GroupPairs = [_ | _],
+            list.map2(call_site_clique_to_html(Pref, Deep, CliquePtr, Percent),
                 GroupPairs, CallSiteLists, ActionPtrLists),
             list.condense(CallSiteLists, CallSites),
             list.condense(ActionPtrLists, ActionPtrs),
-            SortedCallSites = sort_line_groups(
-                Pref ^ pref_criteria, CallSites),
+            SortedCallSites = sort_line_groups(Pref ^ pref_criteria,
+                CallSites),
             BodyHTMLs = list.map(
-                two_id_line_group_to_html(Pref, Deep,
-                    totals_meaningful),
+                two_id_line_group_to_html(Pref, Deep, totals_meaningful),
                 SortedCallSites),
-            HTML =
-                separator_row(Pref, source_proc,
-                    totals_meaningful) ++
-                two_id_line_to_html(Pref, Deep,
-                    totals_meaningful,ProcTotal) ++
-                separator_row(Pref, source_proc,
-                    totals_meaningful) ++
+            HTML = ProcHTML ++
+                separator_row(Pref, source_proc, totals_meaningful) ++
                 string.append_list(BodyHTMLs)
         )
     ;
@@ -907,7 +914,7 @@
 lookup_proc_total_to_html(Pref, Deep, Bold, Prefix, PSPtr) = LineGroup :-
     deep_lookup_ps_own(Deep, PSPtr, Own),
     not (
-        Pref ^ pref_inactive ^ inactive_procs = hide,
+        Pref ^ pref_inactive ^ inactive_procs = inactive_hide,
         is_inactive(Own)
     ),
     deep_lookup_ps_desc(Deep, PSPtr, Desc),
@@ -961,8 +968,7 @@
         BoldEnd = "</B>"
     ),
     HTML = string.format("<TD CLASS=id COLSPAN=%d>%s%s%s%s</TD>\n",
-        [i(Span), s(BoldStart), s(Prefix),
-        s(WrappedProcName), s(BoldEnd)]).
+        [i(Span), s(BoldStart), s(Prefix), s(WrappedProcName), s(BoldEnd)]).
 
 %-----------------------------------------------------------------------------%
 
@@ -991,9 +997,8 @@
             error("call_site_clique_to_html: non-normal_call error")
         ),
         call_site_context(Deep, CSSPtr, FileName, LineNumber),
-        multi_call_site_clique_to_html(Pref, Deep,
-            FileName, LineNumber, Kind, CallerCliquePtr, CSDPtrs,
-            LineGroups, Percent, ActionPtrs)
+        multi_call_site_clique_to_html(Pref, Deep, FileName, LineNumber,
+            Kind, CallerCliquePtr, CSDPtrs, LineGroups, Percent, ActionPtrs)
     ).
 
 :- func maybe_extract_action_clique(deep, clique_ptr, int,
@@ -1013,9 +1018,9 @@
             CSDOwn = CSD ^ csd_own_prof,
             CSDTotal = add_own_to_inherit(CSDOwn, CSDDesc),
             RootTotal = root_total_info(Deep),
-            CSDQuanta = inherit_quanta(CSDTotal),
-            RootQuanta = inherit_quanta(RootTotal),
-            ( CSDQuanta * 100 > RootQuanta * Percent ->
+            CSDCallSeqs = inherit_callseqs(CSDTotal),
+            RootCallSeqs = inherit_callseqs(RootTotal),
+            ( CSDCallSeqs * 100 > RootCallSeqs * Percent ->
                 ActionPtrs = [CalleeCliquePtr]
             ;
                 ActionPtrs = []
@@ -1062,22 +1067,18 @@
     SummaryHTML =
         string.format("<TD CLASS=id>%s:%d</TD>\n",
             [s(escape_html_string(FileName)), i(LineNumber)]) ++
-        %
+
         % NOTE: we don't escape HTML special characters for
         % 'CallSiteName' because it has already been done.
-        %
-        string.format("<TD CLASS=id>%s</TD>\n",
-            [s(CallSiteName)]),
+        string.format("<TD CLASS=id>%s</TD>\n", [s(CallSiteName)]),
     (
         Pref ^ pref_summarize = summarize,
-        LineGroup = line_group(FileName, LineNumber,
-            RawCallSiteName, Own, Desc, SummaryHTML,
-                sub_lines(two_id, []))
+        LineGroup = line_group(FileName, LineNumber, RawCallSiteName,
+            Own, Desc, SummaryHTML, sub_lines(two_id, []))
     ;
         Pref ^ pref_summarize = dont_summarize,
-        LineGroup = line_group(FileName, LineNumber,
-            RawCallSiteName, Own, Desc, SummaryHTML,
-                sub_lines(two_id, SubLines))
+        LineGroup = line_group(FileName, LineNumber, RawCallSiteName,
+            Own, Desc, SummaryHTML, sub_lines(two_id, SubLines))
     ),
     LineGroups = [LineGroup].
 
@@ -1095,12 +1096,10 @@
     call_site_context(Deep, CSSPtr, FileName, LineNumber),
     ( Kind = normal_call_and_callee(CalleePSPtr, _) ->
         LineGroup0 = normal_call_site_summary_to_html(Pref, Deep,
-            FileName, LineNumber, CallerPSPtr, CalleePSPtr,
-            CallSiteCallList)
+            FileName, LineNumber, CallerPSPtr, CalleePSPtr, CallSiteCallList)
     ;
         LineGroup0 = multi_call_site_summary_to_html(Pref, Deep,
-            FileName, LineNumber, Kind,
-            CallerPSPtr, CallSiteCallList)
+            FileName, LineNumber, Kind, CallerPSPtr, CallSiteCallList)
     ),
     CSSContext = string.format("%s:%d",
         [s(escape_html_string(FileName)), i(LineNumber)]),
@@ -1120,8 +1119,7 @@
         Desc = zero_inherit_prof_info,
         SummaryHTML =
             string.format("<TD CLASS=id>%s</TD>\n",
-                [s(proc_static_to_html_ref(Pref,
-                    Deep, CalleePSPtr))]),
+                [s(proc_static_to_html_ref(Pref, Deep, CalleePSPtr))]),
         LineGroup = line_group(FileName, LineNumber,
             ProcName, Own, Desc, SummaryHTML,
             sub_lines(two_id, []))
@@ -1130,8 +1128,7 @@
         require(unify(CalleePSPtr, CalleePSPtrFromCall),
             "call_site_summary_to_html: callee mismatch"),
         LineGroup0 = call_site_summary_group_to_html(Pref, Deep,
-            FileName, LineNumber, ProcName,
-            CallerPSPtr, CallSiteCall),
+            FileName, LineNumber, ProcName, CallerPSPtr, CallSiteCall),
         LineGroup = line_to_two_id_subline_group(LineGroup0)
     ;
         error("normal_call_site_summary_to_html: too many procedures")
@@ -1151,24 +1148,20 @@
         FileName, LineNumber, RawCallSiteName, CallerPSPtr),
         CallSiteCallList),
     sum_line_group_measurements(SubLines, Own, Desc),
-    %
+
     % NOTE: we don't escape HTML special characters for
     % 'CallSiteName' because it has already been done.
-    %
     SummaryHTML =
-        string.format("<TD CLASS=id>%s</TD>\n",
-            [s(CallSiteName)]),
+        string.format("<TD CLASS=id>%s</TD>\n", [s(CallSiteName)]),
     (
         Pref ^ pref_summarize = summarize,
-        LineGroup = line_group(FileName, LineNumber,
-            RawCallSiteName, Own, Desc, SummaryHTML,
-            sub_lines(two_id, []))
+        LineGroup = line_group(FileName, LineNumber, RawCallSiteName,
+            Own, Desc, SummaryHTML, sub_lines(two_id, []))
     ;
         Pref ^ pref_summarize = dont_summarize,
         ContextSubLines = list.map(add_context(""), SubLines),
-        LineGroup = line_group(FileName, LineNumber,
-            RawCallSiteName, Own, Desc, SummaryHTML,
-            sub_lines(two_id, ContextSubLines))
+        LineGroup = line_group(FileName, LineNumber, RawCallSiteName,
+            Own, Desc, SummaryHTML, sub_lines(two_id, ContextSubLines))
     ).
 
 :- func call_site_summary_group_to_html(preferences, deep,
@@ -1207,11 +1200,9 @@
     inherit_prof_info::in, inherit_prof_info::out) is det.
 
 process_call_site_dynamics_group([], _, _,
-        MaybeCalleeCliquePtr, MaybeCalleeCliquePtr,
-        Own, Own, Desc, Desc).
+        MaybeCalleeCliquePtr, MaybeCalleeCliquePtr, Own, Own, Desc, Desc).
 process_call_site_dynamics_group([CSDPtr | CSDPtrs], Deep, CalleePSPtr,
-        MaybeCalleeCliquePtr0, MaybeCalleeCliquePtr,
-        Own0, Own, Desc0, Desc) :-
+        MaybeCalleeCliquePtr0, MaybeCalleeCliquePtr, Own0, Own, Desc0, Desc) :-
     deep_lookup_call_site_dynamics(Deep, CSDPtr, CSD),
     PDPtr = CSD ^ csd_callee,
     deep_lookup_proc_dynamics(Deep, PDPtr, PD),
@@ -1233,8 +1224,7 @@
     Own1 = add_own_to_own(Own0, CSDOwn),
     Desc1 = add_inherit_to_inherit(Desc0, CSDDesc),
     process_call_site_dynamics_group(CSDPtrs, Deep, CalleePSPtr,
-        MaybeCalleeCliquePtr1, MaybeCalleeCliquePtr,
-        Own1, Own, Desc1, Desc).
+        MaybeCalleeCliquePtr1, MaybeCalleeCliquePtr, Own1, Own, Desc1, Desc).
 
 :- pred accumulate_csd_prof_info(deep::in, proc_static_ptr::in,
     call_site_dynamic_ptr::in,
@@ -1280,8 +1270,7 @@
     Context = string.format("%s:%d", [s(escape_html_string(FileName)),
         i(LineNumber)]),
     HTML = call_to_html(Pref, Deep, CallSiteDisplay, Context,
-        CallerPDPtr, CalleePDPtr,
-        MaybeCallerCliquePtr, CalleeCliquePtr),
+        CallerPDPtr, CalleePDPtr, MaybeCallerCliquePtr, CalleeCliquePtr),
     ProcName = escape_html_string(proc_dynamic_name(Deep, CalleePDPtr)),
     LineGroup = line_group(FileName, LineNumber, ProcName,
         CallSiteOwn, CallSiteDesc, HTML, unit).
@@ -1375,7 +1364,7 @@
     ),
     ChosenCliquePtr = clique_ptr(ChosenCliqueNum),
     WrappedProcName = string.format("<A HREF=""%s"">%s</A>",
-        [s(deep_cmd_pref_to_url(Pref, Deep, clique(ChosenCliqueNum))),
+        [s(deep_cmd_pref_to_url(Pref, Deep, deep_cmd_clique(ChosenCliqueNum))),
         s(escape_html_string(ProcName))]),
     (
         CallSiteDisplay ^ display_wrap = wrap_url_always,
@@ -1448,8 +1437,7 @@
             Deep, Result, !IO),
         (
             Result = ok(ExcludeSpec),
-            CallerCSDPtrPairs = list.map(
-                pair_contour(Deep, ExcludeSpec),
+            CallerCSDPtrPairs = list.map(pair_contour(Deep, ExcludeSpec),
                 CallerCSDPtrs),
             MaybeErrorMsg = no
         ;
@@ -1460,10 +1448,10 @@
     ),
     ProcName = proc_static_name(Deep, PSPtr),
     PSPtr = proc_static_ptr(PSI),
-    CmdSite    = proc_callers(PSI, group_by_call_site, 1),
-    CmdProc    = proc_callers(PSI, group_by_proc, 1),
-    CmdModule  = proc_callers(PSI, group_by_module, 1),
-    CmdClique  = proc_callers(PSI, group_by_clique, 1),
+    CmdSite    = deep_cmd_proc_callers(PSI, group_by_call_site, 1),
+    CmdProc    = deep_cmd_proc_callers(PSI, group_by_proc, 1),
+    CmdModule  = deep_cmd_proc_callers(PSI, group_by_module, 1),
+    CmdClique  = deep_cmd_proc_callers(PSI, group_by_clique, 1),
     LinkSite   = "Group callers by call site",
     LinkProc   = "Group callers by procedure",
     LinkModule = "Group callers by module",
@@ -1476,8 +1464,7 @@
         GroupMap = list.foldl(accumulate_csds_by_call_site(Deep),
             CallerCSDPtrPairs, map.init),
         map.to_assoc_list(GroupMap, GroupList),
-        Lines = list.map(
-            proc_callers_call_site_to_html(Pref, Deep, PSPtr),
+        Lines = list.map(proc_callers_call_site_to_html(Pref, Deep, PSPtr),
             GroupList),
         SortedLines = sort_line_groups(Pref ^ pref_criteria, Lines),
         IdFields = source_proc,
@@ -1497,8 +1484,7 @@
         GroupMap = list.foldl(accumulate_csds_by_procedure(Deep),
             CallerCSDPtrPairs, map.init),
         map.to_assoc_list(GroupMap, GroupList),
-        Lines = list.map(
-            proc_callers_proc_to_html(Pref, Deep, PSPtr),
+        Lines = list.map(proc_callers_proc_to_html(Pref, Deep, PSPtr),
             GroupList),
         SortedLines = sort_line_groups(Pref ^ pref_criteria, Lines),
         IdFields = source_proc,
@@ -1518,11 +1504,9 @@
         GroupMap = list.foldl(accumulate_csds_by_module(Deep),
             CallerCSDPtrPairs, map.init),
         map.to_assoc_list(GroupMap, GroupList),
-        RawLines = list.map(
-            proc_callers_module_to_html(Pref, Deep, PSPtr),
+        RawLines = list.map(proc_callers_module_to_html(Pref, Deep, PSPtr),
             GroupList),
-        SortedRawLines = sort_line_groups(Pref ^ pref_criteria,
-            RawLines),
+        SortedRawLines = sort_line_groups(Pref ^ pref_criteria, RawLines),
         SortedLines = add_ranks(SortedRawLines),
         IdFields = rank_module,
         Entity = "module",
@@ -1541,11 +1525,9 @@
         GroupMap = list.foldl(accumulate_csds_by_clique(Deep),
             CallerCSDPtrPairs, map.init),
         map.to_assoc_list(GroupMap, GroupList),
-        RawLines = list.map(
-            proc_callers_clique_to_html(Pref, Deep, PSPtr),
+        RawLines = list.map(proc_callers_clique_to_html(Pref, Deep, PSPtr),
             GroupList),
-        SortedRawLines = sort_line_groups(Pref ^ pref_criteria,
-            RawLines),
+        SortedRawLines = sort_line_groups(Pref ^ pref_criteria, RawLines),
         SortedLines = add_ranks(SortedRawLines),
         IdFields = source_proc,
         Entity = "clique",
@@ -1574,32 +1556,29 @@
         DisplayedLines),
     HTML = string.append_list(DisplayedHTMLs),
     ( BunchNum > 1 ->
-        FirstCmd = proc_callers(PSI, CallerGroups, 1),
+        FirstCmd = deep_cmd_proc_callers(PSI, CallerGroups, 1),
         FirstLink = "First group",
         FirstToggle =
             string.format("<A HREF=""%s"">%s</A>\n",
-                [s(deep_cmd_pref_to_url(Pref, Deep, FirstCmd)),
-                s(FirstLink)])
+                [s(deep_cmd_pref_to_url(Pref, Deep, FirstCmd)), s(FirstLink)])
     ;
         FirstToggle = ""
     ),
     ( BunchNum > 2 ->
-        PrevCmd = proc_callers(PSI, CallerGroups, BunchNum - 1),
+        PrevCmd = deep_cmd_proc_callers(PSI, CallerGroups, BunchNum - 1),
         PrevLink = "Previous group",
         PrevToggle =
             string.format("<A HREF=""%s"">%s</A>\n",
-                [s(deep_cmd_pref_to_url(Pref, Deep, PrevCmd)),
-                s(PrevLink)])
+                [s(deep_cmd_pref_to_url(Pref, Deep, PrevCmd)), s(PrevLink)])
     ;
         PrevToggle = ""
     ),
     ( NumLines > BunchNum * BunchSize ->
-        NextCmd = proc_callers(PSI, CallerGroups, BunchNum + 1),
+        NextCmd = deep_cmd_proc_callers(PSI, CallerGroups, BunchNum + 1),
         NextLink = "Next group",
         NextToggle =
             string.format("<A HREF=""%s"">%s</A>\n",
-                [s(deep_cmd_pref_to_url(Pref, Deep, NextCmd)),
-                s(NextLink)])
+                [s(deep_cmd_pref_to_url(Pref, Deep, NextCmd)), s(NextLink)])
     ;
         NextToggle = ""
     ),
@@ -1641,7 +1620,7 @@
 
 proc_callers_banner(PSI, ProcName, Pref, Deep, NumLines, BunchSize, BunchNum,
         Parent) = HTML :-
-    Cmd = proc(PSI),
+    Cmd = deep_cmd_proc(PSI),
     WrappedProcName = string.format("<A HREF=""%s"">%s</A>",
         [s(deep_cmd_pref_to_url(Pref, Deep, Cmd)),
             s(escape_html_string(ProcName))]),
@@ -1657,8 +1636,7 @@
     ; BunchNum = 1 ->
         HTML = string.format(
             "<H3>There are %d %ss calling %s, showing first %d:</H3>",
-            [i(NumLines), s(Parent), s(WrappedProcName),
-            i(BunchSize)])
+            [i(NumLines), s(Parent), s(WrappedProcName), i(BunchSize)])
     ;
         First = (BunchNum - 1) * BunchSize + 1,
         Last0 = (BunchNum) * BunchSize,
@@ -1669,8 +1647,7 @@
         ),
         HTML = string.format(
             "<H3>There are %d %ss calling %s, showing %d to %d:</H3>",
-            [i(NumLines), s(Parent), s(WrappedProcName),
-            i(First), i(Last)])
+            [i(NumLines), s(Parent), s(WrappedProcName), i(First), i(Last)])
     ).
 
 :- func proc_callers_call_site_to_html(preferences, deep, proc_static_ptr,
@@ -1683,15 +1660,13 @@
     CallerPSPtr = CSS ^ css_container,
     deep_lookup_proc_statics(Deep, CallerPSPtr, CallerPS),
     CallerProcName = CallerPS ^ ps_refined_id,
-    list.foldl2(accumulate_parent_csd_prof_info(Deep, CalleePSPtr),
-        CSDPtrs,
+    list.foldl2(accumulate_parent_csd_prof_info(Deep, CalleePSPtr), CSDPtrs,
         zero_own_prof_info, Own, zero_inherit_prof_info, Desc),
     HTML =
         string.format("<TD CLASS=id>%s:%d</TD>\n",
             [s(FileName), i(LineNumber)]) ++
         string.format("<TD CLASS=id>%s</TD>\n",
-            [s(proc_static_to_html_ref(Pref, Deep,
-                CallerPSPtr))]),
+            [s(proc_static_to_html_ref(Pref, Deep, CallerPSPtr))]),
     LineGroup = line_group(FileName, LineNumber, CallerProcName,
         Own, Desc, HTML, unit).
 
@@ -1703,15 +1678,13 @@
     proc_static_context(Deep, CallerPSPtr, FileName, LineNumber),
     deep_lookup_proc_statics(Deep, CallerPSPtr, CallerPS),
     CallerProcName = CallerPS ^ ps_refined_id,
-    list.foldl2(accumulate_parent_csd_prof_info(Deep, CalleePSPtr),
-        CSDPtrs,
+    list.foldl2(accumulate_parent_csd_prof_info(Deep, CalleePSPtr), CSDPtrs,
         zero_own_prof_info, Own, zero_inherit_prof_info, Desc),
     HTML =
         string.format("<TD CLASS=id>%s:%d</TD>\n",
             [s(FileName), i(LineNumber)]) ++
         string.format("<TD CLASS=id>%s</TD>\n",
-            [s(proc_static_to_html_ref(Pref, Deep,
-                CallerPSPtr))]),
+            [s(proc_static_to_html_ref(Pref, Deep, CallerPSPtr))]),
     LineGroup = line_group(FileName, LineNumber, CallerProcName,
         Own, Desc, HTML, unit).
 
@@ -1720,8 +1693,7 @@
 
 proc_callers_module_to_html(Pref, Deep, CalleePSPtr, ModuleName - CSDPtrs)
         = LineGroup :-
-    list.foldl2(accumulate_parent_csd_prof_info(Deep, CalleePSPtr),
-        CSDPtrs,
+    list.foldl2(accumulate_parent_csd_prof_info(Deep, CalleePSPtr), CSDPtrs,
         zero_own_prof_info, Own, zero_inherit_prof_info, Desc),
     HTML = string.format("<TD CLASS=id>%s</TD>\n",
         [s(module_name_to_html_ref(Pref, Deep, ModuleName))]),
@@ -1735,8 +1707,7 @@
 
 proc_callers_clique_to_html(Pref, Deep, CalleePSPtr, CliquePtr - CSDPtrs)
         = LineGroup :-
-    list.foldl2(accumulate_parent_csd_prof_info(Deep, CalleePSPtr),
-        CSDPtrs,
+    list.foldl2(accumulate_parent_csd_prof_info(Deep, CalleePSPtr), CSDPtrs,
         zero_own_prof_info, Own, zero_inherit_prof_info, Desc),
     deep_lookup_clique_parents(Deep, CliquePtr, EntryCSDPtr),
     deep_lookup_call_site_dynamics(Deep, EntryCSDPtr, EntryCSD),
@@ -1785,8 +1756,7 @@
     deep_lookup_proc_statics(Deep, GroupPSPtr, GroupPS),
     GroupModuleName = GroupPS ^ ps_decl_module,
     ( map.search(Map0, GroupModuleName, CostCSDPtrs0) ->
-        map.det_update(Map0, GroupModuleName, [CostCSDPtr | CostCSDPtrs0],
-            Map)
+        map.det_update(Map0, GroupModuleName, [CostCSDPtr | CostCSDPtrs0], Map)
     ;
         map.det_insert(Map0, GroupModuleName, [CostCSDPtr], Map)
     ).
@@ -1823,10 +1793,8 @@
         add_own_to_own(Own0, CSDOwn) = Own,
         add_inherit_to_inherit(Desc0, CSDDesc) = Desc1,
 
-        deep_lookup_clique_index(Deep, CSD ^ csd_callee,
-            CalleeCliquePtr),
-        deep_lookup_clique_members(Deep, CalleeCliquePtr,
-            CalleeCliquePDPtrs),
+        deep_lookup_clique_index(Deep, CSD ^ csd_callee, CalleeCliquePtr),
+        deep_lookup_clique_members(Deep, CalleeCliquePtr, CalleeCliquePDPtrs),
         list.foldl(compensate_using_comp_table(Deep, CallerPSPtr),
             CalleeCliquePDPtrs, Desc1, Desc)
     ).
@@ -1888,13 +1856,13 @@
 proc_summary_toggles_to_html(Pref, Deep, PSPtr) = HTML :-
     PSPtr = proc_static_ptr(PSI),
     Msg1 = "Parent call sites",
-    Cmd1 = proc_callers(PSI, group_by_call_site, 1),
+    Cmd1 = deep_cmd_proc_callers(PSI, group_by_call_site, 1),
     Msg2 = "Parent procedures",
-    Cmd2 = proc_callers(PSI, group_by_proc, 1),
+    Cmd2 = deep_cmd_proc_callers(PSI, group_by_proc, 1),
     Msg3 = "Parent modules",
-    Cmd3 = proc_callers(PSI, group_by_module, 1),
+    Cmd3 = deep_cmd_proc_callers(PSI, group_by_module, 1),
     Msg4 = "Parent cliques",
-    Cmd4 = proc_callers(PSI, group_by_clique, 1),
+    Cmd4 = deep_cmd_proc_callers(PSI, group_by_clique, 1),
     Link1 = string.format("<A HREF=""%s"">%s</A>\n",
         [s(deep_cmd_pref_to_url(Pref, Deep, Cmd1)), s(Msg1)]),
     Link2 = string.format("<A HREF=""%s"">%s</A>\n",
@@ -1916,7 +1884,7 @@
 
 wrap_clique_links(CliquePtr, Pref0, Deep, Str0, Criteria) = Str :-
     CliquePtr = clique_ptr(CI),
-    Cmd = clique(CI),
+    Cmd = deep_cmd_clique(CI),
     Pref = Pref0 ^ pref_criteria := Criteria,
     URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
     Str = string.format("<A HREF=%s>%s</A>",
@@ -1927,7 +1895,7 @@
 
 wrap_proc_links(PSPtr, Pref0, Deep, Str0, Criteria) = Str :-
     PSPtr = proc_static_ptr(PSI),
-    Cmd = proc(PSI),
+    Cmd = deep_cmd_proc(PSI),
     Pref = Pref0 ^ pref_criteria := Criteria,
     URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
     Str = string.format("<A HREF=%s>%s</A>",
@@ -1939,7 +1907,7 @@
 wrap_proc_callers_links(PSPtr, CallerGroups, BunchNum, Pref0, Deep,
         Str0, Criteria) = Str :-
     PSPtr = proc_static_ptr(PSI),
-    Cmd = proc_callers(PSI, CallerGroups, BunchNum),
+    Cmd = deep_cmd_proc_callers(PSI, CallerGroups, BunchNum),
     Pref = Pref0 ^ pref_criteria := Criteria,
     URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
     Str = string.format("<A HREF=%s>%s</A>",
@@ -1949,7 +1917,7 @@
     order_criteria) = string.
 
 wrap_module_links(ModuleName, Pref0, Deep, Str0, Criteria) = Str :-
-    Cmd = module(ModuleName),
+    Cmd = deep_cmd_module(ModuleName),
     Pref = Pref0 ^ pref_criteria := Criteria,
     URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
     Str = string.format("<A HREF=%s>%s</A>",
@@ -1958,7 +1926,7 @@
 :- func wrap_modules_links(preferences, deep, string, order_criteria) = string.
 
 wrap_modules_links(Pref0, Deep, Str0, Criteria) = Str :-
-    Cmd = modules,
+    Cmd = deep_cmd_modules,
     Pref = Pref0 ^ pref_criteria := Criteria,
     URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
     Str = string.format("<A HREF=%s>%s</A>",
@@ -1976,7 +1944,7 @@
         Str = Str0
     ;
         Criteria = by_cost(CostKind, InclDesc, Scope),
-        Cmd = top_procs(Limit, CostKind, InclDesc, Scope),
+        Cmd = deep_cmd_top_procs(Limit, CostKind, InclDesc, Scope),
         URL = deep_cmd_pref_to_url(Pref, Deep, Cmd),
         Str = string.format("<A HREF=%s>%s</A>",
             [s(URL), s(escape_html_string(Str0))])
Index: read_profile.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/read_profile.m,v
retrieving revision 1.18
diff -u -b -r1.18 read_profile.m
--- read_profile.m	9 Oct 2006 08:09:04 -0000	1.18
+++ read_profile.m	11 Oct 2006 03:49:04 -0000
@@ -132,7 +132,7 @@
 % This must the same string as the one written by MR_write_out_id_string
 % in runtime/mercury_deep_profiling.c.
 
-id_string = "Mercury deep profiler data version 2\n".
+id_string = "Mercury deep profiler data version 3\n".
 
 :- func init_deep(int, int, int, int, int, int, int, int, int, int, int)
     = initial_deep.
@@ -239,7 +239,7 @@
     io::di, io::uo) is det.
 
 read_call_site_static(Res, !IO) :-
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("reading call_site_static.\n", !IO)
     ),
     io_combinator.maybe_error_sequence_4(
@@ -259,7 +259,7 @@
     (
         Res1 = ok({CallSiteStatic, CSSI}),
         Res = ok2(CallSiteStatic, CSSI),
-        trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+        trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
             io.write_string("read call_site_static ", !IO),
             io.write_int(CSSI, !IO),
             io.write_string(": ", !IO),
@@ -276,7 +276,7 @@
     io::di, io::uo) is det.
 
 read_proc_static(Res, !IO) :-
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("reading proc_static.\n", !IO)
     ),
     io_combinator.maybe_error_sequence_6(
@@ -313,7 +313,7 @@
                 RefinedStr, RawStr, FileName, LineNumber,
                 IsInInterface, array(CSSPtrs), not_zeroed),
             Res = ok2(ProcStatic, PSI),
-            trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+            trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
                 io.write_string("read proc_static ", !IO),
                 io.write_int(PSI, !IO),
                 io.write_string(": ", !IO),
@@ -536,7 +536,7 @@
     io::di, io::uo) is det.
 
 read_proc_dynamic(Res, !IO) :-
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("reading proc_dynamic.\n", !IO)
     ),
     io_combinator.maybe_error_sequence_3(
@@ -555,7 +555,7 @@
             PSPtr = make_psptr(PSI),
             ProcDynamic = proc_dynamic(PSPtr, array(Refs)),
             Res = ok2(ProcDynamic, PDI),
-            trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+            trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
                 io.write_string("read proc_dynamic ", !IO),
                 io.write_int(PDI, !IO),
                 io.write_string(": ", !IO),
@@ -575,7 +575,7 @@
     io::di, io::uo) is det.
 
 read_call_site_dynamic(Res, !IO) :-
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("reading call_site_dynamic.\n", !IO)
     ),
     read_ptr(csd, Res1, !IO),
@@ -592,7 +592,7 @@
                 CallSiteDynamic = call_site_dynamic(
                     CallerPDPtr, PDPtr, Profile),
                 Res = ok2(CallSiteDynamic, CSDI),
-                trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+                trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
                     io.write_string("read call_site_dynamic ", !IO),
                     io.write_int(CSDI, !IO),
                     io.write_string(": ", !IO),
@@ -684,7 +684,7 @@
     io::di, io::uo) is det.
 
 read_call_site_slot(Res, !IO) :-
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("reading call_site_slot.\n", !IO)
     ),
     read_call_site_kind(Res1, !IO),
@@ -696,7 +696,7 @@
                 Res2 = ok(CSDI),
                 CSDPtr = make_csdptr(CSDI),
                 Res = ok(slot_normal(CSDPtr)),
-                trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+                trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
                     io.write_string("normal call_site slot ", !IO),
                     io.write_int(CSDI, !IO),
                     io.write_string("\n", !IO)
@@ -720,7 +720,7 @@
                 Res2 = ok(CSDIs),
                 CSDPtrs = list.map(make_csdptr, CSDIs),
                 Res = ok(slot_multi(Zeroed, array(CSDPtrs))),
-                trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+                trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
                     io.write_string("multi call_site slots ", !IO),
                     io.write(CSDIs, !IO),
                     io.write_string("\n", !IO)
@@ -755,7 +755,7 @@
     maybe_error(list(int))::out, io::di, io::uo) is det.
 
 read_multi_call_site_csdis_2(CSDIs0, Res, !IO) :-
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.format("reading multi_call_site_csdi.\n", [], !IO)
     ),
     read_deep_byte(Res0, !IO),
@@ -801,7 +801,7 @@
                 [i(Byte)], Msg),
             Res = error(Msg)
         ),
-        trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+        trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
              io.write_string("call_site_kind ", !IO),
              io.write(Res, !IO),
              io.write_string("\n", !IO)
@@ -848,7 +848,7 @@
             format("unexpected call_site_kind %d", [i(Byte)], Msg),
             Res = error(Msg)
         ),
-        trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+        trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
             io.write_string("call_site_kind_and_callee ", !IO),
             io.write(Res, !IO),
             io.write_string("\n", !IO)
@@ -932,7 +932,7 @@
         Res1 = error(Err),
         Res = error(Err)
     ),
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("string ", !IO),
         io.write(Res, !IO),
         io.write_string("\n", !IO)
@@ -942,7 +942,7 @@
 
 read_ptr(_Kind, Res, !IO) :-
     read_num1(0, Res, !IO),
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("ptr ", !IO),
         io.write(Res, !IO),
         io.write_string("\n", !IO)
@@ -952,7 +952,7 @@
 
 read_num(Res, !IO) :-
     read_num1(0, Res, !IO),
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("num ", !IO),
         io.write(Res, !IO),
         io.write_string("\n", !IO)
@@ -1047,7 +1047,7 @@
 
 read_deep_byte(Res, !IO) :-
     read_byte(Res0, !IO),
-    trace [ compile_time(flag("debug_read_profdeep")), io(!IO) ] (
+    trace [compile_time(flag("debug_read_profdeep")), io(!IO)] (
         io.write_string("byte ", !IO),
         io.write(Res, !IO),
         io.write_string("\n", !IO)
Index: startup.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/startup.m,v
retrieving revision 1.13
diff -u -b -r1.13 startup.m
--- startup.m	29 Sep 2006 06:15:11 -0000	1.13
+++ startup.m	11 Oct 2006 03:49:04 -0000
@@ -12,6 +12,7 @@
 % read_profile.m into the data structure that mdprof_cgi.m needs to service
 % requests for web pages. The algorithm it implements is documented in the
 % deep profiling paper.
+%
 %-----------------------------------------------------------------------------%
 
 :- module startup.
@@ -28,8 +29,8 @@
 %-----------------------------------------------------------------------------%
 
 :- pred read_and_startup(string::in, list(string)::in, bool::in,
-    maybe(io.output_stream)::in, list(string)::in, maybe_error(deep)::out,
-    io::di, io::uo) is det.
+    maybe(io.output_stream)::in, list(string)::in, list(string)::in,
+    maybe_error(deep)::out, io::di, io::uo) is det.
 
 %-----------------------------------------------------------------------------%
 %-----------------------------------------------------------------------------%
@@ -54,12 +55,10 @@
 :- import_module svarray.
 :- import_module svmap.
 
-% :- import_module unsafe.
-
 %-----------------------------------------------------------------------------%
 
 read_and_startup(Machine, DataFileNames, Canonical, MaybeOutputStream,
-    DumpStages, Res, !IO) :-
+        DumpStages, DumpOptions, Res, !IO) :-
     (
         DataFileNames = [],
         % This should have been caught and reported by main.
@@ -76,7 +75,7 @@
         (
             Res0 = ok(InitDeep),
             startup(Machine, DataFileName, Canonical, MaybeOutputStream,
-                DumpStages, InitDeep, Deep, !IO),
+                DumpStages, DumpOptions, InitDeep, Deep, !IO),
             Res = ok(Deep)
         ;
             Res0 = error(Error),
@@ -84,19 +83,19 @@
         )
     ;
         DataFileNames = [_, _ | _],
-        error("mdprof_server: merging of data files " ++
-            "is not yet implemented")
+        error("mdprof_server: merging of data files is not yet implemented")
     ).
 
 :- pred startup(string::in, string::in, bool::in, maybe(io.output_stream)::in,
-    list(string)::in, initial_deep::in, deep::out, io::di, io::uo) is det.
+    list(string)::in, list(string)::in, initial_deep::in, deep::out,
+    io::di, io::uo) is det.
 
-startup(Machine, DataFileName, Canonical, MaybeOutputStream, DumpStages,
-        InitDeep0, Deep, !IO) :-
+startup(Machine, DataFileName, Canonical, MaybeOutputStream,
+        DumpStages, DumpOptions, InitDeep0, Deep, !IO) :-
     InitDeep0 = initial_deep(InitStats, Root,
         CallSiteDynamics0, ProcDynamics, CallSiteStatics0, ProcStatics0),
     maybe_dump(DataFileName, DumpStages, 0,
-        dump_initial_deep(yes, no, yes, yes, yes, yes, InitDeep0), !IO),
+        dump_initial_deep(InitDeep0, DumpOptions), !IO),
 
     maybe_report_msg(MaybeOutputStream,
         "% Mapping static call sites to containing procedures...\n", !IO),
@@ -117,7 +116,7 @@
     InitDeep1 = initial_deep(InitStats, Root,
         CallSiteDynamics, ProcDynamics, CallSiteStatics, ProcStatics),
     maybe_dump(DataFileName, DumpStages, 10,
-        dump_initial_deep(yes, no, yes, yes, yes, yes, InitDeep1), !IO),
+        dump_initial_deep(InitDeep1, DumpOptions), !IO),
     (
         Canonical = no,
         InitDeep = InitDeep1
@@ -131,7 +130,7 @@
         maybe_report_stats(MaybeOutputStream, !IO)
     ),
     maybe_dump(DataFileName, DumpStages, 20,
-        dump_initial_deep(yes, no, yes, yes, yes, yes, InitDeep), !IO),
+        dump_initial_deep(InitDeep, DumpOptions), !IO),
 
     array.max(InitDeep ^ init_proc_dynamics, PDMax),
     NPDs = PDMax + 1,
@@ -159,13 +158,12 @@
     maybe_report_msg(MaybeOutputStream,
         "% Constructing clique parent map...\n", !IO),
 
-        % For each CallSiteDynamic pointer, if it points to
-        % a ProcDynamic which is in a different clique to
-        % the one from which the CallSiteDynamic's parent
-        % came, then this CallSiteDynamic is the entry to
-        % the [lower] clique. We need to compute this information
-        % so that we can print clique-based timing summaries in
-        % the browser.
+    % For each CallSiteDynamic pointer, if it points to a ProcDynamic
+    % which is in a different clique to the one from which the
+    % CallSiteDynamic's parent came, then this CallSiteDynamic is the entry to
+    % the [lower] clique. We need to compute this information so that
+    % we can print clique-based timing summaries in the browser.
+
     array.max(Cliques, CliqueMax),
     NCliques = CliqueMax + 1,
     array.init(NCliques, call_site_dynamic_ptr(-1), CliqueParents0),
@@ -207,7 +205,7 @@
     maybe_report_stats(MaybeOutputStream, !IO),
 
     maybe_report_msg(MaybeOutputStream,
-        "% Propagating time up call graph...\n", !IO),
+        "% Propagating measurements up call graph...\n", !IO),
 
     array.init(NCSDs, zero_inherit_prof_info, CSDDesc0),
     array.init(NPDs, zero_own_prof_info, PDOwn0),
@@ -230,11 +228,17 @@
         PSOwn0, PSDesc0, CSSOwn0, CSSDesc0,
         PDCompTable0, CSDCompTable0, ModuleData),
 
+    maybe_dump(DataFileName, DumpStages, 30,
+        dump_deep(Deep0, DumpOptions), !IO),
+
     array_foldl_from_1(propagate_to_clique, Cliques, Deep0, Deep1),
     maybe_report_msg(MaybeOutputStream,
         "% Done.\n", !IO),
     maybe_report_stats(MaybeOutputStream, !IO),
 
+    maybe_dump(DataFileName, DumpStages, 40,
+        dump_deep(Deep1, DumpOptions), !IO),
+
     maybe_report_msg(MaybeOutputStream,
         "% Summarizing information...\n", !IO),
     summarize_proc_dynamics(Deep1, Deep2),
@@ -242,7 +246,10 @@
     summarize_modules(Deep3, Deep),
     maybe_report_msg(MaybeOutputStream,
         "% Done.\n", !IO),
-    maybe_report_stats(MaybeOutputStream, !IO).
+    maybe_report_stats(MaybeOutputStream, !IO),
+
+    maybe_dump(DataFileName, DumpStages, 50,
+        dump_deep(Deep, DumpOptions), !IO).
 
 :- pred count_quanta(int::in, call_site_dynamic::in, int::in, int::out) is det.
 
@@ -259,13 +266,20 @@
 
 maybe_dump(BaseName, DumpStages, ThisStageNum, Action, !IO) :-
     string.int_to_string(ThisStageNum, ThisStage),
-    ( list.member(ThisStage, DumpStages) ->
+    (
+        (
+            list.member("all", DumpStages)
+        ;
+            list.member(ThisStage, DumpStages)
+        )
+    ->
         string.append_list([BaseName, ".deepdump.", ThisStage], FileName),
         io.open_output(FileName, OpenRes, !IO),
         (
             OpenRes = ok(FileStream),
             io.set_output_stream(FileStream, CurStream, !IO),
             Action(!IO),
+            io.close_output(FileStream, !IO),
             io.set_output_stream(CurStream, _, !IO)
         ;
             OpenRes = error(Error),
@@ -707,8 +721,8 @@
 
 propagate_to_clique(CliqueNumber, Members, !Deep) :-
     array.lookup(!.Deep ^ clique_parents, CliqueNumber, ParentCSDPtr),
-    list.foldl3(propagate_to_proc_dynamic(CliqueNumber, ParentCSDPtr),
-        Members, !Deep, map.init, SumTable, map.init, OverrideMap),
+    list.foldl3(propagate_to_proc_dynamic(CliqueNumber, ParentCSDPtr), Members,
+        !Deep, map.init, SumTable, map.init, OverrideMap),
     ( valid_call_site_dynamic_ptr(!.Deep, ParentCSDPtr) ->
         deep_lookup_call_site_dynamics(!.Deep, ParentCSDPtr, ParentCSD),
         ParentOwn = ParentCSD ^ csd_own_prof,
@@ -765,7 +779,10 @@
     CalleePDPtr = CSD ^ csd_callee,
     deep_lookup_clique_index(!.Deep, CalleePDPtr, ChildCliquePtr),
     ChildCliquePtr = clique_ptr(ChildCliqueNumber),
-    ( ChildCliqueNumber \= CliqueNumber ->
+    ( ChildCliqueNumber = CliqueNumber ->
+        % We don't propagate profiling measurements along intra-clique calls.
+        true
+    ;
         deep_lookup_pd_desc(!.Deep, PDPtr, ProcDesc0),
         deep_lookup_csd_desc(!.Deep, CSDPtr, CalleeDesc),
         CalleeTotal = add_own_to_inherit(CalleeOwn, CalleeDesc),
@@ -773,10 +790,6 @@
         deep_update_pd_desc(PDPtr, ProcDesc, !Deep),
         deep_lookup_csd_comp_table(!.Deep, CSDPtr, CSDCompTable),
         !:PDCompTable = add_comp_tables(!.PDCompTable, CSDCompTable)
-    ;
-        % We don't propagate profiling measurements
-        % along intra-clique calls.
-        true
     ).
 
 %-----------------------------------------------------------------------------%
Index: timeout.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/timeout.m,v
retrieving revision 1.15
diff -u -b -r1.15 timeout.m
--- timeout.m	9 Mar 2006 04:56:41 -0000	1.15
+++ timeout.m	11 Oct 2006 03:49:04 -0000
@@ -387,8 +387,9 @@
     (void) closedir(dir);
 
     /*
-    ** This call will delete the mutex file last, releasing the mutex
+    ** This call will delete the mutex file last, releasing the mutex.
     */
+
     MP_delete_cleanup_files();
     exit(EXIT_SUCCESS);
 }
@@ -461,10 +462,32 @@
 
     res = open(mutex_file, O_CREAT | O_EXCL, 0);
     if (res >= 0) {
+#ifdef  MP_DEBUG_LOCKS
+        FILE    *debug_fp;
+
+        debug_fp = fopen(""/tmp/deep_locks"", ""a"");
+        if (debug_fp != NULL) {
+            fprintf(debug_fp, ""pid %d try: lock %s\\n"",
+                getpid(), mutex_file);
+            fclose(debug_fp);
+        }
+#endif
+
         (void) close(res);
         MP_register_cleanup_file(mutex_file);
         success = MR_TRUE;
     } else if (res < 0 && errno == EEXIST) {
+#ifdef  MP_DEBUG_LOCKS
+        FILE    *debug_fp;
+
+        debug_fp = fopen(""/tmp/deep_locks"", ""a"");
+        if (debug_fp != NULL) {
+            fprintf(debug_fp, ""pid %d try: no lock %s\\n"",
+                getpid(), mutex_file);
+            fclose(debug_fp);
+        }
+#endif
+
         success = MR_FALSE;
     } else {
         MR_fatal_error(""MP_do_try_get_lock failed"");
@@ -481,10 +504,32 @@
     for (;;) {
         res = open(mutex_file, O_CREAT | O_EXCL, 0);
         if (res >= 0) {
+#ifdef  MP_DEBUG_LOCKS
+            FILE    *debug_fp;
+
+            debug_fp = fopen(""/tmp/deep_locks"", ""a"");
+            if (debug_fp != NULL) {
+                fprintf(debug_fp, ""pid %d got lock %s\\n"",
+                    getpid(), mutex_file);
+                fclose(debug_fp);
+            }
+#endif
+
             (void) close(res);
             MP_register_cleanup_file(mutex_file);
             return;
         } else if (res < 0 && errno == EEXIST) {
+#ifdef  MP_DEBUG_LOCKS
+            FILE    *debug_fp;
+
+            debug_fp = fopen(""/tmp/deep_locks"", ""a"");
+            if (debug_fp != NULL) {
+                fprintf(debug_fp, ""pid %d trying to lock %s ...\\n"",
+                    getpid(), mutex_file);
+                fclose(debug_fp);
+            }
+#endif
+
             sleep(5);
             continue;
         } else {
@@ -496,6 +541,17 @@
 void
 MP_do_release_lock(const char *mutex_file)
 {
+#ifdef  MP_DEBUG_LOCKS
+    FILE    *debug_fp;
+
+    debug_fp = fopen(""/tmp/deep_locks"", ""a"");
+    if (debug_fp != NULL) {
+        fprintf(debug_fp, ""pid %d releasing lock %s\\n"",
+            getpid(), mutex_file);
+        fclose(debug_fp);
+    }
+#endif
+
     MP_unregister_cleanup_file(mutex_file);
     (void) unlink(mutex_file);
 }
@@ -552,8 +608,7 @@
 ").
 
 :- pragma foreign_proc("C",
-    setup_signals(MutexFile::in, WantDir::in, WantPrefix::in,
-        S0::di, S::uo),
+    setup_signals(MutexFile::in, WantDir::in, WantPrefix::in, S0::di, S::uo),
     [will_not_call_mercury, promise_pure],
 "
 #ifdef  MR_DEEP_PROFILER_ENABLED
@@ -630,8 +685,7 @@
 #endif
 ").
 
-:- pred do_release_lock(string::in, io::di, io::uo)
-    is det.
+:- pred do_release_lock(string::in, io::di, io::uo) is det.
 
 :- pragma foreign_proc("C",
     do_release_lock(MutexFile::in, S0::di, S::uo),
Index: top_procs.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/deep_profiler/top_procs.m,v
retrieving revision 1.8
diff -u -b -r1.8 top_procs.m
--- top_procs.m	29 Mar 2006 08:07:41 -0000	1.8
+++ top_procs.m	11 Oct 2006 03:49:04 -0000
@@ -127,8 +127,7 @@
         ( Result1 \= (=) ->
             Result = Result1
         ;
-            Result = compare_ps_words_both_overall(Deep,
-                PSI1, PSI2)
+            Result = compare_ps_words_both_overall(Deep, PSI1, PSI2)
         )
     ).
 
@@ -146,61 +145,93 @@
     compare_proc_statics::out(func(in, in, in) = out is det),
     pred(deep, int)::out(pred(in, in) is semidet)) is det.
 
-find_top_sort_predicate(calls,  self,          overall,  yes,
+find_top_sort_predicate(cost_calls,  self,          overall,  yes,
     compare_ps_calls_self_overall,  filter_ps_calls_self).
-find_top_sort_predicate(calls,  self,          per_call, no,
+find_top_sort_predicate(cost_calls,  self,          per_call, no,
     compare_ps_calls_self_overall,  filter_ps_calls_self).
-find_top_sort_predicate(calls,  self_and_desc, overall,  no,
+find_top_sort_predicate(cost_calls,  self_and_desc, overall,  no,
     compare_ps_calls_self_overall,  filter_ps_calls_self).
-find_top_sort_predicate(calls,  self_and_desc, per_call, no,
+find_top_sort_predicate(cost_calls,  self_and_desc, per_call, no,
     compare_ps_calls_self_overall,  filter_ps_calls_self).
-find_top_sort_predicate(redos,  self,          overall,  yes,
+
+find_top_sort_predicate(cost_redos,  self,          overall,  yes,
     compare_ps_redos_self_overall,  filter_ps_redos_self).
-find_top_sort_predicate(redos,  self,          per_call, no,
+find_top_sort_predicate(cost_redos,  self,          per_call, no,
     compare_ps_redos_self_overall,  filter_ps_redos_self).
-find_top_sort_predicate(redos,  self_and_desc, overall,  no,
+find_top_sort_predicate(cost_redos,  self_and_desc, overall,  no,
     compare_ps_redos_self_overall,  filter_ps_redos_self).
-find_top_sort_predicate(redos,  self_and_desc, per_call, no,
+find_top_sort_predicate(cost_redos,  self_and_desc, per_call, no,
     compare_ps_redos_self_overall,  filter_ps_redos_self).
-find_top_sort_predicate(time,   self,          overall,  yes,
+
+find_top_sort_predicate(cost_time,   self,          overall,  yes,
     compare_ps_time_self_overall,   filter_ps_time_self).
-find_top_sort_predicate(time,   self,          per_call, yes,
+find_top_sort_predicate(cost_time,   self,          per_call, yes,
     compare_ps_time_self_percall,   filter_ps_time_self).
-find_top_sort_predicate(time,   self_and_desc, overall,  yes,
+find_top_sort_predicate(cost_time,   self_and_desc, overall,  yes,
     compare_ps_time_both_overall,   filter_ps_time_both).
-find_top_sort_predicate(time,   self_and_desc, per_call, yes,
+find_top_sort_predicate(cost_time,   self_and_desc, per_call, yes,
     compare_ps_time_both_percall,   filter_ps_time_both).
-find_top_sort_predicate(allocs, self,          overall,  yes,
+
+find_top_sort_predicate(cost_callseqs, self,          overall,  yes,
+    compare_ps_callseqs_self_overall, filter_ps_callseqs_self).
+find_top_sort_predicate(cost_callseqs, self,          per_call, yes,
+    compare_ps_callseqs_self_percall, filter_ps_callseqs_self).
+find_top_sort_predicate(cost_callseqs, self_and_desc, overall,  yes,
+    compare_ps_callseqs_both_overall, filter_ps_callseqs_both).
+find_top_sort_predicate(cost_callseqs, self_and_desc, per_call, yes,
+    compare_ps_callseqs_both_percall, filter_ps_callseqs_both).
+
+find_top_sort_predicate(cost_allocs, self,          overall,  yes,
     compare_ps_allocs_self_overall, filter_ps_allocs_self).
-find_top_sort_predicate(allocs, self,          per_call, yes,
+find_top_sort_predicate(cost_allocs, self,          per_call, yes,
     compare_ps_allocs_self_percall, filter_ps_allocs_self).
-find_top_sort_predicate(allocs, self_and_desc, overall,  yes,
+find_top_sort_predicate(cost_allocs, self_and_desc, overall,  yes,
     compare_ps_allocs_both_overall, filter_ps_allocs_both).
-find_top_sort_predicate(allocs, self_and_desc, per_call, yes,
+find_top_sort_predicate(cost_allocs, self_and_desc, per_call, yes,
     compare_ps_allocs_both_percall, filter_ps_allocs_both).
-find_top_sort_predicate(words,  self,          overall,  yes,
+
+find_top_sort_predicate(cost_words,  self,          overall,  yes,
     compare_ps_words_self_overall,  filter_ps_words_self).
-find_top_sort_predicate(words,  self,          per_call, yes,
+find_top_sort_predicate(cost_words,  self,          per_call, yes,
     compare_ps_words_self_percall,  filter_ps_words_self).
-find_top_sort_predicate(words,  self_and_desc, overall,  yes,
+find_top_sort_predicate(cost_words,  self_and_desc, overall,  yes,
     compare_ps_words_both_overall,  filter_ps_words_both).
-find_top_sort_predicate(words,  self_and_desc, per_call, yes,
+find_top_sort_predicate(cost_words,  self_and_desc, per_call, yes,
     compare_ps_words_both_percall,  filter_ps_words_both).
 
 :- pred find_threshold_predicate(cost_kind::in, include_descendants::in,
     bool::out, pred(deep, float, int)::out(pred(in, in, in) is semidet))
     is det.
 
-find_threshold_predicate(calls,  self,          no,  threshold_ps_time_self).
-find_threshold_predicate(calls,  self_and_desc, no,  threshold_ps_time_self).
-find_threshold_predicate(redos,  self,          no,  threshold_ps_time_self).
-find_threshold_predicate(redos,  self_and_desc, no,  threshold_ps_time_self).
-find_threshold_predicate(time,   self,          yes, threshold_ps_time_self).
-find_threshold_predicate(time,   self_and_desc, yes, threshold_ps_time_both).
-find_threshold_predicate(allocs, self,          yes, threshold_ps_allocs_self).
-find_threshold_predicate(allocs, self_and_desc, yes, threshold_ps_allocs_both).
-find_threshold_predicate(words,  self,          yes, threshold_ps_words_self).
-find_threshold_predicate(words,  self_and_desc, yes, threshold_ps_words_both).
+find_threshold_predicate(cost_calls,  self,          no,
+    threshold_ps_time_self).
+find_threshold_predicate(cost_calls,  self_and_desc, no,
+    threshold_ps_time_self).
+
+find_threshold_predicate(cost_redos,  self,          no,
+    threshold_ps_time_self).
+find_threshold_predicate(cost_redos,  self_and_desc, no,
+    threshold_ps_time_self).
+
+find_threshold_predicate(cost_time,   self,          yes,
+    threshold_ps_time_self).
+find_threshold_predicate(cost_time,   self_and_desc, yes,
+    threshold_ps_time_both).
+
+find_threshold_predicate(cost_callseqs, self,          yes,
+    threshold_ps_callseqs_self).
+find_threshold_predicate(cost_callseqs, self_and_desc, yes,
+    threshold_ps_callseqs_both).
+
+find_threshold_predicate(cost_allocs, self,          yes,
+    threshold_ps_allocs_self).
+find_threshold_predicate(cost_allocs, self_and_desc, yes,
+    threshold_ps_allocs_both).
+
+find_threshold_predicate(cost_words,  self,          yes,
+    threshold_ps_words_self).
+find_threshold_predicate(cost_words,  self_and_desc, yes,
+    threshold_ps_words_both).
 
 %-----------------------------------------------------------------------------%
 
@@ -286,6 +317,68 @@
     TotalQuantaPerCall2 = float(TotalQuanta2) / float(Calls2),
     compare(Result, TotalQuantaPerCall2, TotalQuantaPerCall1).
 
+:- func compare_ps_callseqs_self_overall(deep, int, int) = comparison_result.
+
+compare_ps_callseqs_self_overall(Deep, PSI1, PSI2) = Result :-
+    PSOwn = Deep ^ ps_own,
+    array.lookup(PSOwn, PSI1, Own1),
+    array.lookup(PSOwn, PSI2, Own2),
+    OwnCallSeqs1 = callseqs(Own1),
+    OwnCallSeqs2 = callseqs(Own2),
+    compare(Result, OwnCallSeqs2, OwnCallSeqs1).
+
+:- func compare_ps_callseqs_self_percall(deep, int, int) = comparison_result.
+
+compare_ps_callseqs_self_percall(Deep, PSI1, PSI2) = Result :-
+    PSOwn = Deep ^ ps_own,
+    array.lookup(PSOwn, PSI1, Own1),
+    array.lookup(PSOwn, PSI2, Own2),
+    Calls1 = calls(Own1),
+    Calls2 = calls(Own2),
+    OwnCallSeqs1 = callseqs(Own1),
+    OwnCallSeqs2 = callseqs(Own2),
+    OwnCallSeqsPerCall1 = float(OwnCallSeqs1) / float(Calls1),
+    OwnCallSeqsPerCall2 = float(OwnCallSeqs2) / float(Calls2),
+    compare(Result, OwnCallSeqsPerCall2, OwnCallSeqsPerCall1).
+
+:- func compare_ps_callseqs_both_overall(deep, int, int) = comparison_result.
+
+compare_ps_callseqs_both_overall(Deep, PSI1, PSI2) = Result :-
+    PSOwn = Deep ^ ps_own,
+    PSDesc = Deep ^ ps_desc,
+    array.lookup(PSOwn, PSI1, Own1),
+    array.lookup(PSOwn, PSI2, Own2),
+    array.lookup(PSDesc, PSI1, Desc1),
+    array.lookup(PSDesc, PSI2, Desc2),
+    OwnCallSeqs1 = callseqs(Own1),
+    OwnCallSeqs2 = callseqs(Own2),
+    DescCallSeqs1 = inherit_callseqs(Desc1),
+    DescCallSeqs2 = inherit_callseqs(Desc2),
+    TotalCallSeqs1 = OwnCallSeqs1 + DescCallSeqs1,
+    TotalCallSeqs2 = OwnCallSeqs2 + DescCallSeqs2,
+    compare(Result, TotalCallSeqs2, TotalCallSeqs1).
+
+:- func compare_ps_callseqs_both_percall(deep, int, int) = comparison_result.
+
+compare_ps_callseqs_both_percall(Deep, PSI1, PSI2) = Result :-
+    PSOwn = Deep ^ ps_own,
+    PSDesc = Deep ^ ps_desc,
+    array.lookup(PSOwn, PSI1, Own1),
+    array.lookup(PSOwn, PSI2, Own2),
+    array.lookup(PSDesc, PSI1, Desc1),
+    array.lookup(PSDesc, PSI2, Desc2),
+    Calls1 = calls(Own1),
+    Calls2 = calls(Own2),
+    OwnCallSeqs1 = callseqs(Own1),
+    OwnCallSeqs2 = callseqs(Own2),
+    DescCallSeqs1 = inherit_callseqs(Desc1),
+    DescCallSeqs2 = inherit_callseqs(Desc2),
+    TotalCallSeqs1 = OwnCallSeqs1 + DescCallSeqs1,
+    TotalCallSeqs2 = OwnCallSeqs2 + DescCallSeqs2,
+    TotalCallSeqsPerCall1 = float(TotalCallSeqs1) / float(Calls1),
+    TotalCallSeqsPerCall2 = float(TotalCallSeqs2) / float(Calls2),
+    compare(Result, TotalCallSeqsPerCall2, TotalCallSeqsPerCall1).
+
 :- func compare_ps_allocs_self_overall(deep, int, int) = comparison_result.
 
 compare_ps_allocs_self_overall(Deep, PSI1, PSI2) = Result :-
@@ -448,6 +541,26 @@
     TotalQuanta1 = OwnQuanta1 + DescQuanta1,
     TotalQuanta1 > 0.
 
+:- pred filter_ps_callseqs_self(deep::in, int::in) is semidet.
+
+filter_ps_callseqs_self(Deep, PSI1) :-
+    PSOwn = Deep ^ ps_own,
+    array.lookup(PSOwn, PSI1, Own1),
+    OwnCallSeqs1 = callseqs(Own1),
+    OwnCallSeqs1 > 0.
+
+:- pred filter_ps_callseqs_both(deep::in, int::in) is semidet.
+
+filter_ps_callseqs_both(Deep, PSI1) :-
+    PSOwn = Deep ^ ps_own,
+    PSDesc = Deep ^ ps_desc,
+    array.lookup(PSOwn, PSI1, Own1),
+    array.lookup(PSDesc, PSI1, Desc1),
+    OwnCallSeqs1 = callseqs(Own1),
+    DescCallSeqs1 = inherit_callseqs(Desc1),
+    TotalCallSeqs1 = OwnCallSeqs1 + DescCallSeqs1,
+    TotalCallSeqs1 > 0.
+
 :- pred filter_ps_allocs_self(deep::in, int::in) is semidet.
 
 filter_ps_allocs_self(Deep, PSI1) :-
@@ -520,6 +633,36 @@
     RootTotalQuanta = RootOwnQuanta + RootDescQuanta,
     100.0 * float(TotalQuanta) > Threshold * float(RootTotalQuanta).
 
+:- pred threshold_ps_callseqs_self(deep::in, float::in, int::in) is semidet.
+
+threshold_ps_callseqs_self(Deep, Threshold, PSI) :-
+    PSOwn = Deep ^ ps_own,
+    array.lookup(PSOwn, PSI, Own),
+    RootOwn = root_own_info(Deep),
+    RootDesc = root_desc_info(Deep),
+    OwnCallSeqs = callseqs(Own),
+    RootOwnCallSeqs = callseqs(RootOwn),
+    RootDescCallSeqs = inherit_callseqs(RootDesc),
+    RootTotalCallSeqs = RootOwnCallSeqs + RootDescCallSeqs,
+    100.0 * float(OwnCallSeqs) > Threshold * float(RootTotalCallSeqs).
+
+:- pred threshold_ps_callseqs_both(deep::in, float::in, int::in) is semidet.
+
+threshold_ps_callseqs_both(Deep, Threshold, PSI) :-
+    PSOwn = Deep ^ ps_own,
+    PSDesc = Deep ^ ps_desc,
+    array.lookup(PSOwn, PSI, Own),
+    array.lookup(PSDesc, PSI, Desc),
+    RootOwn = root_own_info(Deep),
+    RootDesc = root_desc_info(Deep),
+    OwnCallSeqs = callseqs(Own),
+    RootOwnCallSeqs = callseqs(RootOwn),
+    DescCallSeqs = inherit_callseqs(Desc),
+    RootDescCallSeqs = inherit_callseqs(RootDesc),
+    TotalCallSeqs = OwnCallSeqs + DescCallSeqs,
+    RootTotalCallSeqs = RootOwnCallSeqs + RootDescCallSeqs,
+    100.0 * float(TotalCallSeqs) > Threshold * float(RootTotalCallSeqs).
+
 :- pred threshold_ps_allocs_self(deep::in, float::in, int::in) is semidet.
 
 threshold_ps_allocs_self(Deep, Threshold, PSI) :-
@@ -592,71 +735,91 @@
     ;
         Criteria = by_cost(Measurement, InclDesc, Scope),
         (
-            Measurement = calls,
+            Measurement = cost_calls,
             % We ignore the setting of InclDesc because calls are not
             % inherited from descendants, and we ignore the setting of Scope
             % because sorting on "calls per call" is not useful.
             CompFunc = compare_line_groups_by_calls
         ;
-            Measurement = redos,
+            Measurement = cost_redos,
             CompFunc = compare_line_groups_by_redos
         ;
-            Measurement = time,
+            Measurement = cost_time,
             InclDesc = self,
             Scope = overall,
             CompFunc = compare_line_groups_by_time_self_overall
         ;
-            Measurement = time,
+            Measurement = cost_time,
             InclDesc = self,
             Scope = per_call,
             CompFunc = compare_line_groups_by_time_self_percall
         ;
-            Measurement = time,
+            Measurement = cost_time,
             InclDesc = self_and_desc,
             Scope = overall,
             CompFunc = compare_line_groups_by_time_total_overall
         ;
-            Measurement = time,
+            Measurement = cost_time,
             InclDesc = self_and_desc,
             Scope = per_call,
             CompFunc = compare_line_groups_by_time_total_percall
         ;
-            Measurement = allocs,
+            Measurement = cost_callseqs,
+            InclDesc = self,
+            Scope = overall,
+            CompFunc = compare_line_groups_by_callseqs_self_overall
+        ;
+            Measurement = cost_callseqs,
+            InclDesc = self,
+            Scope = per_call,
+            CompFunc = compare_line_groups_by_callseqs_self_percall
+        ;
+            Measurement = cost_callseqs,
+            InclDesc = self_and_desc,
+            Scope = overall,
+            CompFunc = compare_line_groups_by_callseqs_total_overall
+        ;
+            Measurement = cost_callseqs,
+            InclDesc = self_and_desc,
+            Scope = per_call,
+            CompFunc = compare_line_groups_by_callseqs_total_percall
+        ;
+            Measurement = cost_allocs,
             InclDesc = self,
             Scope = overall,
             CompFunc = compare_line_groups_by_allocs_self_overall
         ;
-            Measurement = allocs,
+            Measurement = cost_allocs,
             InclDesc = self,
             Scope = per_call,
             CompFunc = compare_line_groups_by_allocs_self_percall
         ;
-            Measurement = allocs,
+            Measurement = cost_allocs,
             InclDesc = self_and_desc,
             Scope = overall,
             CompFunc = compare_line_groups_by_allocs_total_overall
         ;
-            Measurement = allocs,
+            Measurement = cost_allocs,
             InclDesc = self_and_desc,
             Scope = per_call,
             CompFunc = compare_line_groups_by_allocs_total_percall
         ;
-            Measurement = words,
+            Measurement = cost_words,
             InclDesc = self,
             Scope = overall,
             CompFunc = compare_line_groups_by_words_self_overall
         ;
-            Measurement = words,
+            Measurement = cost_words,
             InclDesc = self,
             Scope = per_call,
             CompFunc = compare_line_groups_by_words_self_percall
         ;
-            Measurement = words,
+            Measurement = cost_words,
             InclDesc = self_and_desc,
             Scope = overall,
             CompFunc = compare_line_groups_by_words_total_overall
         ;
-            Measurement = words,
+            Measurement = cost_words,
             InclDesc = self_and_desc,
             Scope = per_call,
             CompFunc = compare_line_groups_by_words_total_percall
@@ -752,10 +915,8 @@
     line_group(FL, LL)) = comparison_result.
 
 compare_line_groups_by_time_total_overall(Group1, Group2) = Result :-
-    Quanta1 = quanta(Group1 ^ group_own) +
-        inherit_quanta(Group1 ^ group_desc),
-    Quanta2 = quanta(Group2 ^ group_own) +
-        inherit_quanta(Group2 ^ group_desc),
+    Quanta1 = quanta(Group1 ^ group_own) + inherit_quanta(Group1 ^ group_desc),
+    Quanta2 = quanta(Group2 ^ group_own) + inherit_quanta(Group2 ^ group_desc),
     compare(Result, Quanta2, Quanta1).
 
 :- func compare_line_groups_by_time_total_percall(line_group(FL, LL),
@@ -764,10 +925,8 @@
 compare_line_groups_by_time_total_percall(Group1, Group2) = Result :-
     Calls1 = calls(Group1 ^ group_own),
     Calls2 = calls(Group2 ^ group_own),
-    Quanta1 = quanta(Group1 ^ group_own) +
-        inherit_quanta(Group1 ^ group_desc),
-    Quanta2 = quanta(Group2 ^ group_own) +
-        inherit_quanta(Group2 ^ group_desc),
+    Quanta1 = quanta(Group1 ^ group_own) + inherit_quanta(Group1 ^ group_desc),
+    Quanta2 = quanta(Group2 ^ group_own) + inherit_quanta(Group2 ^ group_desc),
     ( Calls1 = 0 ->
         QuantaPerCall1 = 0.0
     ;
@@ -780,6 +939,66 @@
     ),
     compare(Result, QuantaPerCall2, QuantaPerCall1).
 
+:- func compare_line_groups_by_callseqs_self_overall(line_group(FL, LL),
+    line_group(FL, LL)) = comparison_result.
+
+compare_line_groups_by_callseqs_self_overall(Group1, Group2) = Result :-
+    CallSeqs1 = callseqs(Group1 ^ group_own),
+    CallSeqs2 = callseqs(Group2 ^ group_own),
+    compare(Result, CallSeqs2, CallSeqs1).
+
+:- func compare_line_groups_by_callseqs_self_percall(line_group(FL, LL),
+    line_group(FL, LL)) = comparison_result.
+
+compare_line_groups_by_callseqs_self_percall(Group1, Group2) = Result :-
+    Calls1 = calls(Group1 ^ group_own),
+    Calls2 = calls(Group2 ^ group_own),
+    CallSeqs1 = callseqs(Group1 ^ group_own),
+    CallSeqs2 = callseqs(Group2 ^ group_own),
+    ( Calls1 = 0 ->
+        CallSeqsPerCall1 = 0.0
+    ;
+        CallSeqsPerCall1 = float(CallSeqs1) / float(Calls1)
+    ),
+    ( Calls2 = 0 ->
+        CallSeqsPerCall2 = 0.0
+    ;
+        CallSeqsPerCall2 = float(CallSeqs2) / float(Calls2)
+    ),
+    compare(Result, CallSeqsPerCall2, CallSeqsPerCall1).
+
+:- func compare_line_groups_by_callseqs_total_overall(line_group(FL, LL),
+    line_group(FL, LL)) = comparison_result.
+
+compare_line_groups_by_callseqs_total_overall(Group1, Group2) = Result :-
+    CallSeqs1 = callseqs(Group1 ^ group_own) +
+        inherit_callseqs(Group1 ^ group_desc),
+    CallSeqs2 = callseqs(Group2 ^ group_own) +
+        inherit_callseqs(Group2 ^ group_desc),
+    compare(Result, CallSeqs2, CallSeqs1).
+
+:- func compare_line_groups_by_callseqs_total_percall(line_group(FL, LL),
+    line_group(FL, LL)) = comparison_result.
+
+compare_line_groups_by_callseqs_total_percall(Group1, Group2) = Result :-
+    Calls1 = calls(Group1 ^ group_own),
+    Calls2 = calls(Group2 ^ group_own),
+    CallSeqs1 = callseqs(Group1 ^ group_own) +
+        inherit_callseqs(Group1 ^ group_desc),
+    CallSeqs2 = callseqs(Group2 ^ group_own) +
+        inherit_callseqs(Group2 ^ group_desc),
+    ( Calls1 = 0 ->
+        CallSeqsPerCall1 = 0.0
+    ;
+        CallSeqsPerCall1 = float(CallSeqs1) / float(Calls1)
+    ),
+    ( Calls2 = 0 ->
+        CallSeqsPerCall2 = 0.0
+    ;
+        CallSeqsPerCall2 = float(CallSeqs2) / float(Calls2)
+    ),
+    compare(Result, CallSeqsPerCall2, CallSeqsPerCall1).
+
 :- func compare_line_groups_by_allocs_self_overall(line_group(FL, LL),
     line_group(FL, LL)) = comparison_result.
 
@@ -812,10 +1031,8 @@
     line_group(FL, LL)) = comparison_result.
 
 compare_line_groups_by_allocs_total_overall(Group1, Group2) = Result :-
-    Alloc1 = allocs(Group1 ^ group_own) +
-        inherit_allocs(Group1 ^ group_desc),
-    Alloc2 = allocs(Group2 ^ group_own) +
-        inherit_allocs(Group2 ^ group_desc),
+    Alloc1 = allocs(Group1 ^ group_own) + inherit_allocs(Group1 ^ group_desc),
+    Alloc2 = allocs(Group2 ^ group_own) + inherit_allocs(Group2 ^ group_desc),
     compare(Result, Alloc2, Alloc1).
 
 :- func compare_line_groups_by_allocs_total_percall(line_group(FL, LL),
@@ -824,10 +1041,8 @@
 compare_line_groups_by_allocs_total_percall(Group1, Group2) = Result :-
     Calls1 = calls(Group1 ^ group_own),
     Calls2 = calls(Group2 ^ group_own),
-    Alloc1 = allocs(Group1 ^ group_own) +
-        inherit_allocs(Group1 ^ group_desc),
-    Alloc2 = allocs(Group2 ^ group_own) +
-        inherit_allocs(Group2 ^ group_desc),
+    Alloc1 = allocs(Group1 ^ group_own) + inherit_allocs(Group1 ^ group_desc),
+    Alloc2 = allocs(Group2 ^ group_own) + inherit_allocs(Group2 ^ group_desc),
     ( Calls1 = 0 ->
         AllocPerCall1 = 0.0
     ;
@@ -872,10 +1087,8 @@
     line_group(FL, LL)) = comparison_result.
 
 compare_line_groups_by_words_total_overall(Group1, Group2) = Result :-
-    Words1 = words(Group1 ^ group_own) +
-        inherit_words(Group1 ^ group_desc),
-    Words2 = words(Group2 ^ group_own) +
-        inherit_words(Group2 ^ group_desc),
+    Words1 = words(Group1 ^ group_own) + inherit_words(Group1 ^ group_desc),
+    Words2 = words(Group2 ^ group_own) + inherit_words(Group2 ^ group_desc),
     compare(Result, Words2, Words1).
 
 :- func compare_line_groups_by_words_total_percall(line_group(FL, LL),
@@ -884,10 +1097,8 @@
 compare_line_groups_by_words_total_percall(Group1, Group2) = Result :-
     Calls1 = calls(Group1 ^ group_own),
     Calls2 = calls(Group2 ^ group_own),
-    Words1 = words(Group1 ^ group_own) +
-        inherit_words(Group1 ^ group_desc),
-    Words2 = words(Group2 ^ group_own) +
-        inherit_words(Group2 ^ group_desc),
+    Words1 = words(Group1 ^ group_own) + inherit_words(Group1 ^ group_desc),
+    Words2 = words(Group2 ^ group_own) + inherit_words(Group2 ^ group_desc),
     ( Calls1 = 0 ->
         WordsPerCall1 = 0.0
     ;
cvs diff: Diffing notes
--------------------------------------------------------------------------
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