@@ -333,6 +333,63 @@ end = struct
333333 StringSet. of_list (List. concat paths)
334334end
335335
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+
336393(* Block analysis *)
337394(* Detect each block *)
338395module Blocks : sig
@@ -864,6 +921,7 @@ type compile_info =
864921 ; code : string
865922 ; limit : int
866923 ; debug : Debug .t
924+ ; hints : Hints .t
867925 }
868926
869927let string_of_addr debug_data addr =
@@ -886,9 +944,11 @@ let string_of_addr debug_data addr =
886944 in
887945 Printf. sprintf " %s:%s-%s %s" file (pos loc.loc_start) (pos loc.loc_end) kind)
888946
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
890950
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 =
892952 match Addr.Map. find_opt pc ! tagged_blocks with
893953 | Some old_state -> (
894954 (* 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 =
920980 let state = if Addr.Set. mem pc joins then State. start_block pc state else state in
921981 tagged_blocks := Addr.Map. add pc state ! tagged_blocks;
922982 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 []
924984 in
925985 assert (not (Addr.Map. mem pc ! compiled_blocks));
926986 (* 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 =
9591019 ! compiled_blocks;
9601020 match last with
9611021 | 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')
9631023 | 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)
9661026 | Poptrap (_ , _ ) -> ()
9671027 | Switch (_ , _ ) -> ()
9681028 | Raise _ | Return _ | Stop -> ()
@@ -1289,7 +1349,7 @@ and compile infos pc state (instrs : instr list) =
12891349 let params, state' = State. make_stack nparams state' in
12901350 if debug_parser () then Format. printf " ) {@." ;
12911351 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';
12931353 if debug_parser () then Format. printf " }@." ;
12941354 compile
12951355 infos
@@ -1347,7 +1407,14 @@ and compile infos pc state (instrs : instr list) =
13471407 let params, state' = State. make_stack nparams state' in
13481408 if debug_parser () then Format. printf " ) {@." ;
13491409 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';
13511418 if debug_parser () then Format. printf " }@." ;
13521419 Let
13531420 ( x
@@ -1759,9 +1826,9 @@ and compile infos pc state (instrs : instr list) =
17591826 let it = Array. init isize ~f: (fun i -> base + gets code (base + i)) in
17601827 let bt = Array. init bsize ~f: (fun i -> base + gets code (base + isize + i)) in
17611828 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);
17631830 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);
17651832 match isize, bsize with
17661833 | _ , 0 -> instrs, Switch (x, Array. map it ~f: (fun pc -> pc, [] )), state
17671834 | 0 , _ ->
@@ -1828,10 +1895,18 @@ and compile infos pc state (instrs : instr list) =
18281895 interm_addr
18291896 (Some handler_ctx_state, [] , Pushtrap ((body_addr, [] ), x, (handler_addr, [] )))
18301897 ! compiled_blocks;
1831- compile_block infos.blocks infos.joins infos.debug code handler_addr handler_state;
18321898 compile_block
18331899 infos.blocks
18341900 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
18351910 infos.debug
18361911 code
18371912 body_addr
@@ -1850,6 +1925,7 @@ and compile infos pc state (instrs : instr list) =
18501925 compile_block
18511926 infos.blocks
18521927 infos.joins
1928+ infos.hints
18531929 infos.debug
18541930 code
18551931 addr
@@ -2539,7 +2615,7 @@ type one =
25392615 ; debug : Debug .summary
25402616 }
25412617
2542- let parse_bytecode code globals debug_data =
2618+ let parse_bytecode code globals hints debug_data =
25432619 let immutable = Code.Var.Hashtbl. create 0 in
25442620 let state = State. initial globals immutable in
25452621 Code.Var. reset () ;
@@ -2550,7 +2626,7 @@ let parse_bytecode code globals debug_data =
25502626 then (
25512627 let start = 0 in
25522628
2553- compile_block blocks' joins debug_data code start state;
2629+ compile_block blocks' joins hints debug_data code start state;
25542630 let blocks =
25552631 Addr.Map. mapi
25562632 (fun _ (state , instr , last ) ->
@@ -2674,6 +2750,7 @@ let from_exe
26742750 ?(debug = false )
26752751 ic =
26762752 let debug_data = Debug. create ~include_cmis debug in
2753+ let hints = Hints. create () in
26772754 let toc = Toc. read ic in
26782755 let primitives = read_primitives toc ic in
26792756 let primitive_table = Array. of_list primitives in
@@ -2719,14 +2796,19 @@ let from_exe
27192796 not available.@." );
27202797 if times () then Format. eprintf " read debug events: %a@." Timer. print t;
27212798
2799+ (try
2800+ ignore (Toc. seek_section toc ic " HINT" );
2801+ Hints. read_section hints ic
2802+ with Not_found -> () );
2803+
27222804 let globals = make_globals (Array. length init_data) init_data primitive_table in
27232805 if linkall
27242806 then
27252807 (* export globals *)
27262808 Ocaml_compiler.Symtable.GlobalMap. iter symbols ~f: (fun id n ->
27272809 globals.named_value.(n) < - Some (Ocaml_compiler.Symtable.Global. name id);
27282810 globals.is_exported.(n) < - true );
2729- let p = parse_bytecode code globals debug_data in
2811+ let p = parse_bytecode code globals hints debug_data in
27302812 (* register predefined exception *)
27312813 let body =
27322814 List. fold_left predefined_exceptions ~init: [] ~f: (fun body (i , name ) ->
@@ -2834,6 +2916,7 @@ let from_exe
28342916(* As input: list of primitives + size of global table *)
28352917let from_bytes ~prims ~debug (code : bytecode ) =
28362918 let debug_data = Debug. create ~include_cmis: false true in
2919+ let hints = Hints. create () in
28372920 let t = Timer. make () in
28382921 if Debug. names debug_data
28392922 then
@@ -2856,7 +2939,7 @@ let from_bytes ~prims ~debug (code : bytecode) =
28562939 t
28572940 in
28582941 let globals = make_globals 0 [||] prims in
2859- let p = parse_bytecode code globals debug_data in
2942+ let p = parse_bytecode code globals hints debug_data in
28602943 let gdata = Var. fresh_n " global_data" in
28612944 let need_gdata = ref false in
28622945 let find_name i =
@@ -2988,7 +3071,7 @@ module Reloc = struct
29883071 globals
29893072end
29903073
2991- let from_compilation_units ~includes :_ ~include_cmis ~debug_data l =
3074+ let from_compilation_units ~includes :_ ~include_cmis ~hints ~ debug_data l =
29923075 let reloc = Reloc. create () in
29933076 List. iter l ~f: (fun (compunit , code ) -> Reloc. step1 reloc compunit code);
29943077 List. iter l ~f: (fun (compunit , code ) -> Reloc. step2 reloc compunit code);
@@ -2997,7 +3080,7 @@ let from_compilation_units ~includes:_ ~include_cmis ~debug_data l =
29973080 let l = List. map l ~f: (fun (_ , c ) -> Bytes. to_string c) in
29983081 String. concat ~sep: " " l
29993082 in
3000- let prog = parse_bytecode code globals debug_data in
3083+ let prog = parse_bytecode code globals hints debug_data in
30013084 let gdata = Var. fresh_n " global_data" in
30023085 let need_gdata = ref false in
30033086 let body =
@@ -3049,12 +3132,20 @@ let from_cmo ?(includes = []) ?(include_cmis = false) ?(debug = false) compunit
30493132 seek_in ic compunit.Cmo_format. cu_debug;
30503133 Debug. read_event_list debug_data ~crcs: [] ~includes ~orig: 0 ic);
30513134 if times () then Format. eprintf " read debug events: %a@." Timer. print t;
3052- let p = from_compilation_units ~includes ~include_cmis ~debug_data [ compunit, code ] in
3135+ let hints = Hints. create () in
3136+ if Ocaml_compiler.Cmo_format. hints_pos compunit <> 0
3137+ then (
3138+ seek_in ic (Ocaml_compiler.Cmo_format. hints_pos compunit);
3139+ Hints. read hints ~orig: 0 ic);
3140+ let p =
3141+ from_compilation_units ~includes ~include_cmis ~hints ~debug_data [ compunit, code ]
3142+ in
30533143 Code. invariant p.code;
30543144 p
30553145
30563146let from_cma ?(includes = [] ) ?(include_cmis = false ) ?(debug = false ) lib ic =
30573147 let debug_data = Debug. create ~include_cmis debug in
3148+ let hints = Hints. create () in
30583149 let orig = ref 0 in
30593150 let t = ref 0. in
30603151 let units =
@@ -3067,12 +3158,16 @@ let from_cma ?(includes = []) ?(include_cmis = false) ?(debug = false) lib ic =
30673158 then (
30683159 seek_in ic compunit.Cmo_format. cu_debug;
30693160 Debug. read_event_list debug_data ~crcs: [] ~includes ~orig: ! orig ic);
3161+ if Ocaml_compiler.Cmo_format. hints_pos compunit <> 0
3162+ then (
3163+ seek_in ic (Ocaml_compiler.Cmo_format. hints_pos compunit);
3164+ Hints. read hints ~orig: ! orig ic);
30703165 t := ! t +. Timer. get t0;
30713166 orig := ! orig + compunit.Cmo_format. cu_codesize;
30723167 compunit, code)
30733168 in
30743169 if times () then Format. eprintf " read debug events: %.2f@." ! t;
3075- let p = from_compilation_units ~includes ~include_cmis ~debug_data units in
3170+ let p = from_compilation_units ~includes ~include_cmis ~hints ~ debug_data units in
30763171 Code. invariant p.code;
30773172 p
30783173
0 commit comments