Skip to content

Commit 5336a3c

Browse files
committed
Compiler: consume hints for immutable blocks
1 parent 256a79e commit 5336a3c

File tree

6 files changed

+415
-393
lines changed

6 files changed

+415
-393
lines changed

compiler/lib/ocaml_compiler.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,4 +272,6 @@ module Cmo_format = struct
272272
let imports (t : t) = t.cu_imports
273273

274274
let force_link (t : t) = t.cu_force_link
275+
276+
let hints_pos (t : t) = t.cu_hint
275277
end

compiler/lib/ocaml_compiler.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,6 @@ module Cmo_format : sig
6868
val force_link : t -> bool
6969

7070
val imports : t -> (string * string option) list
71+
72+
val hints_pos : t -> int
7173
end

compiler/lib/parse_bytecode.ml

Lines changed: 101 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,63 @@ end = struct
323323
StringSet.of_list (List.concat paths)
324324
end
325325

326+
module Hints = struct
327+
module Primitive = struct
328+
type boxed_integer =
329+
| Pnativeint
330+
| Pint32
331+
| Pint64
332+
333+
type native_repr =
334+
| Same_as_ocaml_repr
335+
| Unboxed_float
336+
| Unboxed_integer of boxed_integer
337+
| Untagged_immediate
338+
339+
type description =
340+
{ prim_name : string (* Name of primitive or C function *)
341+
; prim_arity : int (* Number of arguments *)
342+
; prim_alloc : bool (* Does it allocates or raise? *)
343+
; prim_native_name : string (* Name of C function for the nat. code gen. *)
344+
; prim_native_repr_args : native_repr list
345+
; prim_native_repr_res : native_repr
346+
}
347+
[@@ocaml.warning "-unused-field"]
348+
end
349+
350+
type optimization_hint =
351+
| Hint_immutable
352+
| Hint_unsafe
353+
| Hint_int of Primitive.boxed_integer
354+
| Hint_array of Lambda.array_kind
355+
| Hint_bigarray of
356+
{ unsafe : bool
357+
; elt_kind : Lambda.bigarray_kind
358+
; layout : Lambda.bigarray_layout
359+
}
360+
| Hint_primitive of Primitive.description
361+
362+
module Int_table = Hashtbl.Make (Int)
363+
364+
type t = { hints : optimization_hint Int_table.t }
365+
366+
let create () = { hints = Int_table.create 17 }
367+
368+
let read t ~orig ic =
369+
let l : (int * optimization_hint) list = input_value ic in
370+
371+
List.iter l ~f:(fun (pos, hint) -> Int_table.add t.hints ((pos + orig) / 4) hint)
372+
373+
let read_section t ic =
374+
let len = input_binary_int ic in
375+
for _i = 0 to len - 1 do
376+
let orig = input_binary_int ic in
377+
read t ~orig ic
378+
done
379+
380+
let find t pc = Int_table.find_all t.hints pc
381+
end
382+
326383
(* Block analysis *)
327384
(* Detect each block *)
328385
module Blocks : sig
@@ -809,6 +866,7 @@ type compile_info =
809866
; code : string
810867
; limit : int
811868
; debug : Debug.t
869+
; hints : Hints.t
812870
}
813871

814872
let string_of_addr debug_data addr =
@@ -831,9 +889,11 @@ let string_of_addr debug_data addr =
831889
in
832890
Printf.sprintf "%s:%s-%s %s" file (pos loc.loc_start) (pos loc.loc_end) kind)
833891

