Avoid loading the cfg explicitly to find a proc desc.

Reviewed By: jeremydubreil

Differential Revision: D3035301

fb-gh-sync-id: 13c9b84
shipit-source-id: 13c9b84
master
Cristiano Calcagno 9 years ago committed by Facebook Github Bot 1
parent 81a59515e4
commit b2969820a4

@ -12,7 +12,6 @@ module L = Logging
(** Module to register and invoke callbacks *)
type proc_callback_args = {
get_cfg : Procname.t -> Cfg.cfg option;
get_proc_desc : Procname.t -> Cfg.Procdesc.t option;
get_procs_in_file : Procname.t -> Procname.t list;
idenv : Idenv.t;
@ -60,9 +59,6 @@ let iterate_procedure_callbacks exe_env caller_pname =
let procedure_language = get_language caller_pname in
Config.curr_language := procedure_language;
let get_cfg proc_name =
Exe_env.get_cfg exe_env proc_name in
let get_proc_desc proc_name =
Exe_env.get_proc_desc exe_env proc_name in
@ -94,7 +90,6 @@ let iterate_procedure_callbacks exe_env caller_pname =
let init_time = Unix.gettimeofday () in
proc_callback
{
get_cfg;
get_proc_desc;
get_procs_in_file;
idenv;

@ -10,7 +10,6 @@
(** Module to register and invoke callbacks *)
type proc_callback_args = {
get_cfg : Procname.t -> Cfg.cfg option;
get_proc_desc : Procname.t -> Cfg.Procdesc.t option;
get_procs_in_file : Procname.t -> Procname.t list;
idenv : Idenv.t;

@ -606,7 +606,8 @@ module Node = struct
(* clone a procedure description and apply the type substitutions where
the parameters are used *)
let proc_desc_specialize_types cfg callee_proc_desc resolved_attributes substitutions =
let proc_desc_specialize_types callee_proc_desc resolved_attributes substitutions =
let cfg = create_cfg () in
let resolved_proc_desc = proc_desc_create cfg resolved_attributes in
let resolved_proc_name = proc_desc_get_proc_name resolved_proc_desc
and callee_start_node = proc_desc_get_start_node callee_proc_desc
@ -1144,28 +1145,22 @@ let store_cfg_to_file (filename : DB.filename) (save_sources : bool) (cfg : cfg)
(** Creates a copy of a procedure description and a list of type substitutions of the form
(name, typ) where name is a parameter. The resulting procedure CFG is isomorphic but
(name, typ) where name is a parameter. The resulting proc desc is isomorphic but
all the type of the parameters are replaced in the instructions according to the list.
The virtual calls are also replaced to match the parameter types *)
let specialize_types caller_cfg callee_proc_name resolved_proc_name args =
let specialize_types callee_proc_desc resolved_proc_name args =
(** TODO (#9333890): This currently only works when the callee is defined in the same file.
Add support to search for the callee procedure description in the execution environment *)
match Procdesc.find_from_name caller_cfg resolved_proc_name with
| Some pdesc -> Some pdesc
| None ->
Option.map
(fun callee_proc_desc ->
let callee_attributes = Procdesc.get_attributes callee_proc_desc in
let resolved_formals =
IList.fold_left2
(fun accu (name, _) (_, arg_typ) -> (name, arg_typ) :: accu)
[] callee_attributes.ProcAttributes.formals args |> IList.rev in
let resolved_attributes =
{ callee_attributes with
ProcAttributes.formals = resolved_formals;
proc_name = resolved_proc_name;
} in
AttributesTable.store_attributes resolved_attributes;
Procdesc.specialize_types
caller_cfg callee_proc_desc resolved_attributes resolved_formals)
(Procdesc.find_from_name caller_cfg callee_proc_name)
let callee_attributes = Procdesc.get_attributes callee_proc_desc in
let resolved_formals =
IList.fold_left2
(fun accu (name, _) (_, arg_typ) -> (name, arg_typ) :: accu)
[] callee_attributes.ProcAttributes.formals args |> IList.rev in
let resolved_attributes =
{ callee_attributes with
ProcAttributes.formals = resolved_formals;
proc_name = resolved_proc_name;
} in
AttributesTable.store_attributes resolved_attributes;
Procdesc.specialize_types
callee_proc_desc resolved_attributes resolved_formals

@ -314,8 +314,8 @@ val check_cfg_connectedness : cfg -> unit
val remove_seed_captured_vars_block : Mangled.t list -> Prop.normal Prop.t -> Prop.normal Prop.t
(** Creates a copy of a procedure description and a list of type substitutions of the form
(name, typ) where name is a parameter. The resulting procedure CFG is isomorphic but
(name, typ) where name is a parameter. The resulting procdesc is isomorphic but
all the type of the parameters are replaced in the instructions according to the list.
The virtual calls are also replaced to match the parameter types *)
val specialize_types :
cfg -> Procname.t -> Procname.t -> (Sil.exp * Sil.typ) list -> Procdesc.t option
Procdesc.t -> Procname.t -> (Sil.exp * Sil.typ) list -> Procdesc.t

@ -100,13 +100,13 @@ let get_cg exe_env =
let get_file_data exe_env pname =
try
Procname.Hash.find exe_env.proc_map pname
Some (Procname.Hash.find exe_env.proc_map pname)
with Not_found ->
begin
match AttributesTable.load_attributes pname with
| None ->
L.err "can't find tenv_cfg_object for %a@." Procname.pp pname;
raise Not_found
None
| Some proc_attributes ->
let loc = proc_attributes.ProcAttributes.loc in
let source_file = loc.Location.file in
@ -115,12 +115,14 @@ let get_file_data exe_env pname =
let cg_fname = DB.source_dir_get_internal_file source_dir ".cg" in
let file_data = new_file_data source_file nLOC cg_fname in
Procname.Hash.replace exe_env.proc_map pname file_data;
file_data
Some file_data
end
(** return the source file associated to the procedure *)
let get_source exe_env pname =
(get_file_data exe_env pname).source
Option.map
(fun file_data -> file_data.source)
(get_file_data exe_env pname)
let file_data_to_tenv file_data =
if file_data.tenv == None
@ -134,17 +136,25 @@ let file_data_to_cfg file_data =
(** return the type environment associated to the procedure *)
let get_tenv exe_env proc_name : Sil.tenv =
let file_data = get_file_data exe_env proc_name in
match file_data_to_tenv file_data with
| Some tenv ->
tenv
match get_file_data exe_env proc_name with
| None ->
failwith ("get_tenv: tenv not found for" ^ Procname.to_string proc_name)
failwith ("get_tenv: file_data not found for" ^ Procname.to_string proc_name)
| Some file_data ->
begin
match file_data_to_tenv file_data with
| Some tenv ->
tenv
| None ->
failwith ("get_tenv: tenv not found for" ^ Procname.to_string proc_name)
end
(** return the cfg associated to the procedure *)
let get_cfg exe_env pname =
let file_data = get_file_data exe_env pname in
file_data_to_cfg file_data
match get_file_data exe_env pname with
| None ->
None
| Some file_data ->
file_data_to_cfg file_data
(** return the proc desc associated to the procedure *)
let get_proc_desc exe_env pname =

@ -30,7 +30,7 @@ val add_cg : initial -> DB.source_dir -> Cg.t option
val get_cg : t -> Cg.t
(** return the source file associated to the procedure *)
val get_source : t -> Procname.t -> DB.source_file
val get_source : t -> Procname.t -> DB.source_file option
(** return the type environment associated to the procedure *)
val get_tenv : t -> Procname.t -> Sil.tenv

@ -1320,8 +1320,6 @@ let do_analysis exe_env =
procs_and_defined_children;
let callbacks =
let get_cfg proc_name =
Exe_env.get_cfg exe_env proc_name in
let get_proc_desc proc_name =
Exe_env.get_proc_desc exe_env proc_name in
let analyze_ondemand proc_desc =
@ -1338,7 +1336,6 @@ let do_analysis exe_env =
Specs.add_summary proc_name summaryre in
{
Ondemand.analyze_ondemand;
get_cfg;
get_proc_desc;
} in
@ -1451,6 +1448,6 @@ let print_stats exe_env =
let proc_shadowed proc_desc =
(** return true if a proc with the same name in another module was analyzed instead *)
let proc_name = Cfg.Procdesc.get_proc_name proc_desc in
Exe_env.get_source exe_env proc_name <> fname in
Exe_env.get_source exe_env proc_name <> Some fname in
print_stats_cfg proc_shadowed cfg)
exe_env

@ -41,14 +41,11 @@ let dirs_to_analyze =
type analyze_ondemand = Cfg.Procdesc.t -> unit
type get_cfg = Procname.t -> Cfg.cfg option
type get_proc_desc = Procname.t -> Cfg.Procdesc.t option
type callbacks =
{
analyze_ondemand : analyze_ondemand;
get_cfg : get_cfg;
get_proc_desc : get_proc_desc;
}
@ -230,10 +227,10 @@ let analyze_proc_name ~propagate_exceptions curr_pdesc callee_pname =
| _ ->
() (* skipping *)
(** Find a cfg for the procedure, perhaps loading it from disk. *)
let get_cfg callee_pname =
(** Find a proc desc for the procedure, perhaps loading it from disk. *)
let get_proc_desc callee_pname =
match !callbacks_ref with
| Some callbacks ->
callbacks.get_cfg callee_pname
callbacks.get_proc_desc callee_pname
| None ->
None

@ -14,19 +14,16 @@ val dirs_to_analyze : StringSet.t option Lazy.t
type analyze_ondemand = Cfg.Procdesc.t -> unit
type get_cfg = Procname.t -> Cfg.cfg option
type get_proc_desc = Procname.t -> Cfg.Procdesc.t option
type callbacks =
{
analyze_ondemand : analyze_ondemand;
get_cfg : get_cfg;
get_proc_desc : get_proc_desc;
}
(** Find a cfg for the procedure, perhaps loading it from disk. *)
val get_cfg : get_cfg
(** Find a proc desc for the procedure, perhaps loading it from disk. *)
val get_proc_desc : get_proc_desc
(** analyze_proc_desc curr_pdesc callee_pdesc
performs an on-demand analysis of callee_pdesc

@ -54,14 +54,9 @@ let check_block_retain_cycle tenv caller_pname prop block_nullified =
let mblock = Sil.pvar_get_name block_nullified in
let block_pname = Procname.mangled_objc_block (Mangled.to_string mblock) in
let block_captured =
let block_pdesc_opt = match Ondemand.get_cfg caller_pname with
| Some caller_cfg ->
Cfg.Procdesc.find_from_name caller_cfg block_pname
| None ->
None in
match block_pdesc_opt with
| Some block_pdesc ->
fst (IList.split (Cfg.Procdesc.get_captured block_pdesc))
match AttributesTable.load_attributes block_pname with
| Some attributes ->
fst (IList.split attributes.ProcAttributes.captured)
| None ->
[] in
let prop' = Cfg.remove_seed_captured_vars_block block_captured prop in
@ -715,24 +710,30 @@ let resolve_java_pname tenv prop args pname call_flags : Procname.t =
(** Resolve the procedure name and run the analysis of the resolved procedure
if not already analyzed *)
let resolve_and_analyze
tenv caller_pdesc prop args callee_pname call_flags : Procname.t * Specs.summary option =
tenv caller_pdesc prop args callee_proc_name call_flags : Procname.t * Specs.summary option =
(* TODO (#9333890): Fix conflict with method overloading by encoding in the procedure name
whether the method is defined or generated by the specialization *)
let analyze_ondemand caller_cfg resolved_pname : unit =
if Procname.equal resolved_pname callee_pname then
Ondemand.analyze_proc_name ~propagate_exceptions:true caller_pdesc callee_pname
let analyze_ondemand resolved_pname : unit =
if Procname.equal resolved_pname callee_proc_name then
Ondemand.analyze_proc_name ~propagate_exceptions:true caller_pdesc callee_proc_name
else
(* Create the type sprecialized procedure description and analyze it directly *)
Option.may
(fun specialized_pdesc ->
Ondemand.analyze_proc_desc ~propagate_exceptions:true caller_pdesc specialized_pdesc)
(Cfg.specialize_types caller_cfg callee_pname resolved_pname args) in
(match Ondemand.get_proc_desc resolved_pname with
| Some resolved_proc_desc ->
Some resolved_proc_desc
| None ->
begin
Option.map
(fun callee_proc_desc ->
Cfg.specialize_types callee_proc_desc resolved_pname args)
(Ondemand.get_proc_desc callee_proc_name)
end) in
let resolved_pname =
resolve_java_pname tenv prop args callee_pname call_flags in
Option.may
(fun caller_cfg ->
analyze_ondemand caller_cfg resolved_pname)
(Ondemand.get_cfg (Cfg.Procdesc.get_proc_name caller_pdesc));
resolve_java_pname tenv prop args callee_proc_name call_flags in
analyze_ondemand resolved_pname;
resolved_pname, Specs.get_summary resolved_pname
@ -1137,12 +1138,7 @@ let rec sym_exec tenv pdesc _instr (prop_: Prop.normal Prop.t) path
Ondemand.analyze_proc_name ~propagate_exceptions:true pdesc resolved_pname;
let callee_pdesc_opt =
match Ondemand.get_cfg pname with
| Some caller_cfg ->
Cfg.Procdesc.find_from_name caller_cfg resolved_pname
| None ->
None in
let callee_pdesc_opt = Ondemand.get_proc_desc resolved_pname in
let ret_typ_opt = Option.map Cfg.Procdesc.get_ret_type callee_pdesc_opt in
let sentinel_result =

@ -315,13 +315,12 @@ let check_one_procedure tenv pname pdesc =
let callback_performance_checker
{ Callbacks.get_cfg; get_proc_desc; proc_desc; proc_name; tenv } =
{ Callbacks.get_proc_desc; proc_desc; proc_name; tenv } =
let callbacks =
let analyze_ondemand pdesc =
check_one_procedure tenv (Cfg.Procdesc.get_proc_name pdesc) pdesc in
{
Ondemand.analyze_ondemand;
get_cfg;
get_proc_desc;
} in
if Ondemand.procedure_should_be_analyzed proc_name

@ -386,7 +386,7 @@ module Main =
(** Eradicate checker for Java @Nullable annotations. *)
let callback_eradicate
({ Callbacks.get_cfg; get_proc_desc; idenv; proc_name } as callback_args) =
({ Callbacks.get_proc_desc; idenv; proc_name } as callback_args) =
let checks =
{
TypeCheck.eradicate = true;
@ -403,7 +403,6 @@ let callback_eradicate
proc_desc = pdesc; } in
{
Ondemand.analyze_ondemand;
get_cfg;
get_proc_desc;
} in

Loading…
Cancel
Save