Skip to content

Commit 3d05b15

Browse files
authored
Compiler: compact program Addr.t (#1968)
* Compiler: compact program Addr.t * Compatibility with OCaml 4.13
1 parent ec4317f commit 3d05b15

File tree

5 files changed

+80
-2
lines changed

5 files changed

+80
-2
lines changed

compiler/lib/code.ml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
*)
2020
open! Stdlib
2121

22+
let stats = Debug.find "stats"
23+
24+
let times = Debug.find "times"
25+
2226
module Addr = struct
2327
type t = int
2428

@@ -827,6 +831,65 @@ let with_invariant = Debug.find "invariant"
827831

828832
let check_defs = false
829833

834+
let do_compact { blocks; start; free_pc = _ } =
835+
let remap =
836+
let max = fst (Addr.Map.max_binding blocks) in
837+
let a = Array.make (max + 1) 0 in
838+
let i = ref 0 in
839+
Addr.Map.iter
840+
(fun pc _ ->
841+
a.(pc) <- !i;
842+
incr i)
843+
blocks;
844+
a
845+
in
846+
let rewrite_cont remap (pc, args) = remap.(pc), args in
847+
let rewrite remap block =
848+
let body =
849+
List.map block.body ~f:(function
850+
| Let (x, Closure (params, cont, loc)) ->
851+
Let (x, Closure (params, rewrite_cont remap cont, loc))
852+
| i -> i)
853+
in
854+
let branch =
855+
match block.branch with
856+
| (Return _ | Raise _ | Stop) as b -> b
857+
| Branch c -> Branch (rewrite_cont remap c)
858+
| Poptrap c -> Poptrap (rewrite_cont remap c)
859+
| Cond (x, c1, c2) -> Cond (x, rewrite_cont remap c1, rewrite_cont remap c2)
860+
| Switch (x, a) -> Switch (x, Array.map a ~f:(rewrite_cont remap))
861+
| Pushtrap (c1, x, c2) -> Pushtrap (rewrite_cont remap c1, x, rewrite_cont remap c2)
862+
in
863+
{ block with body; branch }
864+
in
865+
let blocks =
866+
Addr.Map.fold
867+
(fun pc b blocks -> Addr.Map.add remap.(pc) (rewrite remap b) blocks)
868+
blocks
869+
Addr.Map.empty
870+
in
871+
let free_pc = (Addr.Map.max_binding blocks |> fst) + 1 in
872+
let start = remap.(start) in
873+
{ blocks; start; free_pc }
874+
875+
let compact p =
876+
let t = Timer.make () in
877+
let card = Addr.Map.cardinal p.blocks in
878+
let max = Addr.Map.max_binding p.blocks |> fst in
879+
let ratio = float card /. float max *. 100. in
880+
let do_it = Float.(ratio < 70.) in
881+
let p = if do_it then do_compact p else p in
882+
if times () then Format.eprintf " compact: %a@." Timer.print t;
883+
if stats ()
884+
then
885+
Format.eprintf
886+
"Stats - compact: %d/%d = %.2f%%%s@."
887+
card
888+
max
889+
ratio
890+
(if not do_it then " - ignored" else "");
891+
p
892+
830893
let used_blocks p =
831894
let visited = BitSet.create' p.free_pc in
832895
let rec mark_used pc =

compiler/lib/code.mli

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

308308
val empty : program
309309

310+
val compact : program -> program
311+
310312
val is_empty : program -> bool
311313

312314
val equal : program -> program -> bool

compiler/lib/driver.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ let deadcode' p =
5353
let deadcode p =
5454
let p, _ = deadcode' p in
5555
let p = Deadcode.merge_blocks p in
56+
let p = Code.compact p in
5657
p
5758

5859
let inline p =

compiler/lib/parse_bytecode.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2525,13 +2525,13 @@ let parse_bytecode code globals debug_data =
25252525
})
25262526
!compiled_blocks
25272527
in
2528-
let free_pc = String.length code / 4 in
2528+
let free_pc = (Addr.Map.max_binding blocks |> fst) + 1 in
25292529
{ start; blocks; free_pc })
25302530
else Code.empty
25312531
in
25322532
compiled_blocks := Addr.Map.empty;
25332533
tagged_blocks := Addr.Map.empty;
2534-
p
2534+
Code.compact p
25352535

25362536
module Toc : sig
25372537
type t

compiler/lib/stdlib.ml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,18 @@ module In_channel = struct
11001100
end
11011101
[@@if ocaml_version >= (4, 14, 0)]
11021102

1103+
module Seq = struct
1104+
include Seq
1105+
1106+
let rec mapi_aux f i xs () =
1107+
match xs () with
1108+
| Nil -> Nil
1109+
| Cons (x, xs) -> Cons (f i x, mapi_aux f (i + 1) xs)
1110+
1111+
(* Available since OCaml 4.14 *)
1112+
let[@inline] mapi f xs = mapi_aux f 0 xs
1113+
end
1114+
11031115
let split_lines s =
11041116
if String.equal s ""
11051117
then []

0 commit comments

Comments
 (0)