[infer][IR] introduce a fold function over the procedure descriptions in a file to avoid make copies of mutable data-structures

Summary: This should avoid making copies of procedure descriptions which are mutable data-stuctures.

Reviewed By: sblackshear

Differential Revision: D6658527

fbshipit-source-id: 688a142
master
Jeremy Dubreil 7 years ago committed by Facebook Github Bot
parent b089486b5a
commit 6e1979a3e0

@ -24,6 +24,8 @@ let remove_proc_desc cfg pname = Typ.Procname.Hash.remove cfg pname
let iter_proc_desc cfg f = Typ.Procname.Hash.iter f cfg
let fold_proc_desc cfg f init = Typ.Procname.Hash.fold f cfg init
let find_proc_desc_from_name cfg pname =
try Some (Typ.Procname.Hash.find cfg pname) with Not_found -> None
@ -59,9 +61,6 @@ let get_all_procs cfg =
iter_proc_desc cfg f ; !procs
(** Get the procedures whose body is defined in this cfg *)
let get_defined_procs cfg = List.filter ~f:Procdesc.is_defined (get_all_procs cfg)
(** checks whether a cfg is connected or not *)
let check_cfg_connectedness cfg =
let is_exit_node n =
@ -83,15 +82,13 @@ let check_cfg_connectedness cfg =
(* if the if brances end with a return *)
match succs with [n'] when is_exit_node n' -> false | _ -> Int.equal (List.length preds) 0
in
let do_pdesc pd =
let pname = Procdesc.get_proc_name pd in
let do_pdesc pname pd =
let nodes = Procdesc.get_nodes pd in
(* TODO (T20302015): also check the CFGs for the C-like procedures *)
if not Config.keep_going && Typ.Procname.is_java pname && List.exists ~f:broken_node nodes then
L.(die InternalError) "Broken CFG on %a" Typ.Procname.pp pname
in
let pdescs = get_all_procs cfg in
List.iter ~f:do_pdesc pdescs
iter_proc_desc cfg do_pdesc
let get_load_statement =
@ -112,7 +109,7 @@ let load source =
(** Save the .attr files for the procedures in the cfg. *)
let save_attributes source_file cfg =
let save_proc pdesc =
let save_proc _ pdesc =
let attributes = Procdesc.get_attributes pdesc in
let loc = attributes.loc in
let attributes' =
@ -121,7 +118,7 @@ let save_attributes source_file cfg =
in
Attributes.store attributes'
in
List.iter ~f:save_proc (get_all_procs cfg)
iter_proc_desc cfg save_proc
(** Inline a synthetic (access or bridge) method. *)

@ -32,15 +32,12 @@ val create_proc_desc : t -> ProcAttributes.t -> Procdesc.t
val iter_proc_desc : t -> (Typ.Procname.t -> Procdesc.t -> unit) -> unit
(** Iterate over all the procdesc's *)
val fold_proc_desc : t -> (Typ.Procname.t -> Procdesc.t -> 'a -> 'a) -> 'a -> 'a
(** Fold over all the procdesc's *)
val find_proc_desc_from_name : t -> Typ.Procname.t -> Procdesc.t option
(** Find the procdesc given the proc name. Return None if not found. *)
val get_all_procs : t -> Procdesc.t list
(** Get all the procedures (defined and declared) *)
val get_defined_procs : t -> Procdesc.t list
(** Get the procedures whose body is defined in this cfg *)
val iter_all_nodes : ?sorted:bool -> (Procdesc.t -> Procdesc.Node.t -> unit) -> t -> unit
(** Iterate over all the nodes in the cfg *)

@ -55,7 +55,7 @@ let iterate_procedure_callbacks get_proc_desc exe_env summary proc_desc =
let get_procs_in_file proc_name =
match Exe_env.get_cfg exe_env proc_name with
| Some cfg ->
List.map ~f:Procdesc.get_proc_name (Cfg.get_all_procs cfg)
Cfg.fold_proc_desc cfg (fun pname _ accu -> pname :: accu) []
| None ->
[]
in

@ -546,15 +546,19 @@ let write_all_html_files cluster =
let linereader = LineReader.create () in
Exe_env.iter_files
(fun _ cfg ->
let source_files_in_cfg =
let files = ref SourceFile.Set.empty in
Cfg.iter_proc_desc cfg (fun _ proc_desc ->
if Procdesc.is_defined proc_desc then
let file = (Procdesc.get_loc proc_desc).Location.file in
if is_whitelisted file then files := SourceFile.Set.add file !files else () ) ;
!files
let source_files_in_cfg, pdescs_in_cfg =
Cfg.fold_proc_desc cfg
(fun _ proc_desc (files, pdescs) ->
let updated_files =
if Procdesc.is_defined proc_desc then
let file = (Procdesc.get_loc proc_desc).Location.file in
if is_whitelisted file then SourceFile.Set.add file files else files
else files
in
(updated_files, proc_desc :: pdescs) )
(SourceFile.Set.empty, [])
in
SourceFile.Set.iter
(fun file -> write_html_file linereader file (Cfg.get_all_procs cfg))
(fun file -> write_html_file linereader file pdescs_in_cfg)
source_files_in_cfg )
exe_env

@ -94,9 +94,8 @@ let add_nonnull_to_fields fields tenv =
let analysis cfg tenv =
let initial = FieldsAssignedInConstructors.empty in
let f domain pdesc =
let proc_name = Procdesc.get_proc_name pdesc in
if Typ.Procname.is_constructor proc_name then
let f proc_name pdesc domain =
if Procdesc.is_defined pdesc && Typ.Procname.is_constructor proc_name then
match
FieldsAssignedInConstructorsChecker.compute_post
(ProcData.make pdesc tenv (Ident.IdentHash.create 10))
@ -108,6 +107,5 @@ let analysis cfg tenv =
domain
else domain
in
let procs = Cfg.get_defined_procs cfg in
let fields_assigned_in_constructor = List.fold ~f ~init:initial procs in
let fields_assigned_in_constructor = Cfg.fold_proc_desc cfg f initial in
add_nonnull_to_fields fields_assigned_in_constructor tenv

Loading…
Cancel
Save