diff --git a/basis/debugger/debugger.factor b/basis/debugger/debugger.factor index ce9496291c..2fad0e4c2e 100644 --- a/basis/debugger/debugger.factor +++ b/basis/debugger/debugger.factor @@ -124,11 +124,14 @@ HOOK: signal-error. os ( obj -- ) : primitive-error. ( error -- ) "Unimplemented primitive" print drop ; +: fp-trap-error. ( error -- ) + "Floating point trap" print drop ; + PREDICATE: vm-error < array { { [ dup empty? ] [ drop f ] } { [ dup first "kernel-error" = not ] [ drop f ] } - [ second 0 15 between? ] + [ second 0 16 between? ] } cond ; : vm-errors ( error -- n errors ) @@ -149,6 +152,7 @@ PREDICATE: vm-error < array { 13 [ retainstack-underflow. ] } { 14 [ retainstack-overflow. ] } { 15 [ memory-error. ] } + { 16 [ fp-trap-error. ] } } ; inline M: vm-error summary drop "VM error" ; diff --git a/vm/errors.cpp b/vm/errors.cpp index 610482f576..04a6ebb89b 100644 --- a/vm/errors.cpp +++ b/vm/errors.cpp @@ -130,6 +130,11 @@ void divide_by_zero_error() general_error(ERROR_DIVIDE_BY_ZERO,F,F,NULL); } +void fp_trap_error() +{ + general_error(ERROR_FP_TRAP,F,F,NULL); +} + PRIMITIVE(call_clear) { throw_impl(dpop(),stack_chain->callstack_bottom); @@ -151,4 +156,9 @@ void misc_signal_handler_impl() signal_error(signal_number,signal_callstack_top); } +void fp_signal_handler_impl() +{ + fp_trap_error(); +} + } diff --git a/vm/errors.hpp b/vm/errors.hpp index 11180508e5..e4be61cdbf 100644 --- a/vm/errors.hpp +++ b/vm/errors.hpp @@ -20,6 +20,7 @@ enum vm_error_type ERROR_RS_UNDERFLOW, ERROR_RS_OVERFLOW, ERROR_MEMORY, + ERROR_FP_TRAP, }; void out_of_memory(); @@ -35,6 +36,7 @@ void memory_protection_error(cell addr, stack_frame *native_stack); void signal_error(int signal, stack_frame *native_stack); void type_error(cell type, cell tagged); void not_implemented_error(); +void fp_trap_error(); PRIMITIVE(call_clear); PRIMITIVE(unimplemented); @@ -46,6 +48,7 @@ extern cell signal_fault_addr; extern stack_frame *signal_callstack_top; void memory_signal_handler_impl(); +void fp_signal_handler_impl(); void misc_signal_handler_impl(); } diff --git a/vm/mach_signal.cpp b/vm/mach_signal.cpp index 03edf862a8..50a924f8e4 100644 --- a/vm/mach_signal.cpp +++ b/vm/mach_signal.cpp @@ -28,7 +28,9 @@ http://www.wodeveloper.com/omniLists/macosx-dev/2000/June/msg00137.html */ /* 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. */ -static void call_fault_handler(exception_type_t exception, +static void call_fault_handler( + exception_type_t exception, + exception_data_type_t code, MACH_EXC_STATE_TYPE *exc_state, MACH_THREAD_STATE_TYPE *thread_state) { @@ -52,12 +54,13 @@ static void call_fault_handler(exception_type_t exception, signal_fault_addr = MACH_EXC_STATE_FAULT(exc_state); MACH_PROGRAM_COUNTER(thread_state) = (cell)memory_signal_handler_impl; } - else - { - if(exception == EXC_ARITHMETIC) - signal_number = SIGFPE; - else - signal_number = SIGABRT; + else if(exception == EXC_ARITHMETIC && code != MACH_EXC_INTEGER_DIV) + { + MACH_PROGRAM_COUNTER(thread_state) = (cell)fp_signal_handler_impl; + } + else + { + signal_number = exception == EXC_ARITHMETIC ? SIGFPE : SIGABRT; MACH_PROGRAM_COUNTER(thread_state) = (cell)misc_signal_handler_impl; } } @@ -102,7 +105,7 @@ catch_exception_raise (mach_port_t exception_port, /* Modify registers so to have the thread resume executing the fault handler */ - call_fault_handler(exception,&exc_state,&thread_state); + call_fault_handler(exception,code[0],&exc_state,&thread_state); /* Set the faulting thread's register contents.. diff --git a/vm/os-macosx-ppc.hpp b/vm/os-macosx-ppc.hpp index 84fe50c283..62e71bfa69 100644 --- a/vm/os-macosx-ppc.hpp +++ b/vm/os-macosx-ppc.hpp @@ -18,6 +18,7 @@ Modified for Factor by Slava Pestov */ #define MACH_EXC_STATE_TYPE ppc_exception_state_t #define MACH_EXC_STATE_FLAVOR PPC_EXCEPTION_STATE #define MACH_EXC_STATE_COUNT PPC_EXCEPTION_STATE_COUNT +#define MACH_EXC_INTEGER_DIV EXC_PPC_ZERO_DIVIDE #define MACH_THREAD_STATE_TYPE ppc_thread_state_t #define MACH_THREAD_STATE_FLAVOR PPC_THREAD_STATE #define MACH_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT diff --git a/vm/os-macosx-x86.32.hpp b/vm/os-macosx-x86.32.hpp index 036dc1a398..2275555846 100644 --- a/vm/os-macosx-x86.32.hpp +++ b/vm/os-macosx-x86.32.hpp @@ -16,6 +16,7 @@ Modified for Factor by Slava Pestov */ #define MACH_EXC_STATE_TYPE i386_exception_state_t #define MACH_EXC_STATE_FLAVOR i386_EXCEPTION_STATE #define MACH_EXC_STATE_COUNT i386_EXCEPTION_STATE_COUNT +#define MACH_EXC_INTEGER_DIV EXC_I386_DIV #define MACH_THREAD_STATE_TYPE i386_thread_state_t #define MACH_THREAD_STATE_FLAVOR i386_THREAD_STATE #define MACH_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT diff --git a/vm/os-macosx-x86.64.hpp b/vm/os-macosx-x86.64.hpp index f9d54d875f..b97eb55f26 100644 --- a/vm/os-macosx-x86.64.hpp +++ b/vm/os-macosx-x86.64.hpp @@ -16,6 +16,7 @@ Modified for Factor by Slava Pestov and Daniel Ehrenberg */ #define MACH_EXC_STATE_TYPE x86_exception_state64_t #define MACH_EXC_STATE_FLAVOR x86_EXCEPTION_STATE64 #define MACH_EXC_STATE_COUNT x86_EXCEPTION_STATE64_COUNT +#define MACH_EXC_INTEGER_DIV EXC_I386_DIV #define MACH_THREAD_STATE_TYPE x86_thread_state64_t #define MACH_THREAD_STATE_FLAVOR x86_THREAD_STATE64 #define MACH_THREAD_STATE_COUNT MACHINE_THREAD_STATE_COUNT diff --git a/vm/os-unix.cpp b/vm/os-unix.cpp index 18300949bd..735c614b7a 100644 --- a/vm/os-unix.cpp +++ b/vm/os-unix.cpp @@ -132,6 +132,16 @@ void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap) UAP_PROGRAM_COUNTER(uap) = (cell)misc_signal_handler_impl; } +void fpe_signal_handler(int signal, siginfo_t *siginfo, void *uap) +{ + signal_number = signal; + signal_callstack_top = uap_stack_pointer(uap); + UAP_PROGRAM_COUNTER(uap) = + (siginfo->si_code == FPE_INTDIV || siginfo->si_code == FPE_INTOVF) + ? (cell)misc_signal_handler_impl + : (cell)fp_signal_handler_impl; +} + static void sigaction_safe(int signum, const struct sigaction *act, struct sigaction *oldact) { int ret; @@ -149,6 +159,7 @@ void unix_init_signals() { struct sigaction memory_sigaction; struct sigaction misc_sigaction; + struct sigaction fpe_sigaction; struct sigaction ignore_sigaction; memset(&memory_sigaction,0,sizeof(struct sigaction)); @@ -159,13 +170,19 @@ void unix_init_signals() sigaction_safe(SIGBUS,&memory_sigaction,NULL); sigaction_safe(SIGSEGV,&memory_sigaction,NULL); + memset(&fpe_sigaction,0,sizeof(struct sigaction)); + sigemptyset(&fpe_sigaction.sa_mask); + fpe_sigaction.sa_sigaction = fpe_signal_handler; + fpe_sigaction.sa_flags = SA_SIGINFO; + + sigaction_safe(SIGFPE,&fpe_sigaction,NULL); + memset(&misc_sigaction,0,sizeof(struct sigaction)); sigemptyset(&misc_sigaction.sa_mask); misc_sigaction.sa_sigaction = misc_signal_handler; misc_sigaction.sa_flags = SA_SIGINFO; sigaction_safe(SIGABRT,&misc_sigaction,NULL); - sigaction_safe(SIGFPE,&misc_sigaction,NULL); sigaction_safe(SIGQUIT,&misc_sigaction,NULL); sigaction_safe(SIGILL,&misc_sigaction,NULL);