@@ -323,6 +323,63 @@ end = struct
323323 StringSet. of_list (List. concat paths)
324324end
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 *)
328385module 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
814872let 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 *)
27872856let 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
29433013end
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
30103087let 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
0 commit comments