Skip to content

Commit d9ae7eb

Browse files
authored
flambda-backend: Fix split_default_wrapper when default value could allocate in region (#2162)
1 parent dfc73c9 commit d9ae7eb

File tree

4 files changed

+56
-46
lines changed

4 files changed

+56
-46
lines changed

lambda/lambda.ml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,3 +1716,51 @@ let is_check_enabled ~opt property =
17161716
| Check_all -> true
17171717
| Check_default -> not opt
17181718
| Check_opt_only -> opt
1719+
1720+
1721+
let may_allocate_in_region lam =
1722+
(* loop_region raises, if the lambda might allocate in parent region *)
1723+
let rec loop_region lam =
1724+
shallow_iter ~tail:(function
1725+
| Lexclave body -> loop body
1726+
| lam -> loop_region lam
1727+
) ~non_tail:(fun lam -> loop_region lam) lam
1728+
and loop = function
1729+
| Lvar _ | Lmutvar _ | Lconst _ -> ()
1730+
1731+
| Lfunction {mode=Alloc_heap} -> ()
1732+
| Lfunction {mode=Alloc_local} -> raise Exit
1733+
1734+
| Lapply {ap_mode=Alloc_local}
1735+
| Lsend (_,_,_,_,_,Alloc_local,_,_) -> raise Exit
1736+
1737+
| Lprim (prim, args, _) ->
1738+
begin match primitive_may_allocate prim with
1739+
| Some Alloc_local -> raise Exit
1740+
| None | Some Alloc_heap ->
1741+
List.iter loop args
1742+
end
1743+
| Lregion (body, _layout) ->
1744+
(* [body] might allocate in the parent region because of exclave, and thus
1745+
[Lregion body] might allocate in the current region *)
1746+
loop_region body
1747+
| Lexclave _body ->
1748+
(* [_body] might do local allocations, but not in the current region;
1749+
rather, it's in the parent region *)
1750+
()
1751+
| Lwhile {wh_cond; wh_body} -> loop wh_cond; loop wh_body
1752+
| Lfor {for_from; for_to; for_body} -> loop for_from; loop for_to; loop for_body
1753+
| ( Lapply _ | Llet _ | Lmutlet _ | Lletrec _ | Lswitch _ | Lstringswitch _
1754+
| Lstaticraise _ | Lstaticcatch _ | Ltrywith _
1755+
| Lifthenelse _ | Lsequence _ | Lassign _ | Lsend _
1756+
| Levent _ | Lifused _) as lam ->
1757+
iter_head_constructor loop lam
1758+
in
1759+
if not Config.stack_allocation then false
1760+
else begin
1761+
match loop lam with
1762+
| () -> false
1763+
| exception Exit -> true
1764+
end
1765+
1766+

lambda/lambda.mli

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,3 +795,6 @@ val array_ref_kind : alloc_mode -> array_kind -> array_ref_kind
795795
(** The mode will be discarded if unnecessary for the given [array_kind] *)
796796
val array_set_kind : modify_mode -> array_kind -> array_set_kind
797797
val is_check_enabled : opt:bool -> property -> bool
798+
799+
(* Returns true if the given lambda can allocate on the local stack *)
800+
val may_allocate_in_region : lambda -> bool

lambda/simplif.ml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,11 @@ let split_default_wrapper ~id:fun_id ~kind ~params ~return ~body
784784
->
785785
let wrapper_body, inner = aux ((optparam, id) :: map) add_region rest in
786786
Llet(Strict, k, id, def, wrapper_body), inner
787-
| Lregion (rest, _) -> aux map true rest
787+
| Lregion (rest, ret) ->
788+
let wrapper_body, inner = aux map true rest in
789+
if may_allocate_in_region wrapper_body then
790+
Lregion (wrapper_body, ret), inner
791+
else wrapper_body, inner
788792
| Lexclave rest -> aux map true rest
789793
| _ when map = [] -> raise Exit
790794
| body ->

lambda/translcore.ml

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -143,51 +143,6 @@ let transl_apply_position position =
143143
if Config.stack_allocation then Rc_close_at_apply
144144
else Rc_normal
145145

146-
let may_allocate_in_region lam =
147-
(* loop_region raises, if the lambda might allocate in parent region *)
148-
let rec loop_region lam =
149-
shallow_iter ~tail:(function
150-
| Lexclave body -> loop body
151-
| lam -> loop_region lam
152-
) ~non_tail:(fun lam -> loop_region lam) lam
153-
and loop = function
154-
| Lvar _ | Lmutvar _ | Lconst _ -> ()
155-
156-
| Lfunction {mode=Alloc_heap} -> ()
157-
| Lfunction {mode=Alloc_local} -> raise Exit
158-
159-
| Lapply {ap_mode=Alloc_local}
160-
| Lsend (_,_,_,_,_,Alloc_local,_,_) -> raise Exit
161-
162-
| Lprim (prim, args, _) ->
163-
begin match Lambda.primitive_may_allocate prim with
164-
| Some Alloc_local -> raise Exit
165-
| None | Some Alloc_heap ->
166-
List.iter loop args
167-
end
168-
| Lregion (body, _layout) ->
169-
(* [body] might allocate in the parent region because of exclave, and thus
170-
[Lregion body] might allocate in the current region *)
171-
loop_region body
172-
| Lexclave _body ->
173-
(* [_body] might do local allocations, but not in the current region;
174-
rather, it's in the parent region *)
175-
()
176-
| Lwhile {wh_cond; wh_body} -> loop wh_cond; loop wh_body
177-
| Lfor {for_from; for_to; for_body} -> loop for_from; loop for_to; loop for_body
178-
| ( Lapply _ | Llet _ | Lmutlet _ | Lletrec _ | Lswitch _ | Lstringswitch _
179-
| Lstaticraise _ | Lstaticcatch _ | Ltrywith _
180-
| Lifthenelse _ | Lsequence _ | Lassign _ | Lsend _
181-
| Levent _ | Lifused _) as lam ->
182-
Lambda.iter_head_constructor loop lam
183-
in
184-
if not Config.stack_allocation then false
185-
else begin
186-
match loop lam with
187-
| () -> false
188-
| exception Exit -> true
189-
end
190-
191146
let maybe_region get_layout lam =
192147
let rec remove_tail_markers_and_exclave = function
193148
| Lapply ({ap_region_close = Rc_close_at_apply} as ap) ->

0 commit comments

Comments
 (0)