@@ -354,6 +354,8 @@ let num_call_gc_and_check_bound_points env =
354354 | Lend -> totals
355355 | Lop (Ialloc _) when env.f.fun_fast ->
356356 loop instr.next (call_gc + 1, check_bound)
357+ | Lop (Ipoll _) ->
358+ loop instr.next (call_gc + 1, check_bound)
357359 | Lop (Iintop Icheckbound)
358360 | Lop (Iintop_imm (Icheckbound, _))
359361 | Lop (Ispecific (Ishiftcheckbound _)) ->
@@ -366,6 +368,7 @@ let num_call_gc_and_check_bound_points env =
366368 (* The following four should never be seen, since this function is run
367369 before branch relaxation. *)
368370 | Lop (Ispecific (Ifar_alloc _))
371+ | Lop (Ispecific (Ifar_poll _))
369372 | Lop (Ispecific Ifar_intop_checkbound)
370373 | Lop (Ispecific (Ifar_intop_imm_checkbound _))
371374 | Lop (Ispecific (Ifar_shiftcheckbound _)) -> assert false
@@ -412,6 +415,7 @@ module BR = Branch_relaxation.Make (struct
412415
413416 let classify_instr = function
414417 | Lop (Ialloc _)
418+ | Lop (Ipoll _)
415419 | Lop (Iintop Icheckbound)
416420 | Lop (Iintop_imm (Icheckbound, _))
417421 | Lop (Ispecific (Ishiftcheckbound _)) -> Some Bcc
@@ -459,6 +463,8 @@ module BR = Branch_relaxation.Make (struct
459463 based + begin match size with Single -> 2 | _ -> 1 end
460464 | Lop (Ialloc _) when f.fun_fast -> 5
461465 | Lop (Ispecific (Ifar_alloc _)) when f.fun_fast -> 6
466+ | Lop (Ipoll _) -> 3
467+ | Lop (Ispecific (Ifar_poll _)) -> 4
462468 | Lop (Ialloc { bytes = num_bytes; _ })
463469 | Lop (Ispecific (Ifar_alloc { bytes = num_bytes; _ })) ->
464470 begin match num_bytes with
@@ -517,6 +523,9 @@ module BR = Branch_relaxation.Make (struct
517523 | Lambda.Raise_notrace -> 4
518524 end
519525
526+ let relax_poll ~return_label =
527+ Lop (Ispecific (Ifar_poll { return_label }))
528+
520529 let relax_allocation ~num_bytes ~dbginfo =
521530 Lop (Ispecific (Ifar_alloc { bytes = num_bytes; dbginfo }))
522531
@@ -574,6 +583,40 @@ let assembly_code_for_allocation env i ~n ~far ~dbginfo =
574583 `{emit_label lbl_frame}: add {emit_reg i.res.(0)}, {emit_reg reg_alloc_ptr}, #8\n`
575584 end
576585
586+ let assembly_code_for_poll env i ~far ~return_label =
587+ let lbl_frame = record_frame_label env i.live (Dbg_alloc []) in
588+ let lbl_call_gc = new_label() in
589+ let lbl_after_poll = match return_label with
590+ | None -> new_label()
591+ | Some lbl -> lbl in
592+ let offset = Domainstate.(idx_of_field Domain_young_limit) * 8 in
593+ ` ldr {emit_reg reg_tmp1}, [{emit_reg reg_domain_state_ptr}, #{emit_int offset}]\n`;
594+ ` cmp {emit_reg reg_alloc_ptr}, {emit_reg reg_tmp1}\n`;
595+ if not far then begin
596+ match return_label with
597+ | None ->
598+ ` b.ls {emit_label lbl_call_gc}\n`;
599+ `{emit_label lbl_after_poll}:\n`
600+ | Some return_label ->
601+ ` b.hi {emit_label return_label}\n`;
602+ ` b {emit_label lbl_call_gc}\n`;
603+ end else begin
604+ match return_label with
605+ | None ->
606+ ` b.hi {emit_label lbl_after_poll}\n`;
607+ ` b {emit_label lbl_call_gc}\n`;
608+ `{emit_label lbl_after_poll}:\n`
609+ | Some return_label ->
610+ let lbl = new_label () in
611+ ` b.ls {emit_label lbl}\n`;
612+ ` b {emit_label return_label}\n`;
613+ `{emit_label lbl}: b {emit_label lbl_call_gc}\n`
614+ end;
615+ env.call_gc_sites <-
616+ { gc_lbl = lbl_call_gc;
617+ gc_return_lbl = lbl_after_poll;
618+ gc_frame_lbl = lbl_frame; } :: env.call_gc_sites
619+
577620(* Output .text section directive, or named .text.caml.<name> if enabled. *)
578621
579622let emit_named_text_section func_name =
@@ -727,6 +770,10 @@ let emit_instr env i =
727770 assembly_code_for_allocation env i ~n ~far:false ~dbginfo
728771 | Lop(Ispecific (Ifar_alloc { bytes = n; dbginfo })) ->
729772 assembly_code_for_allocation env i ~n ~far:true ~dbginfo
773+ | Lop(Ipoll { return_label }) ->
774+ assembly_code_for_poll env i ~far:false ~return_label
775+ | Lop(Ispecific (Ifar_poll { return_label })) ->
776+ assembly_code_for_poll env i ~far:true ~return_label
730777 | Lop(Iintop_imm(Iadd, n)) ->
731778 emit_addimm i.res.(0) i.arg.(0) n
732779 | Lop(Iintop_imm(Isub, n)) ->
0 commit comments