Skip to content

Commit ac3fcbb

Browse files
committed
Function call analysis
1 parent 2624a97 commit ac3fcbb

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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 direct_calls_only info f =
40+
Config.Flag.optcall () && Var.Hashtbl.mem info.unambiguous_non_escaping f
41+
42+
let f p info =
43+
let non_escaping = Var.Hashtbl.create 128 in
44+
let ambiguous = Var.Hashtbl.create 128 in
45+
let unambiguous = Var.Hashtbl.create 128 in
46+
fold_closures
47+
p
48+
(fun _ _ (pc, _) _ () ->
49+
traverse
50+
{ fold = Code.fold_children }
51+
(fun pc () ->
52+
block_deps ~info ~non_escaping ~unambiguous ~ambiguous ~blocks:p.blocks pc)
53+
pc
54+
p.blocks
55+
())
56+
();
57+
if debug ()
58+
then
59+
Format.eprintf
60+
"SUMMARY non-escaping:%d unambiguous:%d"
61+
(Var.Hashtbl.length non_escaping)
62+
(Var.Hashtbl.length unambiguous);
63+
Var.Hashtbl.iter (fun x () -> Var.Hashtbl.remove non_escaping x) ambiguous;
64+
if debug ()
65+
then Format.eprintf " unambiguous-non-escaping:%d@." (Var.Hashtbl.length non_escaping);
66+
{ 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)