Skip to content

Commit e4b2087

Browse files
committed
Preserve sharing in nested CMJ summaries
1 parent 03033e8 commit e4b2087

2 files changed

Lines changed: 73 additions & 53 deletions

File tree

jscomp/core/lam_stats_export.ml

Lines changed: 72 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,29 @@ let values_of_export =
4141
Lam_call_summary.Direct_external
4242
{ dynamic_import; id; name; arity; relocatable }
4343
in
44+
(* Preserve sharing in the lambda graph when building recursive CMJ data. *)
45+
let memoize cache key f =
46+
match Ident.Hashtbl.find cache key with
47+
| value -> value
48+
| exception Not_found ->
49+
let value = f () in
50+
Ident.Hashtbl.replace cache ~key ~data:value;
51+
value
52+
in
53+
let arity_cache = Ident.Hashtbl.create 32 in
4454
let rec arity_of_lambda (meta : Lam_stats.t) seen = function
45-
| (Lam.Lvar v | Lmutvar v) as lam -> (
46-
if Ident.Set.mem v seen then Js_cmj_format.single_na
47-
else
48-
let seen = Ident.Set.add v seen in
49-
match Ident.Hashtbl.find meta.ident_tbl v with
50-
| ImmutableBlock elems ->
51-
Js_cmj_format.Submodule
52-
(Array.map elems ~f:(arity_of_element meta seen))
53-
| FunctionId { arity; _ } -> Js_cmj_format.Single arity
54-
| _ | (exception Not_found) ->
55-
Js_cmj_format.Single (Lam_arity_analysis.get_arity meta lam))
55+
| (Lam.Lvar v | Lmutvar v) as lam ->
56+
memoize arity_cache v (fun () ->
57+
if Ident.Set.mem v seen then Js_cmj_format.single_na
58+
else
59+
let seen = Ident.Set.add v seen in
60+
match Ident.Hashtbl.find meta.ident_tbl v with
61+
| ImmutableBlock elems ->
62+
Js_cmj_format.Submodule
63+
(Array.map elems ~f:(arity_of_element meta seen))
64+
| FunctionId { arity; _ } -> Js_cmj_format.Single arity
65+
| _ | (exception Not_found) ->
66+
Js_cmj_format.Single (Lam_arity_analysis.get_arity meta lam))
5667
| Lam.Lprim { primitive = Pmakeblock (_, _, Immutable); args; _ } ->
5768
Js_cmj_format.Submodule
5869
(Array.of_list_map args ~f:(arity_of_lambda meta seen))
@@ -105,19 +116,22 @@ let values_of_export =
105116
(if Lam_call_summary.is_relocatable summary then summary
106117
else Lam_call_summary.Unknown)
107118
in
119+
let nested_call_summary_cache = Ident.Hashtbl.create 32 in
108120
let rec nested_call_summary_of_lambda (meta : Lam_stats.t) seen = function
109-
| (Lam.Lvar v | Lmutvar v) as lam -> (
110-
if Ident.Set.mem v seen then Js_cmj_format.call_summary_unknown
111-
else
112-
let seen = Ident.Set.add v seen in
113-
match Ident.Hashtbl.find meta.ident_tbl v with
114-
| ImmutableBlock elems ->
115-
Js_cmj_format.Call_summary_submodule
116-
(Array.map elems ~f:(nested_call_summary_of_element meta seen))
117-
| FunctionId { call_summary; _ } ->
118-
nested_call_summary_of_summary call_summary
119-
| _ | (exception Not_found) ->
120-
Js_cmj_format.Call_summary (summarize meta lam))
121+
| (Lam.Lvar v | Lmutvar v) as lam ->
122+
memoize nested_call_summary_cache v (fun () ->
123+
if Ident.Set.mem v seen then Js_cmj_format.call_summary_unknown
124+
else
125+
let seen = Ident.Set.add v seen in
126+
match Ident.Hashtbl.find meta.ident_tbl v with
127+
| ImmutableBlock elems ->
128+
Js_cmj_format.Call_summary_submodule
129+
(Array.map elems
130+
~f:(nested_call_summary_of_element meta seen))
131+
| FunctionId { call_summary; _ } ->
132+
nested_call_summary_of_summary call_summary
133+
| _ | (exception Not_found) ->
134+
Js_cmj_format.Call_summary (summarize meta lam))
121135
| Lam.Lprim { primitive = Pmakeblock (_, _, Immutable); args; _ } ->
122136
Js_cmj_format.Call_summary_submodule
123137
(Array.of_list_map args ~f:(nested_call_summary_of_lambda meta seen))
@@ -134,22 +148,26 @@ let values_of_export =
134148
:
135149
Js_cmj_format.cmj_value String.Map.t
136150
->
151+
Ident.Hashtbl.clear arity_cache;
152+
Ident.Hashtbl.clear nested_call_summary_cache;
137153
List.fold_left meta.exports ~init:String.Map.empty ~f:(fun acc x ->
138154
let arity =
139-
match Ident.Hashtbl.find meta.ident_tbl x with
140-
| FunctionId { arity; _ } -> Js_cmj_format.Single arity
141-
| ImmutableBlock elems ->
142-
(* FIXME: field name for dumping *)
143-
Submodule
144-
(Array.map elems
145-
~f:(arity_of_element meta (Ident.Set.singleton x)))
146-
| _ | (exception Not_found) -> (
147-
match Ident.Map.find x export_map with
148-
| Lprim { primitive = Pmakeblock (_, _, Immutable); args; _ } ->
155+
memoize arity_cache x (fun () ->
156+
match Ident.Hashtbl.find meta.ident_tbl x with
157+
| FunctionId { arity; _ } -> Js_cmj_format.Single arity
158+
| ImmutableBlock elems ->
159+
(* FIXME: field name for dumping *)
149160
Submodule
150-
(Array.of_list_map args
151-
~f:(arity_of_lambda meta (Ident.Set.singleton x)))
152-
| _ | (exception Not_found) -> Js_cmj_format.single_na)
161+
(Array.map elems
162+
~f:(arity_of_element meta (Ident.Set.singleton x)))
163+
| _ | (exception Not_found) -> (
164+
match Ident.Map.find x export_map with
165+
| Lprim { primitive = Pmakeblock (_, _, Immutable); args; _ }
166+
->
167+
Submodule
168+
(Array.of_list_map args
169+
~f:(arity_of_lambda meta (Ident.Set.singleton x)))
170+
| _ | (exception Not_found) -> Js_cmj_format.single_na))
153171
in
154172
let persistent_closed_lambda =
155173
match Ident.Map.find x export_map with
@@ -206,25 +224,27 @@ let values_of_export =
206224
| exception Not_found -> Lam_call_summary.Unknown
207225
in
208226
let nested_call_summary =
209-
match Ident.Hashtbl.find meta.ident_tbl x with
210-
| FunctionId { call_summary; _ } ->
211-
nested_call_summary_of_summary call_summary
212-
| ImmutableBlock elems ->
213-
Js_cmj_format.Call_summary_submodule
214-
(Array.map elems
215-
~f:
216-
(nested_call_summary_of_element meta
217-
(Ident.Set.singleton x)))
218-
| _ | (exception Not_found) -> (
219-
match Ident.Map.find x export_map with
220-
| Lprim { primitive = Pmakeblock (_, _, Immutable); args; _ } ->
227+
memoize nested_call_summary_cache x (fun () ->
228+
match Ident.Hashtbl.find meta.ident_tbl x with
229+
| FunctionId { call_summary; _ } ->
230+
nested_call_summary_of_summary call_summary
231+
| ImmutableBlock elems ->
221232
Js_cmj_format.Call_summary_submodule
222-
(Array.of_list_map args
233+
(Array.map elems
223234
~f:
224-
(nested_call_summary_of_lambda meta
235+
(nested_call_summary_of_element meta
225236
(Ident.Set.singleton x)))
226-
| lambda -> Js_cmj_format.Call_summary (summarize meta lambda)
227-
| exception Not_found -> Js_cmj_format.call_summary_unknown)
237+
| _ | (exception Not_found) -> (
238+
match Ident.Map.find x export_map with
239+
| Lprim { primitive = Pmakeblock (_, _, Immutable); args; _ }
240+
->
241+
Js_cmj_format.Call_summary_submodule
242+
(Array.of_list_map args
243+
~f:
244+
(nested_call_summary_of_lambda meta
245+
(Ident.Set.singleton x)))
246+
| lambda -> Js_cmj_format.Call_summary (summarize meta lambda)
247+
| exception Not_found -> Js_cmj_format.call_summary_unknown))
228248
in
229249
match (arity, persistent_closed_lambda, call_summary) with
230250
| Single Arity_na, (None | Some (Lconst Const_module_alias, _)), summary

test/blackbox-tests/cmj-summary-sharing.t

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ recursive CMJ summary data.
2828

2929
$ melc $MEL_STDLIB_FLAGS --mel-stop-after-cmj input.ml
3030
$ if test "$(wc -c < input.cmj)" -lt 100000; then echo shared; else echo duplicated; fi
31-
duplicated
31+
shared

0 commit comments

Comments
 (0)