[java][1/n] split classpath and program modules

Summary: As per title.

Reviewed By: skcho

Differential Revision: D22411395

fbshipit-source-id: 699502382
master
Nikos Gorogiannis 4 years ago committed by Facebook GitHub Bot
parent cbfb9612e5
commit d35807223b

@ -10,9 +10,6 @@ open! IStd
open Javalib_pack
module L = Logging
(** version of Javalib.get_class that does not spam stderr *)
let javalib_get_class = Utils.suppress_stderr2 Javalib.get_class
let split_classpath = String.split ~on:JFile.sep
let classpath_of_paths paths =
@ -193,89 +190,3 @@ let load_from_arguments classes_out_path =
|> classpath_of_paths
in
{classpath; sources= search_sources (); classes}
type callee_status = Translated | Missing of JBasics.class_name * JBasics.method_signature
type classmap = JCode.jcode Javalib.interface_or_class JBasics.ClassMap.t
(** We store for each classname the location of its declaration. This map is filled during
JFrontend.compute_source_icfg and then it is used in JTransType.get_class_struct_typ before we
lose access to JClasspath.program. At the end, the information seats in each Struct.t (stored in
Tenv.t) *)
type java_location_map = Location.t JBasics.ClassMap.t
type program =
{ classpath_channel: Javalib.class_path
; mutable classmap: classmap
; mutable java_location_map: java_location_map
; callees: callee_status Procname.Hash.t }
let get_classmap program = program.classmap
let set_java_location program cn loc =
program.java_location_map <- JBasics.ClassMap.add cn loc program.java_location_map
let get_java_location program cn =
try Some (JBasics.ClassMap.find cn program.java_location_map) with Caml.Not_found -> None
let mem_classmap cn program = JBasics.ClassMap.mem cn program.classmap
let get_classpath_channel program = program.classpath_channel
let add_class cn jclass program =
(* [prefix] must be a fresh class name *)
let prefix = JBasics.cn_name cn ^ Config.java_lambda_marker_infix in
(* we rewrite each class to replace invokedynamic (closure construction)
with equivalent old-style Java code that implements a suitable Java interface *)
let rewritten_jclass, new_classes = Javalib.remove_invokedynamics jclass ~prefix in
program.classmap <- JBasics.ClassMap.add cn rewritten_jclass program.classmap ;
(* the rewrite will generate new classes and we add them to the program *)
JBasics.ClassMap.iter
(fun cn jcl -> program.classmap <- JBasics.ClassMap.add cn jcl program.classmap)
new_classes ;
rewritten_jclass
let set_callee_translated program pname = Procname.Hash.replace program.callees pname Translated
let add_missing_callee program pname cn ms =
if not (Procname.Hash.mem program.callees pname) then
Procname.Hash.add program.callees pname (Missing (cn, ms))
let iter_missing_callees program ~f =
let select proc_name = function Translated -> () | Missing (cn, ms) -> f proc_name cn ms in
Procname.Hash.iter select program.callees
let cleanup program = Javalib.close_class_path program.classpath_channel
let lookup_node cn program =
try Some (JBasics.ClassMap.find cn (get_classmap program))
with Caml.Not_found -> (
try
let jclass = javalib_get_class (get_classpath_channel program) cn in
Some (add_class cn jclass program)
with
| JBasics.No_class_found _ ->
(* TODO T28155039 Figure out when and what to log *)
None
| (JBasics.Class_structure_error _ | Invalid_argument _ | Failure _) as exn ->
L.internal_error "ERROR: %s@." (Exn.to_string exn) ;
None )
let load_program ~classpath classes =
L.(debug Capture Medium) "loading program ... %!" ;
let program =
{ classpath_channel= Javalib.class_path classpath
; classmap= JBasics.ClassMap.empty
; java_location_map= JBasics.ClassMap.empty
; callees= Procname.Hash.create 128 }
in
JBasics.ClassSet.iter (fun cn -> ignore (lookup_node cn program)) classes ;
L.(debug Capture Medium) "done@." ;
program

