Skip to content

Commit 77b8921

Browse files
committed
Make aggressive lambda lifting opt-in
1 parent d1f9b14 commit 77b8921

File tree

6 files changed

+95
-24
lines changed

6 files changed

+95
-24
lines changed

compiler/bin-js_of_ocaml/build_fs.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ function jsoo_create_file_extern(name,content){
8080
~standalone:true
8181
~wrap_with_fun:`Iife
8282
~link:`Needed
83+
~lambda_lift_all:false
8384
~formatter:pfs_fmt
8485
~source_map:false
8586
code

compiler/bin-js_of_ocaml/cmd_arg.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ type t =
7878
; fs_external : bool
7979
; keep_unit_names : bool
8080
; effects : Config.effects_backend
81+
; lambda_lift_all : bool
8182
}
8283

8384
let set_param =
@@ -306,6 +307,14 @@ let options =
306307
None
307308
& info [ "effects" ] ~docv:"KIND" ~doc)
308309
in
310+
let lambda_lift_all =
311+
let doc =
312+
"Lambda-lift all functions in the compilation result. This can improve the \
313+
performance of some programs on some engines (such as V8). Ignored when effects \
314+
are enabled."
315+
in
316+
Arg.(value & flag & info [ "lambda-lift-all" ] ~doc)
317+
in
309318
let build_t
310319
common
311320
set_param
@@ -335,6 +344,7 @@ let options =
335344
js_files
336345
keep_unit_names
337346
effects
347+
lambda_lift_all
338348
shape_files =
339349
let inline_source_content = not sourcemap_don't_inline_content in
340350
let chop_extension s = try Filename.chop_extension s with Invalid_argument _ -> s in
@@ -406,6 +416,7 @@ let options =
406416
; source_map
407417
; keep_unit_names
408418
; effects
419+
; lambda_lift_all
409420
; shape_files
410421
}
411422
in
@@ -440,6 +451,7 @@ let options =
440451
$ js_files
441452
$ keep_unit_names
442453
$ effects
454+
$ lambda_lift_all
443455
$ shape_files)
444456
in
445457
Term.ret t
@@ -662,6 +674,7 @@ let options_runtime_only =
662674
; keep_unit_names = false
663675
; effects
664676
; shape_files = []
677+
; lambda_lift_all = false
665678
}
666679
in
667680
let t =

compiler/bin-js_of_ocaml/cmd_arg.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ type t =
5151
; fs_external : bool
5252
; keep_unit_names : bool
5353
; effects : Config.effects_backend
54+
; lambda_lift_all : bool
5455
}
5556

5657
val options : t Cmdliner.Term.t

