[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
master
Jules Villard 7 years ago committed by Facebook Github Bot
parent ac92e13292
commit 7396a613bb

@ -89,28 +89,40 @@ let tenv_serializer : t Serialization.serializer =
let global_tenv : t option ref = ref None let global_tenv : t option ref = ref None
(** Load a type environment from a file *) let tenv_filename_of_source_file source_file =
let load_from_file (filename: DB.filename) : t option = DB.source_dir_get_internal_file (DB.source_dir_from_source_file source_file) ".tenv"
if DB.equal_filename filename DB.global_tenv_fname then (
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 if is_none !global_tenv then
global_tenv := Serialization.read_from_file tenv_serializer DB.global_tenv_fname ; global_tenv := Serialization.read_from_file tenv_serializer global_tenv_path ;
!global_tenv ) !global_tenv
else Serialization.read_from_file tenv_serializer filename
(** Save a type environment into a file *) let store_to_filename tenv tenv_filename =
let store_to_file (filename: DB.filename) (tenv: t) = Serialization.write_to_file tenv_serializer tenv_filename ~data: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 *)
if DB.equal_filename filename DB.global_tenv_fname then global_tenv := Some tenv ;
Serialization.write_to_file tenv_serializer filename ~data:tenv ;
if Config.debug_mode then 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 out_channel = Out_channel.create debug_filename in
let fmt = Format.formatter_of_out_channel out_channel in let fmt = Format.formatter_of_out_channel out_channel in
Format.fprintf fmt "%a" pp tenv ; Out_channel.close out_channel 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 exception Found of Typ.Name.t
let language_is tenv lang = let language_is tenv lang =

@ -17,8 +17,17 @@ type t
val create : unit -> t val create : unit -> t
(** Create a new type environment. *) (** Create a new type environment. *)
val load_from_file : DB.filename -> t option val load : SourceFile.t -> t option
(** Load a type environment from a file *) (** 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 val lookup : t -> Typ.Name.t -> Typ.Struct.t option
(** Look up a name in the global type environment. *) (** 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"] val pp : Format.formatter -> t -> unit [@@warning "-32"]
(** print a type environment *) (** 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 val language_is : t -> Config.language -> bool
(** Test the language from which the types in the tenv were translated *) (** Test the language from which the types in the tenv were translated *)

@ -18,28 +18,13 @@ module L = Logging
module F = Format module F = Format
(** per-file data: type environment and cfg *) (** per-file data: type environment and cfg *)
type file_data = type file_data = {source: SourceFile.t; mutable tenv: Tenv.t option; mutable cfg: Cfg.t option}
{ 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
(** create a new file_data *) (** create a new file_data *)
let new_file_data source = 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 (* 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. *) until we start filling out these fields. *)
{ source { source
; tenv_file
; tenv= None (* Sil.load_tenv_from_file tenv_file *) ; tenv= None (* Sil.load_tenv_from_file tenv_file *)
; cfg= None (* Cfg.load_cfg_from_file cfg_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 = 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 file_data.tenv
@ -92,11 +77,9 @@ let file_data_to_cfg file_data =
let java_global_tenv = let java_global_tenv =
lazy lazy
( match Tenv.load_from_file DB.global_tenv_fname with ( match Tenv.load_global () with
| None -> | None ->
L.(die InternalError) L.(die InternalError) "Could not load the global tenv"
"Could not load the global tenv at path '%s'"
(DB.filename_to_string DB.global_tenv_fname)
| Some tenv -> | Some tenv ->
tenv ) tenv )
@ -114,8 +97,8 @@ let get_tenv exe_env proc_name =
tenv tenv
| None -> | None ->
L.(die InternalError) L.(die InternalError)
"get_tenv: tenv not found for %a in file '%s'" Typ.Procname.pp proc_name "get_tenv: tenv not found for %a in file '%a'" Typ.Procname.pp proc_name SourceFile.pp
(DB.filename_to_string file_data.tenv_file) ) exe_env.source_file )
| None -> | None ->
L.(die InternalError) "get_tenv: file_data not found for %a" Typ.Procname.pp proc_name L.(die InternalError) "get_tenv: file_data not found for %a" Typ.Procname.pp proc_name

@ -231,11 +231,6 @@ module Results_dir = struct
Unix.openfile full_fname ~mode:Unix.([O_WRONLY; O_CREAT; O_TRUNC]) ~perm:0o777 Unix.openfile full_fname ~mode:Unix.([O_WRONLY; O_CREAT; O_TRUNC]) ~perm:0o777
end end
let global_tenv_fname =
let basename = Config.global_tenv_filename in
Config.captured_dir ^/ basename
let is_source_file path = let is_source_file path =
List.exists ~f:(fun ext -> Filename.check_suffix path ext) Config.source_file_extentions List.exists ~f:(fun ext -> Filename.check_suffix path ext) Config.source_file_extentions

@ -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. 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. *) 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 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 *) (** Check if a path is a Java, C, C++ or Objectve C source file according to the file extention *)

@ -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 part below is a boilerplate in every frontends. *)
(* This could be moved in the cfg_infer module *) (* This could be moved in the cfg_infer module *)
let source_dir = DB.source_dir_from_source_file source_file in 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 ; NullabilityPreanalysis.analysis cfg tenv ;
Cfg.store source_file cfg ; Cfg.store source_file cfg ;
Tenv.sort_fields_tenv tenv ; 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 then Cfg.check_cfg_connectedness cfg ;
if Config.debug_mode || Config.testing_mode || Config.frontend_tests if Config.debug_mode || Config.testing_mode || Config.frontend_tests
|| Option.is_some Config.icfg_dotty_outfile || Option.is_some Config.icfg_dotty_outfile

@ -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 *) (* load a stored global tenv if the file is found, and create a new one otherwise *)
let load_tenv () = let load_tenv () =
match Tenv.load_from_file DB.global_tenv_fname with match Tenv.load_global () with
| None -> | None ->
Tenv.create () Tenv.create ()
| Some _ when Config.models_mode -> | Some _ when Config.models_mode ->
L.(die InternalError) L.(die InternalError)
"Unexpected tenv file %s found while generating the models" "Unexpected global tenv file found in '%s' while generating the models" Config.captured_dir
(DB.filename_to_string DB.global_tenv_fname)
| Some tenv -> | Some tenv ->
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 = let save_tenv tenv =
(* TODO: this prevents per compilation step incremental analysis at this stage *) L.(debug Capture Medium) "writing new global tenv@." ;
if DB.file_exists DB.global_tenv_fname then DB.file_remove DB.global_tenv_fname ; Tenv.store_global tenv
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
(* The program is loaded and translated *) (* The program is loaded and translated *)

Loading…
Cancel
Save