@ -19,33 +19,3 @@ val load_from_verbose_output : string -> t
val load_from_arguments : string -> t
(** load the list of source files and the list of classes from Config.generated_classes *)
type classmap = JCode.jcode Javalib.interface_or_class JBasics.ClassMap.t
type program
val get_classmap : program -> classmap
val set_java_location : program -> JBasics.class_name -> Location.t -> unit
val get_java_location : program -> JBasics.class_name -> Location.t option
val mem_classmap : JBasics.class_name -> program -> bool
val cleanup : program -> unit
val load_program : classpath:string -> JBasics.ClassSet.t -> program
(** load a java program *)
val lookup_node : JBasics.class_name -> program -> JCode.jcode Javalib.interface_or_class option
(** retrieve a Java node from the classname *)
val add_missing_callee :
program -> Procname.t -> JBasics.class_name -> JBasics.method_signature -> unit
(** add the class name of method signature to the list of callees *)
val set_callee_translated : program -> Procname.t -> unit
(** set that the CFG for the procedure has been created *)
val iter_missing_callees :
program -> f:(Procname.t -> JBasics.class_name -> JBasics.method_signature -> unit) -> unit

@ -26,7 +26,7 @@ type t =
; goto_jumps: (int, jump_kind) Hashtbl.t
; cn: JBasics.class_name
; source_file: SourceFile.t
; program: JClasspath.program }
; program: JProgramDesc.t }
let create_context icfg procdesc impl cn source_file program =
{ icfg

@ -32,10 +32,10 @@ type t = private
; goto_jumps: (int, jump_kind) Caml.Hashtbl.t
; cn: JBasics.class_name
; source_file: SourceFile.t
; program: JClasspath.program }
; program: JProgramDesc.t }
val create_context :
icfg -> Procdesc.t -> JBir.t -> JBasics.class_name -> SourceFile.t -> JClasspath.program -> t
icfg -> Procdesc.t -> JBir.t -> JBasics.class_name -> SourceFile.t -> JProgramDesc.t -> t
(** cretes a context for a given method. *)
val get_tenv : t -> Tenv.t

@ -141,7 +141,7 @@ let test_source_file_location source_file program cn node =
jc.Javalib.c_synthetic
in
if not (is_synthetic node) then
match JClasspath.get_java_location program cn with
match JProgramDesc.get_java_location program cn with
| None ->
L.(debug Capture Verbose)
"WARNING SOURCE FILE PARSER: location not found for class %s in source file %s \n"
@ -160,7 +160,7 @@ let create_icfg source_file program tenv icfg cn node =
test_source_file_location source_file program cn node ;
let translate m =
let proc_name = JTransType.translate_method_name program tenv m in
JClasspath.set_callee_translated program proc_name ;
JProgramDesc.set_callee_translated program proc_name ;
if BiabductionModels.mem proc_name then
(* do not translate the method if there is a model for it *)
L.debug Capture Verbose "Skipping method with a model: %a@." Procname.pp proc_name
@ -193,7 +193,7 @@ let should_capture program package_opt source_basename node =
| Some found_pkg ->
String.equal found_pkg pkg
in
if JClasspath.mem_classmap classname program then
if JProgramDesc.mem_classmap classname program then
match Javalib.get_sourcefile node with
| None ->
false
@ -221,7 +221,7 @@ let compute_source_icfg program tenv source_basename package_opt source_file =
(select
(should_capture program package_opt source_basename)
(create_icfg source_file program tenv icfg))
(JClasspath.get_classmap program)
(JProgramDesc.get_classmap program)
in
icfg.JContext.cfg

@ -19,11 +19,11 @@ val is_classname_cached : JBasics.class_name -> bool
(** [is_classname_cached cn] *)
val compute_source_icfg :
JClasspath.program -> Tenv.t -> string -> string option -> SourceFile.t -> Cfg.t
JProgramDesc.t -> Tenv.t -> string -> string option -> SourceFile.t -> Cfg.t
(** [compute_cfg linereader program tenv source_basename source_file] create the control flow graph
for the file [source_file] by translating all the classes in [program] originating from
[source_file] *)
val compute_class_icfg :
SourceFile.t -> JClasspath.program -> Tenv.t -> JCode.jcode Javalib.interface_or_class -> Cfg.t
SourceFile.t -> JProgramDesc.t -> Tenv.t -> JCode.jcode Javalib.interface_or_class -> Cfg.t
(** Compute the CFG for a class *)