compiler/bin-js_of_ocaml/compile.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ let run
156156
; keep_unit_names
157157
; include_runtime
158158
; effects
159+
; lambda_lift_all
159160
; shape_files
160161
} =
161162
let source_map_base =
@@ -279,6 +280,7 @@ let run
279280
~wrap_with_fun
280281
~source_map:(source_map_enabled source_map)
281282
~formatter
283+
~lambda_lift_all
282284
code
283285
| `File, formatter ->
284286
let fs_instr1, fs_instr2 =
@@ -300,6 +302,7 @@ let run
300302
~shapes
301303
?profile
302304
~link
305+
~lambda_lift_all
303306
~wrap_with_fun
304307
~source_map:(source_map_enabled source_map)
305308
~formatter

compiler/lib/driver.ml

Lines changed: 75 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,21 @@ let collects_shapes ~shapes (p : Code.program) =
142142
map)
143143
else StringMap.empty
144144

145+
let all_functions p =
146+
let open Code in
147+
fold_closures
148+
p
149+
(fun name _ _ _ acc ->
150+
match name with
151+
| Some name -> Var.Set.add name acc
152+
| None -> acc)
153+
Var.Set.empty
154+
145155
let effects_and_exact_calls
146156
~keep_flow_data
147157
~deadcode_sentinal
148158
~shapes
159+
~lambda_lift_all
149160
(profile : Profile.t)
150161
p =
151162
let fast =
@@ -166,11 +177,8 @@ let effects_and_exact_calls
166177
else Deadcode.f pure_fun p
167178
in
168179
let p =
169-
match Config.(target (), effects ()) with
170-
| `JavaScript, `Disabled ->
171-
(* If effects are disabled, we lambda-lift aggressively. While not
172-
necessary, it results in a substantial gain in performance in some
173-
programs in Javascript. *)
180+
match lambda_lift_all, Config.target (), Config.effects () with
181+
| true, `JavaScript, `Disabled ->
174182
let to_lift = all_functions p in
175183
let p, _ = Lambda_lifting_simple.f ~to_lift p in
176184
p
@@ -707,17 +715,7 @@ let link_and_pack ?(standalone = true) ?(wrap_with_fun = `Iife) ?(link = `No) p
707715
|> pack ~wrap_with_fun ~standalone
708716
|> check_js
709717

710-
let all_functions p =
711-
let open Code in
712-
fold_closures
713-
p
714-
(fun name _ _ _ acc ->
715-
match name with
716-
| Some name -> Var.Set.add name acc
717-
| None -> acc)
718-
Var.Set.empty
719-
720-
let optimize ~shapes ~profile ~keep_flow_data p =
718+
let optimize ~shapes ~profile ~keep_flow_data ~lambda_lift_all p =
721719
let deadcode_sentinal =
722720
(* If deadcode is disabled, this field is just fresh variable *)
723721
Code.Var.fresh_n "dummy"
@@ -730,7 +728,12 @@ let optimize ~shapes ~profile ~keep_flow_data p =
730728
| O2 -> o2
731729
| O3 -> o3)
732730
+> specialize_js_once_after
733-
+> effects_and_exact_calls ~keep_flow_data ~deadcode_sentinal ~shapes profile
731+
+> effects_and_exact_calls
732+
~keep_flow_data
733+
~deadcode_sentinal
734+
~shapes
735+
~lambda_lift_all
736+
profile
734737
+> map_fst5
735738
(match Config.target (), Config.effects () with
736739
| `JavaScript, `Disabled -> Generate_closure.f
@@ -750,15 +753,26 @@ let optimize ~shapes ~profile ~keep_flow_data p =
750753

751754
let optimize_for_wasm ~shapes ~profile p =
752755
let optimized_code, global_flow_data =
753-
optimize ~shapes ~profile ~keep_flow_data:true p
756+
optimize ~shapes ~profile ~keep_flow_data:true ~lambda_lift_all:false p
754757
in
755758
( optimized_code
756759
, match global_flow_data with
757760
| Some data -> data
758761
| None -> Global_flow.f ~fast:false optimized_code.program )
759762

760-
let full ~standalone ~wrap_with_fun ~shapes ~profile ~link ~source_map ~formatter p =
761-
let optimized_code, _ = optimize ~shapes ~profile ~keep_flow_data:false p in
763+
let full
764+
~standalone
765+
~wrap_with_fun
766+
~shapes
767+
~profile
768+
~link
769+
~source_map
770+
~formatter
771+
~lambda_lift_all
772+
p =
773+
let optimized_code, _ =
774+
optimize ~shapes ~profile ~keep_flow_data:false ~lambda_lift_all p
775+
in
762776
let exported_runtime = not standalone in
763777
let emit formatter =
764778
generate ~exported_runtime ~wrap_with_fun ~warn_on_unhandled_effect:standalone
@@ -778,9 +792,26 @@ let full ~standalone ~wrap_with_fun ~shapes ~profile ~link ~source_map ~formatte
778792
shapes_v;
779793
emit formatter optimized_code, shapes_v
780794

781-
let full_no_source_map ~formatter ~shapes ~standalone ~wrap_with_fun ~profile ~link p =
795+
let full_no_source_map
796+
~formatter
797+
~shapes
798+
~standalone
799+
~wrap_with_fun
800+
~profile
801+
~link
802+
~lambda_lift_all
803+
p =
782804
let (_ : Source_map.info * _) =
783-
full ~shapes ~standalone ~wrap_with_fun ~profile ~link ~source_map:false ~formatter p
805+
full
806+
~shapes
807+
~standalone
808+
~wrap_with_fun
809+
~profile
810+
~link
811+
~source_map:false
812+
~formatter
813+
~lambda_lift_all
814+
p
784815
in
785816
()
786817

@@ -792,17 +823,36 @@ let f
792823
~link
793824
~source_map
794825
~formatter
826+
~lambda_lift_all
795827
p =
796-
full ~standalone ~wrap_with_fun ~shapes ~profile ~link ~source_map ~formatter p
828+
full
829+
~standalone
830+
~wrap_with_fun
831+
~shapes
832+
~profile
833+
~link
834+
~source_map
835+
~formatter
836+
~lambda_lift_all
837+
p
797838

798839
let f'
799840
?(standalone = true)
800841
?(wrap_with_fun = `Iife)
801842
?(profile = Profile.O1)
843+
?(lambda_lift_all = false)
802844
~link
803845
formatter
804846
p =
805-
full_no_source_map ~formatter ~shapes:false ~standalone ~wrap_with_fun ~profile ~link p
847+
full_no_source_map
848+
~formatter
849+
~shapes:false
850+
~standalone
851+
~wrap_with_fun
852+
~profile
853+
~link
854+
~lambda_lift_all
855+
p
806856

807857
let from_string ~prims ~debug s formatter =
808858
let p = Parse_bytecode.from_string ~prims ~debug s in
@@ -813,4 +863,5 @@ let from_string ~prims ~debug s formatter =
813863
~wrap_with_fun:`Anonymous
814864
~profile:O1
815865
~link:`No
866+
~lambda_lift_all:false
816867
p

compiler/lib/driver.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,15 @@ val f :
4343
-> link:[ `All | `All_from of string list | `Needed | `No ]
4444
-> source_map:bool
4545
-> formatter:Pretty_print.t
46+
-> lambda_lift_all:bool
4647
-> Code.program
4748
-> Source_map.info * Shape.t StringMap.t
4849

4950
val f' :
5051
?standalone:bool
5152
-> ?wrap_with_fun:[ `Iife | `Anonymous | `Named of string ]
5253
-> ?profile:Profile.t
54+
-> ?lambda_lift_all:bool
5355
-> link:[ `All | `All_from of string list | `Needed | `No ]
5456
-> Pretty_print.t
5557
-> Code.program

0 commit comments

Comments
 (0)