Skip to content

Commit 5d7f954

Browse files
committed
Function call analysis
1 parent 9c2d923 commit 5d7f954

File tree

2 files changed

+64
-0
lines changed

2 files changed

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

0 commit comments

Comments
 (0)