Skip to content

Commit d900ffa

Browse files
committed
Generate less block parameters when parsing the bytecode
1 parent 3006efd commit d900ffa

File tree

12 files changed

+2465
-2551
lines changed

12 files changed

+2465
-2551
lines changed

compiler/lib/parse_bytecode.ml

Lines changed: 109 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -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
@@ -342,7 +332,7 @@ end
342332
module 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
415430
end
416431

417432
(* Parse constants *)
@@ -803,6 +818,7 @@ let clo_offset_3 = 3
803818

804819
type 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 =
24822507
let 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

compiler/tests-compiler/double-translation/effects_continuations.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ let%expect_test "test-compiler/lib-effects/test1.ml" =
103103
function exceptions$0(s){
104104
try{var _C_ = caml_int_of_string(s), n = _C_;}
105105
catch(exn$0){
106-
var exn = caml_wrap_exception(exn$0);
107-
if(exn[1] !== Stdlib[7]) throw caml_maybe_attach_backtrace(exn, 0);
106+
var exn = caml_wrap_exception(exn$0), tag = exn[1];
107+
if(tag !== Stdlib[7]) throw caml_maybe_attach_backtrace(exn, 0);
108108
var n = 0;
109109
}
110110
try{
@@ -133,8 +133,8 @@ let%expect_test "test-compiler/lib-effects/test1.ml" =
133133
function exceptions$1(s, cont){
134134
try{var _y_ = caml_int_of_string(s), n = _y_;}
135135
catch(exn){
136-
var exn$2 = caml_wrap_exception(exn);
137-
if(exn$2[1] !== Stdlib[7]){
136+
var exn$2 = caml_wrap_exception(exn), tag = exn$2[1];
137+
if(tag !== Stdlib[7]){
138138
var
139139
raise$1 = caml_pop_trap(),
140140
exn$0 = caml_maybe_attach_backtrace(exn$2, 0);

0 commit comments

Comments
 (0)