diff --git a/vm/callstack.c b/vm/callstack.c index 5c3ab0ea79..4461d39b1c 100644 --- a/vm/callstack.c +++ b/vm/callstack.c @@ -40,6 +40,16 @@ F_CALLSTACK *allot_callstack(CELL size) return callstack; } +F_STACK_FRAME *fix_callstack_top(F_STACK_FRAME *top, F_STACK_FRAME *bottom) +{ + F_STACK_FRAME *frame = bottom - 1; + + while(frame >= top) + frame = frame_successor(frame); + + return frame + 1; +} + /* We ignore the topmost frame, the one calling 'callstack', so that set-callstack doesn't get stuck in an infinite loop. diff --git a/vm/callstack.h b/vm/callstack.h index 564dea9738..4033820184 100644 --- a/vm/callstack.h +++ b/vm/callstack.h @@ -5,6 +5,7 @@ F_FASTCALL __attribute__((noinline)) void save_callstack_top(F_STACK_FRAME *call typedef void (*CALLSTACK_ITER)(F_STACK_FRAME *frame); +F_STACK_FRAME *fix_callstack_top(F_STACK_FRAME *top, F_STACK_FRAME *bottom); void iterate_callstack(CELL top, CELL bottom, CALLSTACK_ITER iterator); void iterate_callstack_object(F_CALLSTACK *stack, CALLSTACK_ITER iterator); F_STACK_FRAME *frame_successor(F_STACK_FRAME *frame); diff --git a/vm/errors.c b/vm/errors.c index b8f7a2c52a..27663f1193 100644 --- a/vm/errors.c +++ b/vm/errors.c @@ -35,7 +35,12 @@ void throw_error(CELL error, F_STACK_FRAME *callstack_top) 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) + if(callstack_top) + { + callstack_top = fix_callstack_top( + stack_chain->callstack_bottom,callstack_top); + } + else callstack_top = stack_chain->callstack_top; throw_impl(userenv[BREAK_ENV],callstack_top); diff --git a/vm/os-windows-nt.c b/vm/os-windows-nt.c index f6aa314819..9a54b895b8 100644 --- a/vm/os-windows-nt.c +++ b/vm/os-windows-nt.c @@ -29,7 +29,7 @@ long exception_handler(PEXCEPTION_POINTERS pe) CONTEXT *c = (CONTEXT*)pe->ContextRecord; if(in_code_heap_p(c->Eip)) - signal_callstack_top = (void *)(c->Esp - CELLS); + signal_callstack_top = (void *)c->Esp; else signal_callstack_top = NULL;