Skip to content

Commit bf98aca

Browse files
committed
Function call analysis
1 parent 07c6687 commit bf98aca

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
open! Stdlib
2+
open Code
3+
4+
let debug = Debug.find "call-graph"
5+
6+
let block_deps ~info ~non_escaping ~unambiguous ~ambiguous ~blocks pc =
7+
let block = Addr.Map.find pc blocks in
8+
List.iter block.body ~f:(fun i ->
9+
match i with
10+
| Let (_, Apply { f; _ }) -> (
11+
try
12+
match Var.Tbl.get info.Global_flow.info_approximation f with
13+
| Top -> ()
14+
| Values { known; others } ->
15+
if others || Var.Set.cardinal known > 1
16+
then Var.Set.iter (fun x -> Var.Hashtbl.replace ambiguous x ()) known
17+
else Var.Set.iter (fun x -> Var.Hashtbl.replace unambiguous x ()) known;
18+
if debug ()
19+
then
20+
Format.eprintf
21+
"CALL others:%b known:%d@."
22+
others
23+
(Var.Set.cardinal known)
24+
with Invalid_argument _ -> ())
25+
| Let (x, Closure _) -> (
26+
match Var.Tbl.get info.Global_flow.info_approximation x with
27+
| Top -> ()
28+
| Values { known; others } ->
29+
if Var.Set.cardinal known = 1 && (not others) && Var.Set.mem x known
30+
then (
31+
let may_escape = Var.ISet.mem info.Global_flow.info_may_escape x in
32+
if debug () then Format.eprintf "CLOSURE may-escape:%b@." may_escape;
33+
if not may_escape then Var.Hashtbl.replace non_escaping x ()))
34+
| Let (_, (Prim _ | Block _ | Constant _ | Field _ | Special _))
35+
| Event _ | Assign _ | Set_field _ | Offset_ref _ | Array_set _ -> ())
36+
37+
type t = { unambiguous_non_escaping : unit Var.Hashtbl.t }
38+
39+
let f p info =
40+
let non_escaping = Var.Hashtbl.create 128 in
41+
let ambiguous = Var.Hashtbl.create 128 in
42+
let unambiguous = Var.Hashtbl.create 128 in
43+
fold_closures
44+
p
45+
(fun _ _ (pc, _) _ () ->
46+
traverse
47+
{ fold = Code.fold_children }
48+
(fun pc () ->
49+
block_deps ~info ~non_escaping ~unambiguous ~ambiguous ~blocks:p.blocks pc)
50+
pc
51+
p.blocks
52+
())
53+
();
54+
if debug ()
55+
then
56+
Format.eprintf
57+
"SUMMARY non-escaping:%d unambiguous:%d"
58+
(Var.Hashtbl.length non_escaping)
59+
(Var.Hashtbl.length unambiguous);
60+
Var.Hashtbl.iter (fun x () -> Var.Hashtbl.remove non_escaping x) ambiguous;
61+
if debug ()
62+
then Format.eprintf " unambiguous-non-escaping:%d@." (Var.Hashtbl.length non_escaping);
63+
{ unambiguous_non_escaping = non_escaping }
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type t = { unambiguous_non_escaping : unit Code.Var.Hashtbl.t }
2+
3+
val f : Code.program -> Global_flow.info -> t

0 commit comments

Comments
 (0)