vm: signal handling cleanup
parent
88d0793946
commit
11ddbc03a4
|
@ -13,7 +13,7 @@ char *factor_vm::pinned_alien_offset(cell obj)
|
||||||
{
|
{
|
||||||
alien *ptr = untag<alien>(obj);
|
alien *ptr = untag<alien>(obj);
|
||||||
if(to_boolean(ptr->expired))
|
if(to_boolean(ptr->expired))
|
||||||
general_error(ERROR_EXPIRED,obj,false_object,NULL);
|
general_error(ERROR_EXPIRED,obj,false_object);
|
||||||
if(to_boolean(ptr->base))
|
if(to_boolean(ptr->base))
|
||||||
type_error(ALIEN_TYPE,obj);
|
type_error(ALIEN_TYPE,obj);
|
||||||
else
|
else
|
||||||
|
|
|
@ -18,11 +18,17 @@ callstack *factor_vm::allot_callstack(cell size)
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack_frame *factor_vm::fix_callstack_top(stack_frame *top, stack_frame *bottom)
|
/* If 'stack' points into the middle of the frame, find the nearest valid stack
|
||||||
|
pointer where we can resume execution and hope to capture the call trace without
|
||||||
|
crashing. Also, make sure we have at least 'stack_reserved' bytes available so
|
||||||
|
that we don't run out of callstack space while handling the error. */
|
||||||
|
stack_frame *factor_vm::fix_callstack_top(stack_frame *stack)
|
||||||
{
|
{
|
||||||
stack_frame *frame = bottom - 1;
|
stack_frame *frame = ctx->callstack_bottom - 1;
|
||||||
|
|
||||||
while(frame >= top)
|
while(frame >= stack
|
||||||
|
&& frame >= ctx->callstack_top
|
||||||
|
&& (cell)frame >= ctx->callstack_seg->start + stack_reserved)
|
||||||
frame = frame_successor(frame);
|
frame = frame_successor(frame);
|
||||||
|
|
||||||
return frame + 1;
|
return frame + 1;
|
||||||
|
|
|
@ -144,7 +144,7 @@ void factor_vm::update_word_references(code_block *compiled, bool reset_inline_c
|
||||||
image load */
|
image load */
|
||||||
void factor_vm::undefined_symbol()
|
void factor_vm::undefined_symbol()
|
||||||
{
|
{
|
||||||
general_error(ERROR_UNDEFINED_SYMBOL,false_object,false_object,NULL);
|
general_error(ERROR_UNDEFINED_SYMBOL,false_object,false_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void undefined_symbol()
|
void undefined_symbol()
|
||||||
|
|
|
@ -44,6 +44,17 @@ void context::reset()
|
||||||
reset_context_objects();
|
reset_context_objects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void context::fix_stacks()
|
||||||
|
{
|
||||||
|
if(datastack + sizeof(cell) < datastack_seg->start
|
||||||
|
|| datastack + stack_reserved >= datastack_seg->end)
|
||||||
|
reset_datastack();
|
||||||
|
|
||||||
|
if(retainstack + sizeof(cell) < retainstack_seg->start
|
||||||
|
|| retainstack + stack_reserved >= retainstack_seg->end)
|
||||||
|
reset_retainstack();
|
||||||
|
}
|
||||||
|
|
||||||
context::~context()
|
context::~context()
|
||||||
{
|
{
|
||||||
delete datastack_seg;
|
delete datastack_seg;
|
||||||
|
@ -167,13 +178,13 @@ bool factor_vm::stack_to_array(cell bottom, cell top)
|
||||||
void factor_vm::primitive_datastack()
|
void factor_vm::primitive_datastack()
|
||||||
{
|
{
|
||||||
if(!stack_to_array(ctx->datastack_seg->start,ctx->datastack))
|
if(!stack_to_array(ctx->datastack_seg->start,ctx->datastack))
|
||||||
general_error(ERROR_DS_UNDERFLOW,false_object,false_object,NULL);
|
general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::primitive_retainstack()
|
void factor_vm::primitive_retainstack()
|
||||||
{
|
{
|
||||||
if(!stack_to_array(ctx->retainstack_seg->start,ctx->retainstack))
|
if(!stack_to_array(ctx->retainstack_seg->start,ctx->retainstack))
|
||||||
general_error(ERROR_RS_UNDERFLOW,false_object,false_object,NULL);
|
general_error(ERROR_RETAINSTACK_UNDERFLOW,false_object,false_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns pointer to top of stack */
|
/* returns pointer to top of stack */
|
||||||
|
|
|
@ -8,6 +8,8 @@ enum context_object {
|
||||||
OBJ_CATCHSTACK,
|
OBJ_CATCHSTACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const cell stack_reserved = 1024;
|
||||||
|
|
||||||
struct context {
|
struct context {
|
||||||
|
|
||||||
// First 4 fields accessed directly by compiler. See basis/vm/vm.factor
|
// First 4 fields accessed directly by compiler. See basis/vm/vm.factor
|
||||||
|
@ -41,6 +43,7 @@ struct context {
|
||||||
void reset_callstack();
|
void reset_callstack();
|
||||||
void reset_context_objects();
|
void reset_context_objects();
|
||||||
void reset();
|
void reset();
|
||||||
|
void fix_stacks();
|
||||||
|
|
||||||
cell peek()
|
cell peek()
|
||||||
{
|
{
|
||||||
|
@ -64,19 +67,6 @@ struct context {
|
||||||
datastack += sizeof(cell);
|
datastack += sizeof(cell);
|
||||||
replace(tagged);
|
replace(tagged);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const cell stack_reserved = (64 * sizeof(cell));
|
|
||||||
|
|
||||||
void fix_stacks()
|
|
||||||
{
|
|
||||||
if(datastack + sizeof(cell) < datastack_seg->start
|
|
||||||
|| datastack + stack_reserved >= datastack_seg->end)
|
|
||||||
reset_datastack();
|
|
||||||
|
|
||||||
if(retainstack + sizeof(cell) < retainstack_seg->start
|
|
||||||
|| retainstack + stack_reserved >= retainstack_seg->end)
|
|
||||||
reset_retainstack();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VM_C_API context *new_context(factor_vm *parent);
|
VM_C_API context *new_context(factor_vm *parent);
|
||||||
|
|
|
@ -27,8 +27,10 @@ void out_of_memory()
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::throw_error(cell error, stack_frame *callstack_top)
|
void factor_vm::throw_error(cell error, stack_frame *stack)
|
||||||
{
|
{
|
||||||
|
assert(stack);
|
||||||
|
|
||||||
/* 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]))
|
||||||
|
@ -41,22 +43,13 @@ void factor_vm::throw_error(cell error, stack_frame *callstack_top)
|
||||||
bignum_roots.clear();
|
bignum_roots.clear();
|
||||||
code_roots.clear();
|
code_roots.clear();
|
||||||
|
|
||||||
/* If we had an underflow or overflow, stack pointers might be
|
/* If we had an underflow or overflow, data or retain stack
|
||||||
out of bounds */
|
pointers might be out of bounds */
|
||||||
ctx->fix_stacks();
|
ctx->fix_stacks();
|
||||||
|
|
||||||
ctx->push(error);
|
ctx->push(error);
|
||||||
|
|
||||||
/* Errors thrown from C code pass NULL for this parameter.
|
unwind_native_frames(special_objects[ERROR_HANDLER_QUOT],stack);
|
||||||
Errors thrown from Factor code, or signal handlers, pass the
|
|
||||||
actual stack pointer at the time, since the saved pointer is
|
|
||||||
not necessarily up to date at that point. */
|
|
||||||
if(callstack_top)
|
|
||||||
callstack_top = fix_callstack_top(callstack_top,ctx->callstack_bottom);
|
|
||||||
else
|
|
||||||
callstack_top = ctx->callstack_top;
|
|
||||||
|
|
||||||
unwind_native_frames(special_objects[ERROR_HANDLER_QUOT],callstack_top);
|
|
||||||
}
|
}
|
||||||
/* Error was thrown in early startup before error handler is set, just
|
/* Error was thrown in early startup before error handler is set, just
|
||||||
crash. */
|
crash. */
|
||||||
|
@ -70,62 +63,55 @@ void factor_vm::throw_error(cell error, stack_frame *callstack_top)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *callstack_top)
|
void factor_vm::general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *stack)
|
||||||
{
|
{
|
||||||
throw_error(allot_array_4(special_objects[OBJ_ERROR],
|
throw_error(allot_array_4(special_objects[OBJ_ERROR],
|
||||||
tag_fixnum(error),arg1,arg2),callstack_top);
|
tag_fixnum(error),arg1,arg2),stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void factor_vm::general_error(vm_error_type error, cell arg1, cell arg2)
|
||||||
|
{
|
||||||
|
throw_error(allot_array_4(special_objects[OBJ_ERROR],
|
||||||
|
tag_fixnum(error),arg1,arg2),ctx->callstack_top);
|
||||||
}
|
}
|
||||||
|
|
||||||
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,NULL);
|
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,NULL);
|
general_error(ERROR_NOT_IMPLEMENTED,false_object,false_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test if 'fault' is in the guard page at the top or bottom (depending on
|
void factor_vm::memory_protection_error(cell addr, stack_frame *stack)
|
||||||
offset being 0 or -1) of area+area_size */
|
|
||||||
bool factor_vm::in_page(cell fault, cell area, cell area_size, int offset)
|
|
||||||
{
|
{
|
||||||
int pagesize = getpagesize();
|
if(ctx->datastack_seg->underflow_p(addr))
|
||||||
area += area_size;
|
general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object,stack);
|
||||||
area += offset * pagesize;
|
else if(ctx->datastack_seg->overflow_p(addr))
|
||||||
|
general_error(ERROR_DATASTACK_OVERFLOW,false_object,false_object,stack);
|
||||||
return fault >= area && fault <= area + pagesize;
|
else if(ctx->retainstack_seg->underflow_p(addr))
|
||||||
}
|
general_error(ERROR_RETAINSTACK_UNDERFLOW,false_object,false_object,stack);
|
||||||
|
else if(ctx->retainstack_seg->overflow_p(addr))
|
||||||
void factor_vm::memory_protection_error(cell addr, stack_frame *native_stack)
|
general_error(ERROR_RETAINSTACK_OVERFLOW,false_object,false_object,stack);
|
||||||
{
|
|
||||||
if(in_page(addr, ctx->datastack_seg->start, 0, -1))
|
|
||||||
general_error(ERROR_DS_UNDERFLOW,false_object,false_object,native_stack);
|
|
||||||
else if(in_page(addr, ctx->datastack_seg->start, datastack_size, 0))
|
|
||||||
general_error(ERROR_DS_OVERFLOW,false_object,false_object,native_stack);
|
|
||||||
else if(in_page(addr, ctx->retainstack_seg->start, 0, -1))
|
|
||||||
general_error(ERROR_RS_UNDERFLOW,false_object,false_object,native_stack);
|
|
||||||
else if(in_page(addr, ctx->retainstack_seg->start, retainstack_size, 0))
|
|
||||||
general_error(ERROR_RS_OVERFLOW,false_object,false_object,native_stack);
|
|
||||||
else if(in_page(addr, nursery.end, 0, 0))
|
|
||||||
critical_error("allot_object() missed GC check",0);
|
|
||||||
else
|
else
|
||||||
general_error(ERROR_MEMORY,allot_cell(addr),false_object,native_stack);
|
general_error(ERROR_MEMORY,allot_cell(addr),false_object,stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::signal_error(cell signal, stack_frame *native_stack)
|
void factor_vm::signal_error(cell signal, stack_frame *stack)
|
||||||
{
|
{
|
||||||
general_error(ERROR_SIGNAL,allot_cell(signal),false_object,native_stack);
|
general_error(ERROR_SIGNAL,allot_cell(signal),false_object,stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::divide_by_zero_error()
|
void factor_vm::divide_by_zero_error()
|
||||||
{
|
{
|
||||||
general_error(ERROR_DIVIDE_BY_ZERO,false_object,false_object,NULL);
|
general_error(ERROR_DIVIDE_BY_ZERO,false_object,false_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::fp_trap_error(unsigned int fpu_status, stack_frame *signal_callstack_top)
|
void factor_vm::fp_trap_error(unsigned int fpu_status, stack_frame *stack)
|
||||||
{
|
{
|
||||||
general_error(ERROR_FP_TRAP,tag_fixnum(fpu_status),false_object,signal_callstack_top);
|
general_error(ERROR_FP_TRAP,tag_fixnum(fpu_status),false_object,stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::primitive_call_clear()
|
void factor_vm::primitive_call_clear()
|
||||||
|
|
|
@ -14,10 +14,10 @@ enum vm_error_type
|
||||||
ERROR_C_STRING,
|
ERROR_C_STRING,
|
||||||
ERROR_FFI,
|
ERROR_FFI,
|
||||||
ERROR_UNDEFINED_SYMBOL,
|
ERROR_UNDEFINED_SYMBOL,
|
||||||
ERROR_DS_UNDERFLOW,
|
ERROR_DATASTACK_UNDERFLOW,
|
||||||
ERROR_DS_OVERFLOW,
|
ERROR_DATASTACK_OVERFLOW,
|
||||||
ERROR_RS_UNDERFLOW,
|
ERROR_RETAINSTACK_UNDERFLOW,
|
||||||
ERROR_RS_OVERFLOW,
|
ERROR_RETAINSTACK_OVERFLOW,
|
||||||
ERROR_MEMORY,
|
ERROR_MEMORY,
|
||||||
ERROR_FP_TRAP,
|
ERROR_FP_TRAP,
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,7 +28,7 @@ void factor_vm::io_error()
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
general_error(ERROR_IO,tag_fixnum(errno),false_object,NULL);
|
general_error(ERROR_IO,tag_fixnum(errno),false_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *factor_vm::safe_fopen(char *filename, char *mode)
|
FILE *factor_vm::safe_fopen(char *filename, char *mode)
|
||||||
|
|
|
@ -35,19 +35,9 @@ void factor_vm::call_fault_handler(
|
||||||
MACH_THREAD_STATE_TYPE *thread_state,
|
MACH_THREAD_STATE_TYPE *thread_state,
|
||||||
MACH_FLOAT_STATE_TYPE *float_state)
|
MACH_FLOAT_STATE_TYPE *float_state)
|
||||||
{
|
{
|
||||||
/* There is a race condition here, but in practice an exception
|
MACH_STACK_POINTER(thread_state) = (cell)fix_callstack_top((stack_frame *)MACH_STACK_POINTER(thread_state));
|
||||||
delivered during stack frame setup/teardown or while transitioning
|
|
||||||
from Factor to C is a sign of things seriously gone wrong, not just
|
|
||||||
a divide by zero or stack underflow in the listener */
|
|
||||||
|
|
||||||
/* Are we in compiled Factor code? Then use the current stack pointer */
|
signal_callstack_top = (stack_frame *)MACH_STACK_POINTER(thread_state);
|
||||||
if(in_code_heap_p(MACH_PROGRAM_COUNTER(thread_state)))
|
|
||||||
signal_callstack_top = (stack_frame *)MACH_STACK_POINTER(thread_state);
|
|
||||||
/* Are we in C? Then use the saved callstack top */
|
|
||||||
else
|
|
||||||
signal_callstack_top = NULL;
|
|
||||||
|
|
||||||
MACH_STACK_POINTER(thread_state) = align_stack_pointer(MACH_STACK_POINTER(thread_state));
|
|
||||||
|
|
||||||
/* Now we point the program counter at the right handler function. */
|
/* Now we point the program counter at the right handler function. */
|
||||||
if(exception == EXC_BAD_ACCESS)
|
if(exception == EXC_BAD_ACCESS)
|
||||||
|
|
|
@ -246,7 +246,7 @@ cell factor_vm::unbox_array_size_slow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
general_error(ERROR_ARRAY_SIZE,ctx->pop(),tag_fixnum(array_size_max),NULL);
|
general_error(ERROR_ARRAY_SIZE,ctx->pop(),tag_fixnum(array_size_max));
|
||||||
return 0; /* can't happen */
|
return 0; /* can't happen */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,4 @@ void early_init();
|
||||||
const char *vm_executable_path();
|
const char *vm_executable_path();
|
||||||
const char *default_image_path();
|
const char *default_image_path();
|
||||||
|
|
||||||
template<typename Type> Type align_stack_pointer(Type sp)
|
|
||||||
{
|
|
||||||
return sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,11 +62,6 @@ inline static unsigned int uap_fpu_status(void *uap)
|
||||||
return mach_fpu_status(UAP_FS(uap));
|
return mach_fpu_status(UAP_FS(uap));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type> Type align_stack_pointer(Type sp)
|
|
||||||
{
|
|
||||||
return sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void mach_clear_fpu_status(ppc_float_state_t *float_state)
|
inline static void mach_clear_fpu_status(ppc_float_state_t *float_state)
|
||||||
{
|
{
|
||||||
FPSCR(float_state) &= 0x0007f8ff;
|
FPSCR(float_state) &= 0x0007f8ff;
|
||||||
|
|
|
@ -64,11 +64,6 @@ inline static unsigned int uap_fpu_status(void *uap)
|
||||||
return mach_fpu_status(UAP_FS(uap));
|
return mach_fpu_status(UAP_FS(uap));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type> Type align_stack_pointer(Type sp)
|
|
||||||
{
|
|
||||||
return (Type)((((cell)sp + 4) & ~15) - 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void mach_clear_fpu_status(i386_float_state_t *float_state)
|
inline static void mach_clear_fpu_status(i386_float_state_t *float_state)
|
||||||
{
|
{
|
||||||
MXCSR(float_state) &= 0xffffffc0;
|
MXCSR(float_state) &= 0xffffffc0;
|
||||||
|
|
|
@ -62,11 +62,6 @@ inline static unsigned int uap_fpu_status(void *uap)
|
||||||
return mach_fpu_status(UAP_FS(uap));
|
return mach_fpu_status(UAP_FS(uap));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type> Type align_stack_pointer(Type sp)
|
|
||||||
{
|
|
||||||
return (Type)((((cell)sp + 8) & ~15) - 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static void mach_clear_fpu_status(x86_float_state64_t *float_state)
|
inline static void mach_clear_fpu_status(x86_float_state64_t *float_state)
|
||||||
{
|
{
|
||||||
MXCSR(float_state) &= 0xffffffc0;
|
MXCSR(float_state) &= 0xffffffc0;
|
||||||
|
|
|
@ -85,7 +85,7 @@ void *factor_vm::ffi_dlsym(dll *dll, symbol_char *symbol)
|
||||||
void factor_vm::ffi_dlclose(dll *dll)
|
void factor_vm::ffi_dlclose(dll *dll)
|
||||||
{
|
{
|
||||||
if(dlclose(dll->handle))
|
if(dlclose(dll->handle))
|
||||||
general_error(ERROR_FFI,false_object,false_object,NULL);
|
general_error(ERROR_FFI,false_object,false_object);
|
||||||
dll->handle = NULL;
|
dll->handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ void factor_vm::move_file(const vm_char *path1, const vm_char *path2)
|
||||||
ret = rename((path1),(path2));
|
ret = rename((path1),(path2));
|
||||||
} while(ret < 0 && errno == EINTR);
|
} while(ret < 0 && errno == EINTR);
|
||||||
if(ret < 0)
|
if(ret < 0)
|
||||||
general_error(ERROR_IO,tag_fixnum(errno),false_object,NULL);
|
general_error(ERROR_IO,tag_fixnum(errno),false_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
segment::segment(cell size_, bool executable_p)
|
segment::segment(cell size_, bool executable_p)
|
||||||
|
@ -141,16 +141,7 @@ segment::~segment()
|
||||||
|
|
||||||
void factor_vm::dispatch_signal(void *uap, void (handler)())
|
void factor_vm::dispatch_signal(void *uap, void (handler)())
|
||||||
{
|
{
|
||||||
if(in_code_heap_p(UAP_PROGRAM_COUNTER(uap)))
|
UAP_STACK_POINTER(uap) = fix_callstack_top((stack_frame *)UAP_STACK_POINTER(uap));
|
||||||
{
|
|
||||||
stack_frame *ptr = (stack_frame *)UAP_STACK_POINTER(uap);
|
|
||||||
assert(ptr);
|
|
||||||
signal_callstack_top = ptr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
signal_callstack_top = NULL;
|
|
||||||
|
|
||||||
UAP_STACK_POINTER(uap) = align_stack_pointer(UAP_STACK_POINTER(uap));
|
|
||||||
UAP_PROGRAM_COUNTER(uap) = (cell)handler;
|
UAP_PROGRAM_COUNTER(uap) = (cell)handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,8 @@ LONG factor_vm::exception_handler(PEXCEPTION_POINTERS pe)
|
||||||
PEXCEPTION_RECORD e = (PEXCEPTION_RECORD)pe->ExceptionRecord;
|
PEXCEPTION_RECORD e = (PEXCEPTION_RECORD)pe->ExceptionRecord;
|
||||||
CONTEXT *c = (CONTEXT*)pe->ContextRecord;
|
CONTEXT *c = (CONTEXT*)pe->ContextRecord;
|
||||||
|
|
||||||
|
c->ESP = (cell)fix_callstack_top((stack_frame *)c->ESP);
|
||||||
|
|
||||||
if(in_code_heap_p(c->EIP))
|
if(in_code_heap_p(c->EIP))
|
||||||
signal_callstack_top = (stack_frame *)c->ESP;
|
signal_callstack_top = (stack_frame *)c->ESP;
|
||||||
else
|
else
|
||||||
|
|
|
@ -140,7 +140,7 @@ long getpagesize()
|
||||||
void factor_vm::move_file(const vm_char *path1, const vm_char *path2)
|
void factor_vm::move_file(const vm_char *path1, const vm_char *path2)
|
||||||
{
|
{
|
||||||
if(MoveFileEx((path1),(path2),MOVEFILE_REPLACE_EXISTING) == false)
|
if(MoveFileEx((path1),(path2),MOVEFILE_REPLACE_EXISTING) == false)
|
||||||
general_error(ERROR_IO,tag_fixnum(GetLastError()),false_object,NULL);
|
general_error(ERROR_IO,tag_fixnum(GetLastError()),false_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,16 @@ struct segment {
|
||||||
|
|
||||||
explicit segment(cell size, bool executable_p);
|
explicit segment(cell size, bool executable_p);
|
||||||
~segment();
|
~segment();
|
||||||
|
|
||||||
|
bool underflow_p(cell addr)
|
||||||
|
{
|
||||||
|
return (addr >= start - getpagesize() && addr < start);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool overflow_p(cell addr)
|
||||||
|
{
|
||||||
|
return (addr >= end && addr < end + getpagesize());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
16
vm/vm.hpp
16
vm/vm.hpp
|
@ -160,20 +160,20 @@ struct factor_vm
|
||||||
void primitive_profiling();
|
void primitive_profiling();
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
void throw_error(cell error, stack_frame *callstack_top);
|
void throw_error(cell error, stack_frame *stack);
|
||||||
|
void general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *stack);
|
||||||
|
void general_error(vm_error_type error, cell arg1, cell arg2);
|
||||||
|
void type_error(cell type, cell tagged);
|
||||||
void not_implemented_error();
|
void not_implemented_error();
|
||||||
bool in_page(cell fault, cell area, cell area_size, int offset);
|
void memory_protection_error(cell addr, stack_frame *stack);
|
||||||
void memory_protection_error(cell addr, stack_frame *native_stack);
|
void signal_error(cell signal, stack_frame *stack);
|
||||||
void signal_error(cell signal, stack_frame *native_stack);
|
|
||||||
void divide_by_zero_error();
|
void divide_by_zero_error();
|
||||||
void fp_trap_error(unsigned int fpu_status, stack_frame *signal_callstack_top);
|
void fp_trap_error(unsigned int fpu_status, stack_frame *stack);
|
||||||
void primitive_call_clear();
|
void primitive_call_clear();
|
||||||
void primitive_unimplemented();
|
void primitive_unimplemented();
|
||||||
void memory_signal_handler_impl();
|
void memory_signal_handler_impl();
|
||||||
void misc_signal_handler_impl();
|
void misc_signal_handler_impl();
|
||||||
void fp_signal_handler_impl();
|
void fp_signal_handler_impl();
|
||||||
void type_error(cell type, cell tagged);
|
|
||||||
void general_error(vm_error_type error, cell arg1, cell arg2, stack_frame *native_stack);
|
|
||||||
|
|
||||||
// bignum
|
// bignum
|
||||||
int bignum_equal_p(bignum * x, bignum * y);
|
int bignum_equal_p(bignum * x, bignum * y);
|
||||||
|
@ -582,7 +582,7 @@ struct factor_vm
|
||||||
template<typename Iterator> void iterate_callstack_object(callstack *stack_, Iterator &iterator);
|
template<typename Iterator> void iterate_callstack_object(callstack *stack_, Iterator &iterator);
|
||||||
void check_frame(stack_frame *frame);
|
void check_frame(stack_frame *frame);
|
||||||
callstack *allot_callstack(cell size);
|
callstack *allot_callstack(cell size);
|
||||||
stack_frame *fix_callstack_top(stack_frame *top, stack_frame *bottom);
|
stack_frame *fix_callstack_top(stack_frame *top);
|
||||||
stack_frame *second_from_top_stack_frame();
|
stack_frame *second_from_top_stack_frame();
|
||||||
void primitive_callstack();
|
void primitive_callstack();
|
||||||
code_block *frame_code(stack_frame *frame);
|
code_block *frame_code(stack_frame *frame);
|
||||||
|
|
Loading…
Reference in New Issue