Files
mercury/deep_profiler/startup.m
Zoltan Somogyi 3c07fc2121 Use explicit streams in deep_profiler/*.m.
deep_profiler/analysis_utils.m:
deep_profiler/autopar_find_best_par.m:
deep_profiler/autopar_reports.m:
deep_profiler/autopar_search_callgraph.m:
deep_profiler/autopar_search_goals.m:
deep_profiler/callgraph.m:
deep_profiler/canonical.m:
deep_profiler/cliques.m:
deep_profiler/coverage.m:
deep_profiler/dump.m:
deep_profiler/mdprof_cgi.m:
deep_profiler/mdprof_create_feedback.m:
deep_profiler/mdprof_dump.m:
deep_profiler/mdprof_procrep.m:
deep_profiler/mdprof_report_feedback.m:
deep_profiler/mdprof_test.m:
deep_profiler/profile.m:
deep_profiler/read_profile.m:
deep_profiler/recursion_patterns.m:
deep_profiler/startup.m:
deep_profiler/var_use_analysis.m:
    Replace implicit streams with explicit streams.

    In some places, simplify some code, often using constructs such as
    string.format that either did not exist or were too expensive to use
    when the original code was written.

    Consistenly use the spelling StdErr over Stderr.

    In mdbprof_dump.m, put filename and reason-for-failing-to-open-that-file
    in the right order in an error message.

deep_profiler/DEEP_FLAGS.in:
    Turn on --warn-implicit-stream-calls for the entire deep_profiler
    directory.

mdbcomp/program_representation.m:
mdbcomp/trace_counts.m:
    Replace implicit streams with explicit streams. These are the two mdbcomp
    modules that (a) used to use implicit streams, and (2) are used by the
    deep profiler.

mdbcomp/Mercury.options:
    Turn on --warn-implicit-stream-calls for these two modules.

slice/mcov.m:
slice/mtc_union.m:
    Conform to the changes in mdbcomp.
2021-03-06 18:30:50 +11:00

1120 lines
43 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%---------------------------------------------------------------------------%
% Copyright (C) 2001-2002, 2004-2012 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% File: startup.m.
% Authors: conway, zs.
%
% This module contains the code for turning the raw list of nodes read in by
% 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.
:- interface.
:- import_module dump.
:- import_module profile.
:- import_module bool.
:- import_module io.
:- import_module list.
:- import_module maybe.
%---------------------------------------------------------------------------%
:- pred read_and_startup_default_deep_options(string::in, string::in,
string::in, bool::in, maybe(io.output_stream)::in, list(string)::in,
maybe_error(deep)::out, io::di, io::uo) is det.
:- pred read_and_startup(string::in, string::in,
string::in, bool::in, maybe(io.output_stream)::in, list(string)::in,
dump_options::in, maybe_error(deep)::out, io::di, io::uo) is det.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module array_util.
:- import_module callgraph.
:- import_module canonical.
:- import_module exclude.
:- import_module mdbcomp.
:- import_module mdbcomp.program_representation.
:- import_module mdbcomp.shared_utilities.
:- import_module measurements.
:- import_module read_profile.
:- import_module array.
:- import_module int.
:- import_module map.
:- import_module require.
:- import_module string.
%---------------------------------------------------------------------------%
read_and_startup_default_deep_options(Machine, ScriptName, DataFileName,
Canonical, MaybeOutputStream, DumpStages, Res, !IO) :-
read_and_startup(Machine, ScriptName, DataFileName, Canonical,
MaybeOutputStream, DumpStages, default_dump_options, Res, !IO).
read_and_startup(Machine, ScriptName, DataFileName, Canonical,
MaybeOutputStream, DumpStages, DumpOptions, Result, !IO) :-
% Any limits on stack size bite mostly during startup, which is why
% this call is here. The alternative design would be to invoke
% unlimit_stack separately in every program in this directory.
% That would be error-prone, since adding the call would be easy to miss
% when adding a new program.
unlimit_stack(!IO),
maybe_report_stats(MaybeOutputStream, !IO),
maybe_report_msg(MaybeOutputStream,
"% Reading graph data...\n", !IO),
read_call_graph(DataFileName, DataFileResult, !IO),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
(
DataFileResult = ok(InitDeep),
startup(Machine, ScriptName, DataFileName,
Canonical, MaybeOutputStream, DumpStages, DumpOptions,
InitDeep, Deep, !IO),
Result = ok(Deep)
;
DataFileResult = error(Error),
Result = error(Error)
).
:- func make_progrep_filename(string) = string.
make_progrep_filename(DataFileName) = ProgrepFileName :-
( if string.remove_suffix(DataFileName, ".data", BaseFileName) then
ProgrepFileName = BaseFileName ++ ".procrep"
else
error("Couldn't remove suffix from deep file name: " ++ DataFileName)
).
:- pred startup(string::in, string::in, string::in, bool::in,
maybe(io.output_stream)::in, list(string)::in, dump_options::in,
initial_deep::in, deep::out, io::di, io::uo) is det.
startup(Machine, ScriptName, DataFileName, Canonical, MaybeOutputStream,
DumpStages, DumpOptions, InitDeep0, !:Deep, !IO) :-
InitDeep0 = initial_deep(InitStats, Root,
CallSiteDynamics0, ProcDynamics, CallSiteStatics0, ProcStatics0),
maybe_dump(MaybeOutputStream, DataFileName, DumpStages, 0,
dump_initial_deep(InitDeep0, default_dump_options), !IO),
maybe_report_msg(MaybeOutputStream,
"% Mapping static call sites to containing procedures...\n", !IO),
array_foldl2_from_1(record_css_containers_module_procs, ProcStatics0,
u(CallSiteStatics0), CallSiteStatics, map.init, ModuleProcs),
ModuleDataMap0 = map.map_values_only(initialize_module_data, ModuleProcs),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
maybe_report_msg(MaybeOutputStream,
"% Mapping dynamic call sites to containing procedures...\n", !IO),
array_foldl2_from_1(record_csd_containers_zeroed_pss, ProcDynamics,
u(CallSiteDynamics0), CallSiteDynamics, u(ProcStatics0), ProcStatics),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
InitDeep1 = initial_deep(InitStats, Root,
CallSiteDynamics, ProcDynamics, CallSiteStatics, ProcStatics),
maybe_dump(MaybeOutputStream, DataFileName, DumpStages, 10,
dump_initial_deep(InitDeep1, DumpOptions), !IO),
(
Canonical = no,
InitDeep = InitDeep1
;
Canonical = yes,
maybe_report_msg(MaybeOutputStream,
"% Canonicalizing cliques...\n", !IO),
canonicalize_cliques(InitDeep1, InitDeep),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO)
),
maybe_dump(MaybeOutputStream, DataFileName, DumpStages, 20,
dump_initial_deep(InitDeep, DumpOptions), !IO),
array.max(InitDeep ^ init_proc_dynamics, PDMax),
NPDs = PDMax + 1,
array.max(InitDeep ^ init_call_site_dynamics, CSDMax),
NCSDs = CSDMax + 1,
array.max(InitDeep ^ init_proc_statics, PSMax),
NPSs = PSMax + 1,
array.max(InitDeep ^ init_call_site_statics, CSSMax),
NCSSs = CSSMax + 1,
maybe_report_msg(MaybeOutputStream,
"% Finding cliques...\n", !IO),
find_cliques(InitDeep, CliqueList),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
maybe_report_msg(MaybeOutputStream,
"% Constructing clique indexes...\n", !IO),
make_clique_indexes(NPDs, CliqueList, Cliques, CliqueIndex),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
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.
array.max(Cliques, CliqueMax),
NCliques = CliqueMax + 1,
array.init(NCliques, call_site_dynamic_ptr(-1), CliqueParents0),
array.init(NCSDs, no, CliqueMaybeChildren0),
array_foldl2_from_1(construct_clique_parents(InitDeep, CliqueIndex),
CliqueIndex,
CliqueParents0, CliqueParents,
CliqueMaybeChildren0, CliqueMaybeChildren),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
maybe_report_msg(MaybeOutputStream,
"% Finding procedure callers...\n", !IO),
array.init(NPSs, [], ProcCallers0),
array_foldl_from_1(construct_proc_callers(InitDeep),
CallSiteDynamics, ProcCallers0, ProcCallers),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
maybe_report_msg(MaybeOutputStream,
"% Constructing call site static map...\n", !IO),
array.init(NCSDs, call_site_static_ptr(-1), CallSiteStaticMap0),
array_foldl_from_1(construct_call_site_caller(InitDeep),
ProcDynamics, CallSiteStaticMap0, CallSiteStaticMap),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
maybe_report_msg(MaybeOutputStream,
"% Finding call site calls...\n", !IO),
array.init(NCSSs, map.init, CallSiteCalls0),
array_foldl_from_1(construct_call_site_calls(InitDeep),
ProcDynamics, CallSiteCalls0, CallSiteCalls),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
ProgRepFileName = make_progrep_filename(DataFileName),
maybe_report_msg(MaybeOutputStream,
"% Reading program representation...\n", !IO),
read_prog_rep_file(ProgRepFileName, ProgRepResult, !IO),
(
ProgRepResult = ok(ProgRep),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
MaybeProcRepFile = yes(ok(ProgRep)),
ProgRep = prog_rep(ModuleMap),
map.keys(ModuleMap, ProgRepModules),
(
MaybeOutputStream = yes(OutputStream),
io.write(OutputStream, ProgRepModules, !IO),
io.nl(OutputStream, !IO)
;
MaybeOutputStream = no
),
list.foldl(ensure_module_has_module_data, ProgRepModules,
ModuleDataMap0, ModuleDataMap)
;
ProgRepResult = error(Error),
(
io.open_input(ProgRepFileName, OpenProgRepResult, !IO),
(
OpenProgRepResult = ok(ProgRepStream),
% The file exists, so the error message describes something
% wrong with the file.
io.close_input(ProgRepStream, !IO),
ErrorMessage = io.error_message(Error),
maybe_report_msg(MaybeOutputStream,
"% Error: " ++ ErrorMessage ++ "\n", !IO),
MaybeProcRepFile = yes(error(ErrorMessage)),
ModuleDataMap = ModuleDataMap0
;
OpenProgRepResult = error(_),
% The file does not exist.
MaybeProcRepFile = no,
ModuleDataMap = ModuleDataMap0
)
)
),
ContourFileName = contour_file_name(DataFileName),
string.format("%% Trying to read contour exclusion file `%s'...\n",
[s(ContourFileName)], TryMsg),
maybe_report_msg(MaybeOutputStream, TryMsg, !IO),
read_exclude_file(ContourFileName, ModuleDataMap, ExcludeFile, !IO),
ExcludeFile = exclude_file(_, ExcludeContents),
(
ExcludeContents = no_exclude_file,
maybe_report_msg(MaybeOutputStream,
"% Couldn't open file.\n", !IO)
;
ExcludeContents = unreadable_exclude_file(ExcludeError),
string.format("%% File had unrecoverable errors:\n%% %s.\n",
[s(ExcludeError)], ExcludeErrorMsg),
maybe_report_msg(MaybeOutputStream, ExcludeErrorMsg, !IO)
;
ExcludeContents = readable_exclude_file(_, _),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO)
),
maybe_report_msg(MaybeOutputStream,
"% Propagating measurements up call graph...\n", !IO),
array.init(NCSDs, zero_inherit_prof_info, CSDDesc0),
array.init(NPDs, zero_own_prof_info, PDOwn0),
array_foldl_from_1(sum_call_sites_in_proc_dynamic,
CallSiteDynamics, PDOwn0, PDOwn),
array.init(NPDs, zero_inherit_prof_info, PDDesc0),
array.init(NPSs, zero_own_prof_info, PSOwn0),
array.init(NPSs, zero_inherit_prof_info, PSDesc0),
array.init(NCSSs, zero_own_prof_info, CSSOwn0),
array.init(NCSSs, zero_inherit_prof_info, CSSDesc0),
array.init(NPDs, map.init, PDCompTable0),
array.init(NCSDs, map.init, CSDCompTable0),
CoverageDataType = InitStats ^ prs_deep_flags ^ df_coverage_data_type,
(
CoverageDataType = no_coverage_data,
MaybeStaticCoverage0 = no
;
( CoverageDataType = static_coverage_data
; CoverageDataType = dynamic_coverage_data
),
array.init(NPSs, zero_static_coverage, StaticCoverage0),
MaybeStaticCoverage0 = yes(StaticCoverage0)
),
!:Deep = deep(InitStats, Machine, ScriptName, DataFileName, Root,
CallSiteDynamics, ProcDynamics, CallSiteStatics, ProcStatics,
CliqueIndex, Cliques, CliqueParents, CliqueMaybeChildren,
ProcCallers, CallSiteStaticMap, CallSiteCalls,
PDOwn, PDDesc0, CSDDesc0,
PSOwn0, PSDesc0, CSSOwn0, CSSDesc0,
PDCompTable0, CSDCompTable0, ModuleDataMap, MaybeStaticCoverage0,
ExcludeFile, MaybeProcRepFile, MaybeOutputStream),
array_foldl_from_1(propagate_to_clique, Cliques, !Deep),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
maybe_dump(MaybeOutputStream, DataFileName, DumpStages, 30,
dump_deep(!.Deep, DumpOptions), !IO),
maybe_report_msg(MaybeOutputStream,
"% Summarizing information...\n", !IO),
(
( CoverageDataType = no_coverage_data
; CoverageDataType = static_coverage_data
),
(
CoverageDataType = static_coverage_data,
maybe_report_msg(MaybeOutputStream,
"\t% Summarizing static coverage...\n", !IO),
summarize_proc_statics_coverage(!Deep)
;
CoverageDataType = no_coverage_data
),
maybe_report_msg(MaybeOutputStream,
"\t% Summarizing proc dynamics...\n", !IO),
summarize_proc_dynamics(!Deep)
;
CoverageDataType = dynamic_coverage_data,
maybe_report_msg(MaybeOutputStream,
"\t% Summarizing proc dynamics with coverage...\n", !IO),
summarize_proc_dynamics_with_coverage_data(!Deep)
),
maybe_report_msg(MaybeOutputStream,
"\t% Summarizing call site dynamics...\n", !IO),
summarize_call_site_dynamics(!Deep),
maybe_report_msg(MaybeOutputStream,
"\t% Summarizing modules...\n", !IO),
summarize_modules(!Deep),
maybe_report_msg(MaybeOutputStream,
"% Done.\n", !IO),
maybe_report_stats(MaybeOutputStream, !IO),
maybe_dump(MaybeOutputStream, DataFileName, DumpStages, 40,
dump_deep(!.Deep, DumpOptions), !IO).
:- func contour_file_name(string) = string.
contour_file_name(DataFileName) = ContourFileName :-
( if string.remove_suffix(DataFileName, ".data", BaseFileName) then
ContourFileName = BaseFileName ++ ".contour"
else
error("Couldn't remove suffix from deep file name: " ++ DataFileName)
).
:- pred count_quanta(int::in, call_site_dynamic::in, int::in, int::out) is det.
count_quanta(_N, CSD, Quanta0, Quanta) :-
Quanta = Quanta0 + quanta(CSD ^ csd_own_prof).
:- func initialize_module_data(list(proc_static_ptr)) = module_data.
initialize_module_data(PSPtrs) =
module_data(zero_own_prof_info, zero_inherit_prof_info, PSPtrs).
:- pred ensure_module_has_module_data(string::in,
map(string, module_data)::in, map(string, module_data)::out) is det.
ensure_module_has_module_data(Module, !ModuleDataMap) :-
( if map.search(!.ModuleDataMap, Module, _) then
true
else
Data = module_data(zero_own_prof_info, zero_inherit_prof_info, []),
map.det_insert(Module, Data, !ModuleDataMap)
).
:- pred maybe_dump(maybe(io.text_output_stream)::in,
string::in, list(string)::in, int::in,
pred(io.text_output_stream, io, io)::in(pred(in, di, uo) is det),
io::di, io::uo) is det.
maybe_dump(MaybeOutputStream, BaseName, DumpStages, ThisStageNum,
Action, !IO) :-
string.int_to_string(ThisStageNum, ThisStageStr),
( if
( list.member("all", DumpStages)
; list.member(ThisStageStr, DumpStages)
)
then
FileName = BaseName ++ ".deepdump." ++ ThisStageStr,
io.open_output(FileName, OpenRes, !IO),
(
OpenRes = ok(FileStream),
Action(FileStream, !IO),
io.close_output(FileStream, !IO)
;
OpenRes = error(Error),
io.error_message(Error, Msg),
(
MaybeOutputStream = yes(OutputStream)
;
MaybeOutputStream = no,
io.stderr_stream(OutputStream, !IO)
),
io.format(OutputStream, "%s: %s\n", [s(FileName), s(Msg)], !IO)
)
else
true
).
%---------------------------------------------------------------------------%
:- pred record_css_containers_module_procs(int::in, proc_static::in,
array(call_site_static)::array_di,
array(call_site_static)::array_uo,
map(string, list(proc_static_ptr))::in,
map(string, list(proc_static_ptr))::out) is det.
record_css_containers_module_procs(PSI, PS, !CallSiteStatics, !ModuleProcs) :-
CSSPtrs = PS ^ ps_sites,
PSPtr = proc_static_ptr(PSI),
array.max(CSSPtrs, MaxCS),
record_css_containers_2(MaxCS, PSPtr, CSSPtrs, !CallSiteStatics),
DeclModule = PS ^ ps_decl_module,
( if map.search(!.ModuleProcs, DeclModule, PSPtrs0) then
map.det_update(DeclModule, [PSPtr | PSPtrs0], !ModuleProcs)
else
map.det_insert(DeclModule, [PSPtr], !ModuleProcs)
).
:- pred record_css_containers_2(int::in, proc_static_ptr::in,
array(call_site_static_ptr)::in,
array(call_site_static)::array_di,
array(call_site_static)::array_uo) is det.
record_css_containers_2(SlotNum, PSPtr, CSSPtrs, !CallSiteStatics) :-
( if SlotNum >= 0 then
array.lookup(CSSPtrs, SlotNum, CSSPtr),
lookup_call_site_statics(!.CallSiteStatics, CSSPtr, CSS0),
CSS0 = call_site_static(PSPtr0, SlotNum0,
Kind, LineNumber, GoalPath),
require(unify(PSPtr0, proc_static_ptr(-1)),
"record_css_containers_2: real proc_static_ptr"),
require(unify(SlotNum0, -1),
"record_css_containers_2: real slot_num"),
CSS = call_site_static(PSPtr, SlotNum,
Kind, LineNumber, GoalPath),
update_call_site_statics(CSSPtr, CSS, !CallSiteStatics),
record_css_containers_2(SlotNum - 1, PSPtr, CSSPtrs, !CallSiteStatics)
else
true
).
%---------------------------------------------------------------------------%
:- pred record_csd_containers_zeroed_pss(int::in, proc_dynamic::in,
array(call_site_dynamic)::array_di,
array(call_site_dynamic)::array_uo,
array(proc_static)::array_di, array(proc_static)::array_uo) is det.
record_csd_containers_zeroed_pss(PDI, PD, !CallSiteDynamics, !ProcStatics) :-
CSDArray = PD ^ pd_sites,
PDPtr = proc_dynamic_ptr(PDI),
flatten_call_sites(CSDArray, CSDPtrs, IsZeroed),
record_csd_containers_2(PDPtr, CSDPtrs, !CallSiteDynamics),
(
IsZeroed = zeroed,
PSPtr = PD ^ pd_proc_static,
lookup_proc_statics(!.ProcStatics, PSPtr, PS0),
PS = PS0 ^ ps_is_zeroed := zeroed,
update_proc_statics(PSPtr, PS, !ProcStatics)
;
IsZeroed = not_zeroed
).
:- pred record_csd_containers_2(proc_dynamic_ptr::in,
list(call_site_dynamic_ptr)::in,
array(call_site_dynamic)::array_di,
array(call_site_dynamic)::array_uo) is det.
record_csd_containers_2(_, [], !CallSiteDynamics).
record_csd_containers_2(PDPtr, [CSDPtr | CSDPtrs], !CallSiteDynamics) :-
lookup_call_site_dynamics(!.CallSiteDynamics, CSDPtr, CSD0),
CSD0 = call_site_dynamic(CallerPDPtr0, CalleePDPtr, Own),
require(unify(CallerPDPtr0, proc_dynamic_ptr(-1)),
"record_csd_containers_2: real proc_dynamic_ptr"),
CSD = call_site_dynamic(PDPtr, CalleePDPtr, Own),
update_call_site_dynamics(CSDPtr, CSD, !CallSiteDynamics),
record_csd_containers_2(PDPtr, CSDPtrs, !CallSiteDynamics).
%---------------------------------------------------------------------------%
:- pred construct_clique_parents(initial_deep::in, array(clique_ptr)::in,
int::in, clique_ptr::in,
array(call_site_dynamic_ptr)::array_di,
array(call_site_dynamic_ptr)::array_uo,
array(maybe(clique_ptr))::array_di,
array(maybe(clique_ptr))::array_uo) is det.
construct_clique_parents(InitDeep, CliqueIndex, PDI, CliquePtr,
!CliqueParents, !CliqueMaybeChildren) :-
( if PDI > 0 then
flat_call_sites(InitDeep ^ init_proc_dynamics,
proc_dynamic_ptr(PDI), CSDPtrs),
array_list_foldl2(
construct_clique_parents_2(InitDeep, CliqueIndex, CliquePtr),
CSDPtrs, !CliqueParents, !CliqueMaybeChildren)
else
error("construct_clique_parents: invalid pdi")
).
:- pred construct_clique_parents_2(initial_deep::in, array(clique_ptr)::in,
clique_ptr::in, call_site_dynamic_ptr::in,
array(call_site_dynamic_ptr)::array_di,
array(call_site_dynamic_ptr)::array_uo,
array(maybe(clique_ptr))::array_di,
array(maybe(clique_ptr))::array_uo) is det.
construct_clique_parents_2(InitDeep, CliqueIndex, ParentCliquePtr, CSDPtr,
!CliqueParents, !CliqueMaybeChildren) :-
CSDPtr = call_site_dynamic_ptr(CSDI),
( if CSDI > 0 then
array.lookup(InitDeep ^ init_call_site_dynamics, CSDI, CSD),
ChildPDPtr = CSD ^ csd_callee,
ChildPDPtr = proc_dynamic_ptr(ChildPDI),
( if ChildPDI > 0 then
array.lookup(CliqueIndex, ChildPDI, ChildCliquePtr),
( if ChildCliquePtr \= ParentCliquePtr then
ChildCliquePtr = clique_ptr(ChildCliqueNum),
array.set(ChildCliqueNum, CSDPtr, !CliqueParents),
array.set(CSDI, yes(ChildCliquePtr), !CliqueMaybeChildren)
else
true
)
else
true
)
else
true
).
%---------------------------------------------------------------------------%
:- pred construct_proc_callers(initial_deep::in, int::in,
call_site_dynamic::in,
array(list(call_site_dynamic_ptr))::array_di,
array(list(call_site_dynamic_ptr))::array_uo) is det.
construct_proc_callers(InitDeep, CSDI, CSD, !ProcCallers) :-
PDPtr = CSD ^ csd_callee,
( if valid_proc_dynamic_ptr_raw(InitDeep ^ init_proc_dynamics, PDPtr) then
lookup_proc_dynamics(InitDeep ^ init_proc_dynamics, PDPtr, PD),
PSPtr = PD ^ pd_proc_static,
lookup_proc_callers(!.ProcCallers, PSPtr, Callers0),
Callers = [call_site_dynamic_ptr(CSDI) | Callers0],
update_proc_callers(PSPtr, Callers, !ProcCallers)
else
true
).
:- pred construct_call_site_caller(initial_deep::in, int::in, proc_dynamic::in,
array(call_site_static_ptr)::array_di,
array(call_site_static_ptr)::array_uo) is det.
construct_call_site_caller(InitDeep, _PDI, PD, !CallSiteStaticMap) :-
PSPtr = PD ^ pd_proc_static,
CSDArraySlots = PD ^ pd_sites,
lookup_proc_statics(InitDeep ^ init_proc_statics, PSPtr, PS),
CSSPtrs = PS ^ ps_sites,
array.max(CSDArraySlots, MaxCS),
construct_call_site_caller_2(MaxCS,
InitDeep ^ init_call_site_dynamics, CSSPtrs, CSDArraySlots,
!CallSiteStaticMap).
:- pred construct_call_site_caller_2(int::in, call_site_dynamics::in,
array(call_site_static_ptr)::in,
array(call_site_array_slot)::in,
array(call_site_static_ptr)::array_di,
array(call_site_static_ptr)::array_uo) is det.
construct_call_site_caller_2(SlotNum, Deep, CSSPtrs, CSDArraySlots,
!CallSiteStaticMap) :-
( if SlotNum >= 0 then
array.lookup(CSDArraySlots, SlotNum, CSDArraySlot),
array.lookup(CSSPtrs, SlotNum, CSSPtr),
(
CSDArraySlot = slot_normal(CSDPtr),
construct_call_site_caller_3(Deep, CSSPtr, -1, CSDPtr,
!CallSiteStaticMap)
;
CSDArraySlot = slot_multi(_, CSDPtrs),
array_foldl_from_0(construct_call_site_caller_3(Deep, CSSPtr),
CSDPtrs, !CallSiteStaticMap)
),
construct_call_site_caller_2(SlotNum - 1, Deep, CSSPtrs,
CSDArraySlots, !CallSiteStaticMap)
else
true
).
:- pred construct_call_site_caller_3(call_site_dynamics::in,
call_site_static_ptr::in, int::in, call_site_dynamic_ptr::in,
array(call_site_static_ptr)::array_di,
array(call_site_static_ptr)::array_uo) is det.
construct_call_site_caller_3(CallSiteDynamics, CSSPtr, _Dummy, CSDPtr,
!CallSiteStaticMap) :-
( if valid_call_site_dynamic_ptr_raw(CallSiteDynamics, CSDPtr) then
update_call_site_static_map(CSDPtr, CSSPtr, !CallSiteStaticMap)
else
true
).
%---------------------------------------------------------------------------%
:- pred construct_call_site_calls(initial_deep::in, int::in, proc_dynamic::in,
array(map(proc_static_ptr, list(call_site_dynamic_ptr)))::array_di,
array(map(proc_static_ptr, list(call_site_dynamic_ptr)))::array_uo)
is det.
construct_call_site_calls(InitDeep, _PDI, PD, !CallSiteCalls) :-
PSPtr = PD ^ pd_proc_static,
CSDArraySlots = PD ^ pd_sites,
array.max(CSDArraySlots, MaxCS),
PSPtr = proc_static_ptr(PSI),
array.lookup(InitDeep ^ init_proc_statics, PSI, PS),
CSSPtrs = PS ^ ps_sites,
CallSiteDynamics = InitDeep ^ init_call_site_dynamics,
ProcDynamics = InitDeep ^ init_proc_dynamics,
construct_call_site_calls_2(CallSiteDynamics, ProcDynamics, MaxCS,
CSSPtrs, CSDArraySlots, !CallSiteCalls).
:- pred construct_call_site_calls_2(call_site_dynamics::in, proc_dynamics::in,
int::in, array(call_site_static_ptr)::in,
array(call_site_array_slot)::in,
array(map(proc_static_ptr, list(call_site_dynamic_ptr)))::array_di,
array(map(proc_static_ptr, list(call_site_dynamic_ptr)))::array_uo)
is det.
construct_call_site_calls_2(CallSiteDynamics, ProcDynamics, SlotNum,
CSSPtrs, CSDArraySlots, !CallSiteCalls) :-
( if SlotNum >= 0 then
array.lookup(CSDArraySlots, SlotNum, CSDArraySlot),
array.lookup(CSSPtrs, SlotNum, CSSPtr),
(
CSDArraySlot = slot_normal(CSDPtr),
construct_call_site_calls_3(CallSiteDynamics,
ProcDynamics, CSSPtr, -1, CSDPtr, !CallSiteCalls)
;
CSDArraySlot = slot_multi(_, CSDPtrs),
array_foldl_from_0(
construct_call_site_calls_3(CallSiteDynamics,
ProcDynamics, CSSPtr),
CSDPtrs, !CallSiteCalls)
),
construct_call_site_calls_2(CallSiteDynamics, ProcDynamics,
SlotNum - 1, CSSPtrs, CSDArraySlots, !CallSiteCalls)
else
true
).
:- pred construct_call_site_calls_3(call_site_dynamics::in, proc_dynamics::in,
call_site_static_ptr::in, int::in, call_site_dynamic_ptr::in,
array(map(proc_static_ptr, list(call_site_dynamic_ptr)))::array_di,
array(map(proc_static_ptr, list(call_site_dynamic_ptr)))::array_uo)
is det.
construct_call_site_calls_3(CallSiteDynamics, ProcDynamics, CSSPtr,
_Dummy, CSDPtr, !CallSiteCalls) :-
CSDPtr = call_site_dynamic_ptr(CSDI),
( if CSDI > 0 then
array.lookup(CallSiteDynamics, CSDI, CSD),
PDPtr = CSD ^ csd_callee,
PDPtr = proc_dynamic_ptr(PDI),
array.lookup(ProcDynamics, PDI, PD),
PSPtr = PD ^ pd_proc_static,
CSSPtr = call_site_static_ptr(CSSI),
array.lookup(!.CallSiteCalls, CSSI, CallMap0),
( if map.search(CallMap0, PSPtr, CallList0) then
CallList = [CSDPtr | CallList0],
map.det_update(PSPtr, CallList, CallMap0, CallMap)
else
CallList = [CSDPtr],
map.det_insert(PSPtr, CallList, CallMap0, CallMap)
),
array.set(CSSI, CallMap, !CallSiteCalls)
else
true
).
%---------------------------------------------------------------------------%
:- pred sum_call_sites_in_proc_dynamic(int::in, call_site_dynamic::in,
array(own_prof_info)::array_di, array(own_prof_info)::array_uo) is det.
sum_call_sites_in_proc_dynamic(_, CSD, !PDOwnArray) :-
CalleeOwn = CSD ^ csd_own_prof,
PDPtr = CSD ^ csd_callee,
PDPtr = proc_dynamic_ptr(PDI),
( if PDI > 0 then
array.lookup(!.PDOwnArray, PDI, ProcOwn0),
ProcOwn = add_own_to_own(CalleeOwn, ProcOwn0),
array.set(PDI, ProcOwn, !PDOwnArray)
else
error("sum_call_sites_in_proc_dynamic: invalid pdptr")
).
%---------------------------------------------------------------------------%
:- pred summarize_proc_dynamics(deep::in, deep::out) is det.
summarize_proc_dynamics(Deep0, Deep) :-
PSOwnArray0 = Deep0 ^ ps_own,
PSDescArray0 = Deep0 ^ ps_desc,
array_foldl2_from_1(
summarize_proc_dynamic(Deep0 ^ pd_own, Deep0 ^ pd_desc,
Deep0 ^ pd_comp_table),
Deep0 ^ proc_dynamics,
copy(PSOwnArray0), PSOwnArray,
copy(PSDescArray0), PSDescArray),
Deep = ((Deep0
^ ps_own := PSOwnArray)
^ ps_desc := PSDescArray).
:- pred summarize_proc_dynamic(array(own_prof_info)::in,
array(inherit_prof_info)::in, array(compensation_table)::in,
int::in, proc_dynamic::in,
array(own_prof_info)::array_di, array(own_prof_info)::array_uo,
array(inherit_prof_info)::array_di, array(inherit_prof_info)::array_uo)
is det.
summarize_proc_dynamic(PDOwnArray, PDDescArray, PDCompTableArray, PDI, PD,
PSOwnArray0, PSOwnArray, PSDescArray0, PSDescArray) :-
PSPtr = PD ^ pd_proc_static,
PDPtr = proc_dynamic_ptr(PDI),
lookup_pd_own(PDOwnArray, PDPtr, PDOwn),
lookup_pd_desc(PDDescArray, PDPtr, PDDesc0),
lookup_pd_comp_table(PDCompTableArray, PDPtr, PDCompTable),
( if map.search(PDCompTable, PSPtr, InnerTotal) then
PDDesc = subtract_inherit_from_inherit(InnerTotal, PDDesc0)
else
PDDesc = PDDesc0
),
lookup_ps_own(PSOwnArray0, PSPtr, PSOwn0),
lookup_ps_desc(PSDescArray0, PSPtr, PSDesc0),
add_own_to_own(PDOwn, PSOwn0) = PSOwn,
add_inherit_to_inherit(PDDesc, PSDesc0) = PSDesc,
update_ps_own(PSPtr, PSOwn, u(PSOwnArray0), PSOwnArray),
update_ps_desc(PSPtr, PSDesc, u(PSDescArray0), PSDescArray).
:- pred summarize_proc_dynamics_with_coverage_data(deep::in, deep::out) is det.
summarize_proc_dynamics_with_coverage_data(!Deep) :-
% These arrays are one based, the +1 here is necessary to allocate the
% correct amount of storage.
NPS = !.Deep ^ profile_stats ^ prs_num_ps + 1,
array_foldl3_from_1(
summarize_proc_dynamic_with_coverage(!.Deep ^ pd_own,
!.Deep ^ pd_desc, !.Deep ^ pd_comp_table),
!.Deep ^ proc_dynamics,
init(NPS, zero_own_prof_info), PSOwnArray,
init(NPS, zero_inherit_prof_info), PSDescArray,
init(NPS, zero_static_coverage), CoverageArray),
!Deep ^ ps_own := PSOwnArray,
!Deep ^ ps_desc := PSDescArray,
!Deep ^ maybe_static_coverage := yes(CoverageArray).
:- pred summarize_proc_dynamic_with_coverage(array(own_prof_info)::in,
array(inherit_prof_info)::in, array(compensation_table)::in,
int::in, proc_dynamic::in,
array(own_prof_info)::array_di, array(own_prof_info)::array_uo,
array(inherit_prof_info)::array_di, array(inherit_prof_info)::array_uo,
array(static_coverage_info)::array_di,
array(static_coverage_info)::array_uo)
is det.
summarize_proc_dynamic_with_coverage(PDOwnArray, PDDescArray, PDCompTableArray,
PDI, PD, !PSOwnArray, !PSDescArray, !CoverageArray) :-
summarize_proc_dynamic(PDOwnArray, PDDescArray, PDCompTableArray,
PDI, PD, !PSOwnArray, !PSDescArray),
PSPtr = PD ^ pd_proc_static,
MaybeDynamicCoverage = PD ^ pd_maybe_coverage_points,
(
MaybeDynamicCoverage = yes(DynamicCoverage),
some [!StaticCoverage] (
lookup_ps_coverage(!.CoverageArray, PSPtr, !:StaticCoverage),
add_coverage_arrays(DynamicCoverage, !StaticCoverage),
update_ps_coverage(PSPtr, !.StaticCoverage, !CoverageArray)
)
;
MaybeDynamicCoverage = no,
unexpected($pred, "no coverage point array in proc dynamic")
).
%---------------------------------------------------------------------------%
:- pred summarize_call_site_dynamics(deep::in, deep::out) is det.
summarize_call_site_dynamics(!Deep) :-
CSSOwnArray0 = !.Deep ^ css_own,
CSSDescArray0 = !.Deep ^ css_desc,
array_foldl2_from_1(
summarize_call_site_dynamic(
!.Deep ^ call_site_static_map, !.Deep ^ call_site_statics,
!.Deep ^ csd_desc, !.Deep ^ csd_comp_table),
!.Deep ^ call_site_dynamics,
copy(CSSOwnArray0), CSSOwnArray,
copy(CSSDescArray0), CSSDescArray),
!Deep ^ css_own := CSSOwnArray,
!Deep ^ css_desc := CSSDescArray.
:- pred summarize_call_site_dynamic(call_site_static_map::in,
call_site_statics::in, array(inherit_prof_info)::in,
array(compensation_table)::in, int::in, call_site_dynamic::in,
array(own_prof_info)::array_di, array(own_prof_info)::array_uo,
array(inherit_prof_info)::array_di, array(inherit_prof_info)::array_uo)
is det.
summarize_call_site_dynamic(CallSiteStaticMap, CallSiteStatics,
CSDDescs, CSDCompTableArray, CSDI, CSD,
CSSOwnArray0, CSSOwnArray, CSSDescArray0, CSSDescArray) :-
CSDPtr = call_site_dynamic_ptr(CSDI),
lookup_call_site_static_map(CallSiteStaticMap, CSDPtr, CSSPtr),
CSSPtr = call_site_static_ptr(CSSI),
( if CSSI > 0 then
CSDOwn = CSD ^ csd_own_prof,
lookup_csd_desc(CSDDescs, CSDPtr, CSDDesc0),
lookup_csd_comp_table(CSDCompTableArray, CSDPtr, CSDCompTable),
lookup_call_site_statics(CallSiteStatics, CSSPtr, CSS),
( if map.search(CSDCompTable, CSS ^ css_container, InnerTotal) then
CSDDesc = subtract_inherit_from_inherit(InnerTotal, CSDDesc0)
else
CSDDesc = CSDDesc0
),
lookup_css_own(CSSOwnArray0, CSSPtr, CSSOwn0),
lookup_css_desc(CSSDescArray0, CSSPtr, CSSDesc0),
add_own_to_own(CSDOwn, CSSOwn0) = CSSOwn,
add_inherit_to_inherit(CSDDesc, CSSDesc0) = CSSDesc,
update_css_own(CSSPtr, CSSOwn, u(CSSOwnArray0), CSSOwnArray),
update_css_desc(CSSPtr, CSSDesc, u(CSSDescArray0), CSSDescArray)
else
error("summarize_call_site_dynamic: invalid css ptr")
).
%---------------------------------------------------------------------------%
:- pred summarize_modules(deep::in, deep::out) is det.
summarize_modules(Deep0, Deep) :-
ModuleData0 = Deep0 ^ module_data,
ModuleData =
map.map_values_only(summarize_module_costs(Deep0), ModuleData0),
Deep = Deep0 ^ module_data := ModuleData.
:- func summarize_module_costs(deep, module_data) = module_data.
summarize_module_costs(Deep, ModuleData0) = ModuleData :-
ModuleData0 = module_data(Own0, Desc0, PSPtrs),
list.foldl2(accumulate_ps_costs(Deep), PSPtrs, Own0, Own, Desc0, Desc),
ModuleData = module_data(Own, Desc, PSPtrs).
%---------------------------------------------------------------------------%
:- pred summarize_proc_statics_coverage(deep::in, deep::out) is det.
summarize_proc_statics_coverage(!Deep) :-
NPS = !.Deep ^ profile_stats ^ prs_num_ps,
array_foldl_from_1(
summarize_proc_static_coverage,
!.Deep ^ proc_statics,
init(NPS, zero_static_coverage), CoverageArray),
!Deep ^ maybe_static_coverage := yes(CoverageArray).
:- pred summarize_proc_static_coverage(int::in, proc_static::in,
array(static_coverage_info)::array_di,
array(static_coverage_info)::array_uo) is det.
summarize_proc_static_coverage(Index, PS, !CoverageArray) :-
MaybeCoverage = PS ^ ps_maybe_coverage_points,
(
MaybeCoverage = yes(Coverage0),
array_to_static_coverage(Coverage0, Coverage),
array.set(Index, Coverage, !CoverageArray)
;
MaybeCoverage = no,
unexpected($pred, "no coverage data in proc static")
).
%---------------------------------------------------------------------------%
:- pred accumulate_ps_costs(deep::in, proc_static_ptr::in,
own_prof_info::in, own_prof_info::out,
inherit_prof_info::in, inherit_prof_info::out) is det.
accumulate_ps_costs(Deep, PSPtr, Own0, Own, Desc0, Desc) :-
deep_lookup_ps_own(Deep, PSPtr, PSOwn),
deep_lookup_ps_desc(Deep, PSPtr, PSDesc),
Own = add_own_to_own(Own0, PSOwn),
Desc = add_inherit_to_inherit(Desc0, PSDesc).
%---------------------------------------------------------------------------%
:- pred propagate_to_clique(int::in, list(proc_dynamic_ptr)::in,
deep::in, deep::out) is det.
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),
( if valid_call_site_dynamic_ptr(!.Deep, ParentCSDPtr) then
deep_lookup_call_site_dynamics(!.Deep, ParentCSDPtr, ParentCSD),
ParentOwn = ParentCSD ^ csd_own_prof,
deep_lookup_csd_desc(!.Deep, ParentCSDPtr, ParentDesc0),
subtract_own_from_inherit(ParentOwn, ParentDesc0) = ParentDesc,
deep_update_csd_desc(ParentCSDPtr, ParentDesc, !Deep),
CSDCompTable = apply_override(OverrideMap, SumTable),
deep_update_csd_comp_table(ParentCSDPtr, CSDCompTable, !Deep)
else
true
).
:- pred propagate_to_proc_dynamic(int::in, call_site_dynamic_ptr::in,
proc_dynamic_ptr::in, deep::in, deep::out,
compensation_table::in, compensation_table::out,
compensation_table::in, compensation_table::out) is det.
propagate_to_proc_dynamic(CliqueNumber, ParentCSDPtr, PDPtr, !Deep,
!SumTable, !OverrideTable) :-
flat_call_sites(!.Deep ^ proc_dynamics, PDPtr, CSDPtrs),
list.foldl2(propagate_to_call_site(CliqueNumber, PDPtr),
CSDPtrs, !Deep, map.init, PDCompTable),
deep_update_pd_comp_table(PDPtr, PDCompTable, !Deep),
deep_lookup_pd_desc(!.Deep, PDPtr, ProcDesc),
deep_lookup_pd_own(!.Deep, PDPtr, ProcOwn),
ProcTotal = add_own_to_inherit(ProcOwn, ProcDesc),
!:SumTable = add_comp_tables(!.SumTable, PDCompTable),
deep_lookup_proc_dynamics(!.Deep, PDPtr, PD),
PSPtr = PD ^ pd_proc_static,
deep_lookup_proc_statics(!.Deep, PSPtr, PS),
( if PS ^ ps_is_zeroed = zeroed then
!:OverrideTable = add_to_override(!.OverrideTable, PSPtr, ProcTotal)
else
true
),
( if valid_call_site_dynamic_ptr(!.Deep, ParentCSDPtr) then
deep_lookup_csd_desc(!.Deep, ParentCSDPtr, ParentDesc0),
ParentDesc = add_inherit_to_inherit(ParentDesc0, ProcTotal),
deep_update_csd_desc(ParentCSDPtr, ParentDesc, !Deep)
else
true
).
:- pred propagate_to_call_site(int::in, proc_dynamic_ptr::in,
call_site_dynamic_ptr::in, deep::in, deep::out,
compensation_table::in, compensation_table::out) is det.
propagate_to_call_site(CliqueNumber, PDPtr, CSDPtr, !Deep, !PDCompTable) :-
deep_lookup_call_site_dynamics(!.Deep, CSDPtr, CSD),
CalleeOwn = CSD ^ csd_own_prof,
CalleePDPtr = CSD ^ csd_callee,
deep_lookup_clique_index(!.Deep, CalleePDPtr, ChildCliquePtr),
ChildCliquePtr = clique_ptr(ChildCliqueNumber),
( if ChildCliqueNumber = CliqueNumber then
% We don't propagate profiling measurements along intra-clique calls.
true
else
deep_lookup_pd_desc(!.Deep, PDPtr, ProcDesc0),
deep_lookup_csd_desc(!.Deep, CSDPtr, CalleeDesc),
CalleeTotal = add_own_to_inherit(CalleeOwn, CalleeDesc),
ProcDesc = add_inherit_to_inherit(ProcDesc0, CalleeTotal),
deep_update_pd_desc(PDPtr, ProcDesc, !Deep),
deep_lookup_csd_comp_table(!.Deep, CSDPtr, CSDCompTable),
!:PDCompTable = add_comp_tables(!.PDCompTable, CSDCompTable)
).
%---------------------------------------------------------------------------%
:- func add_comp_tables(compensation_table, compensation_table)
= compensation_table.
add_comp_tables(CompTableA, CompTableB) = CompTable :-
( if map.is_empty(CompTableA) then
CompTable = CompTableB
else if map.is_empty(CompTableB) then
CompTable = CompTableA
else
CompTable = map.union(add_inherit_to_inherit, CompTableA, CompTableB)
).
:- func apply_override(compensation_table, compensation_table)
= compensation_table.
apply_override(CompTableA, CompTableB) = CompTable :-
( if map.is_empty(CompTableA) then
CompTable = CompTableB
else if map.is_empty(CompTableB) then
CompTable = CompTableA
else
CompTable = map.union(select_override_comp, CompTableA, CompTableB)
).
:- func select_override_comp(inherit_prof_info, inherit_prof_info)
= inherit_prof_info.
select_override_comp(OverrideComp, _) = OverrideComp.
:- func add_to_override(compensation_table,
proc_static_ptr, inherit_prof_info) = compensation_table.
add_to_override(!.CompTable, PSPtr, PDTotal) = !:CompTable :-
( if map.search(!.CompTable, PSPtr, Comp0) then
Comp = add_inherit_to_inherit(Comp0, PDTotal),
map.det_update(PSPtr, Comp, !CompTable)
else
map.det_insert(PSPtr, PDTotal, !CompTable)
).
%---------------------------------------------------------------------------%
:- pred flat_call_sites(proc_dynamics::in, proc_dynamic_ptr::in,
list(call_site_dynamic_ptr)::out) is det.
flat_call_sites(ProcDynamics, PDPtr, CSDPtrs) :-
lookup_proc_dynamics(ProcDynamics, PDPtr, PD),
CallSiteArray = PD ^ pd_sites,
flatten_call_sites(CallSiteArray, CSDPtrs, _).
:- pred flatten_call_sites(array(call_site_array_slot)::in,
list(call_site_dynamic_ptr)::out, is_zeroed::out) is det.
flatten_call_sites(CallSiteArray, CSDPtrs, IsZeroed) :-
array.to_list(CallSiteArray, CallSites),
list.foldl2(gather_call_site_csdptrs, CallSites, [], CSDPtrsList0,
not_zeroed, IsZeroed),
list.reverse(CSDPtrsList0, CSDPtrsList),
list.condense(CSDPtrsList, CSDPtrs).
:- pred gather_call_site_csdptrs(call_site_array_slot::in,
list(list(call_site_dynamic_ptr))::in,
list(list(call_site_dynamic_ptr))::out,
is_zeroed::in, is_zeroed::out) is det.
gather_call_site_csdptrs(Slot, CSDPtrs0, CSDPtrs1, IsZeroed0, IsZeroed) :-
(
Slot = slot_normal(CSDPtr),
CSDPtr = call_site_dynamic_ptr(CSDI),
( if CSDI > 0 then
CSDPtrs1 = [[CSDPtr] | CSDPtrs0]
else
CSDPtrs1 = CSDPtrs0
),
IsZeroed = IsZeroed0
;
Slot = slot_multi(IsZeroed1, PtrArray),
array.to_list(PtrArray, PtrList0),
list.filter((pred(CSDPtr::in) is semidet :-
CSDPtr = call_site_dynamic_ptr(CSDI),
CSDI > 0
), PtrList0, PtrList1),
CSDPtrs1 = [PtrList1 | CSDPtrs0],
(
IsZeroed1 = zeroed,
IsZeroed = zeroed
;
IsZeroed1 = not_zeroed,
IsZeroed = IsZeroed0
)
).
%---------------------------------------------------------------------------%
:- pred maybe_report_stats(maybe(io.output_stream)::in,
io::di, io::uo) is det.
% XXX: io.report_stats writes to stderr, which mdprof_cgi has closed.
% We want to write the report to _OutputStream, but the library doesn't
% support that yet.
%
% The stats are needed only when writing the deep profiling paper anyway.
maybe_report_stats(yes(_OutputStream), !IO).
% io.report_stats("standard", !IO).
maybe_report_stats(no, !IO).
:- pred maybe_report_msg(maybe(io.output_stream)::in, string::in,
io::di, io::uo) is det.
maybe_report_msg(yes(OutputStream), Msg, !IO) :-
io.write_string(OutputStream, Msg, !IO),
flush_output(OutputStream, !IO).
maybe_report_msg(no, _, !IO).
%---------------------------------------------------------------------------%
:- end_module startup.
%---------------------------------------------------------------------------%