From 009710cec5e8b9786a5219dc3f682d6010352160 Mon Sep 17 00:00:00 2001 From: Stavros Aronis Date: Mon, 20 Feb 2012 15:54:43 +0100 Subject: Parallel warning generation --- lib/dialyzer/src/dialyzer_coordinator.erl | 38 +++++++++++++++++-------- lib/dialyzer/src/dialyzer_succ_typings.erl | 45 ++++++++++++++++++------------ lib/dialyzer/src/dialyzer_worker.erl | 9 +++++- 3 files changed, 61 insertions(+), 31 deletions(-) (limited to 'lib/dialyzer/src') 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). -- cgit v1.2.3