@@ -44,7 +44,9 @@ let direct_calls_only info f =
4444
4545let call_graph p info call_info =
4646 let under_handler = Var.Hashtbl. create 16 in
47- let rec traverse pc visited nesting =
47+ let callees = Var.Hashtbl. create 16 in
48+ let callers = Var.Hashtbl. create 16 in
49+ let rec traverse name_opt pc visited nesting =
4850 if not (Addr.Set. mem pc visited)
4951 then (
5052 let visited = Addr.Set. add pc visited in
@@ -59,16 +61,25 @@ let call_graph p info call_info =
5961 exact
6062 && (not others)
6163 && Var.Set. for_all (fun f -> direct_calls_only call_info f) known
62- && nesting > 0
6364 then
64- Var.Set. iter
65- (fun f ->
66- (* Format.eprintf "BBB %a@." Code.Var.print f; *)
67- Var.Hashtbl. replace under_handler f () )
68- known)
65+ if nesting > 0
66+ then
67+ Var.Set. iter
68+ (fun f ->
69+ (* Format.eprintf "BBB %a@." Code.Var.print f; *)
70+ Var.Hashtbl. replace under_handler f () )
71+ known
72+ else
73+ Option. iter
74+ ~f: (fun f ->
75+ Var.Set. iter
76+ (fun g ->
77+ Var.Hashtbl. add callees f g;
78+ Var.Hashtbl. add callers g f)
79+ known)
80+ name_opt)
6981 | Let (_, (Closure _ | Prim _ | Block _ | Constant _ | Field _ | Special _))
7082 | Event _ | Assign _ | Set_field _ | Offset_ref _ | Array_set _ -> () );
71-
7283 Code. fold_children
7384 p.blocks
7485 pc
@@ -79,12 +90,15 @@ let call_graph p info call_info =
7990 | Poptrap _ -> nesting - 1
8091 | _ -> nesting
8192 in
82- traverse pc' visited nesting)
93+ traverse name_opt pc' visited nesting)
8394 visited)
8495 else visited
8596 in
86- fold_closures p (fun _ _ (pc , _ ) _ () -> ignore (traverse pc Addr.Set. empty 0 )) () ;
87- under_handler
97+ fold_closures
98+ p
99+ (fun name_opt _ (pc , _ ) _ () -> ignore (traverse name_opt pc Addr.Set. empty 0 ))
100+ () ;
101+ under_handler, callers, callees
88102
89103let function_do_raise p pc =
90104 Code. traverse
@@ -100,26 +114,42 @@ let function_do_raise p pc =
100114 p.blocks
101115 false
102116
117+ let propagate nodes edges eligible =
118+ let rec propagate n =
119+ List. iter
120+ ~f: (fun n' ->
121+ if (not (Var.Hashtbl. mem nodes n')) && eligible n'
122+ then (
123+ Var.Hashtbl. add nodes n' () ;
124+ propagate n'))
125+ (Var.Hashtbl. find_all edges n)
126+ in
127+ Var.Hashtbl. iter (fun n () -> propagate n) nodes
128+
103129let raising_functions p info call_info eligible =
104- let under_handler = call_graph p info call_info in
130+ let under_handler, callers, callees = call_graph p info call_info in
131+ propagate under_handler callees eligible;
105132 let h = Var.Hashtbl. create 16 in
106133 Code. fold_closures
107134 p
108135 (fun name_opt _params (pc , _ ) _ () ->
109136 match name_opt with
110137 | None -> ()
111138 | Some name ->
112- if direct_calls_only call_info name && eligible name && function_do_raise p pc
113- then (
114- if Var.Hashtbl. mem under_handler name then Var.Hashtbl. add h name () ;
115- if false
116- then
117- Format. eprintf
118- " ZZZ %a %b@."
119- Var. print
120- name
121- (Var.Hashtbl. mem under_handler name)))
139+ if
140+ direct_calls_only call_info name
141+ && eligible name
142+ && function_do_raise p pc
143+ && Var.Hashtbl. mem under_handler name
144+ then Var.Hashtbl. add h name () )
122145 () ;
146+ propagate h callers (fun f -> eligible f && Var.Hashtbl. mem under_handler f);
147+ if false
148+ then
149+ Var.Hashtbl. iter
150+ (fun name () ->
151+ Format. eprintf " ZZZ %a %b@." Var. print name (Var.Hashtbl. mem under_handler name))
152+ h;
123153 h
124154
125155let f p info =
0 commit comments