Skip to content

Commit 16efe1b

Browse files
committed
Compiler: faster queue access
1 parent 713bfba commit 16efe1b

File tree

1 file changed

+53
-35
lines changed

1 file changed

+53
-35
lines changed

compiler/lib/generate.ml

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -535,14 +535,25 @@ type queue_elt =
535535
; deps : Code.Var.Set.t
536536
}
537537

538-
let access_queue queue x =
539-
try
540-
let elt = List.assoc x queue in
541-
((elt.prop, elt.deps), elt.ce, elt.loc), List.remove_assoc x queue
542-
with Not_found -> ((fst const_p, Code.Var.Set.singleton x), var x, None), queue
538+
let access_queue ~live queue x =
539+
let idx = Var.idx x in
540+
if idx < Array.length live && Array.unsafe_get live idx = 1
541+
then
542+
match
543+
List.find_map queue ~f:(fun (x', elt) ->
544+
if Code.Var.equal x x' then Some elt else None)
545+
with
546+
| Some elt ->
547+
let[@tail_mod_cons] rec clean x = function
548+
| [] -> []
549+
| ((v, _) as hd) :: rem -> if Code.Var.equal v x then rem else hd :: clean x rem
550+
in
551+
((elt.prop, elt.deps), elt.ce, elt.loc), clean x queue
552+
| None -> ((fst const_p, Code.Var.Set.singleton x), var x, None), queue
553+
else ((fst const_p, Code.Var.Set.singleton x), var x, None), queue
543554

544-
let access_queue_loc queue loc' x =
545-
let (prop, c, loc), queue = access_queue queue x in
555+
let access_queue_loc ~ctx queue loc' x =
556+
let (prop, c, loc), queue = access_queue ~live:ctx.Ctx.live queue x in
546557
(prop, c, Option.value ~default:loc' loc), queue
547558

548559
let should_flush (cond, _) prop = cond <> fst const_p && cond + prop >= fst flush_p
@@ -585,7 +596,7 @@ module Expr_builder : sig
585596

586597
val return : 'a -> 'a t
587598

588-
val access : Var.t -> J.expression t
599+
val access : ctx:Ctx.t -> Var.t -> J.expression t
589600

590601
val access' : ctx:Ctx.t -> prim_arg -> J.expression t
591602

@@ -627,8 +638,8 @@ end = struct
627638
let info ?(need_loc = false) prop st =
628639
(), { st with prop = or_p st.prop prop; need_loc = need_loc || st.need_loc }
629640

630-
let access x st =
631-
let (prop, c, loc), queue = access_queue st.queue x in
641+
let access ~ctx x st =
642+
let (prop, c, loc), queue = access_queue ~live:ctx.Ctx.live st.queue x in
632643
( c
633644
, { st with
634645
prop = or_p st.prop prop
@@ -646,7 +657,7 @@ end = struct
646657
assert (List.is_empty instrs);
647658
(* We only have simple constants here *)
648659
fun st -> js, st
649-
| Pv x -> access x
660+
| Pv x -> access ~ctx x
650661

651662
let statement_loc loc st =
652663
( (match st.loc with
@@ -859,7 +870,7 @@ let visit_all params args =
859870
in
860871
l
861872

862-
let parallel_renaming loc back_edge params args continuation queue =
873+
let parallel_renaming ctx loc back_edge params args continuation queue =
863874
if
864875
back_edge && Config.Flag.es6 ()
865876
(* This is likely slower than using explicit temp variable
@@ -877,7 +888,7 @@ let parallel_renaming loc back_edge params args continuation queue =
877888
loc
878889
(List.fold_left args ~init:(return []) ~f:(fun acc a ->
879890
let* acc = acc in
880-
let* cx = access a in
891+
let* cx = access ~ctx a in
881892
return (cx :: acc)))
882893
in
883894
let never, code = continuation queue in
@@ -900,7 +911,7 @@ let parallel_renaming loc back_edge params args continuation queue =
900911
l
901912
~init:(queue, [], [], Code.Var.Set.empty)
902913
~f:(fun (queue, before, renaming, seen) (y, x) ->
903-
let ((_, deps_x), cx, locx), queue = access_queue_loc queue loc x in
914+
let ((_, deps_x), cx, locx), queue = access_queue_loc ~ctx queue loc x in
904915
let seen' = Code.Var.Set.add y seen in
905916
if not Code.Var.Set.(is_empty (inter seen deps_x))
906917
then
@@ -1326,14 +1337,14 @@ let rec translate_expr ctx loc x e level : (_ * J.statement_list) Expr_builder.t
13261337
let args = remove_unused_tail_args ctx exact trampolined args in
13271338
let* () = info ~need_loc:true mutator_p in
13281339
let in_cps = Var.Set.mem x ctx.Ctx.in_cps in
1329-
let* args = list_map access args in
1330-
let* f = access f in
1340+
let* args = list_map (access ~ctx) args in
1341+
let* f = access ~ctx f in
13311342
return (apply_fun ctx f args exact trampolined in_cps loc, [])
13321343
| Block (tag, a, array_or_not, _mut) ->
13331344
let* contents =
13341345
list_map
13351346
(fun x ->
1336-
let* cx = access x in
1347+
let* cx = access ~ctx x in
13371348
let cx =
13381349
match cx with
13391350
| J.EVar (J.V v) ->
@@ -1352,7 +1363,7 @@ let rec translate_expr ctx loc x e level : (_ * J.statement_list) Expr_builder.t
13521363
in
13531364
return (x, [])
13541365
| Field (x, n, _) ->
1355-
let* cx = access x in
1366+
let* cx = access ~ctx x in
13561367
let* () = info mutable_p in
13571368
return (Mlvalue.Block.field cx n, [])
13581369
| Closure (args, ((pc, _) as cont), cloc) ->
@@ -1450,18 +1461,18 @@ let rec translate_expr ctx loc x e level : (_ * J.statement_list) Expr_builder.t
14501461
in
14511462
return (J.ENew (cc, (if List.is_empty args then None else Some args), loc))
14521463
| Extern "caml_js_get", [ Pv o; Pc (NativeString (Utf f)) ] when J.is_ident' f ->
1453-
let* co = access o in
1464+
let* co = access ~ctx o in
14541465
let* () = info mutable_p in
14551466
return (J.dot co f)
14561467
| Extern "caml_js_set", [ Pv o; Pc (NativeString (Utf f)); v ] when J.is_ident' f
14571468
->
1458-
let* co = access o in
1469+
let* co = access ~ctx o in
14591470
let* cv = access' ~ctx v in
14601471
let* () = info mutator_p in
14611472
return (J.EBin (J.Eq, J.dot co f, cv))
14621473
| Extern "caml_js_delete", [ Pv o; Pc (NativeString (Utf f)) ] when J.is_ident' f
14631474
->
1464-
let* co = access o in
1475+
let* co = access ~ctx o in
14651476
let* () = info mutator_p in
14661477
return (J.EUn (J.Delete, J.dot co f))
14671478
(*
@@ -1584,7 +1595,7 @@ and translate_instr ctx expr_queue loc instr =
15841595
flush_queue
15851596
expr_queue
15861597
loc
1587-
(let* cy = access y in
1598+
(let* cy = access ~ctx y in
15881599
let* () = info mutator_p in
15891600
let* loc = statement_loc loc in
15901601
return [ J.Expression_statement (J.EBin (J.Eq, J.EVar (J.V x), cy)), loc ])
@@ -1625,8 +1636,8 @@ and translate_instr ctx expr_queue loc instr =
16251636
flush_queue
16261637
expr_queue
16271638
loc
1628-
(let* cx = access x in
1629-
let* cy = access y in
1639+
(let* cx = access ~ctx x in
1640+
let* cy = access ~ctx y in
16301641
let* () = info mutator_p in
16311642
let* loc = statement_loc loc in
16321643
return
@@ -1636,7 +1647,7 @@ and translate_instr ctx expr_queue loc instr =
16361647
flush_queue
16371648
expr_queue
16381649
loc
1639-
(let* cx = access x in
1650+
(let* cx = access ~ctx x in
16401651
let expr = Mlvalue.Block.field cx 0 in
16411652
let expr' =
16421653
match n with
@@ -1652,9 +1663,9 @@ and translate_instr ctx expr_queue loc instr =
16521663
flush_queue
16531664
expr_queue
16541665
loc
1655-
(let* cx = access x in
1656-
let* cy = access y in
1657-
let* cz = access z in
1666+
(let* cx = access ~ctx x in
1667+
let* cy = access ~ctx y in
1668+
let* cz = access ~ctx z in
16581669
let* () = info mutator_p in
16591670
let* loc = statement_loc loc in
16601671
return
@@ -1718,7 +1729,7 @@ and translate_instrs_rev (ctx : Ctx.t) loc expr_queue instrs acc_rev muts_map =
17181729
Code.Var.Set.fold
17191730
(fun v (expr_queue, vars, lets) ->
17201731
assert (not (Code.Var.Set.mem v names));
1721-
let (px, cx, locx), expr_queue = access_queue_loc expr_queue loc v in
1732+
let (px, cx, locx), expr_queue = access_queue_loc ~ctx expr_queue loc v in
17221733
let flushed = Code.Var.Set.(equal (snd px) (singleton v)) in
17231734
match
17241735
( flushed
@@ -1760,7 +1771,9 @@ and translate_instrs_rev (ctx : Ctx.t) loc expr_queue instrs acc_rev muts_map =
17601771
match l with
17611772
| [ i ] -> mut_rec, i :: st_rev, expr_queue
17621773
| [] ->
1763-
let (_px, cx, locx), expr_queue = access_queue_loc expr_queue loc x' in
1774+
let (_px, cx, locx), expr_queue =
1775+
access_queue_loc ~ctx expr_queue loc x'
1776+
in
17641777
( mut_rec
17651778
, (J.variable_declaration [ J.V x', (cx, locx) ], locx) :: st_rev
17661779
, expr_queue )
@@ -1982,12 +1995,13 @@ and compile_conditional st queue ~fall_through loc last scope_stack : _ * _ =
19821995
| Stop -> Format.eprintf "stop;@;"
19831996
| Cond (x, _, _) -> Format.eprintf "@[<hv 2>cond(%a){@;" Code.Var.print x
19841997
| Switch (x, _) -> Format.eprintf "@[<hv 2>switch(%a){@;" Code.Var.print x);
1998+
let ctx = st.ctx in
19851999
let res =
19862000
match last with
19872001
| Return x ->
19882002
let open Expr_builder in
19892003
let instrs =
1990-
let* cx = access x in
2004+
let* cx = access ~ctx x in
19912005
let return_expr =
19922006
if Var.equal st.ctx.deadcode_sentinal x then None else Some cx
19932007
in
@@ -2008,7 +2022,7 @@ and compile_conditional st queue ~fall_through loc last scope_stack : _ * _ =
20082022
| Raise (x, k) ->
20092023
let open Expr_builder in
20102024
let instrs =
2011-
let* cx = access x in
2025+
let* cx = access ~ctx x in
20122026
let* loc = statement_loc loc in
20132027
return (throw_statement st.ctx cx k loc)
20142028
in
@@ -2063,7 +2077,9 @@ and compile_conditional st queue ~fall_through loc last scope_stack : _ * _ =
20632077
let never, code = compile_branch st J.N [] cont scope_stack ~fall_through in
20642078
never, flush_all queue loc code
20652079
| Cond (x, c1, c2) ->
2066-
let cx, loc_before, queue = Expr_builder.get queue loc (Expr_builder.access x) in
2080+
let cx, loc_before, queue =
2081+
Expr_builder.get queue loc (Expr_builder.access ~ctx x)
2082+
in
20672083
(* We keep track of the location [loc_before] before the
20682084
expression is evaluated and of the location after [loc]. *)
20692085
let never, b =
@@ -2079,7 +2095,9 @@ and compile_conditional st queue ~fall_through loc last scope_stack : _ * _ =
20792095
in
20802096
never, flush_all queue loc_before b
20812097
| Switch (x, a1) ->
2082-
let cx, loc_before, queue = Expr_builder.get queue loc (Expr_builder.access x) in
2098+
let cx, loc_before, queue =
2099+
Expr_builder.get queue loc (Expr_builder.access ~ctx x)
2100+
in
20832101
(* We keep track of the location [loc_before] before the
20842102
expression is evaluated and of the location after [loc]. *)
20852103
let never, code =
@@ -2107,7 +2125,7 @@ and compile_argument_passing ctx loc queue (pc, args) back_edge continuation =
21072125
then continuation queue
21082126
else
21092127
let block = Addr.Map.find pc ctx.Ctx.blocks in
2110-
parallel_renaming loc back_edge block.params args continuation queue
2128+
parallel_renaming ctx loc back_edge block.params args continuation queue
21112129

21122130
and compile_branch st loc queue ((pc, _) as cont) scope_stack ~fall_through : bool * _ =
21132131
let scope = List.assoc_opt pc scope_stack in

0 commit comments

Comments
 (0)