Skip to content

Commit 2746f0c

Browse files
authored
Compiler: better handling of empty libs (#1169)
1 parent f7371af commit 2746f0c

File tree

7 files changed

+84
-36
lines changed

7 files changed

+84
-36
lines changed

CHANGES.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
# dev (2021-??-??) - ??
2+
3+
## Bug fixes
4+
* Compiler: fix sourcemap warning for empty cma
5+
16
# 3.11.0 (2021-10-06) - Lille
27

38
## Features/Changes

compiler/bin-js_of_ocaml/compile.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,11 @@ let run
116116
in
117117
if times () then Format.eprintf "Start parsing...@.";
118118
let need_debug = Option.is_some source_map || Config.Flag.debuginfo () in
119-
let check_debug debug =
119+
let check_debug (one : Parse_bytecode.one) =
120120
if (not runtime_only)
121121
&& Option.is_some source_map
122-
&& Parse_bytecode.Debug.is_empty debug
122+
&& Parse_bytecode.Debug.is_empty one.debug
123+
&& not (Code.is_empty one.code)
123124
then
124125
warn
125126
"Warning: '--source-map' is enabled but the bytecode program was compiled with \
@@ -141,7 +142,7 @@ let run
141142
Code.(Let (Var.fresh (), Prim (Extern "caml_set_static_env", args))))
142143
in
143144
let output (one : Parse_bytecode.one) ~standalone output_file =
144-
check_debug one.debug;
145+
check_debug one;
145146
let init_pseudo_fs = fs_external && standalone in
146147
(match output_file with
147148
| `Stdout ->

compiler/lib/code.ml

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -531,13 +531,25 @@ let prepend ({ start; blocks; free_pc } as p) body =
531531
let free_pc = free_pc + 1 in
532532
{ start = new_start; blocks; free_pc }
533533

534+
let empty_block = { params = []; handler = None; body = []; branch = Stop }
535+
534536
let empty =
535537
let start = 0 in
536-
let free_pc = 1 in
537-
let blocks =
538-
Addr.Map.singleton start { params = []; handler = None; body = []; branch = Stop }
539-
in
540-
{ start; blocks; free_pc }
538+
let blocks = Addr.Map.singleton start empty_block in
539+
{ start; blocks; free_pc = start + 1 }
540+
541+
let is_empty p =
542+
match Addr.Map.cardinal p.blocks with
543+
| 0 -> true
544+
| 1 -> (
545+
let _, v = Addr.Map.choose p.blocks in
546+
match v with
547+
| { handler = None; body; branch = Stop; params = _ } -> (
548+
match body with
549+
| ([] | [ Let (_, Prim (Extern "caml_get_global_data", _)) ]) when true -> true
550+
| _ -> false)
551+
| _ -> false)
552+
| _ -> false
541553

542554
let fold_children blocks pc f accu =
543555
let block = Addr.Map.find pc blocks in
@@ -601,9 +613,10 @@ let with_invariant = Debug.find "invariant"
601613

602614
let check_defs = false
603615

604-
let invariant { blocks; _ } =
616+
let invariant { blocks; start; _ } =
605617
if with_invariant ()
606-
then
618+
then (
619+
assert (Addr.Map.mem start blocks);
607620
let defs = Array.make (Var.count ()) false in
608621
let check_cont (cont, args) =
609622
let b = Addr.Map.find cont blocks in
@@ -655,4 +668,4 @@ let invariant { blocks; _ } =
655668
Option.iter block.handler ~f:(fun (_, cont) -> check_cont cont);
656669
List.iter block.body ~f:check_instr;
657670
check_last block.branch)
658-
blocks
671+
blocks)

compiler/lib/code.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,8 @@ val prepend : program -> instr list -> program
227227

228228
val empty : program
229229

230+
val is_empty : program -> bool
231+
230232
val eq : program -> program -> bool
231233

232234
val invariant : program -> unit

compiler/lib/generate.ml

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ module Ctx = struct
222222
; live : int array
223223
; share : Share.t
224224
; debug : Parse_bytecode.Debug.t
225-
; exported_runtime : Code.Var.t option
225+
; exported_runtime : (Code.Var.t * bool ref) option
226226
}
227227

228228
let initial ~exported_runtime blocks live share debug =
@@ -275,7 +275,9 @@ let s_var name = J.EVar (J.ident name)
275275

276276
let runtime_fun ctx name =
277277
match ctx.Ctx.exported_runtime with
278-
| Some runtime -> J.EDot (J.EVar (J.V runtime), name)
278+
| Some (runtime, runtime_needed) ->
279+
runtime_needed := true;
280+
J.EDot (J.EVar (J.V runtime), name)
279281
| None -> s_var name
280282

281283
let str_js s = J.EStr (s, `Bytes)
@@ -1891,7 +1893,8 @@ let generate_shared_value ctx =
18911893
(J.Variable_statement
18921894
((match ctx.Ctx.exported_runtime with
18931895
| None -> []
1894-
| Some v ->
1896+
| Some (_, { contents = false }) -> []
1897+
| Some (v, _) ->
18951898
[ J.V v, Some (J.EDot (s_var Constant.global_object, "jsoo_runtime"), J.N)
18961899
])
18971900
@ List.map
@@ -1924,7 +1927,7 @@ let f (p : Code.program) ~exported_runtime ~live_vars debug =
19241927
let t' = Timer.make () in
19251928
let share = Share.get ~alias_prims:exported_runtime p in
19261929
let exported_runtime =
1927-
if exported_runtime then Some (Code.Var.fresh_n "runtime") else None
1930+
if exported_runtime then Some (Code.Var.fresh_n "runtime", ref false) else None
19281931
in
19291932
let ctx = Ctx.initial ~exported_runtime p.blocks live_vars share debug in
19301933
let p = compile_program ctx p.start in

compiler/lib/parse_bytecode.ml

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,22 +2101,29 @@ let parse_bytecode code globals debug_data =
21012101
else blocks
21022102
in
21032103
let blocks' = Blocks.finish_analysis blocks in
2104-
if not (Blocks.is_empty blocks') then compile_block blocks' debug_data code 0 state;
2105-
let blocks =
2106-
Addr.Map.mapi
2107-
(fun _ (state, instr, last) ->
2108-
{ params = State.stack_vars state
2109-
; handler = State.current_handler state
2110-
; body = instr
2111-
; branch = last
2112-
})
2113-
!compiled_blocks
2104+
let p =
2105+
if not (Blocks.is_empty blocks')
2106+
then (
2107+
let start = 0 in
2108+
compile_block blocks' debug_data code start state;
2109+
let blocks =
2110+
Addr.Map.mapi
2111+
(fun _ (state, instr, last) ->
2112+
{ params = State.stack_vars state
2113+
; handler = State.current_handler state
2114+
; body = instr
2115+
; branch = last
2116+
})
2117+
!compiled_blocks
2118+
in
2119+
let blocks = match_exn_traps blocks in
2120+
let free_pc = String.length code / 4 in
2121+
{ start; blocks; free_pc })
2122+
else Code.empty
21142123
in
21152124
compiled_blocks := Addr.Map.empty;
21162125
tagged_blocks := Addr.Set.empty;
2117-
let free_pc = String.length code / 4 in
2118-
let blocks = match_exn_traps blocks in
2119-
{ start = 0; blocks; free_pc }
2126+
p
21202127

21212128
(* HACK - override module *)
21222129

@@ -2317,21 +2324,25 @@ let from_exe
23172324
]
23182325
in
23192326
let gdata = Var.fresh () in
2327+
let need_gdata = ref false in
23202328
let infos =
23212329
[ "toc", Constants.parse (Obj.repr toc)
23222330
; "prim_count", Int (Int32.of_int (Array.length globals.primitives))
23232331
]
23242332
in
23252333
let body =
23262334
List.fold_left infos ~init:body ~f:(fun rem (name, const) ->
2335+
need_gdata := true;
23272336
let c = Var.fresh () in
23282337
Let (c, Constant const)
23292338
:: Let
23302339
( Var.fresh ()
23312340
, Prim (Extern "caml_js_set", [ Pv gdata; Pc (String name); Pv c ]) )
23322341
:: rem)
23332342
in
2334-
Let (gdata, Prim (Extern "caml_get_global_data", [])) :: body
2343+
if !need_gdata
2344+
then Let (gdata, Prim (Extern "caml_get_global_data", [])) :: body
2345+
else body
23352346
else body
23362347
in
23372348
(* List interface files *)
@@ -2387,13 +2398,20 @@ let from_bytes primitives (code : bytecode) =
23872398
let globals = make_globals 0 [||] primitives in
23882399
let p = parse_bytecode code globals debug_data in
23892400
let gdata = Var.fresh () in
2401+
let need_gdata = ref false in
23902402
let body =
23912403
Array.fold_right_i globals.vars ~init:[] ~f:(fun i var l ->
23922404
match var with
2393-
| Some x when globals.is_const.(i) -> Let (x, Field (gdata, i)) :: l
2405+
| Some x when globals.is_const.(i) ->
2406+
need_gdata := true;
2407+
Let (x, Field (gdata, i)) :: l
23942408
| _ -> l)
23952409
in
2396-
let body = Let (gdata, Prim (Extern "caml_get_global_data", [])) :: body in
2410+
let body =
2411+
if !need_gdata
2412+
then Let (gdata, Prim (Extern "caml_get_global_data", [])) :: body
2413+
else body
2414+
in
23972415
prepend p body, debug_data
23982416

23992417
let from_string primitives (code : string) = from_bytes primitives code
@@ -2500,6 +2518,7 @@ let from_compilation_units ~includes:_ ~toplevel ~debug_data l =
25002518
in
25012519
let prog = parse_bytecode code globals debug_data in
25022520
let gdata = Var.fresh_n "global_data" in
2521+
let need_gdata = ref false in
25032522
let body =
25042523
Array.fold_right_i globals.vars ~init:[] ~f:(fun i var l ->
25052524
match var with
@@ -2515,11 +2534,16 @@ let from_compilation_units ~includes:_ ~toplevel ~debug_data l =
25152534
Let (x, Constant cst) :: l
25162535
| Some name ->
25172536
Var.name x name;
2537+
need_gdata := true;
25182538
Let (x, Prim (Extern "caml_js_get", [ Pv gdata; Pc (IString name) ])) :: l
25192539
)
25202540
| _ -> l)
25212541
in
2522-
let body = Let (gdata, Prim (Extern "caml_get_global_data", [])) :: body in
2542+
let body =
2543+
if !need_gdata
2544+
then Let (gdata, Prim (Extern "caml_get_global_data", [])) :: body
2545+
else body
2546+
in
25232547
let cmis =
25242548
if toplevel && Config.Flag.include_cmis ()
25252549
then

compiler/tests-compiler/empty_cma.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ open Util
2121

2222
let%expect_test _ =
2323
compile_lib [] "empty"
24-
|> compile_cmo_to_javascript ~sourcemap:false
24+
|> compile_cmo_to_javascript ~sourcemap:true
2525
|> Filetype.read_js
2626
|> Filetype.string_of_js_text
2727
|> print_endline;
2828
Sys.remove "empty.cma";
2929
Sys.remove "empty.js";
3030
[%expect
3131
{|
32-
(function(joo_global_object)
33-
{"use strict";var runtime=joo_global_object.jsoo_runtime;return}
34-
(function(){return this}()));
32+
(function(joo_global_object){"use strict";return}(function(){return this}()));
33+
34+
//# sourceMappingURL=empty.map
3535
|}]

0 commit comments

Comments
 (0)