Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
11 changes: 9 additions & 2 deletions compiler/lib/duplicate.ml
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,15 @@ let rec blocks_to_rename p pc lst =
p.blocks
lst

let closure p ~f ~params ~cont =
let s = Subst.from_map (bound_variables p ~f ~params ~cont) in
let closure p ~f ~params ~cont live_vars =
let s =
let map = bound_variables p ~f ~params ~cont in
fun x ->
try Var.Map.find x map
with Not_found ->
live_vars.(Var.idx x) <- live_vars.(Var.idx x) + 1;
x
in
let pc, args = cont in
let blocks = blocks_to_rename p pc [] in
let free_pc, m =
Expand Down
1 change: 1 addition & 0 deletions compiler/lib/duplicate.mli
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ val closure :
-> f:Code.Var.t
-> params:Code.Var.t list
-> cont:int * Code.Var.t list
-> int Array.t
-> Code.program * Code.Var.t * Code.Var.t list * (int * Code.Var.t list)
(** Given a program and a closure [f] -- defined by its name,
parameters, and its continuation --, return a program with a copy
Expand Down
4 changes: 3 additions & 1 deletion compiler/lib/inline.ml
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,9 @@ and inline_function ~context i x f args rem state =
let p, params, cont =
if context.live_vars.(Var.idx f) > 0
then (
let p, _f, params, cont = Duplicate.closure p ~f ~params ~cont in
let p, _f, params, cont =
Duplicate.closure p ~f ~params ~cont context.live_vars
in
(* It's ok to ignore the [_f] because the function is not recursive *)
assert (not info.recursive);
p, params, cont)
Expand Down
15 changes: 15 additions & 0 deletions compiler/tests-compiler/dune.inc
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,21 @@
(preprocess
(pps ppx_expect)))

(library
;; compiler/tests-compiler/gh2106.ml
(name gh2106_15)
(enabled_if true)
(modules gh2106)
(libraries js_of_ocaml_compiler unix str jsoo_compiler_expect_tests_helper)
(inline_tests
(enabled_if true)
(deps
(file %{project_root}/compiler/bin-js_of_ocaml/js_of_ocaml.exe)
(file %{project_root}/compiler/bin-jsoo_minify/jsoo_minify.exe)))
(flags (:standard -open Jsoo_compiler_expect_tests_helper))
(preprocess
(pps ppx_expect)))

(library
;; compiler/tests-compiler/gh747.ml
(name gh747_15)
Expand Down
73 changes: 73 additions & 0 deletions compiler/tests-compiler/gh2106.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
(* Js_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
* Copyright (C) 2025 Hugo Heuzard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)

open Util

let%expect_test "inlining" =
let p =
{|
module X : sig
end = struct
external fun_to_js : (unit -> unit) -> unit = "foo"

let[@tail_mod_cons] rec aux f = f () :: aux f

let map_to_list f = aux (fun x -> f x)

let embedded_input_file_handler _ =
fun_to_js (fun _ ->
let _ = map_to_list (fun _ -> assert false) in
())

let _ = embedded_input_file_handler ()
end
|}
in
let p = compile_and_parse ~flags:[ "--debug"; "js_assign" ] p in
print_program p;
[%expect
{|
(function(globalThis){
"use strict";
var
runtime = globalThis.jsoo_runtime,
caml_maybe_attach_backtrace = runtime.caml_maybe_attach_backtrace,
global_data = runtime.caml_get_global_data(),
Assert_failure = global_data.Assert_failure,
_a_ = [0, runtime.caml_string_of_jsbytes("test.ml"), 12, 38];
runtime.foo
(function(param){
function f(param){
throw caml_maybe_attach_backtrace([0, Assert_failure, _a_], 1);
}
var block = [0, f(0), 24029], dst = block, offset = 1;
for(;;){
var dst$0 = [0, f(0), 24029];
dst[offset + 1] = dst$0;
dst = dst$0;
offset = 1;
}
});
var X = [0], Test = [0, X];
runtime.caml_register_global(2, Test, "Test");
return;
}
(globalThis));
//end
|}]
Loading