Skip to content

Commit 285902b

Browse files
Compiler: Effects: keep track of CPS calls (#1648)
Co-authored-by: Jérôme Vouillon <[email protected]>
1 parent c484610 commit 285902b

File tree

5 files changed

+66
-44
lines changed

5 files changed

+66
-44
lines changed

compiler/lib/driver.ml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ let phi p =
8787

8888
let ( +> ) f g x = g (f x)
8989

90-
let map_fst f (x, y) = f x, y
90+
let map_fst f (x, y, z) = f x, y, z
9191

9292
let effects ~deadcode_sentinal p =
9393
if Config.Flag.effects ()
@@ -104,9 +104,11 @@ let effects ~deadcode_sentinal p =
104104
Deadcode.f p
105105
else p, live_vars
106106
in
107-
let p, cps = p |> Effects.f ~flow_info:info ~live_vars +> map_fst Lambda_lifting.f in
108-
p, cps)
109-
else p, (Code.Var.Set.empty : Effects.cps_calls)
107+
p |> Effects.f ~flow_info:info ~live_vars +> map_fst Lambda_lifting.f)
108+
else
109+
( p
110+
, (Code.Var.Set.empty : Effects.trampolined_calls)
111+
, (Code.Var.Set.empty : Effects.in_cps) )
110112

111113
let exact_calls profile ~deadcode_sentinal p =
112114
if not (Config.Flag.effects ())
@@ -193,14 +195,14 @@ let generate
193195
~wrap_with_fun
194196
~warn_on_unhandled_effect
195197
~deadcode_sentinal
196-
((p, live_vars), cps_calls) =
198+
((p, live_vars), trampolined_calls, _) =
197199
if times () then Format.eprintf "Start Generation...@.";
198200
let should_export = should_export wrap_with_fun in
199201
Generate.f
200202
p
201203
~exported_runtime
202204
~live_vars
203-
~cps_calls
205+
~trampolined_calls
204206
~should_export
205207
~warn_on_unhandled_effect
206208
~deadcode_sentinal

compiler/lib/effects.ml

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,9 @@ let jump_closures blocks_to_transform idom : jump_closures =
247247
idom
248248
{ closure_of_jump = Addr.Map.empty; closures_of_alloc_site = Addr.Map.empty }
249249

250-
type cps_calls = Var.Set.t
250+
type trampolined_calls = Var.Set.t
251+
252+
type in_cps = Var.Set.t
251253

252254
type st =
253255
{ mutable new_blocks : Code.block Addr.Map.t * Code.Addr.t
@@ -263,7 +265,8 @@ type st =
263265
; block_order : (Addr.t, int) Hashtbl.t
264266
; live_vars : Deadcode.variable_uses
265267
; flow_info : Global_flow.info
266-
; cps_calls : cps_calls ref
268+
; trampolined_calls : trampolined_calls ref
269+
; in_cps : in_cps ref
267270
}
268271

269272
let add_block st block =
@@ -280,10 +283,11 @@ let allocate_closure ~st ~params ~body ~branch loc =
280283
let name = Var.fresh () in
281284
[ Let (name, Closure (params, (pc, []))), loc ], name
282285

283-
let tail_call ~st ?(instrs = []) ~exact ~check ~f args loc =
286+
let tail_call ~st ?(instrs = []) ~exact ~in_cps ~check ~f args loc =
284287
assert (exact || check);
285288
let ret = Var.fresh () in
286-
if check then st.cps_calls := Var.Set.add ret !(st.cps_calls);
289+
if check then st.trampolined_calls := Var.Set.add ret !(st.trampolined_calls);
290+
if in_cps then st.in_cps := Var.Set.add ret !(st.in_cps);
287291
instrs @ [ Let (ret, Apply { f; args; exact }), loc ], (Return ret, loc)
288292

289293
let cps_branch ~st ~src (pc, args) loc =
@@ -302,7 +306,15 @@ let cps_branch ~st ~src (pc, args) loc =
302306
(* We check the stack depth only for backward edges (so, at
303307
least once per loop iteration) *)
304308
let check = Hashtbl.find st.block_order src >= Hashtbl.find st.block_order pc in
305-
tail_call ~st ~instrs ~exact:true ~check ~f:(closure_of_pc ~st pc) args loc
309+
tail_call
310+
~st
311+
~instrs
312+
~exact:true
313+
~in_cps:false
314+
~check
315+
~f:(closure_of_pc ~st pc)
316+
args
317+
loc
306318