834-
let is_immutable _instr _infos _pc = (* We don't know yet *) Maybe_mutable
892+
let is_immutable _instr infos pc =
893+
let hints = Hints.find infos.hints pc in
894+
if List.mem Hints.Hint_immutable ~set:hints then Immutable else Maybe_mutable
835895

836-
let rec compile_block blocks debug_data code pc state : unit =
896+
let rec compile_block blocks hints debug_data code pc state : unit =
837897
match Addr.Map.find_opt pc !tagged_blocks with
838898
| Some old_state -> (
839899
(* Check that the shape of the stack is compatible with the one used to compile the block *)
@@ -865,7 +925,7 @@ let rec compile_block blocks debug_data code pc state : unit =
865925
let state = State.start_block pc state in
866926
tagged_blocks := Addr.Map.add pc state !tagged_blocks;
867927
let instr, last, state' =
868-
compile { blocks; code; limit; debug = debug_data } pc state []
928+
compile { blocks; code; limit; debug = debug_data; hints } pc state []
869929
in
870930
assert (not (Addr.Map.mem pc !compiled_blocks));
871931
(* When jumping to a block that was already visited and the
@@ -893,10 +953,11 @@ let rec compile_block blocks debug_data code pc state : unit =
893953
in
894954
compiled_blocks := Addr.Map.add pc (state, List.rev instr, last) !compiled_blocks;
895955
match last with
896-
| Branch (pc', _) -> compile_block blocks debug_data code pc' (adjust_state pc')
956+
| Branch (pc', _) ->
957+
compile_block blocks hints debug_data code pc' (adjust_state pc')
897958
| Cond (_, (pc1, _), (pc2, _)) ->
898-
compile_block blocks debug_data code pc1 (adjust_state pc1);
899-
compile_block blocks debug_data code pc2 (adjust_state pc2)
959+
compile_block blocks hints debug_data code pc1 (adjust_state pc1);
960+
compile_block blocks hints debug_data code pc2 (adjust_state pc2)
900961
| Poptrap (_, _) -> ()
901962
| Switch (_, _) -> ()
902963
| Raise _ | Return _ | Stop -> ()
@@ -1222,7 +1283,7 @@ and compile infos pc state (instrs : instr list) =
12221283
let params, state' = State.make_stack nparams state' in
12231284
if debug_parser () then Format.printf ") {@.";
12241285
let state' = State.clear_accu state' in
1225-
compile_block infos.blocks infos.debug code addr state';
1286+
compile_block infos.blocks infos.hints infos.debug code addr state';
12261287
if debug_parser () then Format.printf "}@.";
12271288
let args = State.stack_vars state' in
12281289
let state'', _, _ = Addr.Map.find addr !compiled_blocks in
@@ -1279,7 +1340,7 @@ and compile infos pc state (instrs : instr list) =
12791340
let params, state' = State.make_stack nparams state' in
12801341
if debug_parser () then Format.printf ") {@.";
12811342
let state' = State.clear_accu state' in
1282-
compile_block infos.blocks infos.debug code addr state';
1343+
compile_block infos.blocks infos.hints infos.debug code addr state';
12831344
if debug_parser () then Format.printf "}@.";
12841345
let args = State.stack_vars state' in
12851346
let state'', _, _ = Addr.Map.find addr !compiled_blocks in
@@ -1709,9 +1770,9 @@ and compile infos pc state (instrs : instr list) =
17091770
let it = Array.init isize ~f:(fun i -> base + gets code (base + i)) in
17101771
let bt = Array.init bsize ~f:(fun i -> base + gets code (base + isize + i)) in
17111772
Array.iter it ~f:(fun pc' ->
1712-
compile_block infos.blocks infos.debug code pc' state);
1773+
compile_block infos.blocks infos.hints infos.debug code pc' state);
17131774
Array.iter bt ~f:(fun pc' ->
1714-
compile_block infos.blocks infos.debug code pc' state);
1775+
compile_block infos.blocks infos.hints infos.debug code pc' state);
17151776
match isize, bsize with
17161777
| _, 0 -> instrs, Switch (x, Array.map it ~f:(fun pc -> pc, [])), state
17171778
| 0, _ ->
@@ -1775,9 +1836,10 @@ and compile infos pc state (instrs : instr list) =
17751836
, x
17761837
, (handler_addr, State.stack_vars handler_state) ) )
17771838
!compiled_blocks;
1778-
compile_block infos.blocks infos.debug code handler_addr handler_state;
1839+
compile_block infos.blocks infos.hints infos.debug code handler_addr handler_state;
17791840
compile_block
17801841
infos.blocks
1842+
infos.hints
17811843
infos.debug
17821844
code
17831845
body_addr
@@ -1795,6 +1857,7 @@ and compile infos pc state (instrs : instr list) =
17951857
let addr = pc + 1 in
17961858
compile_block
17971859
infos.blocks
1860+
infos.hints
17981861
infos.debug
17991862
code
18001863
addr
@@ -2476,7 +2539,7 @@ type one =
24762539
; debug : Debug.t
24772540
}
24782541

2479-
let parse_bytecode ~includes code globals debug_data =
2542+
let parse_bytecode ~includes code globals hints debug_data =
24802543
let immutable = ref Code.Var.Set.empty in
24812544
let state = State.initial includes globals immutable in
24822545
Code.Var.reset ();
@@ -2486,7 +2549,7 @@ let parse_bytecode ~includes code globals debug_data =
24862549
if not (Blocks.is_empty blocks')
24872550
then (
24882551
let start = 0 in
2489-
compile_block blocks' debug_data code start state;
2552+
compile_block blocks' hints debug_data code start state;
24902553
let immutable = !immutable in
24912554
let blocks =
24922555
Addr.Map.mapi
@@ -2620,6 +2683,7 @@ let from_exe
26202683
?(debug = false)
26212684
ic =
26222685
let debug_data = Debug.create ~include_cmis debug in
2686+
let hints = Hints.create () in
26232687
let toc = Toc.read ic in
26242688
let primitives = read_primitives toc ic in
26252689
let primitive_table = Array.of_list primitives in
@@ -2665,6 +2729,11 @@ let from_exe
26652729
not available.@.");
26662730
if times () then Format.eprintf " read debug events: %a@." Timer.print t;
26672731

2732+
(try
2733+
ignore (Toc.seek_section toc ic "HINT");
2734+
Hints.read_section hints ic
2735+
with Not_found -> ());
2736+
26682737
let globals = make_globals (Array.length init_data) init_data primitive_table in
26692738
(* Initialize module override mechanism *)
26702739
List.iter override_global ~f:(fun (name, v) ->
@@ -2680,7 +2749,7 @@ let from_exe
26802749
Ocaml_compiler.Symtable.GlobalMap.iter symbols ~f:(fun id n ->
26812750
globals.named_value.(n) <- Some (Ocaml_compiler.Symtable.Global.name id);
26822751
globals.is_exported.(n) <- true);
2683-
let p = parse_bytecode ~includes code globals debug_data in
2752+
let p = parse_bytecode ~includes code globals hints debug_data in
26842753
(* register predefined exception *)
26852754
let body =
26862755
List.fold_left predefined_exceptions ~init:[] ~f:(fun body (i, name) ->
@@ -2786,6 +2855,7 @@ let from_exe
27862855
(* As input: list of primitives + size of global table *)
27872856
let from_bytes ~prims ~debug (code : bytecode) =
27882857
let debug_data = Debug.create ~include_cmis:false true in
2858+
let hints = Hints.create () in
27892859
let t = Timer.make () in
27902860
if Debug.names debug_data
27912861
then
@@ -2803,7 +2873,7 @@ let from_bytes ~prims ~debug (code : bytecode) =
28032873
t
28042874
in
28052875
let globals = make_globals 0 [||] prims in
2806-
let p = parse_bytecode ~includes:[] code globals debug_data in
2876+
let p = parse_bytecode ~includes:[] code globals hints debug_data in
28072877
let gdata = Var.fresh_n "global_data" in
28082878
let need_gdata = ref false in
28092879
let find_name i =
@@ -2942,7 +3012,7 @@ module Reloc = struct
29423012
globals
29433013
end
29443014

2945-
let from_compilation_units ~includes ~include_cmis ~debug_data l =
3015+
let from_compilation_units ~includes ~include_cmis ~hints ~debug_data l =
29463016
let reloc = Reloc.create () in
29473017
List.iter l ~f:(fun (compunit, code) -> Reloc.step1 reloc compunit code);
29483018
List.iter l ~f:(fun (compunit, code) -> Reloc.step2 reloc compunit code);
@@ -2951,7 +3021,7 @@ let from_compilation_units ~includes ~include_cmis ~debug_data l =
29513021
let l = List.map l ~f:(fun (_, c) -> Bytes.to_string c) in
29523022
String.concat ~sep:"" l
29533023
in
2954-
let prog = parse_bytecode ~includes code globals debug_data in
3024+
let prog = parse_bytecode ~includes code globals hints debug_data in
29553025
let gdata = Var.fresh_n "global_data" in
29563026
let need_gdata = ref false in
29573027
let body =
@@ -3003,12 +3073,20 @@ let from_cmo ?(includes = []) ?(include_cmis = false) ?(debug = false) compunit
30033073
seek_in ic compunit.Cmo_format.cu_debug;
30043074
Debug.read_event_list debug_data ~crcs:[] ~includes ~orig:0 ic);
30053075
if times () then Format.eprintf " read debug events: %a@." Timer.print t;
3006-
let p = from_compilation_units ~includes ~include_cmis ~debug_data [ compunit, code ] in
3076+
let hints = Hints.create () in
3077+
if Ocaml_compiler.Cmo_format.hints_pos compunit <> 0
3078+
then (
3079+
seek_in ic (Ocaml_compiler.Cmo_format.hints_pos compunit);
3080+
Hints.read hints ~orig:0 ic);
3081+
let p =
3082+
from_compilation_units ~includes ~include_cmis ~hints ~debug_data [ compunit, code ]
3083+
in
30073084
Code.invariant p.code;
30083085
p
30093086

30103087
let from_cma ?(includes = []) ?(include_cmis = false) ?(debug = false) lib ic =
30113088
let debug_data = Debug.create ~include_cmis debug in
3089+
let hints = Hints.create () in
30123090
let orig = ref 0 in
30133091
let t = ref 0. in
30143092
let units =
@@ -3021,12 +3099,16 @@ let from_cma ?(includes = []) ?(include_cmis = false) ?(debug = false) lib ic =
30213099
then (
30223100
seek_in ic compunit.Cmo_format.cu_debug;
30233101
Debug.read_event_list debug_data ~crcs:[] ~includes ~orig:!orig ic);
3102+
if Ocaml_compiler.Cmo_format.hints_pos compunit <> 0
3103+
then (
3104+
seek_in ic (Ocaml_compiler.Cmo_format.hints_pos compunit);
3105+
Hints.read hints ~orig:!orig ic);
30243106
t := !t +. Timer.get t0;
30253107
orig := !orig + compunit.Cmo_format.cu_codesize;
30263108
compunit, code)
30273109
in
30283110
if times () then Format.eprintf " read debug events: %.2f@." !t;
3029-
let p = from_compilation_units ~includes ~include_cmis ~debug_data units in
3111+
let p = from_compilation_units ~includes ~include_cmis ~hints ~debug_data units in
30303112
Code.invariant p.code;
30313113
p
30323114

compiler/tests-compiler/gh747.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ end
222222
1:
223223
2: //# unitInfo: Provides: Test
224224
3: //# unitInfo: Requires: Stdlib__Printf
225-
4: //# shape: Test:[N,N,[N],N,N,N,N,N,N,N,N,N,N,F(2),F(2),[F(4)]]
225+
4: //# shape: Test:[N,N,[N],N,N,N,N,N,N,N,N,N,[N,N],F(2),F(2),[F(4)]]
226226
5: (function
227227
6: (globalThis){
228228
7: "use strict";

compiler/tests-full/dune

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(rule
22
(targets stdlib.cma.js)
33
(enabled_if
4-
(= %{ocaml_version} "5.2.0"))
4+
(and (> %{ocaml_version} "5.2") (< %{ocaml_version} "5.3")))
55
(action
66
(run
77
%{bin:js_of_ocaml}
@@ -14,7 +14,7 @@
1414
(rule
1515
(targets stdlib.cma.output.js)
1616
(enabled_if
17-
(= %{ocaml_version} "5.2.0"))
17+
(and (> %{ocaml_version} "5.2") (< %{ocaml_version} "5.3")))
1818
(action
1919
(with-stdout-to
2020
%{targets}
@@ -23,7 +23,7 @@
2323
(rule
2424
(alias runtest)
2525
(enabled_if
26-
(= %{ocaml_version} "5.2.0"))
26+
(and (> %{ocaml_version} "5.2") (< %{ocaml_version} "5.3")))
2727
(action
2828
(diff stdlib.cma.expected.js stdlib.cma.output.js)))
2929

0 commit comments

Comments
 (0)