Skip to content

Commit 8acdda1

Browse files
authored
Reset the local stack pointer in exception handlers (#56)
1 parent 8dafa98 commit 8acdda1

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

asmcomp/selectgen.ml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -850,14 +850,16 @@ method emit_expr (env:environment) exp =
850850
None
851851
end
852852
| Ctrywith(e1, v, e2, _dbg) ->
853+
let reg = self#regs_for typ_int in
854+
self#insert env (Iop Ibeginregion) [| |] reg;
853855
let (r1, s1) = self#emit_sequence env e1 in
854856
let rv = self#regs_for typ_val in
855857
let (r2, s2) = self#emit_sequence (env_add v rv env) e2 in
856858
let r = join env r1 s1 r2 s2 in
857859
self#insert env
858860
(Itrywith(s1#extract,
859861
instr_cons (Iop Imove) [|Proc.loc_exn_bucket|] rv
860-
(s2#extract)))
862+
(instr_cons (Iop Iendregion) reg [| |] s2#extract)))
861863
[||] [||];
862864
r
863865
| Cregion e when env.region_tail ->
@@ -1197,12 +1199,15 @@ method emit_tail (env:environment) exp =
11971199
self#insert env (Icatch(rec_flag, List.map aux handlers, s_body))
11981200
[||] [||]
11991201
| Ctrywith(e1, v, e2, _dbg) ->
1202+
let reg = self#regs_for typ_int in
1203+
self#insert env (Iop Ibeginregion) [| |] reg;
12001204
let (opt_r1, s1) = self#emit_sequence env e1 in
12011205
let rv = self#regs_for typ_val in
12021206
let s2 = self#emit_tail_sequence (env_add v rv env) e2 in
12031207
self#insert env
12041208
(Itrywith(s1#extract,
1205-
instr_cons (Iop Imove) [|Proc.loc_exn_bucket|] rv s2))
1209+
instr_cons (Iop Imove) [|Proc.loc_exn_bucket|] rv
1210+
(instr_cons (Iop Iendregion) reg [| |] s2)))
12061211
[||] [||];
12071212
begin match opt_r1 with
12081213
None -> ()
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
(* TEST
2+
* native *)
3+
4+
external local_stack_offset : unit -> int = "caml_local_stack_offset"
5+
6+
let leak () =
7+
let r = local_ ref 42 in
8+
let[@inline never] f () = incr r in
9+
f ();
10+
f ();
11+
raise Exit
12+
13+
let count_leak f =
14+
let before = local_stack_offset () in
15+
f ();
16+
let after = local_stack_offset () in
17+
after - before
18+
19+
let glob = ref 0
20+
21+
let tests =
22+
[ "try", (fun () ->
23+
begin try leak () with Exit -> () end;
24+
incr glob);
25+
"tailtry", (fun () ->
26+
try leak () with Exit -> ());
27+
"match", (fun () ->
28+
let g = match leak () with exception Exit -> glob | () -> glob in
29+
incr g);
30+
"tailmatch", (fun () ->
31+
match leak () with exception Exit -> () | () -> ())
32+
]
33+
34+
let () =
35+
Sys.opaque_identity tests |> List.iter (fun (s,f) ->
36+
Printf.printf "%15s: %d\n" s (count_leak f))
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
try: 0
2+
tailtry: 0
3+
match: 0
4+
tailmatch: 0

0 commit comments

Comments
 (0)