@@ -474,31 +474,44 @@ let emit_call_safety_errors () =
474
474
type stack_realloc = {
475
475
sc_label : Label.t; (* Label of the reallocation code. *)
476
476
sc_return : Label.t; (* Label to return to after reallocation. *)
477
- sc_max_frame_size_in_bytes : int; (* Size for reallocation. *)
477
+ sc_size_in_bytes : int; (* Size for reallocation. *)
478
478
}
479
479
480
- let stack_realloc = ref (None : stack_realloc option )
480
+ let stack_realloc = ref ([] : stack_realloc list )
481
481
482
482
let clear_stack_realloc () =
483
- stack_realloc := None
483
+ stack_realloc := []
484
484
485
485
let emit_stack_realloc () =
486
- begin match !stack_realloc with
487
- | None -> ()
488
- | Some { sc_label; sc_return; sc_max_frame_size_in_bytes; } -> begin
489
- def_label sc_label;
490
- (* Pass the desired frame size on the stack, since all of the
491
- argument-passing registers may be in use.
492
- Also serves to align the stack properly before the call *)
493
- I.push (int (Config.stack_threshold + sc_max_frame_size_in_bytes / 8));
494
- cfi_adjust_cfa_offset 8;
495
- (* measured in words *)
496
- emit_call (Cmm.global_symbol "caml_call_realloc_stack");
497
- I.add (int 8) rsp;
498
- cfi_adjust_cfa_offset (-8);
499
- I.jmp (label sc_return)
500
- end
501
- end
486
+ List.iter
487
+ (fun { sc_label; sc_return; sc_size_in_bytes; } ->
488
+ def_label sc_label;
489
+ (* Pass the desired frame size on the stack, since all of the
490
+ argument-passing registers may be in use.
491
+ Also serves to align the stack properly before the call *)
492
+ I.push (int (Config.stack_threshold + sc_size_in_bytes / 8));
493
+ cfi_adjust_cfa_offset 8;
494
+ (* measured in words *)
495
+ emit_call (Cmm.global_symbol "caml_call_realloc_stack");
496
+ I.add (int 8) rsp;
497
+ cfi_adjust_cfa_offset (-8);
498
+ I.jmp (label sc_return))
499
+ !stack_realloc
500
+
501
+ let emit_stack_check ~size_in_bytes ~save_registers =
502
+ let overflow = new_label () and ret = new_label () in
503
+ let threshold_offset = Domainstate.stack_ctx_words * 8 + Stack_check.stack_threshold_size in
504
+ if save_registers then I.push r10;
505
+ I.lea (mem64 NONE (-(size_in_bytes + threshold_offset)) RSP) r10;
506
+ I.cmp (domain_field Domainstate.Domain_current_stack) r10;
507
+ if save_registers then I.pop r10;
508
+ I.jb (label overflow);
509
+ def_label ret;
510
+ stack_realloc := {
511
+ sc_label = overflow;
512
+ sc_return = ret;
513
+ sc_size_in_bytes = size_in_bytes;
514
+ } :: !stack_realloc
502
515
503
516
(* Record jump tables *)
504
517
type jump_table =
@@ -1856,20 +1869,7 @@ let emit_instr ~first ~fallthrough i =
1856
1869
I.jmp r11
1857
1870
end
1858
1871
| Lstackcheck { max_frame_size_bytes; } ->
1859
- let save_registers = not first in
1860
- let overflow = new_label () and ret = new_label () in
1861
- let threshold_offset = Domainstate.stack_ctx_words * 8 + Stack_check.stack_threshold_size in
1862
- if save_registers then I.push r10;
1863
- I.lea (mem64 NONE (-(max_frame_size_bytes + threshold_offset)) RSP) r10;
1864
- I.cmp (domain_field Domainstate.Domain_current_stack) r10;
1865
- if save_registers then I.pop r10;
1866
- I.jb (label overflow);
1867
- def_label ret;
1868
- stack_realloc := Some {
1869
- sc_label = overflow;
1870
- sc_return = ret;
1871
- sc_max_frame_size_in_bytes = max_frame_size_bytes;
1872
- }
1872
+ emit_stack_check ~size_in_bytes:max_frame_size_bytes ~save_registers:(not first)
1873
1873
1874
1874
let rec emit_all ~first ~fallthrough i =
1875
1875
match i.desc with
@@ -1933,7 +1933,7 @@ let fundecl fundecl =
1933
1933
D.label (label_name (emit_symbol fundecl.fun_name));
1934
1934
emit_debug_info fundecl.fun_dbg;
1935
1935
cfi_startproc ();
1936
- if Config.runtime5 && !Clflags.runtime_variant = "d" then begin
1936
+ if Config.runtime5 && (not Config.no_stack_checks) && !Clflags.runtime_variant = "d" then begin
1937
1937
emit_call (Cmm.global_symbol "caml_assert_stack_invariants");
1938
1938
end;
1939
1939
emit_all ~first:true ~fallthrough:true fundecl.fun_body;
@@ -2199,6 +2199,8 @@ let emit_probe_handler_wrapper p =
2199
2199
let padding = if ((wrapper_frame_size k) mod 16) = 0 then 0 else 8 in
2200
2200
let n = k + padding in
2201
2201
(* Allocate stack space *)
2202
+ if Config.runtime5 && (not Config.no_stack_checks) && (n >= Stack_check.stack_threshold_size) then
2203
+ emit_stack_check ~size_in_bytes:n ~save_registers:true;
2202
2204
emit_stack_offset n;
2203
2205
(* Save all live hard registers *)
2204
2206
let offset = aux_offset + tmp_offset + loc_offset in
0 commit comments