@@ -333,6 +333,63 @@ end = struct
333
333
StringSet. of_list (List. concat paths)
334
334
end
335
335
336
+ module Hints = struct
337
+ module Primitive = struct
338
+ type boxed_integer =
339
+ | Pnativeint
340
+ | Pint32
341
+ | Pint64
342
+
343
+ type native_repr =
344
+ | Same_as_ocaml_repr
345
+ | Unboxed_float
346
+ | Unboxed_integer of boxed_integer
347
+ | Untagged_immediate
348
+
349
+ type description =
350
+ { prim_name : string (* Name of primitive or C function *)
351
+ ; prim_arity : int (* Number of arguments *)
352
+ ; prim_alloc : bool (* Does it allocates or raise? *)
353
+ ; prim_native_name : string (* Name of C function for the nat. code gen. *)
354
+ ; prim_native_repr_args : native_repr list
355
+ ; prim_native_repr_res : native_repr
356
+ }
357
+ [@@ ocaml.warning "-unused-field" ]
358
+ end
359
+
360
+ type optimization_hint =
361
+ | Hint_immutable
362
+ | Hint_unsafe
363
+ | Hint_int of Primitive .boxed_integer
364
+ | Hint_array of Lambda .array_kind
365
+ | Hint_bigarray of
366
+ { unsafe : bool
367
+ ; elt_kind : Lambda .bigarray_kind
368
+ ; layout : Lambda .bigarray_layout
369
+ }
370
+ | Hint_primitive of Primitive .description
371
+
372
+ type t = { hints : optimization_hint Int.Hashtbl .t }
373
+
374
+ let equal (a : optimization_hint ) b = Poly. equal a b
375
+
376
+ let create () = { hints = Int.Hashtbl. create 17 }
377
+
378
+ let read t ~orig ic =
379
+ let l : (int * optimization_hint) list = input_value ic in
380
+
381
+ List. iter l ~f: (fun (pos , hint ) -> Int.Hashtbl. add t.hints ((pos + orig) / 4 ) hint)
382
+
383
+ let read_section t ic =
384
+ let len = input_binary_int ic in
385
+ for _i = 0 to len - 1 do
386
+ let orig = input_binary_int ic in
387
+ read t ~orig ic
388
+ done
389
+
390
+ let find t pc = Int.Hashtbl. find_all t.hints pc
391
+ end
392
+
336
393
(* Block analysis *)
337
394
(* Detect each block *)
338
395
module Blocks : sig
@@ -864,6 +921,7 @@ type compile_info =
864
921
; code : string
865
922
; limit : int
866
923
; debug : Debug .t
924
+ ; hints : Hints .t
867
925
}
868
926
869
927
let string_of_addr debug_data addr =
@@ -886,9 +944,11 @@ let string_of_addr debug_data addr =
886
944
in
887
945
Printf. sprintf " %s:%s-%s %s" file (pos loc.loc_start) (pos loc.loc_end) kind)
888
946
889
- let is_immutable _instr _infos _pc = (* We don't know yet *) Maybe_mutable
947
+ let is_immutable _instr infos pc =
948
+ let hints = Hints. find infos.hints pc in
949
+ if List. mem ~eq: Hints. equal Hints. Hint_immutable hints then Immutable else Maybe_mutable
890
950
891
- let rec compile_block blocks joins debug_data code pc state : unit =
951
+ let rec compile_block blocks joins hints debug_data code pc state : unit =
892
952
match Addr.Map. find_opt pc ! tagged_blocks with
893
953
| Some old_state -> (
894
954
(* Check that the shape of the stack is compatible with the one used to compile the block *)
@@ -920,7 +980,7 @@ let rec compile_block blocks joins debug_data code pc state : unit =
920
980
let state = if Addr.Set. mem pc joins then State. start_block pc state else state in
921
981
tagged_blocks := Addr.Map. add pc state ! tagged_blocks;
922
982
let instr, last, state' =
923
- compile { blocks; joins; code; limit; debug = debug_data } pc state []
983
+ compile { blocks; joins; code; limit; debug = debug_data; hints } pc state []
924
984
in
925
985
assert (not (Addr.Map. mem pc ! compiled_blocks));
926
986
(* When jumping to a block that was already visited and the
@@ -959,10 +1019,10 @@ let rec compile_block blocks joins debug_data code pc state : unit =
959
1019
! compiled_blocks;
960
1020
match last with
961
1021
| Branch (pc' , _ ) ->
962
- compile_block blocks joins debug_data code pc' (adjust_state pc')
1022
+ compile_block blocks joins hints debug_data code pc' (adjust_state pc')
963
1023
| Cond (_ , (pc1 , _ ), (pc2 , _ )) ->
964
- compile_block blocks joins debug_data code pc1 (adjust_state pc1);
965
- compile_block blocks joins debug_data code pc2 (adjust_state pc2)
1024
+ compile_block blocks joins hints debug_data code pc1 (adjust_state pc1);
1025
+ compile_block blocks joins hints debug_data code pc2 (adjust_state pc2)
966
1026
| Poptrap (_ , _ ) -> ()
967
1027
| Switch (_ , _ ) -> ()
968
1028
| Raise _ | Return _ | Stop -> ()
@@ -1289,7 +1349,7 @@ and compile infos pc state (instrs : instr list) =
1289
1349
let params, state' = State. make_stack nparams state' in
1290
1350
if debug_parser () then Format. printf " ) {@." ;
1291
1351
let state' = State. clear_accu state' in
1292
- compile_block infos.blocks infos.joins infos.debug code addr state';
1352
+ compile_block infos.blocks infos.joins infos.hints infos. debug code addr state';
1293
1353
if debug_parser () then Format. printf " }@." ;
1294
1354
compile
1295
1355
infos
@@ -1347,7 +1407,14 @@ and compile infos pc state (instrs : instr list) =
1347
1407
let params, state' = State. make_stack nparams state' in
1348
1408
if debug_parser () then Format. printf " ) {@." ;
1349
1409
let state' = State. clear_accu state' in
1350
- compile_block infos.blocks infos.joins infos.debug code addr state';
1410
+ compile_block
1411
+ infos.blocks
1412
+ infos.joins
1413
+ infos.hints
1414
+ infos.debug
1415
+ code
1416
+ addr
1417
+ state';
1351
1418
if debug_parser () then Format. printf " }@." ;
1352
1419
Let
1353
1420
( x
@@ -1759,9 +1826,9 @@ and compile infos pc state (instrs : instr list) =
1759
1826
let it = Array. init isize ~f: (fun i -> base + gets code (base + i)) in
1760
1827
let bt = Array. init bsize ~f: (fun i -> base + gets code (base + isize + i)) in
1761
1828
Array. iter it ~f: (fun pc' ->
1762
- compile_block infos.blocks infos.joins infos.debug code pc' state);
1829
+ compile_block infos.blocks infos.joins infos.hints infos. debug code pc' state);
1763
1830
Array. iter bt ~f: (fun pc' ->
1764
- compile_block infos.blocks infos.joins infos.debug code pc' state);
1831
+ compile_block infos.blocks infos.joins infos.hints infos. debug code pc' state);
1765
1832
match isize, bsize with
1766
1833
| _ , 0 -> instrs, Switch (x, Array. map it ~f: (fun pc -> pc, [] )), state
1767
1834
| 0 , _ ->
@@ -1828,10 +1895,18 @@ and compile infos pc state (instrs : instr list) =
1828
1895
interm_addr
1829
1896
(Some handler_ctx_state, [] , Pushtrap ((body_addr, [] ), x, (handler_addr, [] )))
1830
1897
! compiled_blocks;
1831
- compile_block infos.blocks infos.joins infos.debug code handler_addr handler_state;
1832
1898
compile_block
1833
1899
infos.blocks
1834
1900
infos.joins
1901
+ infos.hints
1902
+ infos.debug
1903
+ code
1904
+ handler_addr
1905
+ handler_state;
1906
+ compile_block
1907
+ infos.blocks
1908
+ infos.joins
1909
+ infos.hints
1835
1910
infos.debug
1836
1911
code
1837
1912
body_addr
@@ -1850,6 +1925,7 @@ and compile infos pc state (instrs : instr list) =
1850
1925
compile_block
1851
1926
infos.blocks
1852
1927
infos.joins
1928
+ infos.hints
1853
1929
infos.debug
1854
1930
code
1855
1931
addr
@@ -2539,7 +2615,7 @@ type one =
2539
2615
; debug : Debug .summary
2540
2616
}
2541
2617
2542
- let parse_bytecode code globals debug_data =
2618
+ let parse_bytecode code globals hints debug_data =
2543
2619
let immutable = Code.Var.Hashtbl. create 0 in
2544
2620
let state = State. initial globals immutable in
2545
2621
Code.Var. reset () ;
@@ -2550,7 +2626,7 @@ let parse_bytecode code globals debug_data =
2550
2626
then (
2551
2627
let start = 0 in
2552
2628
2553
- compile_block blocks' joins debug_data code start state;
2629
+ compile_block blocks' joins hints debug_data code start state;
2554
2630
let blocks =
2555
2631
Addr.Map. mapi
2556
2632
(fun _ (state , instr , last ) ->
@@ -2674,6 +2750,7 @@ let from_exe
2674
2750
?(debug = false )
2675
2751
ic =
2676
2752
let debug_data = Debug. create ~include_cmis debug in
2753
+ let hints = Hints. create () in
2677
2754
let toc = Toc. read ic in
2678
2755
let primitives = read_primitives toc ic in
2679
2756
let primitive_table = Array. of_list primitives in
@@ -2720,14 +2797,19 @@ let from_exe
2720
2797
available.@." );
2721
2798
if times () then Format. eprintf " read debug events: %a@." Timer. print t;
2722
2799
2800
+ (try
2801
+ ignore (Toc. seek_section toc ic " HINT" );
2802
+ Hints. read_section hints ic
2803
+ with Not_found -> () );
2804
+
2723
2805
let globals = make_globals (Array. length init_data) init_data primitive_table in
2724
2806
if linkall
2725
2807
then
2726
2808
(* export globals *)
2727
2809
Ocaml_compiler.Symtable.GlobalMap. iter symbols ~f: (fun id n ->
2728
2810
globals.named_value.(n) < - Some (Ocaml_compiler.Symtable.Global. name id);
2729
2811
globals.is_exported.(n) < - true );
2730
- let p = parse_bytecode code globals debug_data in
2812
+ let p = parse_bytecode code globals hints debug_data in
2731
2813
(* register predefined exception *)
2732
2814
let body =
2733
2815
List. fold_left predefined_exceptions ~init: [] ~f: (fun body (i , name ) ->
@@ -2835,6 +2917,7 @@ let from_exe
2835
2917
(* As input: list of primitives + size of global table *)
2836
2918
let from_bytes ~prims ~debug (code : bytecode ) =
2837
2919
let debug_data = Debug. create ~include_cmis: false true in
2920
+ let hints = Hints. create () in
2838
2921
let t = Timer. make () in
2839
2922
if Debug. names debug_data
2840
2923
then
@@ -2857,7 +2940,7 @@ let from_bytes ~prims ~debug (code : bytecode) =
2857
2940
t
2858
2941
in
2859
2942
let globals = make_globals 0 [||] prims in
2860
- let p = parse_bytecode code globals debug_data in
2943
+ let p = parse_bytecode code globals hints debug_data in
2861
2944
let gdata = Var. fresh_n " global_data" in
2862
2945
let need_gdata = ref false in
2863
2946
let find_name i =
@@ -2989,7 +3072,7 @@ module Reloc = struct
2989
3072
globals
2990
3073
end
2991
3074
2992
- let from_compilation_units ~includes :_ ~include_cmis ~debug_data l =
3075
+ let from_compilation_units ~includes :_ ~include_cmis ~hints ~ debug_data l =
2993
3076
let reloc = Reloc. create () in
2994
3077
List. iter l ~f: (fun (compunit , code ) -> Reloc. step1 reloc compunit code);
2995
3078
List. iter l ~f: (fun (compunit , code ) -> Reloc. step2 reloc compunit code);
@@ -2998,7 +3081,7 @@ let from_compilation_units ~includes:_ ~include_cmis ~debug_data l =
2998
3081
let l = List. map l ~f: (fun (_ , c ) -> Bytes. to_string c) in
2999
3082
String. concat ~sep: " " l
3000
3083
in
3001
- let prog = parse_bytecode code globals debug_data in
3084
+ let prog = parse_bytecode code globals hints debug_data in
3002
3085
let gdata = Var. fresh_n " global_data" in
3003
3086
let need_gdata = ref false in
3004
3087
let body =
@@ -3050,12 +3133,20 @@ let from_cmo ?(includes = []) ?(include_cmis = false) ?(debug = false) compunit
3050
3133
seek_in ic compunit.Cmo_format. cu_debug;
3051
3134
Debug. read_event_list debug_data ~crcs: [] ~includes ~orig: 0 ic);
3052
3135
if times () then Format. eprintf " read debug events: %a@." Timer. print t;
3053
- let p = from_compilation_units ~includes ~include_cmis ~debug_data [ compunit, code ] in
3136
+ let hints = Hints. create () in
3137
+ if Ocaml_compiler.Cmo_format. hints_pos compunit <> 0
3138
+ then (
3139
+ seek_in ic (Ocaml_compiler.Cmo_format. hints_pos compunit);
3140
+ Hints. read hints ~orig: 0 ic);
3141
+ let p =
3142
+ from_compilation_units ~includes ~include_cmis ~hints ~debug_data [ compunit, code ]
3143
+ in
3054
3144
Code. invariant p.code;
3055
3145
p
3056
3146
3057
3147
let from_cma ?(includes = [] ) ?(include_cmis = false ) ?(debug = false ) lib ic =
3058
3148
let debug_data = Debug. create ~include_cmis debug in
3149
+ let hints = Hints. create () in
3059
3150
let orig = ref 0 in
3060
3151
let t = ref 0. in
3061
3152
let units =
@@ -3068,12 +3159,16 @@ let from_cma ?(includes = []) ?(include_cmis = false) ?(debug = false) lib ic =
3068
3159
then (
3069
3160
seek_in ic compunit.Cmo_format. cu_debug;
3070
3161
Debug. read_event_list debug_data ~crcs: [] ~includes ~orig: ! orig ic);
3162
+ if Ocaml_compiler.Cmo_format. hints_pos compunit <> 0
3163
+ then (
3164
+ seek_in ic (Ocaml_compiler.Cmo_format. hints_pos compunit);
3165
+ Hints. read hints ~orig: ! orig ic);
3071
3166
t := ! t +. Timer. get t0;
3072
3167
orig := ! orig + compunit.Cmo_format. cu_codesize;
3073
3168
compunit, code)
3074
3169
in
3075
3170
if times () then Format. eprintf " read debug events: %.2f@." ! t;
3076
- let p = from_compilation_units ~includes ~include_cmis ~debug_data units in
3171
+ let p = from_compilation_units ~includes ~include_cmis ~hints ~ debug_data units in
3077
3172
Code. invariant p.code;
3078
3173
p
3079
3174
0 commit comments