307319
let cps_jump_cont ~st ~src ((pc, _) as cont) loc =
308320
match Addr.Set.mem pc st.blocks_to_transform with
@@ -365,7 +377,7 @@ let cps_last ~st ~alloc_jump_closures pc ((last, last_loc) : last * loc) ~k :
365377
(* Is the number of successive 'returns' is unbounded is CPS, it
366378
means that we have an unbounded of calls in direct style
367379
(even with tail call optimization) *)
368-
tail_call ~st ~exact:true ~check:false ~f:k [ x ] last_loc
380+
tail_call ~st ~exact:true ~in_cps:false ~check:false ~f:k [ x ] last_loc
369381
| Raise (x, rmode) -> (
370382
assert (List.is_empty alloc_jump_closures);
371383
match Hashtbl.find_opt st.matching_exn_handler pc with
@@ -401,6 +413,7 @@ let cps_last ~st ~alloc_jump_closures pc ((last, last_loc) : last * loc) ~k :
401413
~instrs:
402414
((Let (exn_handler, Prim (Extern "caml_pop_trap", [])), noloc) :: instrs)
403415
~exact:true
416+
~in_cps:false
404417
~check:false
405418
~f:exn_handler
406419
[ x ]
@@ -463,6 +476,7 @@ let cps_instr ~st (instr : instr) : instr =
463476
(* Add the continuation parameter, and change the initial block if
464477
needed *)
465478
let k, cont = Hashtbl.find st.closure_info pc in
479+
st.in_cps := Var.Set.add x !(st.in_cps);
466480
Let (x, Closure (params @ [ k ], cont))
467481
| Let (x, Prim (Extern "caml_alloc_dummy_function", [ size; arity ])) -> (
468482
match arity with
@@ -532,7 +546,7 @@ let cps_block ~st ~k pc block =
532546
let exact =
533547
exact || Global_flow.exact_call st.flow_info f (List.length args)
534548
in
535-
tail_call ~st ~exact ~check:true ~f (args @ [ k ]) loc)
549+
tail_call ~st ~exact ~in_cps:true ~check:true ~f (args @ [ k ]) loc)
536550
| Prim (Extern "%resume", [ Pv stack; Pv f; Pv arg ]) ->
537551
Some
538552
(fun ~k ->
@@ -542,6 +556,7 @@ let cps_block ~st ~k pc block =
542556
~instrs:
543557
[ Let (k', Prim (Extern "caml_resume_stack", [ Pv stack; Pv k ])), noloc ]
544558
~exact:(Global_flow.exact_call st.flow_info f 1)
559+
~in_cps:true
545560
~check:true
546561
~f
547562
[ arg; k' ]
@@ -599,7 +614,8 @@ let cps_block ~st ~k pc block =
599614

600615
let cps_transform ~live_vars ~flow_info ~cps_needed p =
601616
let closure_info = Hashtbl.create 16 in
602-
let cps_calls = ref Var.Set.empty in
617+
let trampolined_calls = ref Var.Set.empty in
618+
let in_cps = ref Var.Set.empty in
603619
let p =
604620
Code.fold_closures_innermost_first
605621
p
@@ -658,7 +674,8 @@ let cps_transform ~live_vars ~flow_info ~cps_needed p =
658674
; block_order = cfg.block_order
659675
; flow_info
660676
; live_vars
661-
; cps_calls
677+
; trampolined_calls
678+
; in_cps
662679
}
663680
in
664681
let function_needs_cps =
@@ -735,7 +752,7 @@ let cps_transform ~live_vars ~flow_info ~cps_needed p =
735752
in
736753
{ start = new_start; blocks; free_pc = new_start + 1 }
737754
in
738-
p, !cps_calls
755+
p, !trampolined_calls, !in_cps
739756

740757
(****)
741758

@@ -927,7 +944,7 @@ let f ~flow_info ~live_vars p =
927944
let cps_needed = Partial_cps_analysis.f p flow_info in
928945
let p, cps_needed = rewrite_toplevel ~cps_needed p in
929946
let p = split_blocks ~cps_needed p in
930-
let p, cps_calls = cps_transform ~live_vars ~flow_info ~cps_needed p in
947+
let p, trampolined_calls, in_cps = cps_transform ~live_vars ~flow_info ~cps_needed p in
931948
if Debug.find "times" () then Format.eprintf " effects: %a@." Timer.print t;
932949
Code.invariant p;
933-
p, cps_calls
950+
p, trampolined_calls, in_cps

compiler/lib/effects.mli

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@
1616
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1717
*)
1818

19-
type cps_calls = Code.Var.Set.t
19+
type trampolined_calls = Code.Var.Set.t
2020

2121
val remove_empty_blocks : live_vars:Deadcode.variable_uses -> Code.program -> Code.program
2222

23+
type in_cps = Code.Var.Set.t
24+
2325
val f :
2426
flow_info:Global_flow.info
2527
-> live_vars:Deadcode.variable_uses
2628
-> Code.program
27-
-> Code.program * cps_calls
29+
-> Code.program * trampolined_calls * in_cps

compiler/lib/generate.ml

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ type fall_through =
5555
type application_description =
5656
{ arity : int
5757
; exact : bool
58-
; cps : bool
58+
; trampolined : bool
5959
}
6060

6161
module Share = struct
@@ -133,7 +133,7 @@ module Share = struct
133133
| _ -> t)
134134

135135
let get
136-
~cps_calls
136+
~trampolined_calls
137137
?alias_strings
138138
?(alias_prims = false)
139139
?(alias_apply = true)
@@ -150,9 +150,9 @@ module Share = struct
150150
match i with
151151
| Let (_, Constant c) -> get_constant c share
152152
| Let (x, Apply { args; exact; _ }) ->
153-
let cps = Var.Set.mem x cps_calls in
154-
if (not exact) || cps
155-
then add_apply { arity = List.length args; exact; cps } share
153+
let trampolined = Var.Set.mem x trampolined_calls in
154+
if (not exact) || trampolined
155+
then add_apply { arity = List.length args; exact; trampolined } share
156156
else share
157157
| Let (_, Special (Alias_prim name)) ->
158158
let name = Primitive.resolve name in
@@ -244,11 +244,11 @@ module Share = struct
244244
try J.EVar (AppMap.find desc t.vars.applies)
245245
with Not_found ->
246246
let x =
247-
let { arity; exact; cps } = desc in
247+
let { arity; exact; trampolined } = desc in
248248
Var.fresh_n
249249
(Printf.sprintf
250250
"caml_%scall%d"
251-
(match exact, cps with
251+
(match exact, trampolined with
252252
| true, false -> assert false
253253
| true, true -> "cps_exact_"
254254
| false, false -> ""
@@ -269,7 +269,7 @@ module Ctx = struct
269269
; exported_runtime : (Code.Var.t * bool ref) option
270270
; should_export : bool
271271
; effect_warning : bool ref
272-
; cps_calls : Effects.cps_calls
272+
; trampolined_calls : Effects.trampolined_calls
273273
; deadcode_sentinal : Var.t
274274
; mutated_vars : Code.Var.Set.t Code.Addr.Map.t
275275
; freevars : Code.Var.Set.t Code.Addr.Map.t
@@ -284,7 +284,7 @@ module Ctx = struct
284284
~freevars
285285
blocks
286286
live
287-
cps_calls
287+
trampolined_calls
288288
share
289289
debug =
290290
{ blocks
@@ -294,7 +294,7 @@ module Ctx = struct
294294
; exported_runtime
295295
; should_export
296296
; effect_warning = ref (not warn_on_unhandled_effect)
297-
; cps_calls
297+
; trampolined_calls
298298
; deadcode_sentinal
299299
; mutated_vars
300300
; freevars
@@ -773,7 +773,7 @@ let parallel_renaming back_edge params args continuation queue =
773773

774774
(****)
775775

776-
let apply_fun_raw ctx f params exact cps =
776+
let apply_fun_raw ctx f params exact trampolined =
777777
let n = List.length params in
778778
let apply_directly =
779779
(* Make sure we are performing a regular call, not a (slower)
@@ -801,7 +801,7 @@ let apply_fun_raw ctx f params exact cps =
801801
, apply_directly
802802
, J.call (runtime_fun ctx "caml_call_gen") [ f; J.array params ] J.N )
803803
in
804-
if cps
804+
if trampolined
805805
then (
806806
assert (Config.Flag.effects ());
807807
(* When supporting effect, we systematically perform tailcall
@@ -814,7 +814,7 @@ let apply_fun_raw ctx f params exact cps =
814814
, J.call (runtime_fun ctx "caml_trampoline_return") [ f; J.array params ] J.N ))
815815
else apply
816816

817-
let generate_apply_fun ctx { arity; exact; cps } =
817+
let generate_apply_fun ctx { arity; exact; trampolined } =
818818
let f' = Var.fresh_n "f" in
819819
let f = J.V f' in
820820
let params =
@@ -829,23 +829,24 @@ let generate_apply_fun ctx { arity; exact; cps } =
829829
( None
830830
, J.fun_
831831
(f :: params)
832-
[ J.Return_statement (Some (apply_fun_raw ctx f' params' exact cps)), J.N ]
832+
[ J.Return_statement (Some (apply_fun_raw ctx f' params' exact trampolined)), J.N
833+
]
833834
J.N )
834835

835-
let apply_fun ctx f params exact cps loc =
836+
let apply_fun ctx f params exact trampolined loc =
836837
(* We always go through an intermediate function when doing CPS
837838
calls. This function first checks the stack depth to prevent
838839
a stack overflow. This makes the code smaller than inlining
839840
the test, and we expect the performance impact to be low
840841
since the function should get inlined by the JavaScript
841842
engines. *)
842-
if Config.Flag.inline_callgen () || (exact && not cps)
843-
then apply_fun_raw ctx f params exact cps
843+
if Config.Flag.inline_callgen () || (exact && not trampolined)
844+
then apply_fun_raw ctx f params exact trampolined
844845
else
845846
let y =
846847
Share.get_apply
847848
(generate_apply_fun ctx)
848-
{ arity = List.length params; exact; cps }
849+
{ arity = List.length params; exact; trampolined }
849850
ctx.Ctx.share
850851
in
851852
J.call y (f :: params) loc
@@ -1028,7 +1029,7 @@ let throw_statement ctx cx k loc =
10281029
let rec translate_expr ctx queue loc x e level : _ * J.statement_list =
10291030
match e with
10301031
| Apply { f; args; exact } ->
1031-
let cps = Var.Set.mem x ctx.Ctx.cps_calls in
1032+
let trampolined = Var.Set.mem x ctx.Ctx.trampolined_calls in
10321033
let args, prop, queue =
10331034
List.fold_right
10341035
~f:(fun x (args, prop, queue) ->
@@ -1039,7 +1040,7 @@ let rec translate_expr ctx queue loc x e level : _ * J.statement_list =
10391040
in
10401041
let (prop', f), queue = access_queue queue f in
10411042
let prop = or_p prop prop' in
1042-
let e = apply_fun ctx f args exact cps loc in
1043+
let e = apply_fun ctx f args exact trampolined loc in
10431044
(e, prop, queue), []
10441045
| Block (tag, a, array_or_not, _mut) ->
10451046
let contents, prop, queue =
@@ -1948,13 +1949,13 @@ let f
19481949
(p : Code.program)
19491950
~exported_runtime
19501951
~live_vars
1951-
~cps_calls
1952+
~trampolined_calls
19521953
~should_export
19531954
~warn_on_unhandled_effect
19541955
~deadcode_sentinal
19551956
debug =
19561957
let t' = Timer.make () in
1957-
let share = Share.get ~cps_calls ~alias_prims:exported_runtime p in
1958+
let share = Share.get ~trampolined_calls ~alias_prims:exported_runtime p in
19581959
let exported_runtime =
19591960
if exported_runtime then Some (Code.Var.fresh_n "runtime", ref false) else None
19601961
in
@@ -1970,7 +1971,7 @@ let f
19701971
~freevars
19711972
p.blocks
19721973
live_vars
1973-
cps_calls
1974+
trampolined_calls
19741975
share
19751976
debug
19761977
in

compiler/lib/generate.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ val f :
2222
Code.program
2323
-> exported_runtime:bool
2424
-> live_vars:Deadcode.variable_uses
25-
-> cps_calls:Effects.cps_calls
25+
-> trampolined_calls:Effects.trampolined_calls
2626
-> should_export:bool
2727
-> warn_on_unhandled_effect:bool
2828
-> deadcode_sentinal:Code.Var.t

0 commit comments

Comments
 (0)