[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 *)
@ -58,10 +55,10 @@ val specialize_types : Procdesc.t -> Typ.Procname.t -> (Exp.t * Typ.t) list -> P
val specialize_with_block_args :
Procdesc.t -> Typ.Procname.t -> Exp.closure option list -> Procdesc.t
(** Creates a copy of a procedure description given a list of possible closures
(** Creates a copy of a procedure description given a list of possible closures
that are passed as arguments to the method. The resulting procdesc is isomorphic but
a) the block parameters are replaces with the closures
b) the parameters of the method are extended with parameters for the captured variables
a) the block parameters are replaces with the closures
b) the parameters of the method are extended with parameters for the captured variables
in the closures *)
val pp_proc_signatures : Format.formatter -> t -> unit

@ -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