[infer][java] Create the procedure descriptions when required instead of creating them beforehand

Summary: This diff simplifies the workflow of creating the procedure descriptions. Instead of creating the all procedure descriptions in a first step and translating the method bodies afterwards, it is simpler to translate to do the two in one step.

Reviewed By: cristianoc

Differential Revision: D4067674

fbshipit-source-id: be9e853
master
Jeremy Dubreil 8 years ago committed by Facebook Github Bot
parent 471beed515
commit 219832a9a8

@ -75,12 +75,12 @@ let add_edges
(** Add a concrete method. *) (** Add a concrete method. *)
let add_cmethod source_file program icfg cm method_kind = let add_cmethod source_file program linereader icfg cm method_kind =
let cfg = icfg.JContext.cfg in
let cn, ms = JBasics.cms_split cm.Javalib.cm_class_method_signature in let cn, ms = JBasics.cms_split cm.Javalib.cm_class_method_signature in
let proc_name_java = JTransType.get_method_procname cn ms method_kind in let proc_name_java = JTransType.get_method_procname cn ms method_kind in
let proc_name = Procname.Java proc_name_java in let proc_name = Procname.Java proc_name_java in
match Cfg.Procdesc.find_from_name cfg proc_name with let jmethod = (Javalib.ConcreteMethod cm) in
match JTrans.create_procdesc source_file program linereader icfg jmethod with
| None -> () | None -> ()
| Some _ when JTrans.is_java_native cm -> () | Some _ when JTrans.is_java_native cm -> ()
| Some procdesc -> | Some procdesc ->
@ -101,15 +101,15 @@ let add_cmethod source_file program icfg cm method_kind =
(** Add an abstract method. *) (** Add an abstract method. *)
let add_amethod icfg am method_kind = let add_amethod source_file program linereader icfg am method_kind =
let cfg = icfg.JContext.cfg in
let cn, ms = JBasics.cms_split am.Javalib.am_class_method_signature in let cn, ms = JBasics.cms_split am.Javalib.am_class_method_signature in
let proc_name_java = JTransType.get_method_procname cn ms method_kind in let proc_name_java = JTransType.get_method_procname cn ms method_kind in
let proc_name = Procname.Java proc_name_java in let proc_name = Procname.Java proc_name_java in
match Cfg.Procdesc.find_from_name cfg proc_name with let jmethod = (Javalib.AbstractMethod am) in
match JTrans.create_procdesc source_file program linereader icfg jmethod with
| None -> () | None -> ()
| Some procdesc -> | Some _ ->
Cg.add_defined_node icfg.JContext.cg (Cfg.Procdesc.get_proc_name procdesc) Cg.add_defined_node icfg.JContext.cg proc_name
let path_of_cached_classname cn = let path_of_cached_classname cn =
@ -142,27 +142,23 @@ let cache_classname cn =
let is_classname_cached cn = let is_classname_cached cn =
Sys.file_exists (path_of_cached_classname cn) Sys.file_exists (path_of_cached_classname cn)
(* Given a source file and a class, translates the code of this class. (* Given a source file and a class, translates the code of this class.
In init - mode, finds out whether this class contains initializers at all, In init - mode, finds out whether this class contains initializers at all,
in this case translates it. In standard mode, all methods are translated *) in this case translates it. In standard mode, all methods are translated *)
let create_icfg source_file linereader program icfg cn node = let create_icfg source_file linereader program icfg cn node =
JUtils.log "\tclassname: %s@." (JBasics.cn_name cn); JUtils.log "\tclassname: %s@." (JBasics.cn_name cn);
cache_classname cn; cache_classname cn;
let cfg = icfg.JContext.cfg in let translate m =
let tenv = icfg.JContext.tenv in
begin
Javalib.m_iter (JTrans.create_procdesc source_file program linereader cfg tenv) node;
Javalib.m_iter (fun m ->
(* each procedure has different scope: start names from id 0 *) (* each procedure has different scope: start names from id 0 *)
Ident.NameGenerator.reset (); Ident.NameGenerator.reset ();
let method_kind = JTransType.get_method_kind m in let method_kind = JTransType.get_method_kind m in
match m with match m with
| Javalib.ConcreteMethod cm -> | Javalib.ConcreteMethod cm ->
add_cmethod source_file program icfg cm method_kind add_cmethod source_file program linereader icfg cm method_kind
| Javalib.AbstractMethod am -> | Javalib.AbstractMethod am ->
add_amethod icfg am method_kind add_amethod source_file program linereader icfg am method_kind in
) node Javalib.m_iter translate node
end
(* returns true for the set of classes that are selected to be translated *) (* returns true for the set of classes that are selected to be translated *)

