@@ -47,8 +47,6 @@ module Debug : sig
4747
4848 val dbg_section_needed : t -> bool
4949
50- val propagate : Code.Var .t list -> Code.Var .t list -> unit
51-
5250 val find : t -> Code.Addr .t -> (int * Ident .t ) list * Env .summary
5351
5452 val find_rec : t -> Code.Addr .t -> (int * Ident .t ) list
@@ -308,14 +306,6 @@ end = struct
308306 | [] -> None
309307 | (source , event ) :: _ -> Some (event_location ~position ~source ~event )
310308
311- let rec propagate l1 l2 =
312- match l1, l2 with
313- | v1 :: r1 , v2 :: r2 ->
314- Var. propagate_name v1 v2;
315- propagate r1 r2
316- | [] , [] -> ()
317- | _ -> assert false
318-
319309 type summary =
320310 { is_empty : bool
321311 ; units : (string * string option , ml_unit ) Hashtbl .t
342332module Blocks : sig
343333 type t
344334
345- val analyse : bytecode -> t
335+ val analyse : bytecode -> t * Addr.Set .t
346336
347337 val next : t -> int -> int
348338
@@ -352,45 +342,68 @@ end = struct
352342
353343 let add blocks pc = Addr.Set. add pc blocks
354344
355- let rec scan blocks code pc len =
345+ let rec scan blocks starts repeats code pc len =
356346 if pc < len
357347 then
358348 match (get_instr_exn code pc).kind with
359- | KNullary -> scan blocks code (pc + 1 ) len
360- | KUnary -> scan blocks code (pc + 2 ) len
361- | KBinary -> scan blocks code (pc + 3 ) len
362- | KNullaryCall -> scan blocks code (pc + 1 ) len
363- | KUnaryCall -> scan blocks code (pc + 2 ) len
364- | KBinaryCall -> scan blocks code (pc + 3 ) len
349+ | KNullary -> scan blocks starts repeats code (pc + 1 ) len
350+ | KUnary -> scan blocks starts repeats code (pc + 2 ) len
351+ | KBinary -> scan blocks starts repeats code (pc + 3 ) len
352+ | KNullaryCall -> scan blocks starts repeats code (pc + 1 ) len
353+ | KUnaryCall -> scan blocks starts repeats code (pc + 2 ) len
354+ | KBinaryCall -> scan blocks starts repeats code (pc + 3 ) len
365355 | KJump ->
366356 let offset = gets code (pc + 1 ) in
367- let blocks = Addr.Set. add (pc + offset + 1 ) blocks in
368- scan blocks code (pc + 2 ) len
357+ let pc' = pc + offset + 1 in
358+ let repeats =
359+ if Addr.Set. mem pc' blocks then Addr.Set. add pc' repeats else repeats
360+ in
361+ let blocks = Addr.Set. add pc' blocks in
362+ let pc'' = pc + 2 in
363+ let starts = Addr.Set. add pc'' starts in
364+ scan blocks starts repeats code pc'' len
369365 | KCond_jump ->
370366 let offset = gets code (pc + 1 ) in
371- let blocks = Addr.Set. add (pc + offset + 1 ) blocks in
372- scan blocks code (pc + 2 ) len
367+ let pc' = pc + offset + 1 in
368+ let repeats =
369+ if Addr.Set. mem pc' blocks then Addr.Set. add pc' repeats else repeats
370+ in
371+ let blocks = Addr.Set. add pc' blocks in
372+ scan blocks starts repeats code (pc + 2 ) len
373373 | KCmp_jump ->
374374 let offset = gets code (pc + 2 ) in
375- let blocks = Addr.Set. add (pc + offset + 2 ) blocks in
376- scan blocks code (pc + 3 ) len
375+ let pc' = pc + offset + 2 in
376+ let repeats =
377+ if Addr.Set. mem pc' blocks then Addr.Set. add pc' repeats else repeats
378+ in
379+ let blocks = Addr.Set. add pc' blocks in
380+ scan blocks starts repeats code (pc + 3 ) len
377381 | KSwitch ->
378382 let sz = getu code (pc + 1 ) in
383+ let repeats = ref repeats in
379384 let blocks = ref blocks in
380- for i = 0 to (sz land 0xffff ) + (sz lsr 16 ) - 1 do
385+ let count = (sz land 0xffff ) + (sz lsr 16 ) in
386+ for i = 0 to count - 1 do
381387 let offset = gets code (pc + 2 + i) in
382- blocks := Addr.Set. add (pc + offset + 2 ) ! blocks
388+ let pc' = pc + offset + 2 in
389+ if Addr.Set. mem pc' ! blocks then repeats := Addr.Set. add pc' ! repeats;
390+ blocks := Addr.Set. add pc' ! blocks
383391 done ;
384- scan ! blocks code (pc + 2 + (sz land 0xffff ) + (sz lsr 16 )) len
392+ let pc'' = pc + 2 + count in
393+ let starts = Addr.Set. add pc'' starts in
394+ scan ! blocks starts ! repeats code pc'' len
385395 | KClosurerec ->
386396 let nfuncs = getu code (pc + 1 ) in
387- scan blocks code (pc + nfuncs + 3 ) len
388- | KClosure -> scan blocks code (pc + 3 ) len
389- | KStop n -> scan blocks code (pc + n + 1 ) len
397+ scan blocks starts repeats code (pc + nfuncs + 3 ) len
398+ | KClosure -> scan blocks starts repeats code (pc + 3 ) len
399+ | KStop n ->
400+ let pc'' = pc + n + 1 in
401+ let starts = Addr.Set. add pc'' starts in
402+ scan blocks starts repeats code pc'' len
390403 | K_will_not_happen -> assert false
391404 else (
392405 assert (pc = len);
393- blocks)
406+ blocks, starts, repeats )
394407
395408 (* invariant: a.(i) <= x < a.(j) *)
396409 let rec find a i j x =
@@ -406,12 +419,14 @@ end = struct
406419 let is_empty x = Array. length x < = 1
407420
408421 let analyse code =
409- let blocks = Addr.Set. empty in
410422 let len = String. length code / 4 in
423+ let blocks, starts, repeats =
424+ scan Addr.Set. empty Addr.Set. empty Addr.Set. empty code 0 len
425+ in
426+ let joins = Addr.Set. union repeats (Addr.Set. diff blocks starts) in
411427 let blocks = add blocks 0 in
412428 let blocks = add blocks len in
413- let blocks = scan blocks code 0 len in
414- Array. of_list (Addr.Set. elements blocks)
429+ Array. of_list (Addr.Set. elements blocks), joins
415430end
416431
417432(* Parse constants *)
@@ -803,6 +818,7 @@ let clo_offset_3 = 3
803818
804819type compile_info =
805820 { blocks : Blocks .t
821+ ; joins : Addr.Set .t
806822 ; code : string
807823 ; limit : int
808824 ; debug : Debug .t
@@ -828,7 +844,7 @@ let string_of_addr debug_data addr =
828844 in
829845 Printf. sprintf " %s:%s-%s %s" file (pos loc.loc_start) (pos loc.loc_end) kind)
830846
831- let rec compile_block blocks debug_data code pc state : unit =
847+ let rec compile_block blocks joins debug_data code pc state : unit =
832848 match Addr.Map. find_opt pc ! tagged_blocks with
833849 | Some old_state -> (
834850 (* Check that the shape of the stack is compatible with the one used to compile the block *)
@@ -857,10 +873,10 @@ let rec compile_block blocks debug_data code pc state : unit =
857873 let limit = Blocks. next blocks pc in
858874 assert (limit > pc);
859875 if debug_parser () then Format. eprintf " Compiling from %d to %d@." pc (limit - 1 );
860- let state = State. start_block pc state in
876+ let state = if Addr.Set. mem pc joins then State. start_block pc state else state in
861877 tagged_blocks := Addr.Map. add pc state ! tagged_blocks;
862878 let instr, last, state' =
863- compile { blocks; code; limit; debug = debug_data } pc state []
879+ compile { blocks; joins; code; limit; debug = debug_data } pc state []
864880 in
865881 assert (not (Addr.Map. mem pc ! compiled_blocks));
866882 (* When jumping to a block that was already visited and the
@@ -873,26 +889,36 @@ let rec compile_block blocks debug_data code pc state : unit =
873889 State. clear_accu state'
874890 | _ , _ -> state'
875891 in
876- let mk_cont pc =
877- let state = adjust_state pc in
878- pc, State. stack_vars state
892+ let mk_cont ((pc , _ ) as cont ) =
893+ if Addr.Set. mem pc joins
894+ then
895+ let state = adjust_state pc in
896+ pc, State. stack_vars state
897+ else cont
879898 in
880899 let last =
881900 match last with
882- | Branch (pc , _ ) -> Branch (mk_cont pc)
883- | Cond (x , (pc1 , _ ), (pc2 , _ )) ->
884- if pc1 = pc2 then Branch (mk_cont pc1) else Cond (x, mk_cont pc1, mk_cont pc2)
885- | Poptrap (pc , _ ) -> Poptrap (mk_cont pc)
886- | Switch (x , a ) -> Switch (x, Array. map a ~f: (fun (pc , _ ) -> mk_cont pc))
901+ | Branch cont -> Branch (mk_cont cont)
902+ | Cond (x , cont1 , cont2 ) ->
903+ if cont_equal cont1 cont2
904+ then Branch (mk_cont cont1)
905+ else Cond (x, mk_cont cont1, mk_cont cont2)
906+ | Poptrap cont -> Poptrap (mk_cont cont)
907+ | Switch (x , a ) -> Switch (x, Array. map a ~f: mk_cont)
887908 | Raise _ | Return _ | Stop -> last
888909 | Pushtrap _ -> assert false
889910 in
890- compiled_blocks := Addr.Map. add pc (state, List. rev instr, last) ! compiled_blocks;
911+ compiled_blocks :=
912+ Addr.Map. add
913+ pc
914+ ((if Addr.Set. mem pc joins then Some state else None ), List. rev instr, last)
915+ ! compiled_blocks;
891916 match last with
892- | Branch (pc' , _ ) -> compile_block blocks debug_data code pc' (adjust_state pc')
917+ | Branch (pc' , _ ) ->
918+ compile_block blocks joins debug_data code pc' (adjust_state pc')
893919 | Cond (_ , (pc1 , _ ), (pc2 , _ )) ->
894- compile_block blocks debug_data code pc1 (adjust_state pc1);
895- compile_block blocks debug_data code pc2 (adjust_state pc2)
920+ compile_block blocks joins debug_data code pc1 (adjust_state pc1);
921+ compile_block blocks joins debug_data code pc2 (adjust_state pc2)
896922 | Poptrap (_ , _ ) -> ()
897923 | Switch (_ , _ ) -> ()
898924 | Raise _ | Return _ | Stop -> ()
@@ -1219,11 +1245,8 @@ and compile infos pc state (instrs : instr list) =
12191245 let params, state' = State. make_stack nparams state' in
12201246 if debug_parser () then Format. printf " ) {@." ;
12211247 let state' = State. clear_accu state' in
1222- compile_block infos.blocks infos.debug code addr state';
1248+ compile_block infos.blocks infos.joins infos. debug code addr state';
12231249 if debug_parser () then Format. printf " }@." ;
1224- let args = State. stack_vars state' in
1225- let state'', _, _ = Addr.Map. find addr ! compiled_blocks in
1226- Debug. propagate (State. stack_vars state'') args;
12271250 compile
12281251 infos
12291252 (pc + 3 )
@@ -1232,7 +1255,7 @@ and compile infos pc state (instrs : instr list) =
12321255 ( x
12331256 , Closure
12341257 ( List. rev params
1235- , (addr, args )
1258+ , (addr, [] )
12361259 , Debug. find_loc infos.debug ~position: After addr ) )
12371260 :: instrs)
12381261 | CLOSUREREC ->
@@ -1280,16 +1303,13 @@ and compile infos pc state (instrs : instr list) =
12801303 let params, state' = State. make_stack nparams state' in
12811304 if debug_parser () then Format. printf " ) {@." ;
12821305 let state' = State. clear_accu state' in
1283- compile_block infos.blocks infos.debug code addr state';
1306+ compile_block infos.blocks infos.joins infos. debug code addr state';
12841307 if debug_parser () then Format. printf " }@." ;
1285- let args = State. stack_vars state' in
1286- let state'', _, _ = Addr.Map. find addr ! compiled_blocks in
1287- Debug. propagate (State. stack_vars state'') args;
12881308 Let
12891309 ( x
12901310 , Closure
12911311 ( List. rev params
1292- , (addr, args )
1312+ , (addr, [] )
12931313 , Debug. find_loc infos.debug ~position: After addr ) )
12941314 :: instr)
12951315 in
@@ -1694,9 +1714,9 @@ and compile infos pc state (instrs : instr list) =
16941714 let it = Array. init isize ~f: (fun i -> base + gets code (base + i)) in
16951715 let bt = Array. init bsize ~f: (fun i -> base + gets code (base + isize + i)) in
16961716 Array. iter it ~f: (fun pc' ->
1697- compile_block infos.blocks infos.debug code pc' state);
1717+ compile_block infos.blocks infos.joins infos. debug code pc' state);
16981718 Array. iter bt ~f: (fun pc' ->
1699- compile_block infos.blocks infos.debug code pc' state);
1719+ compile_block infos.blocks infos.joins infos. debug code pc' state);
17001720 match isize, bsize with
17011721 | _ , 0 -> instrs, Switch (x, Array. map it ~f: (fun pc -> pc, [] )), state
17021722 | 0 , _ ->
@@ -1710,24 +1730,32 @@ and compile infos pc state (instrs : instr list) =
17101730 let isblock_branch = pc + 2 in
17111731 let () =
17121732 tagged_blocks := Addr.Map. add isint_branch state ! tagged_blocks;
1713- let i_state = State. start_block isint_branch state in
1714- let i_args = State. stack_vars i_state in
1733+ let i_args = State. stack_vars state in
17151734 compiled_blocks :=
17161735 Addr.Map. add
17171736 isint_branch
1718- (i_state, [] , Switch (x, Array. map it ~f: (fun pc -> pc, i_args)))
1737+ ( None
1738+ , []
1739+ , Switch
1740+ ( x
1741+ , Array. map it ~f: (fun pc ->
1742+ pc, if Addr.Set. mem pc infos.joins then i_args else [] ) ) )
17191743 ! compiled_blocks
17201744 in
17211745 let () =
17221746 tagged_blocks := Addr.Map. add isblock_branch state ! tagged_blocks;
17231747 let x_tag = Var. fresh () in
1724- let b_state = State. start_block isblock_branch state in
1725- let b_args = State. stack_vars b_state in
1748+ let b_args = State. stack_vars state in
17261749 let instrs = [ Let (x_tag, Prim (Extern " %direct_obj_tag" , [ Pv x ])) ] in
17271750 compiled_blocks :=
17281751 Addr.Map. add
17291752 isblock_branch
1730- (b_state, instrs, Switch (x_tag, Array. map bt ~f: (fun pc -> pc, b_args)))
1753+ ( None
1754+ , instrs
1755+ , Switch
1756+ ( x_tag
1757+ , Array. map bt ~f: (fun pc ->
1758+ pc, if Addr.Set. mem pc infos.joins then b_args else [] ) ) )
17311759 ! compiled_blocks
17321760 in
17331761 let isint_var = Var. fresh () in
@@ -1753,16 +1781,12 @@ and compile infos pc state (instrs : instr list) =
17531781 compiled_blocks :=
17541782 Addr.Map. add
17551783 interm_addr
1756- ( handler_ctx_state
1757- , []
1758- , Pushtrap
1759- ( (body_addr, State. stack_vars state)
1760- , x
1761- , (handler_addr, State. stack_vars handler_state) ) )
1784+ (Some handler_ctx_state, [] , Pushtrap ((body_addr, [] ), x, (handler_addr, [] )))
17621785 ! compiled_blocks;
1763- compile_block infos.blocks infos.debug code handler_addr handler_state;
1786+ compile_block infos.blocks infos.joins infos. debug code handler_addr handler_state;
17641787 compile_block
17651788 infos.blocks
1789+ infos.joins
17661790 infos.debug
17671791 code
17681792 body_addr
@@ -1775,11 +1799,12 @@ and compile infos pc state (instrs : instr list) =
17751799 :: State. Dummy " pushtrap(extra_args)"
17761800 :: state.State. stack
17771801 };
1778- instrs, Branch (interm_addr, [] ), state
1802+ instrs, Branch (interm_addr, State. stack_vars state ), state
17791803 | POPTRAP ->
17801804 let addr = pc + 1 in
17811805 compile_block
17821806 infos.blocks
1807+ infos.joins
17831808 infos.debug
17841809 code
17851810 addr
@@ -2482,16 +2507,22 @@ type one =
24822507let parse_bytecode code globals debug_data =
24832508 let state = State. initial globals in
24842509 Code.Var. reset () ;
2485- let blocks' = Blocks. analyse code in
2510+ let blocks', joins = Blocks. analyse code in
24862511 let p =
24872512 if not (Blocks. is_empty blocks')
24882513 then (
24892514 let start = 0 in
2490- compile_block blocks' debug_data code start state;
2515+ compile_block blocks' joins debug_data code start state;
24912516 let blocks =
24922517 Addr.Map. mapi
24932518 (fun _ (state , instr , last ) ->
2494- { params = State. stack_vars state; body = instr; branch = last })
2519+ { params =
2520+ (match state with
2521+ | Some state -> State. stack_vars state
2522+ | None -> [] )
2523+ ; body = instr
2524+ ; branch = last
2525+ })
24952526 ! compiled_blocks
24962527 in
24972528 let free_pc = String. length code / 4 in
0 commit comments