[Infer][incremental] Procedure-level incrementality

Summary: Adding the option to analyze only procedures whose procdescs have changed
master
Sam Blackshear 10 years ago
parent d99ddd1ede
commit 2d31a8c4aa

@ -638,22 +638,26 @@ let compute_clusters exe_env files_changed : cluster list =
print_clusters_stats clusters'; print_clusters_stats clusters';
clusters' clusters'
(** Check whether the cg file is changed. It is unchanged if for each defined procedure, the .specs (** compute the set of procedures in [cg] changed since the last analysis *)
file exists and is more recent than the cg file. *) let cg_get_changed_procs exe_env source_dir cg =
let cg_check_changed exe_env source_dir cg = let cfg_fname = DB.source_dir_get_internal_file source_dir ".cfg" in
let cg_fname = DB.source_dir_get_internal_file source_dir ".cg" in let cfg_opt = Cfg.load_cfg_from_file cfg_fname in
let defined_nodes = Cg.get_defined_nodes cg in let pdesc_changed pname =
let changed = ref false in match cfg_opt with
let cg_source_file = Cg.get_source cg in | Some cfg -> Cfg.pdesc_is_changed cfg pname
let proc_is_active pname = DB.source_file_equal (Exe_env.get_source exe_env pname) cg_source_file in | None -> true in
let check_needs_update pname = let spec_exists pname =
let is_active = proc_is_active pname in
let spec_fname = Specs.res_dir_specs_filename pname in let spec_fname = Specs.res_dir_specs_filename pname in
if is_active then Sys.file_exists (DB.filename_to_string spec_fname) in
changed := (!changed || not (Sys.file_exists (DB.filename_to_string spec_fname)) || let cfg_modified_after_specs pname =
DB.file_modified_time cg_fname > DB.file_modified_time spec_fname) in let spec_fname = Specs.res_dir_specs_filename pname in
list_iter check_needs_update defined_nodes; DB.file_modified_time cfg_fname > DB.file_modified_time spec_fname in
!changed let is_changed pname =
not (spec_exists pname) || (cfg_modified_after_specs pname && pdesc_changed pname) in
let defined_nodes = Cg.get_defined_nodes cg in
if !Config.incremental_procs then list_filter is_changed defined_nodes
else if list_exists is_changed defined_nodes then defined_nodes
else []
(** Load a .c or .cpp file into an execution environment *) (** Load a .c or .cpp file into an execution environment *)
let load_cg_file (_exe_env: Exe_env.initial) (source_dir : DB.source_dir) exclude_fun = let load_cg_file (_exe_env: Exe_env.initial) (source_dir : DB.source_dir) exclude_fun =
@ -666,24 +670,30 @@ let load_cg_file (_exe_env: Exe_env.initial) (source_dir : DB.source_dir) exclud
(** Return a map of (changed file procname) -> (procs in that file that have changed) *) (** Return a map of (changed file procname) -> (procs in that file that have changed) *)
let compute_files_changed_map _exe_env (source_dirs : DB.source_dir list) exclude_fun = let compute_files_changed_map _exe_env (source_dirs : DB.source_dir list) exclude_fun =
let sorted_dirs = list_sort DB.source_dir_compare source_dirs in let sorted_dirs = list_sort DB.source_dir_compare source_dirs in
let files_changed = ref Procname.Map.empty in let cg_list =
let cg_list = ref [] in list_fold_left
let check_cgs_changed exe_env = (fun cg_list source_dir ->
let check_cg_changed (source_dir, cg) = match load_cg_file _exe_env source_dir exclude_fun with
let is_changed = cg_check_changed exe_env source_dir cg in | None -> cg_list
if is_changed then | Some cg -> (source_dir, cg) :: cg_list)
[]
sorted_dirs in
let exe_env_get_files_changed files_changed_map exe_env =
let cg_get_files_changed files_changed_map (source_dir, cg) =
let changed_procs =
if !incremental_mode = ANALYZE_ALL then Cg.get_defined_nodes cg
else cg_get_changed_procs exe_env source_dir cg in
if changed_procs != [] then
let file_pname = source_file_to_pname (Cg.get_source cg) in let file_pname = source_file_to_pname (Cg.get_source cg) in
let defined_procs = Cg.get_defined_nodes cg in let defined_procs = Cg.get_defined_nodes cg in
files_changed := Procname.Map.add file_pname defined_procs !files_changed in Procname.Map.add file_pname defined_procs files_changed_map
list_iter check_cg_changed !cg_list in else files_changed_map in
list_iter list_fold_left cg_get_files_changed files_changed_map cg_list in
(fun source_dir -> match load_cg_file _exe_env source_dir exclude_fun with
| None -> ()
| Some cg -> cg_list := (source_dir, cg) :: !cg_list)
sorted_dirs;
let exe_env = Exe_env.freeze _exe_env in let exe_env = Exe_env.freeze _exe_env in
if !incremental_mode <> ANALYZE_ALL then check_cgs_changed exe_env; let files_changed =
!files_changed, exe_env if !incremental_mode = ANALYZE_ALL then Procname.Map.empty
else exe_env_get_files_changed Procname.Map.empty exe_env in
files_changed, exe_env
(** Create an exe_env from a cluster. *) (** Create an exe_env from a cluster. *)
let exe_env_from_cluster cluster = let exe_env_from_cluster cluster =

Loading…
Cancel
Save