From 695a3df7be1431c31edd3507bf7d58467c1b8e5f Mon Sep 17 00:00:00 2001 From: Nikos Gorogiannis Date: Fri, 4 Dec 2020 04:12:44 -0800 Subject: [PATCH] [exe-env] refactor into a two-level hashtable Summary: - Eliminate dead `source` field in `field_data` record. - Use a 2-level hashtable structure (`procname` -> `source_file` and `source_file` -> `file_data`) to help potentially using an LRU cache for layer 1. - Use laziness instead of mutability. - Fixed stale comments Reviewed By: jvillard Differential Revision: D25303360 fbshipit-source-id: 68a22d299 --- infer/src/absint/exe_env.ml | 66 ++++++++++++++----------------------- 1 file changed, 25 insertions(+), 41 deletions(-) diff --git a/infer/src/absint/exe_env.ml b/infer/src/absint/exe_env.ml index 0741000d1..f75dfe431 100644 --- a/infer/src/absint/exe_env.ml +++ b/infer/src/absint/exe_env.ml @@ -14,63 +14,47 @@ module F = Format module L = Logging -(** per-file data: type environment and cfg *) -type file_data = - { source: SourceFile.t - ; mutable tenv: Tenv.t option - ; mutable integer_type_widths: Typ.IntegerWidths.t option } +(** per-file data: type environment and integer widths *) +type file_data = {tenv: Tenv.t option Lazy.t; integer_type_widths: Typ.IntegerWidths.t option Lazy.t} (** create a new file_data *) let new_file_data source = - (* 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= None (* Sil.load_tenv_from_file tenv_file *); integer_type_widths= None} + { tenv= lazy (Tenv.load source) + ; integer_type_widths= + lazy (Option.first_some (Typ.IntegerWidths.load source) (Some Typ.IntegerWidths.java)) } -let create_file_data table source = - match SourceFile.Hash.find table source with - | file_data -> +let file_data_of_source table source = + match SourceFile.Hash.find_opt table source with + | Some file_data -> file_data - | exception Caml.Not_found -> + | None -> let file_data = new_file_data source in SourceFile.Hash.add table source file_data ; file_data -type t = - { proc_map: file_data Procname.Hash.t (** map from procedure name to file data *) - ; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) } +type t = {proc_map: SourceFile.t Procname.Hash.t; file_map: file_data SourceFile.Hash.t} let get_file_data exe_env pname = - try Some (Procname.Hash.find exe_env.proc_map pname) - with Caml.Not_found -> - let source_file_opt = - match Attributes.load pname with - | None -> - L.debug Analysis Medium "can't find attributes for %a@." Procname.pp pname ; - None - | Some proc_attributes -> - Some proc_attributes.ProcAttributes.translation_unit - in - let get_file_data_for_source source_file = - let file_data = create_file_data exe_env.file_map source_file in - Procname.Hash.replace exe_env.proc_map pname file_data ; - file_data - in - Option.map ~f:get_file_data_for_source source_file_opt - - -let file_data_to_tenv file_data = - if is_none file_data.tenv then file_data.tenv <- Tenv.load file_data.source ; - file_data.tenv + match Procname.Hash.find_opt exe_env.proc_map pname with + | Some source -> + Some (file_data_of_source exe_env.file_map source) + | None -> ( + match Attributes.load pname with + | None -> + L.debug Analysis Medium "can't find attributes for %a@." Procname.pp pname ; + None + | Some proc_attributes -> + let source_file = proc_attributes.ProcAttributes.translation_unit in + let file_data = file_data_of_source exe_env.file_map source_file in + Procname.Hash.add exe_env.proc_map pname source_file ; + Some file_data ) -let file_data_to_integer_type_widths file_data = - if is_none file_data.integer_type_widths then - file_data.integer_type_widths <- - Option.first_some (Typ.IntegerWidths.load file_data.source) (Some Typ.IntegerWidths.java) ; - file_data.integer_type_widths +let file_data_to_tenv file_data = Lazy.force file_data.tenv +let file_data_to_integer_type_widths file_data = Lazy.force file_data.integer_type_widths let java_global_tenv = lazy