@ -47,7 +47,7 @@ let capture_libs program tenv =
store_icfg fake_source_file cfg ;
JFrontend.cache_classname cn
in
JBasics.ClassMap.iter (capture_class tenv) (JClasspath.get_classmap program)
JBasics.ClassMap.iter (capture_class tenv) (JProgramDesc.get_classmap program)
(* load a stored global tenv if the file is found, and create a new one otherwise *)
@ -74,7 +74,7 @@ let store_callee_attributes tenv program =
~f:(Attributes.store ~proc_desc:None)
(JTrans.create_callee_attributes tenv program cn ms proc_name)
in
JClasspath.iter_missing_callees program ~f
JProgramDesc.iter_missing_callees program ~f
(* The program is loaded and translated *)
@ -106,7 +106,7 @@ let do_all_files sources program =
if Config.dependency_mode then capture_libs program tenv ;
store_callee_attributes tenv program ;
save_tenv tenv ;
JClasspath.cleanup program ;
JProgramDesc.cleanup program ;
L.(debug Capture Quiet) "done capturing all files@."
@ -133,7 +133,7 @@ let main load_sources_and_classes =
L.(debug Capture Quiet)
"Translating %d source files (%d classes)@." (String.Map.length sources)
(JBasics.ClassSet.cardinal classes) ;
let program = JClasspath.load_program ~classpath classes in
let program = JProgramDesc.load_program ~classpath classes in
do_all_files sources program