@ -202,10 +202,6 @@ let get_test_operator op =
| `Lt -> Binop.Lt | `Lt -> Binop.Lt
| `Ne -> Binop.Ne | `Ne -> Binop.Ne
type defined_status =
| Defined of Cfg.Procdesc.t
| Called of Cfg.Procdesc.t
let is_java_native cm = let is_java_native cm =
(cm.Javalib.cm_implementation = Javalib.Native) (cm.Javalib.cm_implementation = Javalib.Native)
@ -233,13 +229,18 @@ let update_init_loc cn ms loc_start =
with Not_found -> init_loc_map := (JBasics.ClassMap.add cn loc_start !init_loc_map) with Not_found -> init_loc_map := (JBasics.ClassMap.add cn loc_start !init_loc_map)
(** Creates a procedure description. *) (** Creates a procedure description. *)
let create_procdesc source_file program linereader cfg tenv m = let create_procdesc source_file program linereader icfg m : Cfg.Procdesc.t option =
let cfg = icfg.JContext.cfg in
let tenv = icfg.JContext.tenv in
let cn, ms = JBasics.cms_split (Javalib.get_class_method_signature m) in let cn, ms = JBasics.cms_split (Javalib.get_class_method_signature m) in
let proc_name_java = JTransType.get_method_procname cn ms (JTransType.get_method_kind m) in let proc_name_java = JTransType.get_method_procname cn ms (JTransType.get_method_kind m) in
let proc_name = Procname.Java proc_name_java in let proc_name = Procname.Java proc_name_java in
if JClasspath.is_model proc_name then if JClasspath.is_model proc_name then
begin
(* do not translate the method if there is a model for it *) (* do not translate the method if there is a model for it *)
JUtils.log "Skipping method with a model: %s@." (Procname.to_string proc_name) JUtils.log "Skipping method with a model: %s@." (Procname.to_string proc_name);
None
end
else else
let trans_access = function let trans_access = function
| `Default -> PredSymb.Default | `Default -> PredSymb.Default
@ -247,6 +248,7 @@ let create_procdesc source_file program linereader cfg tenv m =
| `Private -> PredSymb.Private | `Private -> PredSymb.Private
| `Protected -> PredSymb.Protected in | `Protected -> PredSymb.Protected in
try try
let procdesc =
match m with match m with
| Javalib.AbstractMethod am -> (* create a procdesc with empty body *) | Javalib.AbstractMethod am -> (* create a procdesc with empty body *)
let formals = let formals =
@ -273,9 +275,11 @@ let create_procdesc source_file program linereader cfg tenv m =
let exit_node = Cfg.Node.create cfg Location.dummy exit_kind [] procdesc in let exit_node = Cfg.Node.create cfg Location.dummy exit_kind [] procdesc in
Cfg.Node.set_succs_exn cfg start_node [exit_node] [exit_node]; Cfg.Node.set_succs_exn cfg start_node [exit_node] [exit_node];
Cfg.Procdesc.set_start_node procdesc start_node; Cfg.Procdesc.set_start_node procdesc start_node;
Cfg.Procdesc.set_exit_node procdesc exit_node Cfg.Procdesc.set_exit_node procdesc exit_node;
procdesc
| Javalib.ConcreteMethod cm when is_java_native cm -> | Javalib.ConcreteMethod cm when is_java_native cm ->
let formals = formals_from_signature program tenv cn ms (JTransType.get_method_kind m) in let formals =
formals_from_signature program tenv cn ms (JTransType.get_method_kind m) in
let method_annotation = let method_annotation =
JAnnotation.translate_method proc_name_java cm.Javalib.cm_annotations in JAnnotation.translate_method proc_name_java cm.Javalib.cm_annotations in
let proc_attributes = let proc_attributes =
@ -288,7 +292,7 @@ let create_procdesc source_file program linereader cfg tenv m =
method_annotation; method_annotation;
ret_type = JTransType.return_type program tenv ms; ret_type = JTransType.return_type program tenv ms;
} in } in
ignore (Cfg.Procdesc.create cfg proc_attributes) Cfg.Procdesc.create cfg proc_attributes;
| Javalib.ConcreteMethod cm -> | Javalib.ConcreteMethod cm ->
let impl = get_implementation cm in let impl = get_implementation cm in
let locals, formals = locals_formals program tenv cn impl in let locals, formals = locals_formals program tenv cn impl in
@ -327,10 +331,13 @@ let create_procdesc source_file program linereader cfg tenv m =
Cfg.Procdesc.set_start_node procdesc start_node; Cfg.Procdesc.set_start_node procdesc start_node;
Cfg.Procdesc.set_exit_node procdesc exit_node; Cfg.Procdesc.set_exit_node procdesc exit_node;
Cfg.Node.add_locals_ret_declaration start_node locals; Cfg.Node.add_locals_ret_declaration start_node locals;
procdesc in
Some procdesc
with JBir.Subroutine | JBasics.Class_structure_error _ -> with JBir.Subroutine | JBasics.Class_structure_error _ ->
L.err L.stderr
"create_procdesc raised JBir.Subroutine or JBasics.Class_structure_error on %a@." "create_procdesc raised JBir.Subroutine or JBasics.Class_structure_error on %a@."
Procname.pp proc_name Procname.pp proc_name;
None
let builtin_new = let builtin_new =
Exp.Const (Const.Cfun ModelBuiltins.__new) Exp.Const (Const.Cfun ModelBuiltins.__new)

