2 * Copyright (c) 2019, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
12 module Decl_cache_entry
= struct
13 (* NOTE: we can't simply use a string as a key. In the case of a name
14 conflict, we may put e.g. a function named 'foo' into the cache whose value is
15 one type, and then later try to withdraw a class named 'foo' whose value is
18 The actual value type for [Class_decl] is a [Typing_classes_heap.Classes.t],
19 but that module depends on this module, so we can't write it down or else we
20 will cause a circular dependency. (It could probably be refactored to break
21 the dependency.) We just use [Obj.t] instead, which is better than using
22 [Obj.t] for all of the cases here.
25 | Fun_decl
: string -> Typing_defs.fun_elt t
26 | Class_decl
: string -> Obj.t t
27 | Record_decl
: string -> Typing_defs.record_def_type t
28 | Typedef_decl
: string -> Typing_defs.typedef_type t
29 | Gconst_decl
: string -> Typing_defs.decl_ty t
35 let get_size ~key
:_ ~
value:_
= 1
37 let key_to_log_string : type a
. a key
-> string =
40 | Fun_decl s
-> "FunDecl" ^ s
41 | Class_decl s
-> "ClassDecl" ^ s
42 | Record_decl s
-> "RecordDecl" ^ s
43 | Typedef_decl s
-> "TypedefDecl" ^ s
44 | Gconst_decl s
-> "GconstDecl" ^ s
47 module Decl_cache
= Lru_cache.Cache
(Decl_cache_entry
)
49 module Shallow_decl_cache_entry
= struct
50 type _ t
= Shallow_class_decl
: string -> Shallow_decl_defs.shallow_class t
56 let get_size ~key
:_ ~
value =
57 let words = Obj.reachable_words
(Obj.repr
value) in
58 let bytes = words * Sys.word_size
/ 8 in
61 let key_to_log_string : type a
. a key
-> string =
62 (fun (Shallow_class_decl key
) -> "ClasssShallow" ^ key
)
65 module Shallow_decl_cache
= Lru_cache.Cache
(Shallow_decl_cache_entry
)
67 module Linearization_cache_entry
= struct
69 | Member_resolution_linearization
: string -> Decl_defs.mro_element list t
70 | Ancestor_types_linearization
: string -> Decl_defs.mro_element list t
76 let get_size ~key
:_ ~
value:_
= 1
78 let key_to_log_string : type a
. a key
-> string =
81 | Member_resolution_linearization c
-> "MemberResolution" ^ c
82 | Ancestor_types_linearization c
-> "AncestorTypes" ^ c
85 module Linearization_cache
= Lru_cache.Cache
(Linearization_cache_entry
)
87 type fixme_map
= Pos.t
IMap.t
IMap.t
[@@deriving show
]
89 module Fixme_store
= struct
90 type t
= fixme_map
Relative_path.Map.t
ref
92 let empty = ref Relative_path.Map.empty
94 let get t filename
= Relative_path.Map.find_opt
!t filename
96 let add t filename fixmes
= t
:= Relative_path.Map.add !t filename fixmes
98 let remove t filename
= t
:= Relative_path.Map.remove !t filename
100 let remove_batch t filenames
=
102 Relative_path.Set.fold filenames ~init
:!t ~f
:(fun filename map
->
103 Relative_path.Map.remove map filename
)
106 module Fixmes
= struct
108 hh_fixmes
: Fixme_store.t
;
109 decl_hh_fixmes
: Fixme_store.t
;
110 disallowed_fixmes
: Fixme_store.t
;
113 let get_telemetry ~
(key
: string) (t
: t
) (telemetry
: Telemetry.t
) :
115 let hh_fixme_files = Relative_path.Map.cardinal
!(t
.hh_fixmes
) in
116 let decl_hh_fixme_files = Relative_path.Map.cardinal
!(t
.decl_hh_fixmes
) in
117 let disallowed_fixme_files =
118 Relative_path.Map.cardinal
!(t
.disallowed_fixmes
)
120 if hh_fixme_files + decl_hh_fixme_files + disallowed_fixme_files = 0 then
125 |> Telemetry.int_ ~key
:"hh_fixme_files" ~
value:hh_fixme_files
126 |> Telemetry.int_ ~key
:"decl_hh_fixme_files" ~
value:decl_hh_fixme_files
128 ~key
:"disallowed_fixme_files"
129 ~
value:disallowed_fixme_files
131 Telemetry.object_ telemetry ~key ~
value:sub_telemetry
137 hh_fixmes
= Fixme_store.empty;
138 decl_hh_fixmes
= Fixme_store.empty;
139 disallowed_fixmes
= Fixme_store.empty;
142 module Reverse_naming_table_delta
= struct
143 type pos
= FileInfo.name_type
* Relative_path.t
145 type pos_or_deleted
=
146 | Pos
of pos
* pos list
150 consts
: pos_or_deleted
SMap.t
ref;
151 funs
: pos_or_deleted
SMap.t
ref;
152 types
: pos_or_deleted
SMap.t
ref;
153 funs_canon_key
: pos_or_deleted
SMap.t
ref;
154 types_canon_key
: pos_or_deleted
SMap.t
ref;
159 consts
= ref SMap.empty;
160 funs
= ref SMap.empty;
161 types
= ref SMap.empty;
162 funs_canon_key
= ref SMap.empty;
163 types_canon_key
= ref SMap.empty;
166 let get_telemetry ~
(key
: string) (t
: t
) (telemetry
: Telemetry.t
) :
168 let consts = SMap.cardinal
!(t
.consts) in
169 let funs = SMap.cardinal
!(t
.funs) in
170 let types = SMap.cardinal
!(t
.types) in
171 if consts + funs + types = 0 then
176 |> Telemetry.int_ ~key
:"consts" ~
value:consts
177 |> Telemetry.int_ ~key
:"funs" ~
value:funs
178 |> Telemetry.int_ ~key
:"types" ~
value:types
180 Telemetry.object_ telemetry ~key ~
value:sub_telemetry
183 type local_memory
= {
184 decl_cache
: Decl_cache.t
;
185 shallow_decl_cache
: Shallow_decl_cache.t
;
186 linearization_cache
: Linearization_cache.t
;
187 reverse_naming_table_delta
: Reverse_naming_table_delta.t
;
189 naming_db_path_ref
: Naming_sqlite.db_path
option ref;
194 | Local_memory
of local_memory
196 decl
: Decl_service_client.t
;
200 let t_to_string (t
: t
) : string =
202 | Shared_memory
-> "Shared_memory"
203 | Local_memory _
-> "Local_memory"
204 | Decl_service _
-> "Decl_service"
206 let backend_ref = ref Shared_memory
208 let set_shared_memory_backend () : unit = backend_ref := Shared_memory
210 let set_local_memory_backend
211 ~
(max_num_decls
: int)
212 ~
(max_bytes_shallow_decls
: int)
213 ~
(max_num_linearizations
: int) : unit =
217 decl_cache
= Decl_cache.make ~max_size
:max_num_decls
;
219 Shallow_decl_cache.make ~max_size
:max_bytes_shallow_decls
;
220 linearization_cache
=
221 Linearization_cache.make ~max_size
:max_num_linearizations
;
222 reverse_naming_table_delta
= Reverse_naming_table_delta.make ();
223 fixmes
= empty_fixmes;
224 naming_db_path_ref
= ref None
;
227 let set_local_memory_backend_with_defaults () : unit =
228 (* Shallow decls: some files read ~5k shallow decls, at about 16k / shallow dec,
229 fitting into 73Mb. Hence we guess at 140Mb. *)
230 let max_bytes_shallow_decls = 140 * 1024 * 1024 in
231 (* Linearizations: such files will pick up ~6k linearizations. *)
232 let max_num_linearizations = 10000 in
233 (* TODO: justify max_num_decls *)
234 let max_num_decls = 5000 in
235 set_local_memory_backend
237 ~
max_bytes_shallow_decls
238 ~
max_num_linearizations
240 let set_decl_service_backend (decl
: Decl_service_client.t
) : unit =
241 backend_ref := Decl_service
{ decl
; fixmes
= empty_fixmes }
243 let get () : t
= !backend_ref