aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer
diff options
context:
space:
mode:
authorStavros Aronis <[email protected]>2012-03-29 14:44:08 +0200
committerHenrik Nord <[email protected]>2012-05-21 15:31:23 +0200
commit5c52ff6b5f10c7bd9ce06cdf607e88035c16e079 (patch)
tree26c35deaaae3d2d2ed425f0580d0b6d6f5d258f2 /lib/dialyzer
parent720b65deff021ddb17aaa125046f97ff13ade883 (diff)
downloadotp-5c52ff6b5f10c7bd9ce06cdf607e88035c16e079.tar.gz
otp-5c52ff6b5f10c7bd9ce06cdf607e88035c16e079.tar.bz2
otp-5c52ff6b5f10c7bd9ce06cdf607e88035c16e079.zip
Anonymous time server
Diffstat (limited to 'lib/dialyzer')
-rw-r--r--lib/dialyzer/src/dialyzer.hrl9
-rw-r--r--lib/dialyzer/src/dialyzer_analysis_callgraph.erl42
-rw-r--r--lib/dialyzer/src/dialyzer_coordinator.erl23
-rw-r--r--lib/dialyzer/src/dialyzer_succ_typings.erl71
-rw-r--r--lib/dialyzer/src/dialyzer_timing.erl51
5 files changed, 105 insertions, 91 deletions
diff --git a/lib/dialyzer/src/dialyzer.hrl b/lib/dialyzer/src/dialyzer.hrl
index ebfc6b9731..70ee408f12 100644
--- a/lib/dialyzer/src/dialyzer.hrl
+++ b/lib/dialyzer/src/dialyzer.hrl
@@ -128,6 +128,7 @@
race_detection = false :: boolean(),
behaviours_chk = false :: boolean(),
timing = false :: boolean(),
+ timing_server :: dialyzer_timing:timing_server(),
callgraph_file = "" :: file:filename()}).
-record(options, {files = [] :: [file:filename()],
@@ -156,11 +157,11 @@
%%--------------------------------------------------------------------
--define(timing(Msg,Var,Expr),
+-define(timing(Server, Msg, Var, Expr),
begin
- dialyzer_timing:start_stamp(Msg),
+ dialyzer_timing:start_stamp(Server, Msg),
Var = Expr,
- dialyzer_timing:end_stamp(),
+ dialyzer_timing:end_stamp(Server),
Var
end).
--define(timing(Msg,Expr),?timing(Msg,_T,Expr)).
+-define(timing(Server, Msg, Expr),?timing(Server, Msg, _T, Expr)).
diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
index 641b7eb22a..3bbde12481 100644
--- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
+++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl
@@ -52,7 +52,8 @@
parent :: pid(),
plt :: dialyzer_plt:plt(),
start_from = byte_code :: start_from(),
- use_contracts = true :: boolean()
+ use_contracts = true :: boolean(),
+ timing_server :: dialyzer_timing:timing_server()
}).
-record(server_state, {parent :: pid(), legal_warnings :: [dial_warn_tag()]}).
@@ -64,14 +65,15 @@
-spec start(pid(), [dial_warn_tag()], #analysis{}) -> 'ok'.
start(Parent, LegalWarnings, Analysis) ->
- dialyzer_timing:init(Analysis#analysis.timing),
+ TimingServer = dialyzer_timing:init(Analysis#analysis.timing),
RacesOn = ordsets:is_element(?WARN_RACE_CONDITION, LegalWarnings),
- Analysis0 = Analysis#analysis{race_detection = RacesOn},
+ Analysis0 =
+ Analysis#analysis{race_detection = RacesOn, timing_server = TimingServer},
Analysis1 = expand_files(Analysis0),
Analysis2 = run_analysis(Analysis1),
State = #server_state{parent = Parent, legal_warnings = LegalWarnings},
loop(State, Analysis2, none),
- dialyzer_timing:stop().
+ dialyzer_timing:stop(TimingServer).
run_analysis(Analysis) ->
Self = self(),
@@ -133,7 +135,8 @@ analysis_start(Parent, Analysis) ->
plt = Plt,
parent = Parent,
start_from = Analysis#analysis.start_from,
- use_contracts = Analysis#analysis.use_contracts
+ use_contracts = Analysis#analysis.use_contracts,
+ timing_server = Analysis#analysis.timing_server
},
Files = ordsets:from_list(Analysis#analysis.files),
{Callgraph, NoWarn, TmpCServer0} = compile_and_store(Files, State),
@@ -157,7 +160,7 @@ analysis_start(Parent, Analysis) ->
dialyzer_codeserver:insert_temp_exported_types(MergedExpTypes,
TmpCServer1),
TmpCServer3 = dialyzer_utils:process_record_remote_types(TmpCServer2),
- ?timing("remote",
+ ?timing(State#analysis_state.timing_server, "remote",
dialyzer_contracts:process_contract_remote_types(TmpCServer3))
catch
throw:{error, _ErrorMsg} = Error -> exit(Error)
@@ -186,22 +189,23 @@ analysis_start(Parent, Analysis) ->
send_codeserver_plt(Parent, CServer, State3#analysis_state.plt),
send_analysis_done(Parent, Plt2, State3#analysis_state.doc_plt).
-analyze_callgraph(Callgraph, State) ->
- Codeserver = State#analysis_state.codeserver,
- Parent = State#analysis_state.parent,
- DocPlt = State#analysis_state.doc_plt,
+analyze_callgraph(Callgraph, #analysis_state{codeserver = Codeserver,
+ doc_plt = DocPlt,
+ timing_server = TimingServer,
+ parent = Parent} = State) ->
Plt = dialyzer_plt:insert_callbacks(State#analysis_state.plt, Codeserver),
{NewPlt, NewDocPlt} =
case State#analysis_state.analysis_type of
plt_build ->
- {dialyzer_succ_typings:analyze_callgraph(Callgraph, Plt,
- Codeserver, Parent),
- DocPlt};
+ NewPlt0 =
+ dialyzer_succ_typings:analyze_callgraph(Callgraph, Plt, Codeserver,
+ TimingServer, Parent),
+ {NewPlt0, DocPlt};
succ_typings ->
NoWarn = State#analysis_state.no_warn_unused,
{Warnings, NewPlt0, NewDocPlt0} =
- dialyzer_succ_typings:get_warnings(Callgraph, Plt, DocPlt,
- Codeserver, NoWarn, Parent),
+ dialyzer_succ_typings:get_warnings(Callgraph, Plt, DocPlt, Codeserver,
+ NoWarn, TimingServer, Parent),
send_warnings(State#analysis_state.parent, Warnings),
{NewPlt0, NewDocPlt0}
end,
@@ -234,14 +238,16 @@ make_compile_init(#analysis_state{codeserver = Codeserver,
start_from = StartFrom}.
compile_and_store(Files, #analysis_state{codeserver = CServer,
+ timing_server = Timing,
parent = Parent} = State) ->
send_log(Parent, "Reading files and computing callgraph... "),
{T1, _} = statistics(runtime),
Callgraph = dialyzer_callgraph:new(),
CompileInit = make_compile_init(State, Callgraph),
{{Failed, NoWarn, Modules}, NextLabel} =
- ?timing("compile",
- dialyzer_coordinator:parallel_job(compile, Files, CompileInit)),
+ ?timing(Timing, "compile", _C1,
+ dialyzer_coordinator:parallel_job(compile, Files,
+ CompileInit, Timing)),
CServer2 = dialyzer_codeserver:set_next_core_label(NextLabel, CServer),
case Failed =:= [] of
true ->
@@ -259,7 +265,7 @@ compile_and_store(Files, #analysis_state{codeserver = CServer,
Msg1 = io_lib:format("done in ~.2f secs\nRemoving edges... ", [(T2-T1)/1000]),
send_log(Parent, Msg1),
Callgraph =
- ?timing("clean", _C3,
+ ?timing(Timing, "clean", _C2,
cleanup_callgraph(State, CServer2, Callgraph, Modules)),
{T3, _} = statistics(runtime),
Msg2 = io_lib:format("done in ~.2f secs\n", [(T3-T2)/1000]),
diff --git a/lib/dialyzer/src/dialyzer_coordinator.erl b/lib/dialyzer/src/dialyzer_coordinator.erl
index e81da5c456..b91fc95959 100644
--- a/lib/dialyzer/src/dialyzer_coordinator.erl
+++ b/lib/dialyzer/src/dialyzer_coordinator.erl
@@ -26,7 +26,7 @@
-module(dialyzer_coordinator).
%%% Export for dialyzer main process
--export([parallel_job/3]).
+-export([parallel_job/4]).
%%% Exports for all possible workers
-export([wait_activation/0, job_done/3]).
@@ -44,6 +44,7 @@
-define(MAP, dialyzer_coordinator_map).
-type coordinator() :: {pid(), pid()}. %%opaque
+-type timing() :: dialyzer_timing:timing_server().
-type scc() :: [mfa_or_funlbl()].
-type mode() :: 'typesig' | 'dataflow' | 'compile' | 'warnings'.
@@ -85,20 +86,20 @@
%%--------------------------------------------------------------------
--spec parallel_job('compile', compile_jobs(), compile_init_data()) ->
+-spec parallel_job('compile', compile_jobs(), compile_init_data(), timing()) ->
{compile_result(), integer()};
- ('typesig', typesig_jobs(), typesig_init_data()) ->
+ ('typesig', typesig_jobs(), typesig_init_data(), timing()) ->
typesig_result();
- ('dataflow', dataflow_jobs(), dataflow_init_data()) ->
- dataflow_result();
- ('warnings', warnings_jobs(), warnings_init_data()) ->
- warnings_result().
+ ('dataflow', dataflow_jobs(), dataflow_init_data(),
+ timing()) -> dataflow_result();
+ ('warnings', warnings_jobs(), warnings_init_data(),
+ timing()) -> warnings_result().
-parallel_job(Mode, Jobs, InitData) ->
- State = spawn_jobs(Mode, Jobs, InitData),
+parallel_job(Mode, Jobs, InitData, Timing) ->
+ State = spawn_jobs(Mode, Jobs, InitData, Timing),
collect_result(State).
-spawn_jobs(Mode, Jobs, InitData) ->
+spawn_jobs(Mode, Jobs, InitData, Timing) ->
Collector = self(),
Regulator = spawn_regulator(),
Coordinator = {Collector, Regulator},
@@ -123,7 +124,7 @@ spawn_jobs(Mode, Jobs, InitData) ->
'typesig' -> "SCCs";
_ -> "modules"
end,
- dialyzer_timing:send_size_info(JobCount, Unit),
+ dialyzer_timing:send_size_info(Timing, JobCount, Unit),
InitResult =
case Mode of
'compile' -> dialyzer_analysis_callgraph:compile_init_result();
diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl
index 9f61f9ff6f..9ca5a66dab 100644
--- a/lib/dialyzer/src/dialyzer_succ_typings.erl
+++ b/lib/dialyzer/src/dialyzer_succ_typings.erl
@@ -28,8 +28,8 @@
-module(dialyzer_succ_typings).
-export([analyze_callgraph/3,
- analyze_callgraph/4,
- get_warnings/6
+ analyze_callgraph/5,
+ get_warnings/7
]).
-export([
@@ -74,6 +74,7 @@
codeserver :: dialyzer_codeserver:codeserver(),
no_warn_unused :: set(),
parent = none :: parent(),
+ timing_server :: dialyzer_timing:timing_server(),
plt :: dialyzer_plt:plt()}).
%%--------------------------------------------------------------------
@@ -83,33 +84,38 @@
dialyzer_plt:plt().
analyze_callgraph(Callgraph, Plt, Codeserver) ->
- analyze_callgraph(Callgraph, Plt, Codeserver, none).
+ analyze_callgraph(Callgraph, Plt, Codeserver, none, none).
-spec analyze_callgraph(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(),
- dialyzer_codeserver:codeserver(), parent()) ->
+ dialyzer_codeserver:codeserver(),
+ dialyzer_timing:timing_server(), parent()) ->
dialyzer_plt:plt().
-analyze_callgraph(Callgraph, Plt, Codeserver, Parent) ->
+analyze_callgraph(Callgraph, Plt, Codeserver, TimingServer, Parent) ->
NewState =
- init_state_and_get_success_typings(Callgraph, Plt, Codeserver, Parent),
+ init_state_and_get_success_typings(Callgraph, Plt, Codeserver,
+ TimingServer, Parent),
dialyzer_plt:restore_full_plt(NewState#st.plt, Plt).
%%--------------------------------------------------------------------
-init_state_and_get_success_typings(Callgraph, Plt, Codeserver, Parent) ->
+init_state_and_get_success_typings(Callgraph, Plt, Codeserver,
+ TimingServer, Parent) ->
{SCCs, Callgraph1} =
- ?timing("order", dialyzer_callgraph:finalize(Callgraph)),
+ ?timing(TimingServer, "order", dialyzer_callgraph:finalize(Callgraph)),
State = #st{callgraph = Callgraph1, plt = dialyzer_plt:get_mini_plt(Plt),
- codeserver = Codeserver, parent = Parent},
+ codeserver = Codeserver, parent = Parent,
+ timing_server = TimingServer},
get_refined_success_typings(SCCs, State).
-get_refined_success_typings(SCCs, #st{callgraph = Callgraph} = State) ->
+get_refined_success_typings(SCCs, #st{callgraph = Callgraph,
+ timing_server = TimingServer} = State) ->
case find_succ_typings(SCCs, State) of
{fixpoint, State1} -> State1;
{not_fixpoint, NotFixpoint1, State1} ->
{ModulePostorder, ModCallgraph} =
?timing(
- "order", _C1,
+ TimingServer, "order", _C1,
dialyzer_callgraph:module_postorder_from_funs(NotFixpoint1,
Callgraph)),
ModState = State1#st{callgraph = ModCallgraph},
@@ -119,7 +125,7 @@ get_refined_success_typings(SCCs, #st{callgraph = Callgraph} = State) ->
{not_fixpoint, NotFixpoint2, State2} ->
%% Need to reset the callgraph.
{NewSCCs, Callgraph2} =
- ?timing("order", _C2,
+ ?timing(TimingServer, "order", _C2,
dialyzer_callgraph:reset_from_funs(NotFixpoint2,
ModCallgraph)),
NewState = State2#st{callgraph = Callgraph2},
@@ -130,12 +136,14 @@ get_refined_success_typings(SCCs, #st{callgraph = Callgraph} = State) ->
-type doc_plt() :: 'undefined' | dialyzer_plt:plt().
-spec get_warnings(dialyzer_callgraph:callgraph(), dialyzer_plt:plt(),
doc_plt(), dialyzer_codeserver:codeserver(), set(),
- pid()) ->
+ dialyzer_timing:timing_server(), pid()) ->
{[dial_warning()], dialyzer_plt:plt(), doc_plt()}.
-get_warnings(Callgraph, Plt, DocPlt, Codeserver, NoWarnUnused, Parent) ->
+get_warnings(Callgraph, Plt, DocPlt, Codeserver,
+ NoWarnUnused, TimingServer, Parent) ->
InitState =
- init_state_and_get_success_typings(Callgraph, Plt, Codeserver, Parent),
+ init_state_and_get_success_typings(Callgraph, Plt, Codeserver,
+ TimingServer, Parent),
NewState = InitState#st{no_warn_unused = NoWarnUnused},
Mods = dialyzer_callgraph:modules(NewState#st.callgraph),
MiniPlt = NewState#st.plt,
@@ -143,22 +151,22 @@ get_warnings(Callgraph, Plt, DocPlt, Codeserver, NoWarnUnused, Parent) ->
dialyzer_contracts:get_invalid_contract_warnings(Mods, Codeserver, MiniPlt),
MiniDocPlt = dialyzer_plt:get_mini_plt(DocPlt),
ModWarns =
- ?timing("warning", get_warnings_from_modules(Mods, NewState, MiniDocPlt)),
+ ?timing(TimingServer, "warning",
+ get_warnings_from_modules(Mods, NewState, MiniDocPlt)),
{postprocess_warnings(CWarns ++ ModWarns, Codeserver),
dialyzer_plt:restore_full_plt(MiniPlt, Plt),
dialyzer_plt:restore_full_plt(MiniDocPlt, DocPlt)}.
get_warnings_from_modules(Mods, State, DocPlt) ->
#st{callgraph = Callgraph, codeserver = Codeserver,
- no_warn_unused = NoWarnUnused, plt = Plt} = State,
- Init = {Callgraph, Codeserver, NoWarnUnused, Plt, DocPlt},
- dialyzer_coordinator:parallel_job(warnings, Mods, Init).
+ no_warn_unused = NoWarnUnused, plt = Plt,
+ timing_server = TimingServer} = State,
+ Init = {Codeserver, Callgraph, NoWarnUnused, Plt, DocPlt},
+ dialyzer_coordinator:parallel_job(warnings, Mods, Init, TimingServer).
--type warning_servers() :: term().
+-spec collect_warnings(module(), warnings_init_data()) -> [dial_warning()].
--spec collect_warnings(module(), warning_servers()) -> [dial_warning()].
-
-collect_warnings(M, {Callgraph, Codeserver, NoWarnUnused, Plt, DocPlt}) ->
+collect_warnings(M, {Codeserver, Callgraph, NoWarnUnused, Plt, DocPlt}) ->
ModCode = dialyzer_codeserver:lookup_mod_code(M, Codeserver),
Records = dialyzer_codeserver:lookup_mod_records(M, Codeserver),
Contracts = dialyzer_codeserver:lookup_mod_contracts(M, Codeserver),
@@ -212,13 +220,14 @@ postprocess_dataflow_warns([{?WARN_CONTRACT_RANGE, {CallF, CallL}, Msg}|Rest],
end.
refine_succ_typings(Modules, #st{codeserver = Codeserver,
- callgraph = Callgraph,
- plt = Plt} = State) ->
- ?debug("Module postorder: ~p\n", [ModulePostorder]),
+ callgraph = Callgraph,
+ plt = Plt,
+ timing_server = Timing} = State) ->
+ ?debug("Module postorder: ~p\n", [Modules]),
Init = {Codeserver, Callgraph, Plt},
NotFixpoint =
- ?timing("refine",
- dialyzer_coordinator:parallel_job(dataflow, Modules, Init)),
+ ?timing(Timing, "refine",
+ dialyzer_coordinator:parallel_job(dataflow, Modules, Init, Timing)),
?debug("==================== Dataflow done ====================\n\n", []),
case NotFixpoint =:= [] of
true -> {fixpoint, State};
@@ -313,11 +322,11 @@ compare_types_1([], [], _Strict, NotFixpoint) ->
end.
find_succ_typings(SCCs, #st{codeserver = Codeserver, callgraph = Callgraph,
- plt = Plt} = State) ->
+ plt = Plt, timing_server = Timing} = State) ->
Init = {Codeserver, Callgraph, Plt},
NotFixpoint =
- ?timing("typesig",
- dialyzer_coordinator:parallel_job(typesig, SCCs, Init)),
+ ?timing(Timing, "typesig",
+ dialyzer_coordinator:parallel_job(typesig, SCCs, Init, Timing)),
?debug("==================== Typesig done ====================\n\n", []),
case NotFixpoint =:= [] of
true -> {fixpoint, State};
diff --git a/lib/dialyzer/src/dialyzer_timing.erl b/lib/dialyzer/src/dialyzer_timing.erl
index d5e6d1476d..15d8795a37 100644
--- a/lib/dialyzer/src/dialyzer_timing.erl
+++ b/lib/dialyzer/src/dialyzer_timing.erl
@@ -26,27 +26,20 @@
-module(dialyzer_timing).
--export([init/1, start_stamp/1, send_size_info/2, end_stamp/0, stop/0]).
+-export([init/1, start_stamp/2, send_size_info/3, end_stamp/1, stop/1]).
--spec init(boolean()) -> ok.
+-export_type([timing_server/0]).
-init(Active) ->
- Pid = spawn_link(fun() -> loop_init(Active) end),
- register(?MODULE, Pid),
- ok.
+-type timing_server() :: pid() | 'none'.
-loop_init(Active) ->
+-spec init(boolean()) -> timing_server().
+
+init(Active) ->
case Active of
true ->
io:format("\n"),
- loop(now(), 0, "");
- false -> dummy_loop()
- end.
-
-dummy_loop() ->
- receive
- {Pid, stop, _Now} -> Pid ! ok;
- _ -> dummy_loop()
+ spawn_link(fun() -> loop(now(), 0, "") end);
+ false -> none
end.
loop(LastNow, Size, Unit) ->
@@ -73,28 +66,32 @@ loop(LastNow, Size, Unit) ->
Pid ! ok
end.
--spec start_stamp(string()) -> ok.
+-spec start_stamp(timing_server(), string()) -> ok.
-start_stamp(Msg) ->
- ?MODULE ! {stamp, Msg, now()},
+start_stamp(none, _) -> ok;
+start_stamp(Pid, Msg) ->
+ Pid ! {stamp, Msg, now()},
ok.
--spec end_stamp() -> ok.
+-spec end_stamp(timing_server()) -> ok.
-end_stamp() ->
- ?MODULE ! {stamp, now()},
+end_stamp(none) -> ok;
+end_stamp(Pid) ->
+ Pid ! {stamp, now()},
ok.
--spec send_size_info(integer(), string()) -> ok.
+-spec send_size_info(timing_server(), integer(), string()) -> ok.
-send_size_info(Size, Unit) ->
- ?MODULE ! {size, Size, Unit},
+send_size_info(none, _, _) -> ok;
+send_size_info(Pid, Size, Unit) ->
+ Pid ! {size, Size, Unit},
ok.
--spec stop() -> ok.
+-spec stop(timing_server()) -> ok.
-stop() ->
- ?MODULE ! {self(), stop, now()},
+stop(none) -> ok;
+stop(Pid) ->
+ Pid ! {self(), stop, now()},
receive ok -> ok end.
diff(T2, T1) ->