/* Modify a suspended thread's thread_state so that when the thread resumes executing, the call frame of the current C primitive (if any) is rewound, and the appropriate Factor error is thrown from the top-most Factor frame. */ void factor_vm::call_fault_handler(exception_type_t exception, exception_data_type_t code, MACH_EXC_STATE_TYPE* exc_state, MACH_THREAD_STATE_TYPE* thread_state, MACH_FLOAT_STATE_TYPE* float_state) { cell handler = 0; if (exception == EXC_BAD_ACCESS) { signal_fault_addr = MACH_EXC_STATE_FAULT(exc_state); signal_fault_pc = (cell)MACH_PROGRAM_COUNTER(thread_state); verify_memory_protection_error(signal_fault_addr); handler = (cell)factor::memory_signal_handler_impl; } else if (exception == EXC_ARITHMETIC && code != MACH_EXC_INTEGER_DIV) { signal_fpu_status = fpu_status(mach_fpu_status(float_state)); mach_clear_fpu_status(float_state); handler = (cell)factor::fp_signal_handler_impl; } else { switch (exception) { case EXC_ARITHMETIC: signal_number = SIGFPE; break; case EXC_BAD_INSTRUCTION: signal_number = SIGILL; break; default: signal_number = SIGABRT; break; } handler = (cell)factor::synchronous_signal_handler_impl; } FACTOR_ASSERT(handler != 0); dispatch_signal_handler((cell*)&MACH_STACK_POINTER(thread_state), (cell*)&MACH_PROGRAM_COUNTER(thread_state), (cell)handler); }
inline static unsigned int uap_fpu_status(void *uap) { return mach_fpu_status(UAP_FS(uap)); }