@@ -470,31 +470,44 @@ let emit_call_safety_errors () =
470
470
type stack_realloc = {
471
471
sc_label : Label.t; (* Label of the reallocation code. *)
472
472
sc_return : Label.t; (* Label to return to after reallocation. *)
473
- sc_max_frame_size_in_bytes : int; (* Size for reallocation. *)
473
+ sc_size_in_bytes : int; (* Size for reallocation. *)
474
474
}
475
475
476
- let stack_realloc = ref (None : stack_realloc option )
476
+ let stack_realloc = ref ([] : stack_realloc list )
477
477
478
478
let clear_stack_realloc () =
479
- stack_realloc := None
479
+ stack_realloc := []
480
480
481
481
let emit_stack_realloc () =
482
- begin match !stack_realloc with
483
- | None -> ()
484
- | Some { sc_label; sc_return; sc_max_frame_size_in_bytes; } -> begin
485
- def_label sc_label;
486
- (* Pass the desired frame size on the stack, since all of the
487
- argument-passing registers may be in use.
488
- Also serves to align the stack properly before the call *)
489
- I.push (int (Config.stack_threshold + sc_max_frame_size_in_bytes / 8));
490
- cfi_adjust_cfa_offset 8;
491
- (* measured in words *)
492
- emit_call (Cmm.global_symbol "caml_call_realloc_stack");
493
- I.add (int 8) rsp;
494
- cfi_adjust_cfa_offset (-8);
495
- I.jmp (label sc_return)
496
- end
497
- end
482
+ List.iter
483
+ (fun { sc_label; sc_return; sc_size_in_bytes; } ->
484
+ def_label sc_label;
485
+ (* Pass the desired frame size on the stack, since all of the
486
+ argument-passing registers may be in use.
487
+ Also serves to align the stack properly before the call *)
488
+ I.push (int (Config.stack_threshold + sc_size_in_bytes / 8));
489
+ cfi_adjust_cfa_offset 8;
490
+ (* measured in words *)
491
+ emit_call (Cmm.global_symbol "caml_call_realloc_stack");
492
+ I.add (int 8) rsp;
493
+ cfi_adjust_cfa_offset (-8);
494
+ I.jmp (label sc_return))
495
+ !stack_realloc
496
+
497
+ let emit_stack_check ~size_in_bytes ~save_registers =
498
+ let overflow = new_label () and ret = new_label () in
499
+ let threshold_offset = Domainstate.stack_ctx_words * 8 + Stack_check.stack_threshold_size in
500
+ if save_registers then I.push r10;
501
+ I.lea (mem64 NONE (-(size_in_bytes + threshold_offset)) RSP) r10;
502
+ I.cmp (domain_field Domainstate.Domain_current_stack) r10;
503
+ if save_registers then I.pop r10;
504
+ I.jb (label overflow);
505
+ def_label ret;
506
+ stack_realloc := {
507
+ sc_label = overflow;
508
+ sc_return = ret;
509
+ sc_size_in_bytes = size_in_bytes;
510
+ } :: !stack_realloc
498
511
499
512
(* Record jump tables *)
500
513
type jump_table =
@@ -1828,20 +1841,7 @@ let emit_instr ~first ~fallthrough i =
1828
1841
I.jmp r11
1829
1842
end
1830
1843
| Lstackcheck { max_frame_size_bytes; } ->
1831
- let save_registers = not first in
1832
- let overflow = new_label () and ret = new_label () in
1833
- let threshold_offset = Domainstate.stack_ctx_words * 8 + Stack_check.stack_threshold_size in
1834
- if save_registers then I.push r10;
1835
- I.lea (mem64 NONE (-(max_frame_size_bytes + threshold_offset)) RSP) r10;
1836
- I.cmp (domain_field Domainstate.Domain_current_stack) r10;
1837
- if save_registers then I.pop r10;
1838
- I.jb (label overflow);
1839
- def_label ret;
1840
- stack_realloc := Some {
1841
- sc_label = overflow;
1842
- sc_return = ret;
1843
- sc_max_frame_size_in_bytes = max_frame_size_bytes;
1844
- }
1844
+ emit_stack_check ~size_in_bytes:max_frame_size_bytes ~save_registers:(not first)
1845
1845
1846
1846
let rec emit_all ~first ~fallthrough i =
1847
1847
match i.desc with
@@ -2164,6 +2164,8 @@ let emit_probe_handler_wrapper p =
2164
2164
let padding = if ((wrapper_frame_size k) mod 16) = 0 then 0 else 8 in
2165
2165
let n = k + padding in
2166
2166
(* Allocate stack space *)
2167
+ if Config.runtime5 && (not Config.no_stack_checks) && (n >= Stack_check.stack_threshold_size) then
2168
+ emit_stack_check ~size_in_bytes:n ~save_registers:true;
2167
2169
emit_stack_offset n;
2168
2170
(* Save all live hard registers *)
2169
2171
let offset = aux_offset + tmp_offset + loc_offset in
0 commit comments