@ -20,11 +20,6 @@ type translation =
| Prune of Cfg.Node.t * Cfg.Node.t | Prune of Cfg.Node.t * Cfg.Node.t
| Loop of Cfg.Node.t * Cfg.Node.t * Cfg.Node.t | Loop of Cfg.Node.t * Cfg.Node.t * Cfg.Node.t
(** data structure to identify whether a method is defined in the given program *)
type defined_status =
| Defined of Cfg.Procdesc.t
| Called of Cfg.Procdesc.t
val is_java_native : JCode.jcode Javalib.concrete_method -> bool val is_java_native : JCode.jcode Javalib.concrete_method -> bool
(** [create_procdesc linereader cfg tenv program m] creates a procedure description (** [create_procdesc linereader cfg tenv program m] creates a procedure description
@ -33,10 +28,9 @@ val create_procdesc :
DB.source_file -> DB.source_file ->
JClasspath.program -> JClasspath.program ->
Printer.LineReader.t -> Printer.LineReader.t ->
Cfg.cfg -> JContext.icfg ->
Tenv.t ->
JCode.jcode Javalib.jmethod -> JCode.jcode Javalib.jmethod ->
unit Cfg.Procdesc.t option
(** returns the implementation of a given method *) (** returns the implementation of a given method *)
val get_implementation : JCode.jcode Javalib.concrete_method -> JBir.t val get_implementation : JCode.jcode Javalib.concrete_method -> JBir.t

Loading…
Cancel
Save