diff --git a/compiler/lib/magic_number.ml b/compiler/lib/magic_number.ml index 403280afc0..900b96943f 100644 --- a/compiler/lib/magic_number.ml +++ b/compiler/lib/magic_number.ml @@ -68,7 +68,7 @@ let () = let current = Ocaml_version.current in if Ocaml_version.compare current [ 4; 13 ] < 0 then failwith "OCaml version unsupported. Upgrade to OCaml 4.13 or newer." - else if Ocaml_version.compare current [ 5; 6 ] >= 0 + else if Ocaml_version.compare current [ 5; 7 ] >= 0 then failwith "OCaml version unsupported. Upgrade js_of_ocaml." let v = snd (of_string Ocaml_common.Config.exec_magic_number) diff --git a/compiler/lib/parse_bytecode.ml b/compiler/lib/parse_bytecode.ml index c3897da95d..2dd1771c7e 100644 --- a/compiler/lib/parse_bytecode.ml +++ b/compiler/lib/parse_bytecode.ml @@ -2529,11 +2529,13 @@ and compile infos pc state (instrs : instr list) = Var.print arg; let state, tail = - match Ocaml_version.compare Ocaml_version.current [ 5; 2 ] < 0 with - | true -> State.pop 2 state, Pc (Int (Targetint.of_int_exn 0)) - | false -> - let tail = State.peek 2 state in - State.pop 3 state, Pv tail + if + Ocaml_version.compare Ocaml_version.current [ 5; 2 ] < 0 + || Ocaml_version.compare Ocaml_version.current [ 5; 6 ] >= 0 + then State.pop 2 state, Pc (Int (Targetint.of_int_exn 0)) + else + let tail = State.peek 2 state in + State.pop 3 state, Pv tail in compile infos @@ -2546,11 +2548,13 @@ and compile infos pc state (instrs : instr list) = let arg = State.peek 1 state in let x, state = State.fresh_var state in let tail = - match Ocaml_version.compare Ocaml_version.current [ 5; 2 ] < 0 with - | true -> Pc (Int (Targetint.of_int_exn 0)) - | false -> - let tail = State.peek 2 state in - Pv tail + if + Ocaml_version.compare Ocaml_version.current [ 5; 2 ] < 0 + || Ocaml_version.compare Ocaml_version.current [ 5; 6 ] >= 0 + then Pc (Int (Targetint.of_int_exn 0)) + else + let tail = State.peek 2 state in + Pv tail in if debug_parser () then @@ -2579,13 +2583,18 @@ and compile infos pc state (instrs : instr list) = | REPERFORMTERM -> let eff = State.accu state in let stack = State.peek 0 state in - let tail = State.peek 1 state in - let state = State.pop 2 state in + let tail, state = + if Ocaml_version.compare Ocaml_version.current [ 5; 6 ] >= 0 + then Pc (Int (Targetint.of_int_exn 0)), State.pop 1 state + else + let tail = State.peek 1 state in + Pv tail, State.pop 2 state + in let x, state = State.fresh_var state in if debug_parser () then Format.printf "return reperform(%a, %a)@." Var.print eff Var.print stack; - ( Let (x, Prim (Extern "%reperform", [ Pv eff; Pv stack; Pv tail ])) :: instrs + ( Let (x, Prim (Extern "%reperform", [ Pv eff; Pv stack; tail ])) :: instrs , Return x , state ) | EVENT | BREAK | FIRST_UNIMPLEMENTED_OP -> assert false) diff --git a/compiler/tests-jsoo/calc_lexer.mll b/compiler/tests-jsoo/calc_lexer.mll index 4986ea12a5..5025bd062b 100644 --- a/compiler/tests-jsoo/calc_lexer.mll +++ b/compiler/tests-jsoo/calc_lexer.mll @@ -14,3 +14,4 @@ rule token = parse | '(' { LPAREN } | ')' { RPAREN } | eof { raise Eof } + | _ as c { failwith (Printf.sprintf "unexpected character %C" c) } diff --git a/compiler/tests-jsoo/lib-gc/test_gc.ml b/compiler/tests-jsoo/lib-gc/test_gc.ml index d3e2d16b6d..f33725fb29 100644 --- a/compiler/tests-jsoo/lib-gc/test_gc.ml +++ b/compiler/tests-jsoo/lib-gc/test_gc.ml @@ -36,5 +36,5 @@ type control = let () = assert ((Gc.get ()).custom_minor_max_size = 0); - assert ((Gc.stat ()).forced_major_collections = 0); + assert (((Gc.stat [@alert "-deprecated"]) ()).forced_major_collections = 0); assert ((Gc.quick_stat ()).forced_major_collections = 0) diff --git a/compiler/tests-jsoo/test_gc.ml b/compiler/tests-jsoo/test_gc.ml index 4e1685c06c..8226e28c7d 100644 --- a/compiler/tests-jsoo/test_gc.ml +++ b/compiler/tests-jsoo/test_gc.ml @@ -31,7 +31,7 @@ let ok () = print_endline "OK" let ko size = Printf.printf "size=%d, ocaml_version=%s" size Sys.ocaml_version let%expect_test "stat" = - let s = Gc.stat () in + let s = (Gc.stat [@alert "-deprecated"]) () in let size = Obj.size (Obj.repr s) in (match size with | 18 when ocaml_version >= (5, 5) -> ok () diff --git a/compiler/tests-ocaml/lib-hashtbl/dune b/compiler/tests-ocaml/lib-hashtbl/dune index c6aa851e80..e1e3e482b9 100644 --- a/compiler/tests-ocaml/lib-hashtbl/dune +++ b/compiler/tests-ocaml/lib-hashtbl/dune @@ -20,6 +20,6 @@ (deps ../../../LICENSE) (modules htbl) (build_if - (>= %{ocaml_version} 5)) + (>= %{ocaml_version} 5.5)) (libraries) (modes js wasm)) diff --git a/compiler/tests-ocaml/lib-hashtbl/htbl.ml b/compiler/tests-ocaml/lib-hashtbl/htbl.ml index 4af75a9f02..b5249de2d6 100644 --- a/compiler/tests-ocaml/lib-hashtbl/htbl.ml +++ b/compiler/tests-ocaml/lib-hashtbl/htbl.ml @@ -130,10 +130,12 @@ module HofM (M: Map.S) : Hashtbl.SeededS with type key = M.key = let copy = Hashtbl.copy let add = Hashtbl.add let remove = Hashtbl.remove + let find_and_remove = Hashtbl.find_and_remove let find = Hashtbl.find let find_opt = Hashtbl.find_opt let find_all = Hashtbl.find_all let replace = Hashtbl.replace + let find_and_replace = Hashtbl.find_and_replace let mem = Hashtbl.mem let iter = Hashtbl.iter let fold = Hashtbl.fold @@ -272,3 +274,19 @@ let () = let l = List.sort compare l in List.iter (fun (k, v) -> Printf.printf "%i,%i\n" k v) l; Printf.printf "%i elements\n" (Hashtbl.length h) + +let () = + let h = Hashtbl.create 16 in + Hashtbl.add h 0 0; + assert (Hashtbl.find_and_replace h 0 1 = Some 0); + assert (Hashtbl.find_and_remove h 0 = Some 1); + assert (Hashtbl.find_and_remove h 0 = None); + assert (Hashtbl.find_and_replace h 0 1 = None); + assert (Hashtbl.find_and_remove h 0 = Some 1); + Hashtbl.clear h; + Hashtbl.add h 0 0; + Hashtbl.add h 0 1; + assert (Hashtbl.find_and_replace h 0 2 = Some 1); + assert (Hashtbl.find_and_remove h 0 = Some 2); + assert (Hashtbl.find_and_remove h 0 = Some 0); + assert (Hashtbl.find_and_remove h 0 = None); diff --git a/dune-project b/dune-project index e35053e5c4..806ce38546 100644 --- a/dune-project +++ b/dune-project @@ -19,7 +19,7 @@ (description "Js_of_ocaml is a compiler from OCaml bytecode to JavaScript. It makes it possible to run pure OCaml programs in JavaScript environment like browsers and Node.js") (depends - (ocaml (and (>= 4.13) (< 5.6))) + (ocaml (and (>= 4.13) (< 5.7))) (num :with-test) (ppx_expect (and (>= v0.16.1) :with-test)) (ppxlib (>= 0.33)) diff --git a/js_of_ocaml-compiler.opam b/js_of_ocaml-compiler.opam index 1c7e4f20eb..10963ded9c 100644 --- a/js_of_ocaml-compiler.opam +++ b/js_of_ocaml-compiler.opam @@ -13,7 +13,7 @@ doc: "https://ocsigen.org/js_of_ocaml/latest/manual/overview" bug-reports: "https://github.com/ocsigen/js_of_ocaml/issues" depends: [ "dune" {>= "3.20"} - "ocaml" {>= "4.13" & < "5.6"} + "ocaml" {>= "4.13" & < "5.7"} "num" {with-test} "ppx_expect" {>= "v0.16.1" & with-test} "ppxlib" {>= "0.33"} diff --git a/lib/gen_stubs/dune b/lib/gen_stubs/dune index 019242693e..3a46ceeb69 100644 --- a/lib/gen_stubs/dune +++ b/lib/gen_stubs/dune @@ -1,3 +1,5 @@ (executable (name gen_stubs) - (libraries compiler-libs.common)) + (libraries compiler-libs.common) + (preprocess + (pps ppx_optcomp_light))) diff --git a/lib/gen_stubs/gen_stubs.ml b/lib/gen_stubs/gen_stubs.ml index 190780b53c..c7ac7042a3 100644 --- a/lib/gen_stubs/gen_stubs.ml +++ b/lib/gen_stubs/gen_stubs.ml @@ -28,6 +28,29 @@ void %s () { s s +let collect_prims externals _mapper desc = + let l = List.filter (fun x -> x.[0] <> '%') desc.Parsetree.pval_prim in + externals := List.fold_right String_set.add l !externals; + desc +[@@if ocaml_version < (5, 6, 0)] + +let collect_prims externals _mapper desc = + (match desc.Parsetree.pprim_kind with + | Pprim_decl (_, l) -> + let l = List.filter (fun x -> x.[0] <> '%') l in + externals := List.fold_right String_set.add l !externals + | Pprim_alias _ -> ()); + desc +[@@if ocaml_version >= (5, 6, 0)] + +let make_mapper externals = + { Ast_mapper.default_mapper with value_description = collect_prims externals } +[@@if ocaml_version < (5, 6, 0)] + +let make_mapper externals = + { Ast_mapper.default_mapper with primitive_description = collect_prims externals } +[@@if ocaml_version >= (5, 6, 0)] + let () = let mls = ref [] in let except_mls = ref [] in @@ -39,12 +62,7 @@ let () = let get_externals l = let l = List.filter real_ml l in let externals = ref String_set.empty in - let value_description _mapper desc = - let l = List.filter (fun x -> x.[0] <> '%') desc.Parsetree.pval_prim in - externals := List.fold_right String_set.add l !externals; - desc - in - let mapper = { Ast_mapper.default_mapper with value_description } in + let mapper = make_mapper externals in List.iter (fun ml -> let in_ = open_in ml in diff --git a/runtime/js/effect.js b/runtime/js/effect.js index b1ac8c5f3c..eed14b8450 100644 --- a/runtime/js/effect.js +++ b/runtime/js/effect.js @@ -139,6 +139,7 @@ function caml_make_unhandled_effect_exn(eff) { //Requires: caml_get_cps_fun //If: effects //Version: >= 5.0 +//Version: < 5.6 function caml_perform_effect(eff, k0) { if (caml_current_stack.e === 0) { var exn = caml_make_unhandled_effect_exn(eff); @@ -157,6 +158,30 @@ function caml_perform_effect(eff, k0) { : caml_trampoline_return(handler, [eff, cont, last_fiber, k1]); } +//Provides: caml_perform_effect +//Requires: caml_pop_fiber, caml_stack_check_depth, caml_trampoline_return +//Requires: caml_make_unhandled_effect_exn, caml_current_stack +//Requires: caml_get_cps_fun +//If: effects +//Version: >= 5.6 +function caml_perform_effect(eff, k0) { + if (caml_current_stack.e === 0) { + var exn = caml_make_unhandled_effect_exn(eff); + throw exn; + } + // Get current effect handler + var handler = caml_current_stack.h[3]; + var last_fiber = caml_current_stack; + last_fiber.k = k0; + var cont = [245 /*continuation*/, last_fiber, last_fiber]; + // Move to parent fiber and execute the effect handler there + // The handler is defined in Stdlib.Effect, so we know that the arity matches + var k1 = caml_pop_fiber(); + return caml_stack_check_depth() + ? caml_get_cps_fun(handler)(eff, cont, k1) + : caml_trampoline_return(handler, [eff, cont, k1]); +} + //Provides: caml_reperform_effect //Requires: caml_pop_fiber, caml_stack_check_depth, caml_trampoline_return //Requires: caml_make_unhandled_effect_exn, caml_current_stack @@ -164,6 +189,7 @@ function caml_perform_effect(eff, k0) { //Requires: caml_get_cps_fun //If: effects //Version: >= 5.0 +//Version: < 5.6 function caml_reperform_effect(eff, cont, last, k0) { if (caml_current_stack.e === 0) { var exn = caml_make_unhandled_effect_exn(eff); @@ -185,6 +211,36 @@ function caml_reperform_effect(eff, cont, last, k0) { : caml_trampoline_return(handler, [eff, cont, last_fiber, k1]); } +//Provides: caml_reperform_effect +//Requires: caml_pop_fiber, caml_stack_check_depth, caml_trampoline_return +//Requires: caml_make_unhandled_effect_exn, caml_current_stack +//Requires: caml_resume_stack, caml_continuation_use_noexc +//Requires: caml_get_cps_fun +//If: effects +//Version: >= 5.6 +function caml_reperform_effect(eff, cont, _last, k0) { + if (caml_current_stack.e === 0) { + var exn = caml_make_unhandled_effect_exn(eff); + var stack = caml_continuation_use_noexc(cont); + caml_resume_stack(stack, cont[2], k0); + throw exn; + } + // Get current effect handler + var handler = caml_current_stack.h[3]; + var last_fiber = caml_current_stack; + last_fiber.k = k0; + // [cont_last_fiber] is gone in OCaml 5.6, but we still maintain the tail + // at cont[2] ourselves on every (re)perform. + cont[2].e = last_fiber; + cont[2] = last_fiber; + // Move to parent fiber and execute the effect handler there + // The handler is defined in Stdlib.Effect, so we know that the arity matches + var k1 = caml_pop_fiber(); + return caml_stack_check_depth() + ? caml_get_cps_fun(handler)(eff, cont, k1) + : caml_trampoline_return(handler, [eff, cont, k1]); +} + //Provides: caml_get_cps_fun //If: effects //If: !doubletranslate diff --git a/runtime/js/gc.js b/runtime/js/gc.js index 15ca706460..df7fcdb31a 100644 --- a/runtime/js/gc.js +++ b/runtime/js/gc.js @@ -196,3 +196,22 @@ function caml_gc_tweak_list_active(_unit) { function caml_gc_tweak_list_active(_unit) { return 0; } + +//Provides: caml_runtime_hashtbl_randomized +//Version: >= 5.6 +var caml_runtime_hashtbl_randomized = 0; + +//Provides: caml_runtime_hashtbl_randomize +//Requires: caml_runtime_hashtbl_randomized +//Version: >= 5.6 +function caml_runtime_hashtbl_randomize(_unit) { + caml_runtime_hashtbl_randomized = 1; + return 0; +} + +//Provides: caml_runtime_hashtbl_is_randomized +//Requires: caml_runtime_hashtbl_randomized +//Version: >= 5.6 +function caml_runtime_hashtbl_is_randomized(_unit) { + return caml_runtime_hashtbl_randomized; +} diff --git a/runtime/wasm/array.wat b/runtime/wasm/array.wat index 46ac866ff1..3f936387ea 100644 --- a/runtime/wasm/array.wat +++ b/runtime/wasm/array.wat @@ -29,7 +29,9 @@ (global $empty_array (ref eq) (array.new_fixed $block 1 (ref.i31 (i32.const 0)))) - (func $caml_make_vect (export "caml_make_vect") (export "caml_array_make") + (func $caml_make_vect + (export "caml_make_vect") (export "caml_array_make") + (export "caml_uniform_array_make") (param $n (ref eq)) (param $v (ref eq)) (result (ref eq)) (local $sz i32) (local $b (ref $block)) (local $f f64) (local.set $sz (i31.get_s (ref.cast (ref i31) (local.get $n)))) diff --git a/runtime/wasm/effect.wat b/runtime/wasm/effect.wat index 00ef85d8e8..ec9e37dd27 100644 --- a/runtime/wasm/effect.wat +++ b/runtime/wasm/effect.wat @@ -297,6 +297,8 @@ (field $eff (ref eq)) (field $cont (ref eq))))) +(@if (< ocaml_version (5 6 0)) +(@then (func $call_effect_handler (param $tail (ref eq)) (param $venv (ref eq)) (result (ref eq)) (local $env (ref $call_handler_env)) @@ -309,7 +311,27 @@ (local.tee $handler (ref.cast (ref $closure_3) (struct.get $call_handler_env $handler (local.get $env)))) - (struct.get $closure_3 1 (local.get $handler)))) + (struct.get $closure_3 1 (local.get $handler))))) +(@else + (type $function_2 + (func (param (ref eq) (ref eq) (ref eq)) (result (ref eq)))) + (type $closure_2 + (sub $closure + (struct (field (ref $function_1)) (field (ref $function_2))))) + + (func $call_effect_handler + (param $_tail (ref eq)) (param $venv (ref eq)) (result (ref eq)) + (local $env (ref $call_handler_env)) + (local $handler (ref $closure_2)) + (local.set $env (ref.cast (ref $call_handler_env) (local.get $venv))) + (return_call_ref $function_2 + (struct.get $call_handler_env $eff (local.get $env)) + (struct.get $call_handler_env $cont (local.get $env)) + (local.tee $handler + (ref.cast (ref $closure_2) + (struct.get $call_handler_env $handler (local.get $env)))) + (struct.get $closure_2 1 (local.get $handler))))) +) (func $do_perform (param $k0 (ref $cont)) (param $eff (ref eq)) @@ -379,6 +401,8 @@ (local.get $k1) (struct.get $cont $cont_func (local.get $k1)))) +(@if (< ocaml_version (5 6 0)) +(@then (func $reperform (export "%reperform") (param $eff (ref eq)) (param $cont (ref eq)) (param $tail (ref eq)) (result (ref eq)) @@ -392,7 +416,29 @@ (return_call $capture_continuation (ref.func $do_reperform) (struct.new $reperform - (local.get $eff) (local.get $cont) (local.get $tail)))) + (local.get $eff) (local.get $cont) (local.get $tail))))) +(@else + (func $reperform (export "%reperform") + (param $eff (ref eq)) (param $cont (ref eq)) (param $_tail (ref eq)) + (result (ref eq)) + (local $tail (ref eq)) + ;; [cont_last_fiber] is gone in OCaml 5.6, but we still maintain the + ;; tail at cont[2] ourselves on every (re)perform. + (local.set $tail + (array.get $block (ref.cast (ref $block) (local.get $cont)) + (i32.const 2))) + (if (ref.is_null (struct.get $fiber $next (global.get $stack))) + (then + (return_call $resume + (call $caml_continuation_use_noexc (local.get $cont)) + (global.get $raise_unhandled) + (local.get $eff) + (local.get $tail)))) + (return_call $capture_continuation + (ref.func $do_reperform) + (struct.new $reperform + (local.get $eff) (local.get $cont) (local.get $tail))))) +) ;; Allocate a stack @@ -444,6 +490,9 @@ (result (ref eq)))) (type $cps_closure (sub (struct (field (ref $function_2))))) (type $cps_closure_0 (sub (struct (field (ref $function_1))))) + (type $cps_closure_2 + (sub $cps_closure + (struct (field (ref $function_2)) (field (ref $function_3))))) (type $cps_closure_3 (sub $cps_closure (struct (field (ref $function_2)) (field (ref $function_4))))) @@ -684,6 +733,8 @@ (call $caml_named_value (global.get $already_resumed)))) (ref.i31 (i32.const 0))) +(@if (< ocaml_version (5 6 0)) +(@then (func (export "caml_perform_effect") (param $eff (ref eq)) (param $k0 (ref eq)) (result (ref eq)) (local $handler (ref eq)) (local $k1 (ref eq)) @@ -706,8 +757,35 @@ (local.get $eff) (local.get $cont) (local.get $last_fiber) (local.get $k1) (local.get $handler) (struct.get $cps_closure_3 1 - (ref.cast (ref $cps_closure_3) (local.get $handler))))) + (ref.cast (ref $cps_closure_3) (local.get $handler)))))) +(@else + (func (export "caml_perform_effect") + (param $eff (ref eq)) (param $k0 (ref eq)) (result (ref eq)) + (local $handler (ref eq)) (local $k1 (ref eq)) + (local $cont (ref $block)) + (local $last_fiber (ref $cps_fiber)) + (if (ref.is_null + (struct.get $cps_fiber $next (global.get $cps_fiber_stack))) + (then + (return_call $raise_unhandled + (local.get $eff) (ref.i31 (i32.const 0))))) + (local.set $handler + (struct.get $cps_fiber $effect (global.get $cps_fiber_stack))) + (local.set $last_fiber (global.get $cps_fiber_stack)) + (struct.set $cps_fiber $cont (local.get $last_fiber) (local.get $k0)) + (local.set $cont + (array.new_fixed $block 3 (ref.i31 (global.get $cont_tag)) + (local.get $last_fiber) (local.get $last_fiber))) + (local.set $k1 (call $caml_pop_fiber)) + (return_call_ref $function_3 + (local.get $eff) (local.get $cont) + (local.get $k1) (local.get $handler) + (struct.get $cps_closure_2 1 + (ref.cast (ref $cps_closure_2) (local.get $handler)))))) +) +(@if (< ocaml_version (5 6 0)) +(@then (func (export "caml_reperform_effect") (param $eff (ref eq)) (param $vcont (ref eq)) (param $vtail (ref eq)) (param $k0 (ref eq)) (result (ref eq)) @@ -738,7 +816,44 @@ (local.get $k1) (local.get $handler) (struct.get $cps_closure_3 1 - (ref.cast (ref $cps_closure_3) (local.get $handler))))) + (ref.cast (ref $cps_closure_3) (local.get $handler)))))) +(@else + (func (export "caml_reperform_effect") + (param $eff (ref eq)) (param $vcont (ref eq)) (param $_vtail (ref eq)) + (param $k0 (ref eq)) (result (ref eq)) + (local $handler (ref eq)) (local $k1 (ref eq)) + (local $cont (ref $block)) + (local $tail (ref $cps_fiber)) (local $last_fiber (ref $cps_fiber)) + (local.set $cont (ref.cast (ref $block) (local.get $vcont))) + ;; [cont_last_fiber] is gone in OCaml 5.6, but we still maintain the + ;; tail at cont[2] ourselves on every (re)perform. + (local.set $tail + (ref.cast (ref $cps_fiber) + (array.get $block (local.get $cont) (i32.const 2)))) + (if (ref.is_null + (struct.get $cps_fiber $next (global.get $cps_fiber_stack))) + (then + (drop + (call $caml_resume_stack + (call $caml_continuation_use_noexc (local.get $vcont)) + (local.get $tail) + (local.get $k0))) + (return_call $raise_unhandled + (local.get $eff) (ref.i31 (i32.const 0))))) + (local.set $handler + (struct.get $cps_fiber $effect (global.get $cps_fiber_stack))) + (local.set $last_fiber (global.get $cps_fiber_stack)) + (struct.set $cps_fiber $cont (local.get $last_fiber) (local.get $k0)) + (struct.set $cps_fiber $next (local.get $tail) (local.get $last_fiber)) + (array.set $block (local.get $cont) (i32.const 2) (local.get $last_fiber)) + (local.set $k1 (call $caml_pop_fiber)) + (return_call_ref $function_3 + (local.get $eff) (local.get $cont) + (local.get $k1) + (local.get $handler) + (struct.get $cps_closure_2 1 + (ref.cast (ref $cps_closure_2) (local.get $handler)))))) +) (func $cps_call_handler (param $handler (ref eq)) (param $x (ref eq)) (result (ref eq)) diff --git a/runtime/wasm/gc.wat b/runtime/wasm/gc.wat index bf36b21af5..40b23315f1 100644 --- a/runtime/wasm/gc.wat +++ b/runtime/wasm/gc.wat @@ -176,4 +176,18 @@ (func (export "caml_gc_tweak_list_active") (param (ref eq)) (result (ref eq)) (ref.i31 (i32.const 0))) + +(@if (>= ocaml_version (5 6 0)) +(@then + (global $caml_runtime_hashtbl_randomized (mut i32) (i32.const 0)) + + (func (export "caml_runtime_hashtbl_randomize") + (param (ref eq)) (result (ref eq)) + (global.set $caml_runtime_hashtbl_randomized (i32.const 1)) + (ref.i31 (i32.const 0))) + + (func (export "caml_runtime_hashtbl_is_randomized") + (param (ref eq)) (result (ref eq)) + (ref.i31 (global.get $caml_runtime_hashtbl_randomized))) +)) ) diff --git a/tools/toplevel_expect/gen.ml b/tools/toplevel_expect/gen.ml index eceee8853e..c49746845f 100644 --- a/tools/toplevel_expect/gen.ml +++ b/tools/toplevel_expect/gen.ml @@ -42,4 +42,5 @@ let () = | 5, 3 -> dump_file "toplevel_expect_test.ml-5.3" | 5, 4 -> dump_file "toplevel_expect_test.ml-5.4" | 5, 5 -> dump_file "toplevel_expect_test.ml-5.4" + | 5, 6 -> dump_file "toplevel_expect_test.ml-5.4" | _ -> failwith ("unsupported version " ^ Sys.ocaml_version))