Skip to content

Commit 82d6c3e

Browse files
committed
Several fixes for partial application and currying
- Applications with omitted parameters are now always typed Apply_nontail, and build_apply now correctly propagates this across Omitted params - In multiple-argument functions, only insert a region after the last arg. That is, (fun a b c -> E) with no [@Curry] annotations should have a region around E but never around any intermediate lambdas. This fixes a segfault bug triggered by local functions with very many arguments (exceeding Lambda.max_arity). - Functions without a region (esp. uncurried ones made partial by e.g. mutable patterns) may now nonetheless be marked 'region=true' in Lambda, if they happen to contain no local allocations. (This helps tail call optimisation. See the test partial.ml)
1 parent d05c70c commit 82d6c3e

File tree

8 files changed

+633
-23
lines changed

8 files changed

+633
-23
lines changed

lambda/translcore.ml

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ let transl_apply_position position =
108108
| Nontail -> Rc_normal
109109
| Tail -> Rc_close_at_apply
110110

111-
let maybe_region lam =
111+
let may_allocate_in_region lam =
112112
let rec loop = function
113113
| Lvar _ | Lconst _ -> ()
114114

@@ -140,11 +140,11 @@ let maybe_region lam =
140140
| Levent _ | Lifused _) as lam ->
141141
Lambda.iter_head_constructor loop lam
142142
in
143-
let may_allocate_in_region lam =
144-
match loop lam with
145-
| () -> false
146-
| exception Exit -> true
147-
in
143+
match loop lam with
144+
| () -> false
145+
| exception Exit -> true
146+
147+
let maybe_region lam =
148148
let rec remove_tail_markers = function
149149
| Lapply ({ap_region_close = Rc_close_at_apply} as ap) ->
150150
Lapply ({ap with ap_region_close = Rc_normal})
@@ -893,7 +893,7 @@ and transl_apply ~scopes
893893
?(mode=Alloc_heap)
894894
lam sargs loc
895895
=
896-
let lapply funct args loc pos =
896+
let lapply funct args loc pos mode =
897897
match funct, pos with
898898
| Lsend((Self | Public) as k, lmet, lobj, [], _, _, _), _ ->
899899
Lsend(k, lmet, lobj, args, pos, mode, loc)
@@ -912,7 +912,8 @@ and transl_apply ~scopes
912912
Lsend(k, lmet, lobj, largs @ args, pos, mode, loc)
913913
| Lapply ({ ap_region_close = Rc_normal } as ap), Rc_normal ->
914914
Lapply
915-
{ap with ap_args = ap.ap_args @ args; ap_loc = loc; ap_region_close = pos}
915+
{ap with ap_args = ap.ap_args @ args; ap_loc = loc;
916+
ap_region_close = pos; ap_mode = mode}
916917
| lexp, _ ->
917918
Lapply {
918919
ap_loc=loc;
@@ -926,8 +927,9 @@ and transl_apply ~scopes
926927
ap_probe=None;
927928
}
928929
in
929-
let rec build_apply lam args loc pos = function
930+
let rec build_apply lam args loc pos ap_mode = function
930931
| Omitted { mode_closure; mode_arg; mode_ret } :: l ->
932+
assert (pos = Rc_normal);
931933
let defs = ref [] in
932934
let protect name lam =
933935
match lam with
@@ -938,7 +940,7 @@ and transl_apply ~scopes
938940
Lvar id
939941
in
940942
let lam =
941-
if args = [] then lam else lapply lam (List.rev args) loc pos
943+
if args = [] then lam else lapply lam (List.rev args) loc pos ap_mode
942944
in
943945
let handle = protect "func" lam in
944946
let l =
@@ -952,10 +954,10 @@ and transl_apply ~scopes
952954
let id_arg = Ident.create_local "param" in
953955
let body =
954956
let loc = map_scopes enter_partial_or_eta_wrapper loc in
955-
let body = build_apply handle [Lvar id_arg] loc Rc_normal l in
956957
let mode = transl_alloc_mode mode_closure in
957958
let arg_mode = transl_alloc_mode mode_arg in
958959
let ret_mode = transl_alloc_mode mode_ret in
960+
let body = build_apply handle [Lvar id_arg] loc Rc_normal ret_mode l in
959961
let nlocal =
960962
match join_mode mode (join_mode arg_mode ret_mode) with
961963
| Alloc_local -> 1
@@ -973,8 +975,8 @@ and transl_apply ~scopes
973975
List.fold_right
974976
(fun (id, lam) body -> Llet(Strict, Pgenval, id, lam, body))
975977
!defs body
976-
| Arg arg :: l -> build_apply lam (arg :: args) loc pos l
977-
| [] -> lapply lam (List.rev args) loc pos
978+
| Arg arg :: l -> build_apply lam (arg :: args) loc pos ap_mode l
979+
| [] -> lapply lam (List.rev args) loc pos ap_mode
978980
in
979981
let args =
980982
List.map
@@ -984,7 +986,7 @@ and transl_apply ~scopes
984986
| Arg exp -> Arg (transl_exp ~scopes exp))
985987
sargs
986988
in
987-
build_apply lam [] loc position args
989+
build_apply lam [] loc position mode args
988990

989991
and transl_curried_function
990992
~scopes loc return
@@ -1113,15 +1115,18 @@ and transl_function0
11131115
(value_kind pat.pat_env pat.pat_type))
11141116
(value_kind pat.pat_env pat.pat_type) other_cases
11151117
in
1118+
let body =
1119+
Matching.for_function ~scopes loc repr (Lvar param)
1120+
(transl_cases ~scopes cases) partial
1121+
in
1122+
let region = region || not (may_allocate_in_region body) in
11161123
let nlocal =
11171124
if not region then 1
11181125
else match join_mode mode arg_mode with
11191126
| Alloc_local -> 1
11201127
| Alloc_heap -> 0
11211128
in
1122-
((Curried {nlocal}, [param, kind], return, region),
1123-
Matching.for_function ~scopes loc repr (Lvar param)
1124-
(transl_cases ~scopes cases) partial)
1129+
((Curried {nlocal}, [param, kind], return, region), body)
11251130

11261131
and transl_function ~scopes e param cases partial region =
11271132
let mode = transl_value_mode e.exp_mode in

0 commit comments

Comments
 (0)