Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Effects: double translation of functions and dynamic switching between direct-style and CPS code #1461

Open
wants to merge 80 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 71 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
120f235
Effects: double translation of functions and
OlivierNicole Mar 9, 2023
38f0462
Add caml_assume_no_effects primitive and tests
OlivierNicole Jun 11, 2024
7f769be
CR: Fix non-raised Unhandled with assume_no_perform
OlivierNicole Nov 20, 2024
0192c16
CR: Commit suggestion for compiler/lib/driver.ml
OlivierNicole Nov 20, 2024
10f8752
Fix runtime deps, add missing test
OlivierNicole Nov 20, 2024
92e41d8
CR
OlivierNicole Nov 22, 2024
de30b43
CR
OlivierNicole Nov 22, 2024
77c2331
Runtime format
OlivierNicole Nov 22, 2024
22584e4
Factorize substitution logic
OlivierNicole Nov 27, 2024
370a0b0
CR: make caml_callback an alias of caml_call_gen...
OlivierNicole Nov 28, 2024
e980a1b
Promote tests
OlivierNicole Nov 28, 2024
55cbe59
CR: Fix caml_trampoline_cps and rename it to caml_resume
OlivierNicole Nov 28, 2024
ef3bc27
CR: First fixes to Lambda_lifting_simple
OlivierNicole Nov 28, 2024
c2f39d3
Simplify and clarify Lambda_lifting_simple
OlivierNicole Nov 29, 2024
21c955b
Format runtime
OlivierNicole Nov 29, 2024
5ed1a30
Fix bug: functions inside CPS functions were not lambda-lifted
OlivierNicole Nov 29, 2024
efb7892
Runtime: fix caml_uncaught_effect_handler
vouillon Nov 29, 2024
5b7c9e4
Runtime: the trampoline now distinguish direct and CPS calls
vouillon Nov 29, 2024
1d34f2b
Fix unregistered test and add one for nested handler
OlivierNicole Dec 3, 2024
425e526
Uses 'tests' dune stanza
OlivierNicole Dec 3, 2024
f605852
Reformat dune files and remove leftover files
OlivierNicole Dec 3, 2024
9586742
CR: Fixes in Lambda_lifting_simple
OlivierNicole Dec 3, 2024
b62ba9a
CR: remove unnecessary conditionals in Effects
OlivierNicole Dec 3, 2024
ffa361b
CR: Remove duplicate instruction
OlivierNicole Dec 4, 2024
d5cb751
CR: Apply suggested simplifications
OlivierNicole Dec 4, 2024
49ca07e
Add test for lambda-lifting of mutually recursive functions
OlivierNicole Dec 4, 2024
13ede20
CR
OlivierNicole Dec 4, 2024
68b1334
Revert addition of no longer necessary Freevars functions
OlivierNicole Dec 4, 2024
cf89d76
Add wasm mode to double translation tests
OlivierNicole Dec 4, 2024
d874120
CR: Add missing Wasm stubs
OlivierNicole Dec 4, 2024
259973a
Revert "Add wasm mode to double translation tests"
OlivierNicole Dec 5, 2024
64a6beb
Update dune.inc
OlivierNicole Dec 5, 2024
028027a
CR
OlivierNicole Dec 5, 2024
17a051f
CR
OlivierNicole Dec 5, 2024
1ff3b10
Use copy_file rather than duplicate tests
OlivierNicole Dec 6, 2024
f5ed63b
Update comment
OlivierNicole Dec 6, 2024
0807507
CR: Factorize some code
OlivierNicole Dec 6, 2024
21e750a
CR
OlivierNicole Dec 6, 2024
b734492
CR: simplify
OlivierNicole Dec 6, 2024
343f270
Simplify function rewrite_instr
vouillon Dec 9, 2024
28690a7
Function assume_no_perform makes perform fail for all effect implemen…
vouillon Dec 9, 2024
43eb25b
CR: Add --effects option
OlivierNicole Dec 10, 2024
0835a69
Fix Dynlink and limit use of --enable=effects
OlivierNicole Dec 11, 2024
29c6a82
Reformat
OlivierNicole Dec 12, 2024
b8a3799
CR
OlivierNicole Dec 12, 2024
733f4dc
CR
OlivierNicole Dec 12, 2024
618bc52
CR: add missing bound check
OlivierNicole Dec 12, 2024
244267e
CR: Simplification in compiler/lib/effects.ml
OlivierNicole Dec 12, 2024
b705214
CR: simplify closure allocation
OlivierNicole Dec 12, 2024
f1441bc
Javascript runtime: stop using 'arguments'
OlivierNicole Dec 12, 2024
4107e24
Fix too early effects backend setting
OlivierNicole Dec 12, 2024
9b8a90b
Fix uses of `--enable=effects` in lib-wasm/
vouillon Dec 12, 2024
cc38500
Move assume_no_perform to Jsoo_runtime
OlivierNicole Dec 12, 2024
31be126
Fix: move C primitive
OlivierNicole Dec 12, 2024
26a2b6d
CR
OlivierNicole Dec 13, 2024
f736e33
CR: rephrase comment
OlivierNicole Dec 16, 2024
68d02df
CR: Move effects backend choice logic
OlivierNicole Dec 16, 2024
35b27b0
CR: simplify
OlivierNicole Dec 16, 2024
12adc93
Docs: document double translation better
OlivierNicole Dec 16, 2024
b778d47
Fix warning
OlivierNicole Dec 16, 2024
1910866
Fix another warning
OlivierNicole Dec 16, 2024
6536533
Update manual/effects.wiki
OlivierNicole Dec 16, 2024
cfdca94
CR: revert some changes in docs
OlivierNicole Dec 16, 2024
f914e22
Don't set effects_backend in _cmd_arg_ modules
hhugo Dec 17, 2024
865f90e
Fix compilation
OlivierNicole Dec 17, 2024
9c28e19
CR
OlivierNicole Dec 17, 2024
b025490
CR: add CONFIG macro
OlivierNicole Dec 17, 2024
796e973
Re-export Jsoo_runtime from the js_of_ocaml library
OlivierNicole Dec 19, 2024
dded0e8
Fix spurious free var warning over CONFIG macro
OlivierNicole Dec 19, 2024
c4e594f
CR: Update compiler/lib/driver.ml
OlivierNicole Dec 19, 2024
6bb65e4
Remove duplicate effects flag
OlivierNicole Dec 20, 2024
6391bd6
CR: more explicit type for effects backend
OlivierNicole Dec 21, 2024
51b3d50
CR: doc phrasing
OlivierNicole Dec 22, 2024
3109620
CR: revert obsolete change
OlivierNicole Dec 22, 2024
821537d
Fix assertion
OlivierNicole Dec 22, 2024
3a52728
CR: comment to justify constant
OlivierNicole Dec 22, 2024
5541f1b
reformat
OlivierNicole Dec 22, 2024
01595fc
Fixes
OlivierNicole Dec 22, 2024
7066f6b
Fix assert failure
OlivierNicole Dec 23, 2024
0eeaafe
reformat
OlivierNicole Dec 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* Merged Wasm_of_ocaml (#1724)
* Lib: removed no longer relevant Js.optdef type annotations (#1769)
* Misc: drop support for IE
* Effects: add an optional feature of "dynamic switching" between CPS and direct style, resulting in better performance when no effect handler is installed

## Bug fixes
* Fix small bug in global data flow analysis (#1768)
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ optimized:
[More](http://ocsigen.org/js_of_ocaml/dev/manual/tailcall) about tail call
optimization.

Effect handlers are supported with the `--enable=effects` flag.
Effect handlers are supported with the `--effects={cps,double-translation}`
flag.

## Data representation

Expand Down
4 changes: 2 additions & 2 deletions README_wasm_of_ocaml.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ In particular, the output code requires the following [Wasm extensions](https://

OCaml 5.x code using effect handlers can be compiled in two different ways:
One can enable the CPS transformation from `js_of_ocaml` by passing the
`--enable=effects` flag. Without the flag `wasm_of_ocaml` will instead emit code
utilizing
`--effects=cps` flag. Without the flag `wasm_of_ocaml` will instead default to
`--effects=jspi` and emit code utilizing
- [the JavaScript-Promise Integration extension](https://github.com/WebAssembly/js-promise-integration/blob/main/proposals/js-promise-integration/Overview.md)


Expand Down
51 changes: 47 additions & 4 deletions compiler/bin-js_of_ocaml/cmd_arg.ml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,16 @@ let trim_trailing_dir_sep s =

let normalize_include_dirs dirs = List.map dirs ~f:trim_trailing_dir_sep

let normalize_effects effects common =
(* For backward compatibility, consider that [--enable effects] alone means
[--effects cps] *)
match effects with
| None ->
if List.mem "effects" ~set:common.Jsoo_cmdline.Arg.optim.enable
then Some Config.Cps
else None
| Some _ -> effects

type t =
{ common : Jsoo_cmdline.Arg.t
; (* compile option *)
Expand All @@ -65,6 +75,7 @@ type t =
; fs_output : string option
; fs_external : bool
; keep_unit_names : bool
; effects : Config.effects_backend option
}

let wrap_with_fun_conv =
Expand Down Expand Up @@ -253,6 +264,18 @@ let options =
& opt (some string) None
& info [ "ofs" ] ~docs:filesystem_section ~docv:"FILE" ~doc)
in
let effects =
let doc =
"Select an implementation of effect handlers. [$(docv)] should be one of $(b,cps) \
or $(b,double-translation). Effects won't be supported if unspecified."
in
Arg.(
value
& opt
(some (enum [ "cps", Config.Cps; "double-translation", Double_translation ]))
None
& info [ "effects" ] ~docv:"KIND" ~doc)
in
let build_t
common
set_param
Expand All @@ -279,7 +302,8 @@ let options =
output_file
input_file
js_files
keep_unit_names =
keep_unit_names
effects =
let inline_source_content = not sourcemap_don't_inline_content in
let chop_extension s = try Filename.chop_extension s with Invalid_argument _ -> s in
let runtime_files = js_files in
Expand Down Expand Up @@ -318,6 +342,7 @@ let options =
let params : (string * string) list = List.flatten set_param in
let static_env : (string * string) list = List.flatten set_env in
let include_dirs = normalize_include_dirs include_dirs in
let effects = normalize_effects effects common in
`Ok
{ common
; params
Expand All @@ -341,6 +366,7 @@ let options =
; bytecode
; source_map
; keep_unit_names
; effects
}
in
let t =
Expand Down Expand Up @@ -371,7 +397,8 @@ let options =
$ output_file
$ input_file
$ js_files
$ keep_unit_names)
$ keep_unit_names
$ effects)
in
Term.ret t

Expand Down Expand Up @@ -496,6 +523,18 @@ let options_runtime_only =
& opt (some string) None
& info [ "ofs" ] ~docs:filesystem_section ~docv:"FILE" ~doc)
in
let effects =
let doc =
"Select an implementation of effect handlers. [$(docv)] should be one of $(b,cps) \
or $(b,double-translation). Effects are not allowed by default."
hhugo marked this conversation as resolved.
Show resolved Hide resolved
in
Arg.(
value
& opt
(some (enum [ "cps", Config.Cps; "double-translation", Double_translation ]))
None
& info [ "effects" ] ~docv:"KIND" ~doc)
in
let build_t
common
toplevel
Expand All @@ -515,7 +554,8 @@ let options_runtime_only =
sourcemap_root
target_env
output_file
js_files =
js_files
effects =
let inline_source_content = not sourcemap_don't_inline_content in
let chop_extension s = try Filename.chop_extension s with Invalid_argument _ -> s in
let runtime_files = js_files in
Expand Down Expand Up @@ -544,6 +584,7 @@ let options_runtime_only =
let params : (string * string) list = List.flatten set_param in
let static_env : (string * string) list = List.flatten set_env in
let include_dirs = normalize_include_dirs include_dirs in
let effects = normalize_effects effects common in
`Ok
{ common
; params
Expand All @@ -567,6 +608,7 @@ let options_runtime_only =
; bytecode = `None
; source_map
; keep_unit_names = false
; effects
}
in
let t =
Expand All @@ -590,6 +632,7 @@ let options_runtime_only =
$ sourcemap_root
$ target_env
$ output_file
$ js_files)
$ js_files
$ effects)
in
Term.ret t
1 change: 1 addition & 0 deletions compiler/bin-js_of_ocaml/cmd_arg.mli
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type t =
; fs_output : string option
; fs_external : bool
; keep_unit_names : bool
; effects : Config.effects_backend option
}

val options : t Cmdliner.Term.t
Expand Down
2 changes: 2 additions & 0 deletions compiler/bin-js_of_ocaml/compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ let run
; export_file
; keep_unit_names
; include_runtime
; effects
} =
let source_map_base = Option.map ~f:snd source_map in
let source_map =
Expand All @@ -165,6 +166,7 @@ let run
let custom_header = common.Jsoo_cmdline.Arg.custom_header in
Config.set_target `JavaScript;
Jsoo_cmdline.Arg.eval common;
Config.set_effects_backend effects;
Linker.reset ();
(match output_file with
| `Stdout, _ -> ()
Expand Down
47 changes: 43 additions & 4 deletions compiler/bin-wasm_of_ocaml/cmd_arg.ml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ let trim_trailing_dir_sep s =

let normalize_include_dirs dirs = List.map dirs ~f:trim_trailing_dir_sep

let normalize_effects effects common =
(* For backward compatibility, consider that [--enable effects] alone means [--effects cps] *)
match effects with
| None ->
if List.mem "effects" ~set:common.Jsoo_cmdline.Arg.optim.enable
then Some Config.Cps
else None
| Some Config.Cps -> Some Config.Cps
| Some _ -> failwith "Unexpected effects backend"

type t =
{ common : Jsoo_cmdline.Arg.t
; (* compile option *)
Expand All @@ -51,6 +61,7 @@ type t =
; sourcemap_don't_inline_content : bool
; params : (string * string) list
; include_dirs : string list
; effects : Config.effects_backend option
}

let options =
Expand Down Expand Up @@ -103,6 +114,16 @@ let options =
let doc = "Add [$(docv)] to the list of include directories." in
Arg.(value & opt_all string [] & info [ "I" ] ~docv:"DIR" ~doc)
in
let effects =
let doc =
"Select an implementation of effect handlers. [$(docv)] should be one of $(b,jspi) \
(the default) or $(b,cps)."
in
Arg.(
value
& opt (enum [ "jspi", None; "cps", Some Config.Cps ]) None
& info [ "effects" ] ~docv:"KIND" ~doc)
in
let build_t
common
set_param
Expand All @@ -115,7 +136,8 @@ let options =
sourcemap_root
output_file
input_file
runtime_files =
runtime_files
effects =
let chop_extension s = try Filename.chop_extension s with Invalid_argument _ -> s in
let output_file =
let ext =
Expand All @@ -133,6 +155,7 @@ let options =
let params : (string * string) list = List.flatten set_param in
let enable_source_maps = (not no_sourcemap) && sourcemap in
let include_dirs = normalize_include_dirs include_dirs in
let effects = normalize_effects effects common in
`Ok
{ common
; params
Expand All @@ -145,6 +168,7 @@ let options =
; enable_source_maps
; sourcemap_root
; sourcemap_don't_inline_content
; effects
}
in
let t =
Expand All @@ -161,7 +185,8 @@ let options =
$ sourcemap_root
$ output_file
$ input_file
$ runtime_files)
$ runtime_files
$ effects)
in
Term.ret t

Expand Down Expand Up @@ -204,6 +229,16 @@ let options_runtime_only =
& opt_all (list (pair ~sep:'=' (enum all) string)) []
& info [ "set" ] ~docv:"PARAM=VALUE" ~doc)
in
let effects =
let doc =
"Select an implementation of effect handlers. [$(docv)] should be one of $(b,jspi) \
(the default) or $(b,cps)."
in
Arg.(
value
& opt (enum [ "jspi", None; "cps", Some Config.Cps ]) None
& info [ "effects" ] ~docv:"KIND" ~doc)
in
let build_t
common
set_param
Expand All @@ -213,10 +248,12 @@ let options_runtime_only =
sourcemap_don't_inline_content
sourcemap_root
output_file
runtime_files =
runtime_files
effects =
let params : (string * string) list = List.flatten set_param in
let enable_source_maps = (not no_sourcemap) && sourcemap in
let include_dirs = normalize_include_dirs include_dirs in
let effects = normalize_effects effects common in
`Ok
{ common
; params
Expand All @@ -229,6 +266,7 @@ let options_runtime_only =
; enable_source_maps
; sourcemap_root
; sourcemap_don't_inline_content
; effects
}
in
let t =
Expand All @@ -242,6 +280,7 @@ let options_runtime_only =
$ sourcemap_don't_inline_content
$ sourcemap_root
$ output_file
$ runtime_files)
$ runtime_files
$ effects)
in
Term.ret t
1 change: 1 addition & 0 deletions compiler/bin-wasm_of_ocaml/cmd_arg.mli
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type t =
; sourcemap_don't_inline_content : bool
; params : (string * string) list
; include_dirs : string list
; effects : Config.effects_backend option
}

val options : t Cmdliner.Term.t
Expand Down
2 changes: 2 additions & 0 deletions compiler/bin-wasm_of_ocaml/compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,11 @@ let run
; include_dirs
; sourcemap_root
; sourcemap_don't_inline_content
; effects
} =
Config.set_target `Wasm;
Jsoo_cmdline.Arg.eval common;
Config.set_effects_backend effects;
Generate.init ();
let output_file = fst output_file in
if debug_mem () then Debug.start_profiling output_file;
Expand Down
6 changes: 5 additions & 1 deletion compiler/lib-dynlink/js_of_ocaml_compiler_dynlink.ml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ let () =
| Sys.(Native | Bytecode | Other _) -> failwith "Expected backend `js_of_ocaml`");
let global = J.pure_js_expr "globalThis" in
Config.Flag.set "use-js-string" (Jsoo_runtime.Sys.Config.use_js_string ());
Config.Flag.set "effects" (Jsoo_runtime.Sys.Config.effects ());
Config.set_effects_backend
(match Jsoo_runtime.Sys.Config.effects () with
| None -> None
| Some Jsoo_runtime.Sys.Config.Cps -> Some Config.Cps
| Some Jsoo_runtime.Sys.Config.Double_translation -> Some Config.Double_translation);
Linker.reset ();
(* this needs to stay synchronized with toplevel.js *)
let toplevel_compile (s : string) (debug : Instruct.debug_event list array) :
Expand Down
16 changes: 12 additions & 4 deletions compiler/lib-runtime-files/gen/gen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,11 @@ let rec list_product l =
let tail = list_product xs in
List.concat_map values ~f:(fun v -> List.map tail ~f:(fun l -> (key, v) :: l))

let bool = [ true; false ]
let bool = [ `Bool true; `Bool false ]

let effects_backends =
let open Js_of_ocaml_compiler.Config in
[ `Effects None; `Effects (Some Cps); `Effects (Some Double_translation) ]

let () =
Js_of_ocaml_compiler.Config.set_target `JavaScript;
Expand All @@ -60,11 +64,15 @@ let () =
let fragments =
List.map rest ~f:(fun f -> f, Js_of_ocaml_compiler.Linker.Fragment.parse_file f)
in
let variants = list_product [ "use-js-string", bool; "effects", bool ] in
let variants =
list_product [ "use-js-string", bool; "effects", effects_backends ]
in
(* load all files to make sure they are valid *)
List.iter variants ~f:(fun setup ->
List.iter setup ~f:(fun (name, b) ->
Js_of_ocaml_compiler.Config.Flag.set name b);
List.iter setup ~f:(fun (name, v) ->
match v with
| `Bool b -> Js_of_ocaml_compiler.Config.Flag.set name b
| `Effects b -> Js_of_ocaml_compiler.Config.set_effects_backend b);
List.iter Js_of_ocaml_compiler.Target_env.all ~f:(fun target_env ->
Js_of_ocaml_compiler.Linker.reset ();
List.iter fragments ~f:(fun (filename, frags) ->
Expand Down
2 changes: 1 addition & 1 deletion compiler/lib-wasm/gc_target.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1706,7 +1706,7 @@ let post_process_function_body = Initialize_locals.f
let entry_point ~toplevel_fun =
let code =
let* () =
if Config.Flag.effects ()
if Option.is_some (Config.effects ())
then
let* f =
register_import
Expand Down
Loading
Loading