Skip to content

Commit a980df2

Browse files
committed
HashCachedContextLifter: Introduce the lifter and the option
Using hashcache on contexes makes a big difference in memory usage (churn) and a reasonable improvement on runtime when HashConsing is disabled. This is particularly important for the upcoming parallel solvers
1 parent 746d436 commit a980df2

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

src/common/domains/printable.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ struct
176176

177177
let lift m = {m; lazy_hash = LazyHash.make m}
178178
let unlift {m; _} = m
179+
let relift x = x
179180

180181
let lift_f f x = f (unlift x)
181182
let lift_f' f x = lift @@ lift_f f x

src/config/options.schema.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,13 @@
513513
"type": "boolean",
514514
"default": true
515515
},
516+
"hashcached": {
517+
"title": "ana.opt.hashcached",
518+
"description":
519+
"Should we try to save memory and speed up equality by caching hashes of contexts? This is useful when hashconsing is off",
520+
"type": "boolean",
521+
"default": false
522+
},
516523
"equal": {
517524
"title": "ana.opt.equal",
518525
"description":

src/framework/control.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ let spec_module: (module Spec) Lazy.t = lazy (
2828
|> lift true (module WidenContextLifterSide) (* option checked in functor *)
2929
(* hashcons before witness to reduce duplicates, because witness re-uses contexts in domain and requires tag for PathSensitive3 *)
3030
|> lift (get_bool "ana.opt.hashcons" || arg_enabled) (module HashconsContextLifter)
31+
|> lift (get_bool "ana.opt.hashcached") (module HashCachedContextLifter)
3132
|> lift arg_enabled (module HashconsLifter)
3233
|> lift arg_enabled (module WitnessConstraints.PathSensitive3)
3334
|> lift (not arg_enabled) (module PathSensitive2)

src/lifters/specLifters.ml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,88 @@ struct
180180
let event man e oman = S.event (conv man) e (conv oman)
181181
end
182182

183+
(** Lifts a [Spec] so that the context is [HashCached]. *)
184+
module HashCachedContextLifter (S:Spec)
185+
: Spec with module D = S.D
186+
and module G = S.G
187+
and module C = Printable.HashCached (S.C)
188+
=
189+
struct
190+
module D = S.D
191+
module G = S.G
192+
module C = Printable.HashCached (S.C)
193+
module V = S.V
194+
module P = S.P
195+
196+
let name () = S.name () ^" context hashcached"
197+
198+
type marshal = S.marshal
199+
let init = S.init
200+
let finalize = S.finalize
201+
202+
let startstate = S.startstate
203+
let exitstate = S.exitstate
204+
let morphstate = S.morphstate
205+
206+
let conv man =
207+
{ man with context = (fun () -> C.unlift (man.context ())) }
208+
209+
let context man fd = C.lift % S.context (conv man) fd
210+
let startcontext () = C.lift @@ S.startcontext ()
211+
212+
let sync man reason =
213+
S.sync (conv man) reason
214+
215+
let query man (type a) (q: a Queries.t): a Queries.result =
216+
match q with
217+
| Queries.IterPrevVars f ->
218+
let g i (n, c, j) e = f i (n, Obj.repr (C.lift (Obj.obj c)), j) e in
219+
S.query (conv man) (Queries.IterPrevVars g)
220+
| _ -> S.query (conv man) q
221+
222+
let assign man lv e =
223+
S.assign (conv man) lv e
224+
225+
let vdecl man v =
226+
S.vdecl (conv man) v
227+
228+
let branch man e tv =
229+
S.branch (conv man) e tv
230+
231+
let body man f =
232+
S.body (conv man) f
233+
234+
let return man r f =
235+
S.return (conv man) r f
236+
237+
let asm man =
238+
S.asm (conv man)
239+
240+
let skip man =
241+
S.skip (conv man)
242+
243+
let enter man r f args =
244+
S.enter (conv man) r f args
245+
246+
let special man r f args =
247+
S.special (conv man) r f args
248+
249+
let combine_env man r fe f args fc es f_ask =
250+
S.combine_env (conv man) r fe f args (Option.map C.unlift fc) es f_ask
251+
252+
let combine_assign man r fe f args fc es f_ask =
253+
S.combine_assign (conv man) r fe f args (Option.map C.unlift fc) es f_ask
254+
255+
let threadenter man ~multiple lval f args =
256+
S.threadenter (conv man) ~multiple lval f args
257+
258+
let threadspawn man ~multiple lval f args fman =
259+
S.threadspawn (conv man) ~multiple lval f args (conv fman)
260+
261+
let paths_as_set man = S.paths_as_set (conv man)
262+
let event man e oman = S.event (conv man) e (conv oman)
263+
end
264+
183265
(* see option ana.opt.equal *)
184266
module OptEqual (S: Spec) = struct
185267
module D = struct include S.D let equal x y = x == y || equal x y end

0 commit comments

Comments
 (0)