VM: Refactor errors to Factor style

db4
Erik Charlebois 2013-05-11 21:59:37 -04:00
parent d6bc190f51
commit e9c0476f15
2 changed files with 147 additions and 172 deletions

View File

@ -1,203 +1,180 @@
#include "master.hpp" #include "master.hpp"
namespace factor namespace factor {
{
bool factor_vm::fatal_erroring_p; bool factor_vm::fatal_erroring_p;
static inline void fa_diddly_atal_error() static inline void fa_diddly_atal_error() {
{ printf("fatal_error in fatal_error!\n");
printf("fatal_error in fatal_error!\n"); breakpoint();
breakpoint(); ::_exit(86);
::_exit(86);
} }
void fatal_error(const char *msg, cell tagged) void fatal_error(const char* msg, cell tagged) {
{ if (factor_vm::fatal_erroring_p)
if (factor_vm::fatal_erroring_p) fa_diddly_atal_error();
fa_diddly_atal_error();
factor_vm::fatal_erroring_p = true; factor_vm::fatal_erroring_p = true;
std::cout << "fatal_error: " << msg; std::cout << "fatal_error: " << msg;
std::cout << ": " << (void*)tagged; std::cout << ": " << (void*)tagged;
std::cout << std::endl; std::cout << std::endl;
abort(); abort();
} }
void critical_error(const char *msg, cell tagged) void critical_error(const char* msg, cell tagged) {
{ std::cout << "You have triggered a bug in Factor. Please report.\n";
std::cout << "You have triggered a bug in Factor. Please report.\n"; std::cout << "critical_error: " << msg;
std::cout << "critical_error: " << msg; std::cout << ": " << std::hex << tagged << std::dec;
std::cout << ": " << std::hex << tagged << std::dec; std::cout << std::endl;
std::cout << std::endl; current_vm()->factorbug();
current_vm()->factorbug();
} }
void out_of_memory() void out_of_memory() {
{ std::cout << "Out of memory\n\n";
std::cout << "Out of memory\n\n"; current_vm()->dump_generations();
current_vm()->dump_generations(); abort();
abort();
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::general_error(vm_error_type error, cell arg1_, cell arg2_) void factor_vm::general_error(vm_error_type error, cell arg1_, cell arg2_) {
{ data_root<object> arg1(arg1_, this);
data_root<object> arg1(arg1_,this); data_root<object> arg2(arg2_, this);
data_root<object> arg2(arg2_,this);
faulting_p = true; faulting_p = true;
/* If we had an underflow or overflow, data or retain stack /* If we had an underflow or overflow, data or retain stack
pointers might be out of bounds, so fix them before allocating pointers might be out of bounds, so fix them before allocating
anything */ anything */
ctx->fix_stacks(); ctx->fix_stacks();
/* If error was thrown during heap scan, we re-enable the GC */ /* If error was thrown during heap scan, we re-enable the GC */
gc_off = false; gc_off = false;
/* If the error handler is set, we rewind any C stack frames and /* If the error handler is set, we rewind any C stack frames and
pass the error to user-space. */ pass the error to user-space. */
if(!current_gc && to_boolean(special_objects[ERROR_HANDLER_QUOT])) if (!current_gc && to_boolean(special_objects[ERROR_HANDLER_QUOT])) {
{
#ifdef FACTOR_DEBUG #ifdef FACTOR_DEBUG
/* Doing a GC here triggers all kinds of funny errors */ /* Doing a GC here triggers all kinds of funny errors */
primitive_compact_gc(); primitive_compact_gc();
#endif #endif
/* Now its safe to allocate and GC */ /* Now its safe to allocate and GC */
cell error_object = allot_array_4(special_objects[OBJ_ERROR], cell error_object =
tag_fixnum(error),arg1.value(),arg2.value()); allot_array_4(special_objects[OBJ_ERROR], tag_fixnum(error),
arg1.value(), arg2.value());
ctx->push(error_object); ctx->push(error_object);
/* Reset local roots */ /* Reset local roots */
data_roots.clear(); data_roots.clear();
bignum_roots.clear(); bignum_roots.clear();
code_roots.clear(); code_roots.clear();
/* The unwind-native-frames subprimitive will clear faulting_p /* The unwind-native-frames subprimitive will clear faulting_p
if it was successfully reached. */ if it was successfully reached. */
unwind_native_frames(special_objects[ERROR_HANDLER_QUOT], unwind_native_frames(special_objects[ERROR_HANDLER_QUOT],
ctx->callstack_top); ctx->callstack_top);
} } /* Error was thrown in early startup before error handler is set, so just
/* Error was thrown in early startup before error handler is set, so just crash. */
crash. */ else {
else std::cout << "You have triggered a bug in Factor. Please report.\n";
{ std::cout << "error: " << error << std::endl;
std::cout << "You have triggered a bug in Factor. Please report.\n"; std::cout << "arg 1: ";
std::cout << "error: " << error << std::endl; print_obj(arg1.value());
std::cout << "arg 1: "; print_obj(arg1.value()); std::cout << std::endl; std::cout << std::endl;
std::cout << "arg 2: "; print_obj(arg2.value()); std::cout << std::endl; std::cout << "arg 2: ";
factorbug(); print_obj(arg2.value());
abort(); std::cout << std::endl;
} factorbug();
abort();
}
} }
void factor_vm::type_error(cell type, cell tagged) void factor_vm::type_error(cell type, cell tagged) {
{ general_error(ERROR_TYPE, tag_fixnum(type), tagged);
general_error(ERROR_TYPE,tag_fixnum(type),tagged);
} }
void factor_vm::not_implemented_error() void factor_vm::not_implemented_error() {
{ general_error(ERROR_NOT_IMPLEMENTED, false_object, false_object);
general_error(ERROR_NOT_IMPLEMENTED,false_object,false_object);
} }
void factor_vm::verify_memory_protection_error(cell addr) void factor_vm::verify_memory_protection_error(cell addr) {
{ /* Called from the OS-specific top halves of the signal handlers to
/* Called from the OS-specific top halves of the signal handlers to make sure it's safe to dispatch to memory_protection_error */
make sure it's safe to dispatch to memory_protection_error */ if (fatal_erroring_p)
if(fatal_erroring_p) fa_diddly_atal_error();
fa_diddly_atal_error(); if (faulting_p && !code->safepoint_p(addr))
if(faulting_p && !code->safepoint_p(addr)) fatal_error("Double fault", addr);
fatal_error("Double fault", addr); else if (fep_p)
else if(fep_p) fatal_error("Memory protection fault during low-level debugger", addr);
fatal_error("Memory protection fault during low-level debugger", addr); else if (atomic::load(&current_gc_p))
else if(atomic::load(&current_gc_p)) fatal_error("Memory protection fault during gc", addr);
fatal_error("Memory protection fault during gc", addr);
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::memory_protection_error(cell pc, cell addr) void factor_vm::memory_protection_error(cell pc, cell addr) {
{ if (code->safepoint_p(addr))
if(code->safepoint_p(addr)) safepoint.handle_safepoint(this, pc);
safepoint.handle_safepoint(this, pc); else if (ctx->datastack_seg->underflow_p(addr))
else if(ctx->datastack_seg->underflow_p(addr)) general_error(ERROR_DATASTACK_UNDERFLOW, false_object, false_object);
general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object); else if (ctx->datastack_seg->overflow_p(addr))
else if(ctx->datastack_seg->overflow_p(addr)) general_error(ERROR_DATASTACK_OVERFLOW, false_object, false_object);
general_error(ERROR_DATASTACK_OVERFLOW,false_object,false_object); else if (ctx->retainstack_seg->underflow_p(addr))
else if(ctx->retainstack_seg->underflow_p(addr)) general_error(ERROR_RETAINSTACK_UNDERFLOW, false_object, false_object);
general_error(ERROR_RETAINSTACK_UNDERFLOW,false_object,false_object); else if (ctx->retainstack_seg->overflow_p(addr))
else if(ctx->retainstack_seg->overflow_p(addr)) general_error(ERROR_RETAINSTACK_OVERFLOW, false_object, false_object);
general_error(ERROR_RETAINSTACK_OVERFLOW,false_object,false_object); else if (ctx->callstack_seg->underflow_p(addr))
else if(ctx->callstack_seg->underflow_p(addr)) general_error(ERROR_CALLSTACK_OVERFLOW, false_object, false_object);
general_error(ERROR_CALLSTACK_OVERFLOW,false_object,false_object); else if (ctx->callstack_seg->overflow_p(addr))
else if(ctx->callstack_seg->overflow_p(addr)) general_error(ERROR_CALLSTACK_UNDERFLOW, false_object, false_object);
general_error(ERROR_CALLSTACK_UNDERFLOW,false_object,false_object); else
else general_error(ERROR_MEMORY, from_unsigned_cell(addr), false_object);
general_error(ERROR_MEMORY,from_unsigned_cell(addr),false_object);
} }
/* Allocates memory */ /* Allocates memory */
void factor_vm::signal_error(cell signal) void factor_vm::signal_error(cell signal) {
{ general_error(ERROR_SIGNAL, from_unsigned_cell(signal), false_object);
general_error(ERROR_SIGNAL,from_unsigned_cell(signal),false_object);
} }
void factor_vm::divide_by_zero_error() void factor_vm::divide_by_zero_error() {
{ general_error(ERROR_DIVIDE_BY_ZERO, false_object, false_object);
general_error(ERROR_DIVIDE_BY_ZERO,false_object,false_object);
} }
void factor_vm::fp_trap_error(unsigned int fpu_status) void factor_vm::fp_trap_error(unsigned int fpu_status) {
{ general_error(ERROR_FP_TRAP, tag_fixnum(fpu_status), false_object);
general_error(ERROR_FP_TRAP,tag_fixnum(fpu_status),false_object);
} }
/* For testing purposes */ /* For testing purposes */
void factor_vm::primitive_unimplemented() void factor_vm::primitive_unimplemented() { not_implemented_error(); }
{
not_implemented_error(); void factor_vm::memory_signal_handler_impl() {
memory_protection_error(signal_fault_pc, signal_fault_addr);
if (!signal_resumable) {
/* In theory we should only get here if the callstack overflowed during a
safepoint */
general_error(ERROR_CALLSTACK_OVERFLOW, false_object, false_object);
}
} }
void factor_vm::memory_signal_handler_impl() void memory_signal_handler_impl() {
{ current_vm()->memory_signal_handler_impl();
memory_protection_error(signal_fault_pc, signal_fault_addr);
if (!signal_resumable)
{
/* In theory we should only get here if the callstack overflowed during a
safepoint */
general_error(ERROR_CALLSTACK_OVERFLOW,false_object,false_object);
}
} }
void memory_signal_handler_impl() void factor_vm::synchronous_signal_handler_impl() {
{ signal_error(signal_number);
current_vm()->memory_signal_handler_impl();
} }
void factor_vm::synchronous_signal_handler_impl() void synchronous_signal_handler_impl() {
{ current_vm()->synchronous_signal_handler_impl();
signal_error(signal_number);
} }
void synchronous_signal_handler_impl() void factor_vm::fp_signal_handler_impl() {
{ /* Clear pending exceptions to avoid getting stuck in a loop */
current_vm()->synchronous_signal_handler_impl(); set_fpu_state(get_fpu_state());
fp_trap_error(signal_fpu_status);
} }
void factor_vm::fp_signal_handler_impl() void fp_signal_handler_impl() { current_vm()->fp_signal_handler_impl(); }
{
/* Clear pending exceptions to avoid getting stuck in a loop */
set_fpu_state(get_fpu_state());
fp_trap_error(signal_fpu_status);
}
void fp_signal_handler_impl()
{
current_vm()->fp_signal_handler_impl();
}
} }

View File

@ -1,32 +1,30 @@
namespace factor namespace factor {
{
/* Runtime errors */ /* Runtime errors */
enum vm_error_type enum vm_error_type {
{ ERROR_EXPIRED = 0,
ERROR_EXPIRED = 0, ERROR_IO,
ERROR_IO, ERROR_NOT_IMPLEMENTED,
ERROR_NOT_IMPLEMENTED, ERROR_TYPE,
ERROR_TYPE, ERROR_DIVIDE_BY_ZERO,
ERROR_DIVIDE_BY_ZERO, ERROR_SIGNAL,
ERROR_SIGNAL, ERROR_ARRAY_SIZE,
ERROR_ARRAY_SIZE, ERROR_C_STRING,
ERROR_C_STRING, ERROR_FFI,
ERROR_FFI, ERROR_UNDEFINED_SYMBOL,
ERROR_UNDEFINED_SYMBOL, ERROR_DATASTACK_UNDERFLOW,
ERROR_DATASTACK_UNDERFLOW, ERROR_DATASTACK_OVERFLOW,
ERROR_DATASTACK_OVERFLOW, ERROR_RETAINSTACK_UNDERFLOW,
ERROR_RETAINSTACK_UNDERFLOW, ERROR_RETAINSTACK_OVERFLOW,
ERROR_RETAINSTACK_OVERFLOW, ERROR_CALLSTACK_UNDERFLOW,
ERROR_CALLSTACK_UNDERFLOW, ERROR_CALLSTACK_OVERFLOW,
ERROR_CALLSTACK_OVERFLOW, ERROR_MEMORY,
ERROR_MEMORY, ERROR_FP_TRAP,
ERROR_FP_TRAP, ERROR_INTERRUPT,
ERROR_INTERRUPT,
}; };
void fatal_error(const char *msg, cell tagged); void fatal_error(const char* msg, cell tagged);
void critical_error(const char *msg, cell tagged); void critical_error(const char* msg, cell tagged);
void out_of_memory(); void out_of_memory();
void memory_signal_handler_impl(); void memory_signal_handler_impl();
void fp_signal_handler_impl(); void fp_signal_handler_impl();