Grab native stack pointer from signal handler
parent
917a42cb4a
commit
756cea6164
6
TODO.txt
6
TODO.txt
|
@ -25,10 +25,8 @@
|
|||
- variable width word wrap
|
||||
- graphical crossref tool
|
||||
- inspector where slot values can be changed
|
||||
- compiled call traces:
|
||||
- should be independent of whenever the runtime was built with
|
||||
-fomit-frame-pointer on ppc
|
||||
- we don't know if signal handlers run with the same stack or not
|
||||
- compiled call traces do not work if the runtime is built with
|
||||
-fomit-frame-pointer on ppc
|
||||
- use crc32 instead of modification date in reload-modules
|
||||
- models: don't do redundant work
|
||||
- top level window positioning on ms windows
|
||||
|
|
382
vm/alien.c
382
vm/alien.c
|
@ -1,191 +1,191 @@
|
|||
#include "factor.h"
|
||||
|
||||
/* test if alien is no longer valid (it survived an image save/load) */
|
||||
void primitive_expired(void)
|
||||
{
|
||||
CELL object = dpeek();
|
||||
|
||||
if(type_of(object) == ALIEN_TYPE)
|
||||
{
|
||||
F_ALIEN *alien = untag_alien_fast(object);
|
||||
drepl(tag_boolean(alien->expired));
|
||||
}
|
||||
else if(object == F)
|
||||
drepl(T);
|
||||
else
|
||||
drepl(F);
|
||||
}
|
||||
|
||||
/* gets the address of an object representing a C pointer */
|
||||
void *alien_offset(CELL object)
|
||||
{
|
||||
F_ALIEN *alien;
|
||||
F_ARRAY *array;
|
||||
|
||||
switch(type_of(object))
|
||||
{
|
||||
case BYTE_ARRAY_TYPE:
|
||||
array = untag_array_fast(object);
|
||||
return array + 1;
|
||||
case ALIEN_TYPE:
|
||||
alien = untag_alien_fast(object);
|
||||
if(alien->expired)
|
||||
general_error(ERROR_EXPIRED,object,F,true);
|
||||
return alien_offset(alien->alien) + alien->displacement;
|
||||
case F_TYPE:
|
||||
return NULL;
|
||||
default:
|
||||
type_error(ALIEN_TYPE,object);
|
||||
return (void*)-1; /* can't happen */
|
||||
}
|
||||
}
|
||||
|
||||
/* pop an object representing a C pointer */
|
||||
void *unbox_alien(void)
|
||||
{
|
||||
return alien_offset(dpop());
|
||||
}
|
||||
|
||||
/* make an alien */
|
||||
CELL allot_alien(CELL delegate, CELL displacement)
|
||||
{
|
||||
REGISTER_ROOT(delegate);
|
||||
F_ALIEN *alien = allot_object(ALIEN_TYPE,sizeof(F_ALIEN));
|
||||
UNREGISTER_ROOT(delegate);
|
||||
alien->alien = delegate;
|
||||
alien->displacement = displacement;
|
||||
alien->expired = false;
|
||||
return tag_object(alien);
|
||||
}
|
||||
|
||||
/* make an alien and push */
|
||||
void box_alien(void* ptr)
|
||||
{
|
||||
if(ptr == NULL)
|
||||
dpush(F);
|
||||
else
|
||||
dpush(allot_alien(F,(CELL)ptr));
|
||||
}
|
||||
|
||||
/* make an alien pointing at an offset of another alien */
|
||||
void primitive_displaced_alien(void)
|
||||
{
|
||||
CELL alien = dpop();
|
||||
CELL displacement = unbox_unsigned_cell();
|
||||
if(alien == F && displacement == 0)
|
||||
dpush(F);
|
||||
else
|
||||
dpush(allot_alien(alien,displacement));
|
||||
}
|
||||
|
||||
/* address of an object representing a C pointer. Explicitly throw an error
|
||||
if the object is a byte array, as a sanity check. */
|
||||
void primitive_alien_address(void)
|
||||
{
|
||||
CELL object = dpop();
|
||||
if(type_of(object) == BYTE_ARRAY_TYPE)
|
||||
type_error(ALIEN_TYPE,object);
|
||||
else
|
||||
box_unsigned_cell((CELL)alien_offset(object));
|
||||
}
|
||||
|
||||
/* image loading */
|
||||
void fixup_alien(F_ALIEN *d)
|
||||
{
|
||||
d->expired = true;
|
||||
}
|
||||
|
||||
/* pop ( alien n ) from datastack, return alien's address plus n */
|
||||
INLINE void *alien_pointer(void)
|
||||
{
|
||||
F_FIXNUM offset = unbox_signed_cell();
|
||||
return unbox_alien() + offset;
|
||||
}
|
||||
|
||||
/* define words to read/write values at an alien address */
|
||||
#define DEF_ALIEN_SLOT(name,type,boxer) \
|
||||
void primitive_alien_##name (void) \
|
||||
{ \
|
||||
box_##boxer (*(type*)alien_pointer()); \
|
||||
} \
|
||||
void primitive_set_alien_##name (void) \
|
||||
{ \
|
||||
type* ptr = alien_pointer(); \
|
||||
type value = unbox_##boxer(); \
|
||||
*ptr = value; \
|
||||
}
|
||||
|
||||
DEF_ALIEN_SLOT(signed_cell,F_FIXNUM,signed_cell)
|
||||
DEF_ALIEN_SLOT(unsigned_cell,CELL,unsigned_cell)
|
||||
DEF_ALIEN_SLOT(signed_8,s64,signed_8)
|
||||
DEF_ALIEN_SLOT(unsigned_8,u64,unsigned_8)
|
||||
DEF_ALIEN_SLOT(signed_4,s32,signed_4)
|
||||
DEF_ALIEN_SLOT(unsigned_4,u32,unsigned_4)
|
||||
DEF_ALIEN_SLOT(signed_2,s16,signed_2)
|
||||
DEF_ALIEN_SLOT(unsigned_2,u16,unsigned_2)
|
||||
DEF_ALIEN_SLOT(signed_1,u8,signed_1)
|
||||
DEF_ALIEN_SLOT(unsigned_1,u8,unsigned_1)
|
||||
DEF_ALIEN_SLOT(float,float,float)
|
||||
DEF_ALIEN_SLOT(double,double,double)
|
||||
|
||||
/* for FFI calls passing structs by value */
|
||||
void unbox_value_struct(void *dest, CELL size)
|
||||
{
|
||||
memcpy(dest,unbox_alien(),size);
|
||||
}
|
||||
|
||||
/* for FFI callbacks receiving structs by value */
|
||||
void box_value_struct(void *src, CELL size)
|
||||
{
|
||||
F_ARRAY *array = allot_byte_array(size);
|
||||
memcpy(array + 1,src,size);
|
||||
dpush(tag_object(array));
|
||||
}
|
||||
|
||||
/* for FFI calls returning an 8-byte struct. This only
|
||||
happens on Intel Mac OS X */
|
||||
void box_value_pair(CELL x, CELL y)
|
||||
{
|
||||
F_ARRAY *array = allot_byte_array(2 * sizeof(CELL));
|
||||
set_array_nth(array,0,x);
|
||||
set_array_nth(array,1,y);
|
||||
dpush(tag_object(array));
|
||||
}
|
||||
|
||||
/* open a native library and push a handle */
|
||||
void primitive_dlopen(void)
|
||||
{
|
||||
primitive_string_to_char_alien();
|
||||
F_DLL* dll = allot_object(DLL_TYPE,sizeof(F_DLL));
|
||||
dll->path = dpop();
|
||||
ffi_dlopen(dll,true);
|
||||
dpush(tag_object(dll));
|
||||
}
|
||||
|
||||
/* look up a symbol in a native library */
|
||||
void primitive_dlsym(void)
|
||||
{
|
||||
CELL dll = dpop();
|
||||
REGISTER_ROOT(dll);
|
||||
char *sym = unbox_char_string();
|
||||
UNREGISTER_ROOT(dll);
|
||||
|
||||
F_DLL *d;
|
||||
|
||||
if(dll == F)
|
||||
d = NULL;
|
||||
else
|
||||
{
|
||||
d = untag_dll(dll);
|
||||
if(d->dll == NULL)
|
||||
general_error(ERROR_EXPIRED,dll,F,true);
|
||||
}
|
||||
|
||||
box_alien(ffi_dlsym(d,sym,true));
|
||||
}
|
||||
|
||||
/* close a native library handle */
|
||||
void primitive_dlclose(void)
|
||||
{
|
||||
ffi_dlclose(untag_dll(dpop()));
|
||||
}
|
||||
#include "factor.h"
|
||||
|
||||
/* test if alien is no longer valid (it survived an image save/load) */
|
||||
void primitive_expired(void)
|
||||
{
|
||||
CELL object = dpeek();
|
||||
|
||||
if(type_of(object) == ALIEN_TYPE)
|
||||
{
|
||||
F_ALIEN *alien = untag_alien_fast(object);
|
||||
drepl(tag_boolean(alien->expired));
|
||||
}
|
||||
else if(object == F)
|
||||
drepl(T);
|
||||
else
|
||||
drepl(F);
|
||||
}
|
||||
|
||||
/* gets the address of an object representing a C pointer */
|
||||
void *alien_offset(CELL object)
|
||||
{
|
||||
F_ALIEN *alien;
|
||||
F_ARRAY *array;
|
||||
|
||||
switch(type_of(object))
|
||||
{
|
||||
case BYTE_ARRAY_TYPE:
|
||||
array = untag_array_fast(object);
|
||||
return array + 1;
|
||||
case ALIEN_TYPE:
|
||||
alien = untag_alien_fast(object);
|
||||
if(alien->expired)
|
||||
simple_error(ERROR_EXPIRED,object,F);
|
||||
return alien_offset(alien->alien) + alien->displacement;
|
||||
case F_TYPE:
|
||||
return NULL;
|
||||
default:
|
||||
type_error(ALIEN_TYPE,object);
|
||||
return (void*)-1; /* can't happen */
|
||||
}
|
||||
}
|
||||
|
||||
/* pop an object representing a C pointer */
|
||||
void *unbox_alien(void)
|
||||
{
|
||||
return alien_offset(dpop());
|
||||
}
|
||||
|
||||
/* make an alien */
|
||||
CELL allot_alien(CELL delegate, CELL displacement)
|
||||
{
|
||||
REGISTER_ROOT(delegate);
|
||||
F_ALIEN *alien = allot_object(ALIEN_TYPE,sizeof(F_ALIEN));
|
||||
UNREGISTER_ROOT(delegate);
|
||||
alien->alien = delegate;
|
||||
alien->displacement = displacement;
|
||||
alien->expired = false;
|
||||
return tag_object(alien);
|
||||
}
|
||||
|
||||
/* make an alien and push */
|
||||
void box_alien(void* ptr)
|
||||
{
|
||||
if(ptr == NULL)
|
||||
dpush(F);
|
||||
else
|
||||
dpush(allot_alien(F,(CELL)ptr));
|
||||
}
|
||||
|
||||
/* make an alien pointing at an offset of another alien */
|
||||
void primitive_displaced_alien(void)
|
||||
{
|
||||
CELL alien = dpop();
|
||||
CELL displacement = unbox_unsigned_cell();
|
||||
if(alien == F && displacement == 0)
|
||||
dpush(F);
|
||||
else
|
||||
dpush(allot_alien(alien,displacement));
|
||||
}
|
||||
|
||||
/* address of an object representing a C pointer. Explicitly throw an error
|
||||
if the object is a byte array, as a sanity check. */
|
||||
void primitive_alien_address(void)
|
||||
{
|
||||
CELL object = dpop();
|
||||
if(type_of(object) == BYTE_ARRAY_TYPE)
|
||||
type_error(ALIEN_TYPE,object);
|
||||
else
|
||||
box_unsigned_cell((CELL)alien_offset(object));
|
||||
}
|
||||
|
||||
/* image loading */
|
||||
void fixup_alien(F_ALIEN *d)
|
||||
{
|
||||
d->expired = true;
|
||||
}
|
||||
|
||||
/* pop ( alien n ) from datastack, return alien's address plus n */
|
||||
INLINE void *alien_pointer(void)
|
||||
{
|
||||
F_FIXNUM offset = unbox_signed_cell();
|
||||
return unbox_alien() + offset;
|
||||
}
|
||||
|
||||
/* define words to read/write values at an alien address */
|
||||
#define DEF_ALIEN_SLOT(name,type,boxer) \
|
||||
void primitive_alien_##name (void) \
|
||||
{ \
|
||||
box_##boxer (*(type*)alien_pointer()); \
|
||||
} \
|
||||
void primitive_set_alien_##name (void) \
|
||||
{ \
|
||||
type* ptr = alien_pointer(); \
|
||||
type value = unbox_##boxer(); \
|
||||
*ptr = value; \
|
||||
}
|
||||
|
||||
DEF_ALIEN_SLOT(signed_cell,F_FIXNUM,signed_cell)
|
||||
DEF_ALIEN_SLOT(unsigned_cell,CELL,unsigned_cell)
|
||||
DEF_ALIEN_SLOT(signed_8,s64,signed_8)
|
||||
DEF_ALIEN_SLOT(unsigned_8,u64,unsigned_8)
|
||||
DEF_ALIEN_SLOT(signed_4,s32,signed_4)
|
||||
DEF_ALIEN_SLOT(unsigned_4,u32,unsigned_4)
|
||||
DEF_ALIEN_SLOT(signed_2,s16,signed_2)
|
||||
DEF_ALIEN_SLOT(unsigned_2,u16,unsigned_2)
|
||||
DEF_ALIEN_SLOT(signed_1,u8,signed_1)
|
||||
DEF_ALIEN_SLOT(unsigned_1,u8,unsigned_1)
|
||||
DEF_ALIEN_SLOT(float,float,float)
|
||||
DEF_ALIEN_SLOT(double,double,double)
|
||||
|
||||
/* for FFI calls passing structs by value */
|
||||
void unbox_value_struct(void *dest, CELL size)
|
||||
{
|
||||
memcpy(dest,unbox_alien(),size);
|
||||
}
|
||||
|
||||
/* for FFI callbacks receiving structs by value */
|
||||
void box_value_struct(void *src, CELL size)
|
||||
{
|
||||
F_ARRAY *array = allot_byte_array(size);
|
||||
memcpy(array + 1,src,size);
|
||||
dpush(tag_object(array));
|
||||
}
|
||||
|
||||
/* for FFI calls returning an 8-byte struct. This only
|
||||
happens on Intel Mac OS X */
|
||||
void box_value_pair(CELL x, CELL y)
|
||||
{
|
||||
F_ARRAY *array = allot_byte_array(2 * sizeof(CELL));
|
||||
set_array_nth(array,0,x);
|
||||
set_array_nth(array,1,y);
|
||||
dpush(tag_object(array));
|
||||
}
|
||||
|
||||
/* open a native library and push a handle */
|
||||
void primitive_dlopen(void)
|
||||
{
|
||||
primitive_string_to_char_alien();
|
||||
F_DLL* dll = allot_object(DLL_TYPE,sizeof(F_DLL));
|
||||
dll->path = dpop();
|
||||
ffi_dlopen(dll,true);
|
||||
dpush(tag_object(dll));
|
||||
}
|
||||
|
||||
/* look up a symbol in a native library */
|
||||
void primitive_dlsym(void)
|
||||
{
|
||||
CELL dll = dpop();
|
||||
REGISTER_ROOT(dll);
|
||||
char *sym = unbox_char_string();
|
||||
UNREGISTER_ROOT(dll);
|
||||
|
||||
F_DLL *d;
|
||||
|
||||
if(dll == F)
|
||||
d = NULL;
|
||||
else
|
||||
{
|
||||
d = untag_dll(dll);
|
||||
if(d->dll == NULL)
|
||||
simple_error(ERROR_EXPIRED,dll,F);
|
||||
}
|
||||
|
||||
box_alien(ffi_dlsym(d,sym,true));
|
||||
}
|
||||
|
||||
/* close a native library handle */
|
||||
void primitive_dlclose(void)
|
||||
{
|
||||
ffi_dlclose(untag_dll(dpop()));
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
image load */
|
||||
void undefined_symbol(void)
|
||||
{
|
||||
general_error(ERROR_UNDEFINED_SYMBOL,F,F,true);
|
||||
simple_error(ERROR_UNDEFINED_SYMBOL,F,F);
|
||||
}
|
||||
|
||||
#define CREF(array,i) ((CELL)(array) + CELLS * (i))
|
||||
|
|
|
@ -114,7 +114,7 @@ void primitive_next_object(void)
|
|||
CELL type;
|
||||
|
||||
if(!gc_off)
|
||||
general_error(ERROR_HEAP_SCAN,F,F,true);
|
||||
simple_error(ERROR_HEAP_SCAN,F,F);
|
||||
|
||||
if(heap_scan_ptr >= tenured.here)
|
||||
{
|
||||
|
|
|
@ -235,7 +235,7 @@ void factorbug(void)
|
|||
fprintf(stderr,"%lx\n",(CELL)CARD_TO_ADDR(card));
|
||||
}
|
||||
else if(strcmp(cmd,"t") == 0)
|
||||
general_error(ERROR_USER_INTERRUPT,F,F,true);
|
||||
simple_error(ERROR_USER_INTERRUPT,F,F);
|
||||
else if(strcmp(cmd,"q") == 0)
|
||||
return;
|
||||
else if(strcmp(cmd,"x") == 0)
|
||||
|
|
2
vm/io.c
2
vm/io.c
|
@ -21,7 +21,7 @@ void init_c_io(void)
|
|||
void io_error(void)
|
||||
{
|
||||
CELL error = tag_object(from_char_string(strerror(errno)));
|
||||
general_error(ERROR_IO,error,F,true);
|
||||
simple_error(ERROR_IO,error,F);
|
||||
}
|
||||
|
||||
void primitive_fopen(void)
|
||||
|
|
|
@ -24,14 +24,14 @@ static mach_port_t our_exception_port;
|
|||
static void
|
||||
memory_protection_handler (void *fault_addr)
|
||||
{
|
||||
memory_protection_error((CELL)fault_addr,SIGSEGV);
|
||||
memory_protection_error((CELL)fault_addr,SIGSEGV,native_stack_pointer());
|
||||
abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
arithmetic_handler (void *ignore)
|
||||
{
|
||||
signal_error(SIGFPE);
|
||||
signal_error(SIGFPE,native_stack_pointer());
|
||||
abort ();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ NS_DURING
|
|||
{
|
||||
CELL e = error;
|
||||
error = F;
|
||||
general_error(ERROR_OBJECTIVE_C,e,F,true);
|
||||
simple_error(ERROR_OBJECTIVE_C,e,F);
|
||||
}
|
||||
|
||||
interpreter_loop();
|
||||
|
|
30
vm/os-unix.c
30
vm/os-unix.c
|
@ -22,8 +22,8 @@ void ffi_dlopen(F_DLL *dll, bool error)
|
|||
{
|
||||
if(error)
|
||||
{
|
||||
general_error(ERROR_FFI,F,
|
||||
tag_object(from_char_string(dlerror())),true);
|
||||
simple_error(ERROR_FFI,F,
|
||||
tag_object(from_char_string(dlerror())));
|
||||
}
|
||||
else
|
||||
dll->dll = NULL;
|
||||
|
@ -42,9 +42,9 @@ void *ffi_dlsym(F_DLL *dll, char *symbol, bool error)
|
|||
{
|
||||
if(error)
|
||||
{
|
||||
general_error(ERROR_FFI,
|
||||
simple_error(ERROR_FFI,
|
||||
tag_object(from_char_string(symbol)),
|
||||
tag_object(from_char_string(dlerror())),true);
|
||||
tag_object(from_char_string(dlerror())));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -56,8 +56,8 @@ void ffi_dlclose(F_DLL *dll)
|
|||
{
|
||||
if(dlclose(dll->dll))
|
||||
{
|
||||
general_error(ERROR_FFI,tag_object(
|
||||
from_char_string(dlerror())),F,true);
|
||||
simple_error(ERROR_FFI,tag_object(
|
||||
from_char_string(dlerror())),F);
|
||||
}
|
||||
dll->dll = NULL;
|
||||
}
|
||||
|
@ -158,14 +158,21 @@ void dealloc_segment(F_SEGMENT *block)
|
|||
free(block);
|
||||
}
|
||||
|
||||
void memory_signal_handler(int signal, siginfo_t* siginfo, void* uap)
|
||||
INLINE F_STACK_FRAME *uap_stack_pointer(void *uap)
|
||||
{
|
||||
memory_protection_error((CELL)siginfo->si_addr, signal);
|
||||
ucontext_t *ucontext = (ucontext_t *)uap;
|
||||
return (F_STACK_FRAME *)ucontext->uc_stack.ss_sp;
|
||||
}
|
||||
|
||||
void misc_signal_handler(int signal, siginfo_t* siginfo, void* uap)
|
||||
void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
signal_error(signal);
|
||||
memory_protection_error((CELL)siginfo->si_addr,signal,
|
||||
uap_stack_pointer(uap));
|
||||
}
|
||||
|
||||
void misc_signal_handler(int signal, siginfo_t *siginfo, void *uap)
|
||||
{
|
||||
signal_error(signal,uap_stack_pointer(uap));
|
||||
}
|
||||
|
||||
static void sigaction_safe(int signum, const struct sigaction *act, struct sigaction *oldact)
|
||||
|
@ -174,7 +181,8 @@ static void sigaction_safe(int signum, const struct sigaction *act, struct sigac
|
|||
do
|
||||
{
|
||||
ret = sigaction(signum, act, oldact);
|
||||
} while(ret == -1 && errno == EINTR);
|
||||
}
|
||||
while(ret == -1 && errno == EINTR);
|
||||
}
|
||||
|
||||
void unix_init_signals(void)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <dlfcn.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#define DLLEXPORT
|
||||
#define SETJMP(jmpbuf) sigsetjmp(jmpbuf,1)
|
||||
|
|
|
@ -48,7 +48,8 @@ void ffi_dlopen (F_DLL *dll, bool error)
|
|||
{
|
||||
dll->dll = NULL;
|
||||
if(error)
|
||||
general_error(ERROR_FFI, F, tag_object(get_error_message()),true);
|
||||
simple_error(ERROR_FFI,F,
|
||||
tag_object(get_error_message()));
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
@ -65,9 +66,9 @@ void *ffi_dlsym (F_DLL *dll, char *symbol, bool error)
|
|||
if (!sym)
|
||||
{
|
||||
if(error)
|
||||
general_error(ERROR_FFI,
|
||||
simple_error(ERROR_FFI,
|
||||
tag_object(from_char_string(symbol)),
|
||||
tag_object(get_error_message()),true);
|
||||
tag_object(get_error_message()));
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
@ -222,7 +223,8 @@ void seh_call(void (*func)(), exception_handler_t *handler)
|
|||
|
||||
static long exception_handler(PEXCEPTION_RECORD rec, void *frame, void *ctx, void *dispatch)
|
||||
{
|
||||
memory_protection_error(rec->ExceptionInformation[1], SIGSEGV);
|
||||
memory_protection_error(rec->ExceptionInformation[1],
|
||||
SIGSEGV,native_stack_pointer());
|
||||
return -1; /* unreachable */
|
||||
}
|
||||
|
||||
|
|
59
vm/run.c
59
vm/run.c
|
@ -75,7 +75,7 @@ void interpreter_loop(void)
|
|||
if(stack_chain->next)
|
||||
return;
|
||||
|
||||
general_error(ERROR_CS_UNDERFLOW,F,F,false);
|
||||
simple_error(ERROR_CS_UNDERFLOW,F,F);
|
||||
}
|
||||
|
||||
callframe_end = get(cs);
|
||||
|
@ -121,7 +121,7 @@ void run_callback(CELL quot)
|
|||
/* XT of deferred words */
|
||||
void undefined(F_WORD* word)
|
||||
{
|
||||
general_error(ERROR_UNDEFINED_WORD,tag_word(word),F,true);
|
||||
simple_error(ERROR_UNDEFINED_WORD,tag_word(word),F);
|
||||
}
|
||||
|
||||
/* XT of compound definitions */
|
||||
|
@ -258,14 +258,13 @@ void early_error(CELL error)
|
|||
}
|
||||
|
||||
/* allocates memory */
|
||||
CELL allot_native_stack_trace(void)
|
||||
CELL allot_native_stack_trace(F_STACK_FRAME *stack)
|
||||
{
|
||||
F_STACK_FRAME *frame = native_stack_pointer();
|
||||
GROWABLE_ARRAY(array);
|
||||
|
||||
while(frame < stack_chain->native_stack_pointer)
|
||||
while(stack < stack_chain->native_stack_pointer)
|
||||
{
|
||||
CELL return_address = RETURN_ADDRESS(frame);
|
||||
CELL return_address = RETURN_ADDRESS(stack);
|
||||
|
||||
if(return_address >= compiling.base
|
||||
&& return_address <= compiling.limit)
|
||||
|
@ -276,16 +275,16 @@ CELL allot_native_stack_trace(void)
|
|||
GROWABLE_ADD(array,cell);
|
||||
}
|
||||
|
||||
F_STACK_FRAME *prev = PREVIOUS_FRAME(frame);
|
||||
F_STACK_FRAME *prev = PREVIOUS_FRAME(stack);
|
||||
|
||||
if(prev <= frame)
|
||||
if(prev <= stack)
|
||||
{
|
||||
fprintf(stderr,"*** Unusual C stack layout (why?)\n");
|
||||
fflush(stderr);
|
||||
break;
|
||||
}
|
||||
|
||||
frame = prev;
|
||||
stack = prev;
|
||||
}
|
||||
|
||||
GROWABLE_TRIM(array);
|
||||
|
@ -293,12 +292,12 @@ CELL allot_native_stack_trace(void)
|
|||
return tag_object(array);
|
||||
}
|
||||
|
||||
void throw_error(CELL error, bool keep_stacks)
|
||||
void throw_error(CELL error, bool keep_stacks, F_STACK_FRAME *native_stack)
|
||||
{
|
||||
early_error(error);
|
||||
|
||||
REGISTER_ROOT(error);
|
||||
thrown_native_stack_trace = allot_native_stack_trace();
|
||||
thrown_native_stack_trace = allot_native_stack_trace(native_stack);
|
||||
UNREGISTER_ROOT(error);
|
||||
|
||||
throwing = true;
|
||||
|
@ -313,7 +312,7 @@ void throw_error(CELL error, bool keep_stacks)
|
|||
|
||||
void primitive_throw(void)
|
||||
{
|
||||
throw_error(dpop(),true);
|
||||
throw_error(dpop(),true,native_stack_pointer());
|
||||
}
|
||||
|
||||
void primitive_die(void)
|
||||
|
@ -321,51 +320,57 @@ void primitive_die(void)
|
|||
factorbug();
|
||||
}
|
||||
|
||||
void general_error(F_ERRORTYPE error, CELL arg1, CELL arg2, bool keep_stacks)
|
||||
void general_error(F_ERRORTYPE error, CELL arg1, CELL arg2,
|
||||
bool keep_stacks, F_STACK_FRAME *native_stack)
|
||||
{
|
||||
throw_error(allot_array_4(userenv[ERROR_ENV],
|
||||
tag_fixnum(error),arg1,arg2),keep_stacks);
|
||||
tag_fixnum(error),arg1,arg2),keep_stacks,native_stack);
|
||||
}
|
||||
|
||||
void memory_protection_error(CELL addr, int signal)
|
||||
void simple_error(F_ERRORTYPE error, CELL arg1, CELL arg2)
|
||||
{
|
||||
general_error(error,arg1,arg2,true,native_stack_pointer());
|
||||
}
|
||||
|
||||
void memory_protection_error(CELL addr, int signal, F_STACK_FRAME *native_stack)
|
||||
{
|
||||
gc_off = true;
|
||||
|
||||
if(in_page(addr, ds_bot, 0, -1))
|
||||
general_error(ERROR_DS_UNDERFLOW,F,F,false);
|
||||
general_error(ERROR_DS_UNDERFLOW,F,F,false,native_stack);
|
||||
else if(in_page(addr, ds_bot, ds_size, 0))
|
||||
general_error(ERROR_DS_OVERFLOW,F,F,false);
|
||||
general_error(ERROR_DS_OVERFLOW,F,F,false,native_stack);
|
||||
else if(in_page(addr, rs_bot, 0, -1))
|
||||
general_error(ERROR_RS_UNDERFLOW,F,F,false);
|
||||
general_error(ERROR_RS_UNDERFLOW,F,F,false,native_stack);
|
||||
else if(in_page(addr, rs_bot, rs_size, 0))
|
||||
general_error(ERROR_RS_OVERFLOW,F,F,false);
|
||||
general_error(ERROR_RS_OVERFLOW,F,F,false,native_stack);
|
||||
else if(in_page(addr, cs_bot, 0, -1))
|
||||
general_error(ERROR_CS_UNDERFLOW,F,F,false);
|
||||
general_error(ERROR_CS_UNDERFLOW,F,F,false,native_stack);
|
||||
else if(in_page(addr, cs_bot, cs_size, 0))
|
||||
general_error(ERROR_CS_OVERFLOW,F,F,false);
|
||||
general_error(ERROR_CS_OVERFLOW,F,F,false,native_stack);
|
||||
else if(in_page(addr, nursery.limit, 0, 0))
|
||||
critical_error("Out of memory in allot",0);
|
||||
|
||||
signal_error(signal);
|
||||
signal_error(signal,native_stack);
|
||||
}
|
||||
|
||||
void signal_error(int signal)
|
||||
void signal_error(int signal, F_STACK_FRAME *native_stack)
|
||||
{
|
||||
gc_off = true;
|
||||
general_error(ERROR_SIGNAL,tag_fixnum(signal),F,false);
|
||||
general_error(ERROR_SIGNAL,tag_fixnum(signal),F,false,native_stack);
|
||||
}
|
||||
|
||||
void type_error(CELL type, CELL tagged)
|
||||
{
|
||||
general_error(ERROR_TYPE,tag_fixnum(type),tagged,true);
|
||||
simple_error(ERROR_TYPE,tag_fixnum(type),tagged);
|
||||
}
|
||||
|
||||
void divide_by_zero_error(void)
|
||||
{
|
||||
general_error(ERROR_DIVIDE_BY_ZERO,F,F,true);
|
||||
simple_error(ERROR_DIVIDE_BY_ZERO,F,F);
|
||||
}
|
||||
|
||||
void memory_error(void)
|
||||
{
|
||||
general_error(ERROR_MEMORY,F,F,true);
|
||||
simple_error(ERROR_MEMORY,F,F);
|
||||
}
|
||||
|
|
10
vm/run.h
10
vm/run.h
|
@ -188,11 +188,13 @@ CELL thrown_rs;
|
|||
|
||||
void fatal_error(char* msg, CELL tagged);
|
||||
void critical_error(char* msg, CELL tagged);
|
||||
void throw_error(CELL error, bool keep_stacks);
|
||||
void throw_error(CELL error, bool keep_stacks, F_STACK_FRAME *native_stack);
|
||||
void early_error(CELL error);
|
||||
void general_error(F_ERRORTYPE error, CELL arg1, CELL arg2, bool keep_stacks);
|
||||
void memory_protection_error(CELL addr, int signal);
|
||||
void signal_error(int signal);
|
||||
void general_error(F_ERRORTYPE error, CELL arg1, CELL arg2,
|
||||
bool keep_stacks, F_STACK_FRAME *native_stack);
|
||||
void simple_error(F_ERRORTYPE error, CELL arg1, CELL arg2);
|
||||
void memory_protection_error(CELL addr, int signal, F_STACK_FRAME *native_stacks);
|
||||
void signal_error(int signal, F_STACK_FRAME *native_stack);
|
||||
void type_error(CELL type, CELL tagged);
|
||||
void divide_by_zero_error(void);
|
||||
void memory_error(void);
|
||||
|
|
10
vm/types.c
10
vm/types.c
|
@ -20,7 +20,7 @@ F_ARRAY *allot_array_internal(CELL type, F_FIXNUM capacity)
|
|||
|
||||
if(capacity < 0)
|
||||
{
|
||||
general_error(ERROR_NEGATIVE_ARRAY_SIZE,allot_integer(capacity),F,true);
|
||||
simple_error(ERROR_NEGATIVE_ARRAY_SIZE,allot_integer(capacity),F);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
|
@ -48,7 +48,7 @@ F_ARRAY *allot_byte_array(F_FIXNUM size)
|
|||
{
|
||||
if(size < 0)
|
||||
{
|
||||
general_error(ERROR_NEGATIVE_ARRAY_SIZE,allot_integer(size),F,true);
|
||||
simple_error(ERROR_NEGATIVE_ARRAY_SIZE,allot_integer(size),F);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ F_STRING* allot_string_internal(F_FIXNUM capacity)
|
|||
|
||||
if(capacity < 0)
|
||||
{
|
||||
general_error(ERROR_NEGATIVE_ARRAY_SIZE,allot_integer(capacity),F,true);
|
||||
simple_error(ERROR_NEGATIVE_ARRAY_SIZE,allot_integer(capacity),F);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
|
@ -309,7 +309,7 @@ F_ARRAY *allot_c_string(CELL capacity, CELL size)
|
|||
CELL capacity = string_capacity(s); \
|
||||
F_ARRAY *_c_str; \
|
||||
if(check && !check_string(s,sizeof(type))) \
|
||||
general_error(ERROR_C_STRING,tag_object(s),F,true); \
|
||||
simple_error(ERROR_C_STRING,tag_object(s),F); \
|
||||
REGISTER_STRING(s); \
|
||||
_c_str = allot_c_string(capacity,sizeof(type)); \
|
||||
UNREGISTER_STRING(s); \
|
||||
|
@ -323,7 +323,7 @@ F_ARRAY *allot_c_string(CELL capacity, CELL size)
|
|||
if(sizeof(type) == sizeof(u16)) \
|
||||
{ \
|
||||
if(check && !check_string(s,sizeof(type))) \
|
||||
general_error(ERROR_C_STRING,tag_object(s),F,true); \
|
||||
simple_error(ERROR_C_STRING,tag_object(s),F); \
|
||||
return (type*)(s + 1); \
|
||||
} \
|
||||
else \
|
||||
|
|
Loading…
Reference in New Issue