From ee5abef97c303ea7ac6e782cf7c949d84f856326 Mon Sep 17 00:00:00 2001 From: Phoebe Nichols Date: Wed, 24 Jul 2019 11:52:25 -0700 Subject: [PATCH] Invalidate summaries for changed procedures Summary: This implements incremental diff analysis by deleting only the summaries that need to be re-analyzed, keeping all summaries corresponding to procedures that have not been changed (or had a callee change). Reviewed By: jvillard Differential Revision: D16358474 fbshipit-source-id: 660a704a0 --- infer/src/backend/CallGraph.ml | 8 ++++++++ infer/src/backend/CallGraph.mli | 8 ++++++-- infer/src/backend/InferAnalyze.ml | 16 ++++++++++++++++ infer/src/backend/ReverseAnalysisCallGraph.mli | 2 -- infer/src/backend/SpecsFiles.mli | 4 ---- infer/src/backend/TaskScheduler.ml | 5 +---- infer/src/base/Config.mli | 3 +-- 7 files changed, 32 insertions(+), 14 deletions(-) diff --git a/infer/src/backend/CallGraph.ml b/infer/src/backend/CallGraph.ml index 72324cac4..679c668cb 100644 --- a/infer/src/backend/CallGraph.ml +++ b/infer/src/backend/CallGraph.ml @@ -158,3 +158,11 @@ let get_unflagged_leaves g = (fun _id (n : Node.t) acc -> if n.flag || List.exists n.successors ~f:(mem g) then acc else n :: acc ) g.node_map [] + + +let iter_flagged graph ~f = + NodeMap.iter (fun _id node -> if node.Node.flag then f node else ()) graph.node_map + + +(** choose some reasonable minimum capacity that also is a prime number *) +let default_initial_capacity = 1009 diff --git a/infer/src/backend/CallGraph.mli b/infer/src/backend/CallGraph.mli index 6a0fbcb92..eb7dd7ac9 100644 --- a/infer/src/backend/CallGraph.mli +++ b/infer/src/backend/CallGraph.mli @@ -56,11 +56,15 @@ val trim_id_map : t -> unit val remove_unflagged_and_unflag_all : t -> unit (** remove all nodes with flag set to false, and set flag to false on all remaining nodes *) -(* suppress unused value warning until this is used for T47276251 *) val add_edge : t -> pname:Typ.Procname.t -> successor_pname:Typ.Procname.t -> unit - [@@warning "-32"] (** add an edge from [pname] to [successor_pname] in the graph, creating a node for [pname] if there isn't one already *) val create_node : t -> Typ.Procname.t -> Typ.Procname.t sexp_list -> unit (** create a new node with edges from [pname] to [successor_pnames] in the graph *) + +val iter_flagged : t -> f:(Node.t -> unit) -> unit +(** iterate over the nodes in the graph with flag set to true *) + +val default_initial_capacity : int +(** reasonable minimum capacity for the graph that is prime *) diff --git a/infer/src/backend/InferAnalyze.ml b/infer/src/backend/InferAnalyze.ml index a781c0461..0918b83bd 100644 --- a/infer/src/backend/InferAnalyze.ml +++ b/infer/src/backend/InferAnalyze.ml @@ -141,12 +141,28 @@ let analyze source_files_to_analyze = collected_stats ) +let invalidate_changed_procedures changed_files = + L.progress "Incremental analysis: invalidating procedures that have been changed@." ; + let reverse_callgraph = CallGraph.create CallGraph.default_initial_capacity in + ReverseAnalysisCallGraph.build reverse_callgraph ; + SourceFile.Set.iter + (fun sf -> + SourceFiles.proc_names_of_source sf + |> List.iter ~f:(CallGraph.flag_reachable reverse_callgraph) ) + changed_files ; + CallGraph.iter_flagged reverse_callgraph ~f:(fun node -> SpecsFiles.delete node.pname) ; + (* save some memory *) + CallGraph.reset reverse_callgraph + + let main ~changed_files = register_active_checkers () ; if Config.reanalyze then ( L.progress "Invalidating procedures to be reanalyzed@." ; Summary.OnDisk.reset_all ~filter:(Lazy.force Filtering.procedures_filter) () ; L.progress "Done@." ) + else if Config.incremental_analysis then + Option.iter ~f:invalidate_changed_procedures changed_files else DB.Results_dir.clean_specs_dir () ; let source_files = get_source_files_to_analyze ~changed_files in (* empty all caches to minimize the process heap to have less work to do when forking *) diff --git a/infer/src/backend/ReverseAnalysisCallGraph.mli b/infer/src/backend/ReverseAnalysisCallGraph.mli index feb608232..d64f21d60 100644 --- a/infer/src/backend/ReverseAnalysisCallGraph.mli +++ b/infer/src/backend/ReverseAnalysisCallGraph.mli @@ -6,7 +6,5 @@ *) open! IStd -(* Suppress unused value warning until this is used for incremental diff analysis *) val build : CallGraph.t -> unit - [@@warning "-32"] (** Build the graph from the summaries in the .specs files *) diff --git a/infer/src/backend/SpecsFiles.mli b/infer/src/backend/SpecsFiles.mli index 3daafbe6b..0be7a220b 100644 --- a/infer/src/backend/SpecsFiles.mli +++ b/infer/src/backend/SpecsFiles.mli @@ -7,17 +7,13 @@ open! IStd -(* Suppress unused value warning until this is used for incremental diff analysis *) val iter : f:(Summary.t -> unit) -> unit - [@@warning "-32"] (** Iterates over all summaries from the .specs files *) val iter_from_config : f:(Summary.t -> unit) -> unit (** Iterates over all sumaries from the .specs files unless a list of specs files has been passed on the command line *) -(* Suppress unused value warning until this is used for incremental diff analysis *) val delete : Typ.Procname.t -> unit - [@@warning "-32"] (** Delete the .specs file associated with a summary and remove the summary from the caches in Summary.ml and ondemand.ml *) diff --git a/infer/src/backend/TaskScheduler.ml b/infer/src/backend/TaskScheduler.ml index fb17c54d2..b222151a5 100644 --- a/infer/src/backend/TaskScheduler.ml +++ b/infer/src/backend/TaskScheduler.ml @@ -38,14 +38,11 @@ let count_procedures () = count -(** choose some reasonable minimum capacity that also is a prime number *) -let initial_call_graph_capacity = 1009 - let bottom_up sources : target task_generator = (* this will potentially grossly overapproximate the tasks *) let remaining = ref (count_procedures ()) in let remaining_tasks () = !remaining in - let syntactic_call_graph = CallGraph.create initial_call_graph_capacity in + let syntactic_call_graph = CallGraph.create CallGraph.default_initial_capacity in let initialized = ref false in let pending : CallGraph.Node.t list ref = ref [] in let scheduled = ref Typ.Procname.Set.empty in diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index 627de22c3..8cdc78b21 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -191,8 +191,7 @@ val unsafe_unret : string val use_cost_threshold : bool -(* Suppress unused value warning because the incremental analysis feature is not yet complete *) -val incremental_analysis : bool [@@warning "-32"] +val incremental_analysis : bool val weak : string