diff --git a/ocaml/runtime/arm64.S b/ocaml/runtime/arm64.S index b6ae681454c..cfcb85b3803 100644 --- a/ocaml/runtime/arm64.S +++ b/ocaml/runtime/arm64.S @@ -203,6 +203,7 @@ G(name): #define Cstack_sp(reg) [reg, #8] #define Cstack_sp_offset 8 #define Cstack_prev(reg) [reg, #16] +#define Cstack_async_exn_handler(reg) [reg, #24] /* struct stack_handler */ #define Handler_value(reg) [reg] @@ -352,7 +353,7 @@ FUNCTION(caml_call_realloc_stack) ldp x29, x30, [sp], 16 add sp, sp, 16 /* pop argument */ ADDRGLOBAL(x0, caml_exn_Stack_overflow) - b G(caml_raise_exn) + b G(caml_raise_async) CFI_ENDPROC END_FUNCTION(caml_call_realloc_stack) @@ -543,7 +544,9 @@ L(jump_to_caml): ldr ALLOC_PTR, Caml_state(young_ptr) /* Build (16-byte aligned) struct c_stack_link on the C stack */ ldr x8, Caml_state(c_stack) - stp x8, xzr, [sp, -16]! /* C_stack_prev, pad */ + ldr x9, Caml_state(async_exn_handler) + stp x8, x9, [sp, -16]! + /* C_stack_prev, C_stack_async_exn_handler */ CFI_ADJUST(16) stp xzr, xzr, [sp, -16]! /* C_stack_stack, C_stack_sp */ CFI_ADJUST(16) @@ -563,6 +566,10 @@ L(jump_to_caml): adr x10, L(trap_handler) stp x9, x10, [x8, -16]! mov TRAP_PTR, x8 + /* Note that the async exception handler chain always goes through + Caml_state, unlike the normal exception handler chain, which goes + through the TRAP_PTR register. */ + str x8, Caml_state(async_exn_handler) /* Switch stacks and call the OCaml code */ mov sp, x8 #ifdef ASM_CFI_SUPPORTED @@ -598,6 +605,9 @@ L(return_result): ldr x9, Caml_state(c_stack) mov sp, x9 CFI_RESTORE_STATE + /* Restore saved async exception pointer */ + ldr x8, Cstack_async_exn_handler(sp) + str x8, Caml_state(async_exn_handler) /* Pop the struct c_stack_link */ ldr x8, Cstack_prev(sp) add sp, sp, 32 diff --git a/ocaml/runtime4/arm64.S b/ocaml/runtime4/arm64.S index 3484dbcbc50..1f65ab1b441 100644 --- a/ocaml/runtime4/arm64.S +++ b/ocaml/runtime4/arm64.S @@ -401,8 +401,6 @@ FUNCTION(caml_start_program) /* Address of OCaml code to call is in TMP2 */ /* Arguments to the OCaml code are in x0...x7 */ -/* CR mshinwell: asynchronous exceptions are not yet implemented here */ - L(jump_to_caml): /* Set up stack frame and save callee-save registers */ CFI_OFFSET(29, -160) @@ -425,15 +423,19 @@ L(jump_to_caml): ldr x8, Caml_state(bottom_of_stack) ldr x9, Caml_state(last_return_address) ldr x10, Caml_state(gc_regs) + ldr x11, Caml_state(async_exception_pointer) stp x8, x9, [sp, -32]! /* 16-byte alignment */ CFI_ADJUST(32) str x10, [sp, 16] + str x11, [sp, 24] /* Setup a trap frame to catch exceptions escaping the OCaml code */ ldr x8, Caml_state(exn_handler) adr x9, L(trap_handler) stp x8, x9, [sp, -16]! CFI_ADJUST(16) add TRAP_PTR, sp, #0 + /* Store the async exception pointer */ + str TRAP_PTR, Caml_state(async_exception_pointer) /* Reload allocation pointer */ ldr ALLOC_PTR, Caml_state(young_ptr) /* Call the OCaml code */ @@ -445,12 +447,14 @@ L(caml_retaddr): str x8, Caml_state(exn_handler) /* Pop the callback link, restoring the global variables */ L(return_result): + ldr x11, [sp, 24] ldr x10, [sp, 16] ldp x8, x9, [sp], 32 CFI_ADJUST(-32) str x8, Caml_state(bottom_of_stack) str x9, Caml_state(last_return_address) str x10, Caml_state(gc_regs) + str x11, Caml_state(async_exception_pointer) /* Update allocation pointer */ str ALLOC_PTR, Caml_state(young_ptr) /* Reload callee-save registers and return address */ @@ -556,9 +560,10 @@ FUNCTION(caml_raise_exception) FUNCTION(caml_stack_overflow) /* Load the exception bucket */ ADDRGLOBAL(x0, caml_exn_Stack_overflow) - /* Cut stack at current trap handler */ - mov sp, TRAP_PTR - /* Pop previous handler and jump to it */ + /* Cut stack at current async exn trap handler */ + ldr TMP, Caml_state(async_exception_pointer) + mov sp, TMP + /* Pop handler and jump to it */ ldr TMP, [sp, 8] ldr TRAP_PTR, [sp], 16 br TMP