From 7396a613bbd251c0f92c338d8e273f6df719cdec Mon Sep 17 00:00:00 2001 From: Jules Villard Date: Wed, 24 Jan 2018 09:49:53 -0800 Subject: [PATCH] [tenv] change interface to take `SourceFile.t` instead of `DB.filename` Summary: Also, make it explicit when we load the global tenv instead of the per-file tenv. This allows for some nice simplifications in some places, notably: - `tenv_file` is gone from `Exe_env.file_data` - `DB.global_tenv_fname` is no more This will help moving the tenv from the capture/source_file/ directories on the filesystem to the database, as keys for the relevant table are `SourceFile.t`. Reviewed By: mbouaziz Differential Revision: D6796594 fbshipit-source-id: 1ffd5b0 --- infer/src/IR/Tenv.ml | 40 +++++++++++++++++++++++------------- infer/src/IR/Tenv.mli | 16 ++++++++++----- infer/src/backend/exe_env.ml | 29 ++++++-------------------- infer/src/base/DB.ml | 5 ----- infer/src/base/DB.mli | 3 --- infer/src/clang/cFrontend.ml | 3 +-- infer/src/java/jMain.ml | 13 +++++------- 7 files changed, 49 insertions(+), 60 deletions(-) diff --git a/infer/src/IR/Tenv.ml b/infer/src/IR/Tenv.ml index 3b6c800a9..6cef92f1e 100644 --- a/infer/src/IR/Tenv.ml +++ b/infer/src/IR/Tenv.ml @@ -89,28 +89,40 @@ let tenv_serializer : t Serialization.serializer = let global_tenv : t option ref = ref None -(** Load a type environment from a file *) -let load_from_file (filename: DB.filename) : t option = - if DB.equal_filename filename DB.global_tenv_fname then ( - if is_none !global_tenv then - global_tenv := Serialization.read_from_file tenv_serializer DB.global_tenv_fname ; - !global_tenv ) - else Serialization.read_from_file tenv_serializer filename +let tenv_filename_of_source_file source_file = + DB.source_dir_get_internal_file (DB.source_dir_from_source_file source_file) ".tenv" -(** Save a type environment into a file *) -let store_to_file (filename: DB.filename) (tenv: t) = - (* update in-memory global tenv for later uses by this process, e.g. in single-core mode the - frontend and backend run in the same process *) - if DB.equal_filename filename DB.global_tenv_fname then global_tenv := Some tenv ; - Serialization.write_to_file tenv_serializer filename ~data:tenv ; +let load source_file : t option = + tenv_filename_of_source_file source_file |> Serialization.read_from_file tenv_serializer + + +let global_tenv_path = Config.(captured_dir ^/ global_tenv_filename) |> DB.filename_from_string + +let load_global () : t option = + if is_none !global_tenv then + global_tenv := Serialization.read_from_file tenv_serializer global_tenv_path ; + !global_tenv + + +let store_to_filename tenv tenv_filename = + Serialization.write_to_file tenv_serializer tenv_filename ~data:tenv ; if Config.debug_mode then - let debug_filename = DB.filename_to_string (DB.filename_add_suffix filename ".debug") in + let debug_filename = DB.filename_to_string (DB.filename_add_suffix tenv_filename ".debug") in let out_channel = Out_channel.create debug_filename in let fmt = Format.formatter_of_out_channel out_channel in Format.fprintf fmt "%a" pp tenv ; Out_channel.close out_channel +let store source_file tenv = tenv_filename_of_source_file source_file |> store_to_filename tenv + +let store_global tenv = + (* update in-memory global tenv for later uses by this process, e.g. in single-core mode the + frontend and backend run in the same process *) + global_tenv := Some tenv ; + store_to_filename tenv global_tenv_path + + exception Found of Typ.Name.t let language_is tenv lang = diff --git a/infer/src/IR/Tenv.mli b/infer/src/IR/Tenv.mli index 423925e68..e8618ccf7 100644 --- a/infer/src/IR/Tenv.mli +++ b/infer/src/IR/Tenv.mli @@ -17,8 +17,17 @@ type t val create : unit -> t (** Create a new type environment. *) -val load_from_file : DB.filename -> t option -(** Load a type environment from a file *) +val load : SourceFile.t -> t option +(** Load a type environment for a source file *) + +val load_global : unit -> t option +(** load the global type environment (Java) *) + +val store : SourceFile.t -> t -> unit +(** Save a type environment into a file *) + +val store_global : t -> unit +(** save a global type environment (Java) *) val lookup : t -> Typ.Name.t -> Typ.Struct.t option (** Look up a name in the global type environment. *) @@ -37,8 +46,5 @@ val sort_fields_tenv : t -> unit val pp : Format.formatter -> t -> unit [@@warning "-32"] (** print a type environment *) -val store_to_file : DB.filename -> t -> unit -(** Save a type environment into a file *) - val language_is : t -> Config.language -> bool (** Test the language from which the types in the tenv were translated *) diff --git a/infer/src/backend/exe_env.ml b/infer/src/backend/exe_env.ml index 8792c206e..df897ba4e 100644 --- a/infer/src/backend/exe_env.ml +++ b/infer/src/backend/exe_env.ml @@ -18,28 +18,13 @@ module L = Logging module F = Format (** per-file data: type environment and cfg *) -type file_data = - { source: SourceFile.t - ; tenv_file: DB.filename - ; mutable tenv: Tenv.t option - ; mutable cfg: Cfg.t option } - -(** get the path to the tenv file, which either one tenv file per source file or a global tenv file *) -let tenv_of_source source = - let source_dir = DB.source_dir_from_source_file source in - let per_source_tenv_filename = DB.source_dir_get_internal_file source_dir ".tenv" in - if Sys.file_exists (DB.filename_to_string per_source_tenv_filename) = `Yes then - per_source_tenv_filename - else DB.global_tenv_fname - +type file_data = {source: SourceFile.t; mutable tenv: Tenv.t option; mutable cfg: Cfg.t option} (** create a new file_data *) let new_file_data source = - let tenv_file = tenv_of_source source in (* Do not fill in tenv and cfg as they can be quite large. This makes calls to fork() cheaper until we start filling out these fields. *) { source - ; tenv_file ; tenv= None (* Sil.load_tenv_from_file tenv_file *) ; cfg= None (* Cfg.load_cfg_from_file cfg_file *) } @@ -81,7 +66,7 @@ let get_file_data exe_env pname = let file_data_to_tenv file_data = - if is_none file_data.tenv then file_data.tenv <- Tenv.load_from_file file_data.tenv_file ; + if is_none file_data.tenv then file_data.tenv <- Tenv.load file_data.source ; file_data.tenv @@ -92,11 +77,9 @@ let file_data_to_cfg file_data = let java_global_tenv = lazy - ( match Tenv.load_from_file DB.global_tenv_fname with + ( match Tenv.load_global () with | None -> - L.(die InternalError) - "Could not load the global tenv at path '%s'" - (DB.filename_to_string DB.global_tenv_fname) + L.(die InternalError) "Could not load the global tenv" | Some tenv -> tenv ) @@ -114,8 +97,8 @@ let get_tenv exe_env proc_name = tenv | None -> L.(die InternalError) - "get_tenv: tenv not found for %a in file '%s'" Typ.Procname.pp proc_name - (DB.filename_to_string file_data.tenv_file) ) + "get_tenv: tenv not found for %a in file '%a'" Typ.Procname.pp proc_name SourceFile.pp + exe_env.source_file ) | None -> L.(die InternalError) "get_tenv: file_data not found for %a" Typ.Procname.pp proc_name diff --git a/infer/src/base/DB.ml b/infer/src/base/DB.ml index a9775f945..c1641a4a5 100644 --- a/infer/src/base/DB.ml +++ b/infer/src/base/DB.ml @@ -231,11 +231,6 @@ module Results_dir = struct Unix.openfile full_fname ~mode:Unix.([O_WRONLY; O_CREAT; O_TRUNC]) ~perm:0o777 end -let global_tenv_fname = - let basename = Config.global_tenv_filename in - Config.captured_dir ^/ basename - - let is_source_file path = List.exists ~f:(fun ext -> Filename.check_suffix path ext) Config.source_file_extentions diff --git a/infer/src/base/DB.mli b/infer/src/base/DB.mli index a54a00c0a..47b1c5add 100644 --- a/infer/src/base/DB.mli +++ b/infer/src/base/DB.mli @@ -109,9 +109,6 @@ val update_file_with_lock : string -> string -> (string -> string) -> unit If the file does not exist, it is created, and update is given the empty string. A lock is used to allow write attempts in parallel. *) -val global_tenv_fname : filename -(** get the path of the global type environment (only used in Java) *) - val is_source_file : string -> bool (** Check if a path is a Java, C, C++ or Objectve C source file according to the file extention *) diff --git a/infer/src/clang/cFrontend.ml b/infer/src/clang/cFrontend.ml index 38b8c7bb4..1ecee9f18 100644 --- a/infer/src/clang/cFrontend.ml +++ b/infer/src/clang/cFrontend.ml @@ -51,11 +51,10 @@ let do_source_file (translation_unit_context: CFrontend_config.translation_unit_ (* This part below is a boilerplate in every frontends. *) (* This could be moved in the cfg_infer module *) let source_dir = DB.source_dir_from_source_file source_file in - let tenv_file = DB.source_dir_get_internal_file source_dir ".tenv" in NullabilityPreanalysis.analysis cfg tenv ; Cfg.store source_file cfg ; Tenv.sort_fields_tenv tenv ; - Tenv.store_to_file tenv_file tenv ; + Tenv.store source_file tenv ; if Config.debug_mode then Cfg.check_cfg_connectedness cfg ; if Config.debug_mode || Config.testing_mode || Config.frontend_tests || Option.is_some Config.icfg_dotty_outfile diff --git a/infer/src/java/jMain.ml b/infer/src/java/jMain.ml index ad799cfb6..fa37a149c 100644 --- a/infer/src/java/jMain.ml +++ b/infer/src/java/jMain.ml @@ -65,23 +65,20 @@ let capture_libs linereader program tenv = (* load a stored global tenv if the file is found, and create a new one otherwise *) let load_tenv () = - match Tenv.load_from_file DB.global_tenv_fname with + match Tenv.load_global () with | None -> Tenv.create () | Some _ when Config.models_mode -> L.(die InternalError) - "Unexpected tenv file %s found while generating the models" - (DB.filename_to_string DB.global_tenv_fname) + "Unexpected global tenv file found in '%s' while generating the models" Config.captured_dir | Some tenv -> tenv -(* Store to a file the type environment containing all the types required to perform the analysis *) +(** Store to a file the type environment containing all the types required to perform the analysis *) let save_tenv tenv = - (* TODO: this prevents per compilation step incremental analysis at this stage *) - if DB.file_exists DB.global_tenv_fname then DB.file_remove DB.global_tenv_fname ; - L.(debug Capture Medium) "writing new tenv %s@." (DB.filename_to_string DB.global_tenv_fname) ; - Tenv.store_to_file DB.global_tenv_fname tenv + L.(debug Capture Medium) "writing new global tenv@." ; + Tenv.store_global tenv (* The program is loaded and translated *)