@ -0,0 +1,97 @@
(*
* Copyright (c) 2009-2013, Monoidics ltd.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
open Javalib_pack
module L = Logging
let javalib_get_class = Utils.suppress_stderr2 Javalib.get_class
type callee_status = Translated | Missing of JBasics.class_name * JBasics.method_signature
type classmap = JCode.jcode Javalib.interface_or_class JBasics.ClassMap.t
(** We store for each classname the location of its declaration. This map is filled during
JFrontend.compute_source_icfg and then it is used in JTransType.get_class_struct_typ before we
lose access to program. At the end, the information seats in each Struct.t (stored in Tenv.t) *)
type java_location_map = Location.t JBasics.ClassMap.t
type t =
{ classpath_channel: Javalib.class_path
; mutable classmap: classmap
; mutable java_location_map: java_location_map
; callees: callee_status Procname.Hash.t }
let get_classmap program = program.classmap
let set_java_location program cn loc =
program.java_location_map <- JBasics.ClassMap.add cn loc program.java_location_map
let get_java_location program cn =
try Some (JBasics.ClassMap.find cn program.java_location_map) with Caml.Not_found -> None
let mem_classmap cn program = JBasics.ClassMap.mem cn program.classmap
let get_classpath_channel program = program.classpath_channel
let add_class cn jclass program =
(* [prefix] must be a fresh class name *)
let prefix = JBasics.cn_name cn ^ Config.java_lambda_marker_infix in
(* we rewrite each class to replace invokedynamic (closure construction)
with equivalent old-style Java code that implements a suitable Java interface *)
let rewritten_jclass, new_classes = Javalib.remove_invokedynamics jclass ~prefix in
program.classmap <- JBasics.ClassMap.add cn rewritten_jclass program.classmap ;
(* the rewrite will generate new classes and we add them to the program *)
JBasics.ClassMap.iter
(fun cn jcl -> program.classmap <- JBasics.ClassMap.add cn jcl program.classmap)
new_classes ;
rewritten_jclass
let set_callee_translated program pname = Procname.Hash.replace program.callees pname Translated
let add_missing_callee program pname cn ms =
if not (Procname.Hash.mem program.callees pname) then
Procname.Hash.add program.callees pname (Missing (cn, ms))
let iter_missing_callees program ~f =
let select proc_name = function Translated -> () | Missing (cn, ms) -> f proc_name cn ms in
Procname.Hash.iter select program.callees
let cleanup program = Javalib.close_class_path program.classpath_channel
let lookup_node cn program =
try Some (JBasics.ClassMap.find cn (get_classmap program))
with Caml.Not_found -> (
try
let jclass = javalib_get_class (get_classpath_channel program) cn in
Some (add_class cn jclass program)
with
| JBasics.No_class_found _ ->
(* TODO T28155039 Figure out when and what to log *)
None
| (JBasics.Class_structure_error _ | Invalid_argument _ | Failure _) as exn ->
L.internal_error "ERROR: %s@." (Exn.to_string exn) ;
None )
let load_program ~classpath classes =
L.(debug Capture Medium) "loading program ... %!" ;
let program =
{ classpath_channel= Javalib.class_path classpath
; classmap= JBasics.ClassMap.empty
; java_location_map= JBasics.ClassMap.empty
; callees= Procname.Hash.create 128 }
in
JBasics.ClassSet.iter (fun cn -> ignore (lookup_node cn program)) classes ;
L.(debug Capture Medium) "done@." ;
program

@ -0,0 +1,39 @@
(*
* Copyright (c) 2009-2013, Monoidics ltd.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
open Javalib_pack
type classmap = JCode.jcode Javalib.interface_or_class JBasics.ClassMap.t
type t
val get_classmap : t -> classmap
val set_java_location : t -> JBasics.class_name -> Location.t -> unit
val get_java_location : t -> JBasics.class_name -> Location.t option
val mem_classmap : JBasics.class_name -> t -> bool
val cleanup : t -> unit
val load_program : classpath:string -> JBasics.ClassSet.t -> t
(** load a java program *)
val lookup_node : JBasics.class_name -> t -> JCode.jcode Javalib.interface_or_class option
(** retrieve a Java node from the classname *)
val add_missing_callee : t -> Procname.t -> JBasics.class_name -> JBasics.method_signature -> unit
(** add the class name of method signature to the list of callees *)
val set_callee_translated : t -> Procname.t -> unit
(** set that the CFG for the procedure has been created *)
val iter_missing_callees :
t -> f:(Procname.t -> JBasics.class_name -> JBasics.method_signature -> unit) -> unit

@ -371,7 +371,7 @@ and skip_comments action = parse
open Javalib_pack
(** We scan source file [file] and record location of each class declaration *)
let collect_class_location (program:JClasspath.program) (file:SourceFile.t) =
let collect_class_location (program:JProgramDesc.t)(file:SourceFile.t) =
let path = SourceFile.to_abs_path file in
if String.is_suffix path ~suffix:".java" then (
let cin = In_channel.create path in
@ -381,7 +381,7 @@ and skip_comments action = parse
let cn : JBasics.class_name = JBasics.make_cn classname in
Logging.debug Capture Verbose "set_java_location %s with location %a@."
(JBasics.cn_name cn) Location.pp_file_pos loc;
JClasspath.set_java_location program cn loc in
JProgramDesc.set_java_location program cn loc in
try (
class_scan { record_location; stack; } (from_channel cin) ;
In_channel.close cin )

@ -332,7 +332,7 @@ let create_callee_attributes tenv program cn ms procname =
; is_abstract }
with Caml.Not_found -> None
in
Option.bind ~f (JClasspath.lookup_node cn program)
Option.bind ~f (JProgramDesc.lookup_node cn program)
let create_empty_cfg source_file procdesc =
@ -624,7 +624,7 @@ let method_invocation (context : JContext.t) loc pc var_opt cn ms sil_obj_opt ex
in
let resolve_method (context : JContext.t) cn ms =
let rec search_in_parents get_parents cn =
match JClasspath.lookup_node cn context.program with
match JProgramDesc.lookup_node cn context.program with
| None ->
None
| Some node ->

@ -21,7 +21,7 @@ val is_java_native : JCode.jcode Javalib.concrete_method -> bool
val create_callee_attributes :
Tenv.t
-> JClasspath.program
-> JProgramDesc.t
-> JBasics.class_name
-> JBasics.method_signature
-> Procname.t
@ -29,7 +29,7 @@ val create_callee_attributes :
val create_am_procdesc :
SourceFile.t
-> JClasspath.program
-> JProgramDesc.t
-> JContext.icfg
-> Javalib.abstract_method
-> Procname.t
@ -38,7 +38,7 @@ val create_am_procdesc :
val create_native_procdesc :
SourceFile.t
-> JClasspath.program
-> JProgramDesc.t
-> JContext.icfg
-> JCode.jcode Javalib.concrete_method
-> Procname.t
@ -47,7 +47,7 @@ val create_native_procdesc :
val create_empty_procdesc :
SourceFile.t
-> JClasspath.program
-> JProgramDesc.t
-> JContext.icfg
-> JCode.jcode Javalib.concrete_method
-> Procname.t
@ -55,7 +55,7 @@ val create_empty_procdesc :
val create_cm_procdesc :
SourceFile.t
-> JClasspath.program
-> JProgramDesc.t
-> JContext.icfg
-> JCode.jcode Javalib.concrete_method
-> Procname.t

@ -274,7 +274,7 @@ let rec get_method_procname program tenv cn ms kind =
and translate_method_name program tenv m =
let cn, ms = JBasics.cms_split (Javalib.get_class_method_signature m) in
let proc_name = get_method_procname program tenv cn ms (get_method_kind m) in
JClasspath.add_missing_callee program proc_name cn ms ;
JProgramDesc.add_missing_callee program proc_name cn ms ;
proc_name
@ -284,7 +284,7 @@ and get_all_fields program tenv cn =
(statics, fields)
in
let trans_fields classname =
match JClasspath.lookup_node classname program with
match JProgramDesc.lookup_node classname program with
| Some (Javalib.JClass jclass) ->
let superclass_fields =
match jclass.Javalib.c_super_class with
@ -325,7 +325,7 @@ and get_class_struct_typ =
Javalib.m_fold (fun m procnames -> translate_method_name program tenv m :: procnames) node []
in
let node_name = Javalib.get_name node in
let java_location : Location.t option = JClasspath.get_java_location program node_name in
let java_location : Location.t option = JProgramDesc.get_java_location program node_name in
( match java_location with
| Some loc ->
L.debug Capture Verbose "Java location %s -> %a@." (JBasics.cn_name node_name)
@ -344,7 +344,7 @@ and get_class_struct_typ =
Tenv.mk_struct ~dummy:true tenv name
| None -> (
seen := JBasics.ClassSet.add cn !seen ;
match JClasspath.lookup_node cn program with
match JProgramDesc.lookup_node cn program with
| None ->
Tenv.mk_struct ~dummy:true tenv name
| Some (Javalib.JInterface jinterface as node) ->

@ -16,7 +16,7 @@ val create_fieldname : JBasics.class_name -> JBasics.field_signature -> Fieldnam
val get_method_kind : JCode.jcode Javalib.jmethod -> Procname.Java.kind
val get_method_procname :
JClasspath.program
JProgramDesc.t
-> Tenv.t
-> JBasics.class_name
-> JBasics.method_signature
@ -24,35 +24,33 @@ val get_method_procname :
-> Procname.t
(** returns a procedure name based on the class name and the method's signature *)
val translate_method_name :
JClasspath.program -> Tenv.t -> JCode.jcode Javalib.jmethod -> Procname.t
val translate_method_name : JProgramDesc.t -> Tenv.t -> JCode.jcode Javalib.jmethod -> Procname.t
(** translate the SIL procedure name of the Java method *)
val get_class_struct_typ : JClasspath.program -> Tenv.t -> JBasics.class_name -> Struct.t
val get_class_struct_typ : JProgramDesc.t -> Tenv.t -> JBasics.class_name -> Struct.t
(** [get_class_struct_typ program tenv cn] returns the struct_typ representation of the class *)
val get_class_type_no_pointer : JClasspath.program -> Tenv.t -> JBasics.class_name -> Typ.t
val get_class_type_no_pointer : JProgramDesc.t -> Tenv.t -> JBasics.class_name -> Typ.t
(** [get_class_type_no_pointer program tenv cn] returns the sil type representation of the class
without the pointer part *)
val get_class_type : JClasspath.program -> Tenv.t -> JBasics.class_name -> Typ.t
val get_class_type : JProgramDesc.t -> Tenv.t -> JBasics.class_name -> Typ.t
(** [get_class_type program tenv cn] returns the sil type representation of the class *)
val is_autogenerated_assert_field : Fieldname.t -> bool
(** return true if [field_name] is the autogenerated C.$assertionsDisabled field for class C *)
val sizeof_of_object_type :
JClasspath.program -> Tenv.t -> JBasics.object_type -> Subtype.t -> Exp.t
val sizeof_of_object_type : JProgramDesc.t -> Tenv.t -> JBasics.object_type -> Subtype.t -> Exp.t
(** create sizeof expressions from the object type and the list of subtypes *)
val value_type : JClasspath.program -> Tenv.t -> JBasics.value_type -> Typ.t
val value_type : JProgramDesc.t -> Tenv.t -> JBasics.value_type -> Typ.t
(** transforms a Java type to a Typ.t. *)
val param_type :
JClasspath.program -> Tenv.t -> JBasics.class_name -> JBir.var -> JBasics.value_type -> Typ.t
JProgramDesc.t -> Tenv.t -> JBasics.class_name -> JBir.var -> JBasics.value_type -> Typ.t
(** return the type of a formal parameter, looking up the class name in case of "this" *)
val return_type : JClasspath.program -> Tenv.t -> JBasics.method_signature -> Typ.t
val return_type : JProgramDesc.t -> Tenv.t -> JBasics.method_signature -> Typ.t
(** Returns the return type of the method based on the return type specified in ms. *)
val expr_type : JContext.t -> JBir.expr -> Typ.t

Loading…
Cancel
Save