|
19 | 19 | *)
|
20 | 20 | open! Stdlib
|
21 | 21 |
|
| 22 | +let stats = Debug.find "stats" |
| 23 | + |
| 24 | +let times = Debug.find "times" |
| 25 | + |
22 | 26 | module Addr = struct
|
23 | 27 | type t = int
|
24 | 28 |
|
@@ -827,6 +831,65 @@ let with_invariant = Debug.find "invariant"
|
827 | 831 |
|
828 | 832 | let check_defs = false
|
829 | 833 |
|
| 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 | + |
830 | 893 | let used_blocks p =
|
831 | 894 | let visited = BitSet.create' p.free_pc in
|
832 | 895 | let rec mark_used pc =
|
|
0 commit comments