aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer
diff options
context:
space:
mode:
authorStavros Aronis <[email protected]>2012-02-20 15:54:43 +0100
committerHenrik Nord <[email protected]>2012-05-21 15:31:19 +0200
commit009710cec5e8b9786a5219dc3f682d6010352160 (patch)
treedb8ad51ffea3f8287b36cc6e531e8495ccfe0b55 /lib/dialyzer
parent60e682897f98d9374b96c6324759f302170b2a17 (diff)
downloadotp-009710cec5e8b9786a5219dc3f682d6010352160.tar.gz
otp-009710cec5e8b9786a5219dc3f682d6010352160.tar.bz2
otp-009710cec5e8b9786a5219dc3f682d6010352160.zip
Parallel warning generation
Diffstat (limited to 'lib/dialyzer')
-rw-r--r--lib/dialyzer/src/dialyzer_coordinator.erl38
-rw-r--r--lib/dialyzer/src/dialyzer_succ_typings.erl45
-rw-r--r--lib/dialyzer/src/dialyzer_worker.erl9
3 files changed, 61 insertions, 31 deletions
diff --git a/lib/dialyzer/src/dialyzer_coordinator.erl b/lib/dialyzer/src/dialyzer_coordinator.erl
index 9bcd7e4c63..93159ce7df 100644
--- a/lib/dialyzer/src/dialyzer_coordinator.erl
+++ b/lib/dialyzer/src/dialyzer_coordinator.erl
@@ -53,9 +53,14 @@
%%% Exports for all possible workers
-export([job_done/3]).
-%%% Exports for the typesig and dataflow analysis main process
--export([scc_spawn/2,
- receive_not_fixpoint/0]).
+%%% Export for the typesig, dataflow and warnings main process
+-export([scc_spawn/2]).
+
+%%% Export for the typesig and dataflow analysis main process
+-export([receive_not_fixpoint/0]).
+
+%%% Export for warning main process
+-export([receive_warnings/0]).
%%% Exports for the typesig and dataflow analysis workers
-export([sccs_to_pids_reply/0,
@@ -79,10 +84,11 @@
-type coordinator() :: pid(). %%opaque
-type map() :: dict().
--type scc() :: [mfa_or_funlbl()].
--type mode() :: 'typesig' | 'dataflow' | 'compile'.
+-type scc() :: [mfa_or_funlbl()] | module().
+-type mode() :: 'typesig' | 'dataflow' | 'compile' | 'warnings'.
-type servers() :: dialyzer_succ_typings:servers() |
- dialyzer_analysis_callgraph:servers().
+ dialyzer_analysis_callgraph:servers() |
+ dialyzer_succ_typings:warning_servers().
-record(state, {parent :: pid(),
mode :: mode(),
@@ -91,7 +97,8 @@
job_to_pid :: map(),
next_label :: integer(),
result :: [mfa_or_funlbl()] |
- dialyzer_analysis_callgraph:result(),
+ dialyzer_analysis_callgraph:result() |
+ [dial_warning()],
init_job_data :: servers()
}).
@@ -99,8 +106,7 @@
%%--------------------------------------------------------------------
--spec start('typesig' | 'dataflow', dialyzer_succ_typings:servers()) -> pid();
- ('compile', dialyzer_analysis_callgraph:servers()) -> pid().
+-spec start(mode(), servers()) -> coordinator().
start(Mode, Servers) ->
{ok, Pid} = gen_server:start(?MODULE, {self(), Mode, Servers}, []),
@@ -150,7 +156,8 @@ send_done_to_parent(#state{mode = Mode,
Msg =
case Mode of
X when X =:= 'typesig'; X =:= 'dataflow' -> {not_fixpoint, Result};
- 'compile' -> {compilation_data, Result, NextLabel}
+ 'compile' -> {compilation_data, Result, NextLabel};
+ 'warnings' -> {warnings, Result}
end,
Parent ! Msg,
ok.
@@ -168,6 +175,11 @@ receive_compilation_data() ->
{CompilationData, NextLabel}
end.
+-spec receive_warnings() -> [dial_warning()].
+
+receive_warnings() ->
+ receive {warnings, Warnings} -> Warnings end.
+
-spec compiler_spawn(file:filename(), coordinator()) -> ok.
compiler_spawn(Filename, Coordinator) ->
@@ -186,7 +198,7 @@ init({Parent, Mode, InitJobData}) ->
InitState = #state{parent = Parent, mode = Mode, init_job_data = InitJobData},
State =
case Mode of
- X when X =:= 'typesig'; X =:= 'dataflow' ->
+ X when X =:= 'typesig'; X =:= 'dataflow'; X =:= 'warnings' ->
InitState#state{result = [], job_to_pid = new_map()};
'compile' ->
InitResult = dialyzer_analysis_callgraph:compile_coordinator_init(),
@@ -215,7 +227,9 @@ handle_cast({done, Job, NewData},
X when X =:= 'typesig'; X =:= 'dataflow' ->
ordsets:union(OldResult, NewData);
'compile' ->
- dialyzer_analysis_callgraph:add_to_result(Job, NewData, OldResult)
+ dialyzer_analysis_callgraph:add_to_result(Job, NewData, OldResult);
+ 'warnings' ->
+ NewData ++ OldResult
end,
UpdatedState = State#state{result = NewResult},
Action =
diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl
index e901677ce2..fbd333f905 100644
--- a/lib/dialyzer/src/dialyzer_succ_typings.erl
+++ b/lib/dialyzer/src/dialyzer_succ_typings.erl
@@ -38,10 +38,11 @@
collect_scc_data/2,
collect_refine_scc_data/2,
find_required_by/2,
- find_depends_on/2
+ find_depends_on/2,
+ collect_warnings/2
]).
--export_type([servers/0, scc_data/0, scc_refine_data/0]).
+-export_type([servers/0, scc_data/0, scc_refine_data/0, warning_servers/0]).
%%-define(DEBUG, true).
@@ -128,20 +129,31 @@ get_warnings(Callgraph, Plt, DocPlt, Codeserver, NoWarnUnused, Parent) ->
init_state_and_get_success_typings(Callgraph, Plt, Codeserver, Parent),
NewState = InitState#st{no_warn_unused = NoWarnUnused},
Mods = dialyzer_callgraph:modules(NewState#st.callgraph),
- CWarns = dialyzer_contracts:get_invalid_contract_warnings(Mods, Codeserver,
- NewState#st.plt),
+ MiniPlt = NewState#st.plt,
+ CWarns =
+ dialyzer_contracts:get_invalid_contract_warnings(Mods, Codeserver, MiniPlt),
MiniDocPlt = dialyzer_plt:get_mini_plt(DocPlt),
- {Warnings, FinalPlt, FinalDocPlt} =
- ?timing("warning",
- get_warnings_from_modules(Mods, NewState, MiniDocPlt, CWarns)),
- {postprocess_warnings(Warnings, Codeserver),
- dialyzer_plt:restore_full_plt(FinalPlt, Plt),
- dialyzer_plt:restore_full_plt(FinalDocPlt, DocPlt)}.
-
-get_warnings_from_modules([M|Ms], State, DocPlt, Acc) when is_atom(M) ->
- send_log(State#st.parent, io_lib:format("Getting warnings for ~w\n", [M])),
+ ModWarns =
+ ?timing("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,
+ Servers = {Callgraph, Codeserver, NoWarnUnused, Plt, DocPlt},
+ Coordinator = dialyzer_coordinator:start('warnings', Servers),
+ Spawner = fun(M) -> dialyzer_coordinator:scc_spawn(M, Coordinator) end,
+ lists:foreach(Spawner, Mods),
+ dialyzer_coordinator:all_spawned(Coordinator),
+ dialyzer_coordinator:receive_warnings().
+
+-type warning_servers() :: term().
+
+-spec collect_warnings(module(), warning_servers()) -> [dial_warning()].
+
+collect_warnings(M, {Callgraph, Codeserver, 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),
@@ -154,11 +166,8 @@ get_warnings_from_modules([M|Ms], State, DocPlt, Acc) when is_atom(M) ->
Records, NoWarnUnused),
Attrs = cerl:module_attrs(ModCode),
Warnings3 = dialyzer_behaviours:check_callbacks(M, Attrs, Plt, Codeserver),
- NewDocPlt = insert_into_doc_plt(FunTypes, Callgraph, DocPlt),
- get_warnings_from_modules(Ms, State, NewDocPlt,
- [Warnings1, Warnings2, Warnings3|Acc]);
-get_warnings_from_modules([], #st{plt = Plt}, DocPlt, Acc) ->
- {lists:flatten(Acc), Plt, DocPlt}.
+ DocPlt = insert_into_doc_plt(FunTypes, Callgraph, DocPlt),
+ lists:flatten([Warnings1, Warnings2, Warnings3]).
postprocess_warnings(RawWarnings, Codeserver) ->
Pred =
diff --git a/lib/dialyzer/src/dialyzer_worker.erl b/lib/dialyzer/src/dialyzer_worker.erl
index 48dae7cb56..6608b78f0a 100644
--- a/lib/dialyzer/src/dialyzer_worker.erl
+++ b/lib/dialyzer/src/dialyzer_worker.erl
@@ -64,7 +64,7 @@ launch(Mode, Job, Servers, Coordinator) ->
InitState =
case Mode of
X when X =:= 'typesig'; X =:= 'dataflow' -> initializing;
- 'compile' -> running
+ X when X =:= 'compile'; X =:= 'warnings' -> running
end,
spawn(fun() -> loop(InitState, State) end).
@@ -109,6 +109,10 @@ loop(running, #state{mode = 'compile'} = State) ->
Error
end,
report_to_coordinator(Result, State);
+loop(running, #state{mode = 'warnings'} = State) ->
+ ?debug("Warning: ~s\n",[State#state.job]),
+ Result = collect_warnings(State),
+ report_to_coordinator(Result, State);
loop(running, #state{mode = Mode} = State) when
Mode =:= 'typesig'; Mode =:= 'dataflow' ->
?debug("Run: ~p\n",[State#state.job]),
@@ -184,3 +188,6 @@ ask_coordinator_for_label(EstimatedSize, #state{coordinator = Coordinator}) ->
continue_compilation(Label, Data) ->
dialyzer_analysis_callgraph:continue_compilation(Label, Data).
+
+collect_warnings(#state{job = Job, servers = Servers}) ->
+ dialyzer_succ_typings:collect_warnings(Job, Servers).