| 
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