diff --git a/vm/callstack.cpp b/vm/callstack.cpp index 70378da1d5..830ef6b35c 100755 --- a/vm/callstack.cpp +++ b/vm/callstack.cpp @@ -3,14 +3,6 @@ namespace factor { -void factor_vm::check_frame(stack_frame *frame) -{ -#ifdef FACTOR_DEBUG - check_code_pointer((cell)frame->entry_point); - FACTOR_ASSERT(frame->size != 0); -#endif -} - callstack *factor_vm::allot_callstack(cell size) { callstack *stack = allot(callstack_object_size(size)); @@ -26,22 +18,23 @@ This means that if 'callstack' is called in tail position, we will have popped a necessary frame... however this word is only called by continuation implementation, and user code shouldn't be calling it at all, so we leave it as it is for now. */ -stack_frame *factor_vm::second_from_top_stack_frame(context *ctx) +void *factor_vm::second_from_top_stack_frame(context *ctx) { - stack_frame *frame = ctx->bottom_frame(); - while(frame >= ctx->callstack_top - && frame_successor(frame) >= ctx->callstack_top - && frame_successor(frame_successor(frame)) >= ctx->callstack_top) + void *frame_top = ctx->callstack_top; + for (unsigned i = 0; i < 2; ++i) { - frame = frame_successor(frame); + void *pred = frame_predecessor(frame_top); + if (pred >= ctx->callstack_bottom) + return frame_top; + frame_top = pred; } - return frame + 1; + return frame_top; } cell factor_vm::capture_callstack(context *ctx) { - stack_frame *top = second_from_top_stack_frame(ctx); - stack_frame *bottom = ctx->callstack_bottom; + void *top = second_from_top_stack_frame(ctx); + void *bottom = ctx->callstack_bottom; fixnum size = std::max((fixnum)0,(fixnum)bottom - (fixnum)top); @@ -61,49 +54,13 @@ void factor_vm::primitive_callstack_for() ctx->push(capture_callstack(other_ctx)); } -code_block *factor_vm::frame_code(stack_frame *frame) +void *factor_vm::frame_predecessor(void *frame_top) { - check_frame(frame); - return (code_block *)frame->entry_point - 1; -} - -code_block_type factor_vm::frame_type(stack_frame *frame) -{ - return frame_code(frame)->type(); -} - -cell factor_vm::frame_executing(stack_frame *frame) -{ - return frame_code(frame)->owner; -} - -cell factor_vm::frame_executing_quot(stack_frame *frame) -{ - return frame_code(frame)->owner_quot(); -} - -stack_frame *factor_vm::frame_successor(stack_frame *frame) -{ - check_frame(frame); - return (stack_frame *)((cell)frame - frame->size); -} - -cell factor_vm::frame_offset(stack_frame *frame) -{ - char *return_address = (char *)FRAME_RETURN_ADDRESS(frame,this); - FACTOR_ASSERT(return_address != 0); - return frame_code(frame)->offset(return_address); -} - -void factor_vm::set_frame_offset(stack_frame *frame, cell offset) -{ - char *entry_point = (char *)frame_code(frame)->entry_point(); - FRAME_RETURN_ADDRESS(frame,this) = entry_point + offset; -} - -cell factor_vm::frame_scan(stack_frame *frame) -{ - return frame_code(frame)->scan(this, FRAME_RETURN_ADDRESS(frame,this)); + void *addr = frame_return_address((void*)frame_top); + FACTOR_ASSERT(addr != 0); + code_block *owner = code->code_block_for_address((cell)addr); + cell frame_size = owner->stack_frame_size_for_address((cell)addr); + return (void*)((char*)frame_top + frame_size); } struct stack_frame_accumulator { @@ -145,14 +102,18 @@ void factor_vm::primitive_callstack_to_array() } -stack_frame *factor_vm::innermost_stack_frame(stack_frame *bottom, stack_frame *top) +void *factor_vm::innermost_stack_frame(void *bottom, void *top) { - stack_frame *frame = bottom - 1; - - while(frame >= top && frame_successor(frame) >= top) - frame = frame_successor(frame); - - return frame; + /* if (top < bottom) + { + void *pred = frame_predecessor(top); + if (pred < bottom) + return pred; + else + return top; + } + else */ + return top; } /* Some primitives implementing a limited form of callstack mutation. @@ -160,15 +121,17 @@ Used by the single stepper. */ void factor_vm::primitive_innermost_stack_frame_executing() { callstack *stack = untag_check(ctx->pop()); - stack_frame *frame = innermost_stack_frame(stack->bottom(), stack->top()); - ctx->push(frame_executing_quot(frame)); + void *frame = innermost_stack_frame(stack->bottom(), stack->top()); + void *addr = frame_return_address(frame); + ctx->push(code->code_block_for_address((cell)addr)->owner_quot()); } void factor_vm::primitive_innermost_stack_frame_scan() { callstack *stack = untag_check(ctx->pop()); - stack_frame *frame = innermost_stack_frame(stack->bottom(), stack->top()); - ctx->push(frame_scan(frame)); + void *frame = innermost_stack_frame(stack->bottom(), stack->top()); + void *addr = frame_return_address(frame); + ctx->push(code->code_block_for_address((cell)addr)->scan(this,addr)); } void factor_vm::primitive_set_innermost_stack_frame_quot() @@ -181,10 +144,11 @@ void factor_vm::primitive_set_innermost_stack_frame_quot() jit_compile_quot(quot.value(),true); - stack_frame *inner = innermost_stack_frame(stack->bottom(), stack->top()); - cell offset = frame_offset(inner); - inner->entry_point = quot->entry_point; - set_frame_offset(inner,offset); + void *inner = innermost_stack_frame(stack->bottom(), stack->top()); + void *addr = frame_return_address(inner); + code_block *block = code->code_block_for_address((cell)addr); + cell offset = block->offset(addr); + set_frame_return_address(inner, (char*)quot->entry_point + offset); } void factor_vm::primitive_callstack_bounds() diff --git a/vm/callstack.hpp b/vm/callstack.hpp index 0872afe331..f4fbac2d91 100755 --- a/vm/callstack.hpp +++ b/vm/callstack.hpp @@ -27,16 +27,6 @@ inline void factor_vm::iterate_callstack_object(callstack *stack_, code_block *owner = code->code_block_for_address((cell)fixed_addr); cell frame_size = owner->stack_frame_size_for_address((cell)fixed_addr); -#ifdef FACTOR_DEBUG - // check our derived owner and frame size against the ones stored in the frame - // by the function prolog - stack_frame *frame = (stack_frame*)((char*)frame_top + frame_size) - 1; - void *fixed_entry_point = - (void*)fixup.translate_code((code_block*)frame->entry_point); - FACTOR_ASSERT(owner->entry_point() == fixed_entry_point); - FACTOR_ASSERT(frame_size == frame->size); -#endif - iterator(frame_top, frame_size, owner, fixed_addr); frame_offset += frame_size; } @@ -72,16 +62,6 @@ inline void factor_vm::iterate_callstack(context *ctx, Iterator &iterator, Fixup cell frame_size = fixed_owner->stack_frame_size_for_address((cell)fixed_addr); -#ifdef FACTOR_DEBUG - // check our derived owner and frame size against the ones stored in the frame - // by the function prolog - stack_frame *frame = (stack_frame*)(frame_top + frame_size) - 1; - void *fixed_entry_point = Fixup::translated_code_block_map - ? (void*)fixup.translate_code((code_block*)frame->entry_point) - : frame->entry_point; - FACTOR_ASSERT(owner->entry_point() == fixed_entry_point); - FACTOR_ASSERT(frame_size == frame->size); -#endif void *fixed_addr_for_iter = Fixup::translated_code_block_map ? fixed_addr : addr; diff --git a/vm/code_block_visitor.hpp b/vm/code_block_visitor.hpp index 4bd6092052..2baa6d1aa7 100644 --- a/vm/code_block_visitor.hpp +++ b/vm/code_block_visitor.hpp @@ -49,9 +49,6 @@ struct call_frame_code_block_visitor { : fixup.fixup_code(owner); void *fixed_addr = compiled->address_for_offset(owner->offset(addr)); set_frame_return_address(frame_top, fixed_addr); - // XXX remove this when prolog data is removed - stack_frame *frame = (stack_frame*)((char*)frame_top + frame_size) - 1; - frame->entry_point = compiled->entry_point(); } }; diff --git a/vm/code_blocks.cpp b/vm/code_blocks.cpp index 3781453c76..0d17225128 100755 --- a/vm/code_blocks.cpp +++ b/vm/code_blocks.cpp @@ -508,14 +508,13 @@ struct find_symbol_at_address_visitor { image load. It finds the symbol and library, and throws an error. */ void factor_vm::undefined_symbol() { - stack_frame *frame = innermost_stack_frame(ctx->callstack_bottom, - ctx->callstack_top); - code_block *compiled = frame_code(frame); - cell return_address = (cell)FRAME_RETURN_ADDRESS(frame, this); - find_symbol_at_address_visitor visitor(this, return_address); + void *frame = innermost_stack_frame(ctx->callstack_bottom, ctx->callstack_top); + void *return_address = frame_return_address(frame); + code_block *compiled = code->code_block_for_address((cell)return_address); + find_symbol_at_address_visitor visitor(this, (cell)return_address); compiled->each_instruction_operand(visitor); if (!to_boolean(visitor.symbol)) - critical_error("Can't find RT_DLSYM at return address", return_address); + critical_error("Can't find RT_DLSYM at return address", (cell)return_address); else general_error(ERROR_UNDEFINED_SYMBOL,visitor.symbol,visitor.library); } diff --git a/vm/contexts.hpp b/vm/contexts.hpp index 30ed74ecd9..79b4c9fd30 100644 --- a/vm/contexts.hpp +++ b/vm/contexts.hpp @@ -20,8 +20,8 @@ struct context { // First 4 fields accessed directly by compiler. See basis/vm/vm.factor /* Factor callstack pointers */ - stack_frame *callstack_top; - stack_frame *callstack_bottom; + void *callstack_top; + void *callstack_bottom; /* current datastack top pointer */ cell datastack; @@ -73,11 +73,6 @@ struct context { datastack += sizeof(cell); replace(tagged); } - - stack_frame *bottom_frame() - { - return callstack_bottom - 1; - } }; VM_C_API context *new_context(factor_vm *parent); diff --git a/vm/cpu-ppc.hpp b/vm/cpu-ppc.hpp index abaa965065..101f8a43db 100644 --- a/vm/cpu-ppc.hpp +++ b/vm/cpu-ppc.hpp @@ -7,7 +7,7 @@ namespace factor #define FACTOR_CPU_STRING "ppc.32" #endif -#define CALLSTACK_BOTTOM(ctx) (stack_frame *)(ctx->callstack_seg->end - 32) +#define CALLSTACK_BOTTOM(ctx) (void *)(ctx->callstack_seg->end - 32) /* In the instruction sequence: diff --git a/vm/cpu-x86.cpp b/vm/cpu-x86.cpp index 1687becedb..bb52f406af 100644 --- a/vm/cpu-x86.cpp +++ b/vm/cpu-x86.cpp @@ -13,18 +13,16 @@ void factor_vm::dispatch_signal_handler(cell *sp, cell *pc, cell handler) the signal handler to do its thing, and launch the handler without going through the resumable subprimitive. */ signal_resumable = false; - stack_frame *frame = ctx->bottom_frame(); + void *frame_top = (void*)ctx->callstack_top; - while((cell)frame >= *sp - && frame >= ctx->callstack_top - && (cell)frame >= ctx->callstack_seg->start + stack_reserved) + while(frame_top < ctx->callstack_bottom + && (cell)frame_top < ctx->callstack_seg->start + stack_reserved) { - frame = frame_successor(frame); + frame_top = frame_predecessor(frame_top); } - cell newsp = (cell)(frame+1); - *sp = newsp; - ctx->callstack_top = (stack_frame*)newsp; + *sp = (cell)frame_top; + ctx->callstack_top = frame_top; *pc = handler; } else { signal_resumable = true; diff --git a/vm/cpu-x86.hpp b/vm/cpu-x86.hpp index 45731976b9..8eba75b9fc 100755 --- a/vm/cpu-x86.hpp +++ b/vm/cpu-x86.hpp @@ -1,8 +1,6 @@ namespace factor { -#define FRAME_RETURN_ADDRESS(frame,vm) *(void **)(vm->frame_successor(frame) + 1) - inline static void* frame_return_address(void *frame_top) { return *(void**)frame_top; @@ -13,7 +11,7 @@ inline static void set_frame_return_address(void *frame_top, void *return_addres *(void**)frame_top = return_address; } -#define CALLSTACK_BOTTOM(ctx) (stack_frame *)(ctx->callstack_seg->end - sizeof(cell) * 5) +#define CALLSTACK_BOTTOM(ctx) (void *)(ctx->callstack_seg->end - sizeof(cell) * 5) inline static void flush_icache(cell start, cell len) {} diff --git a/vm/entry_points.cpp b/vm/entry_points.cpp index f3a834eb17..a3cbcd1317 100755 --- a/vm/entry_points.cpp +++ b/vm/entry_points.cpp @@ -26,7 +26,7 @@ template Func factor_vm::get_entry_point(cell n) return (Func)entry_point_word->entry_point; } -void factor_vm::unwind_native_frames(cell quot, stack_frame *to) +void factor_vm::unwind_native_frames(cell quot, void *to) { tagged entry_point_word(special_objects[UNWIND_NATIVE_FRAMES_WORD]); void *func = entry_point_word->entry_point; diff --git a/vm/entry_points.hpp b/vm/entry_points.hpp index 7c7a1b9394..fc3ae2e400 100755 --- a/vm/entry_points.hpp +++ b/vm/entry_points.hpp @@ -2,7 +2,7 @@ namespace factor { typedef void (* c_to_factor_func_type)(cell quot); -typedef void (* unwind_native_frames_func_type)(cell quot, stack_frame *to); +typedef void (* unwind_native_frames_func_type)(cell quot, void *to); typedef cell (* get_fpu_state_func_type)(); typedef void (* set_fpu_state_func_type)(cell state); diff --git a/vm/layouts.hpp b/vm/layouts.hpp index d6c11a611d..1972fe622b 100644 --- a/vm/layouts.hpp +++ b/vm/layouts.hpp @@ -349,30 +349,18 @@ struct dll : public object { void *handle; }; -struct stack_frame { - /* Updated by procedure prologue with procedure start address */ - void *entry_point; - /* Frame size in bytes */ - cell size; -}; - struct callstack : public object { static const cell type_number = CALLSTACK_TYPE; /* tagged */ cell length; - stack_frame *frame_at(cell offset) const - { - return (stack_frame *)((char *)(this + 1) + offset); - } - void *frame_top_at(cell offset) const { return (void *)((char *)(this + 1) + offset); } - stack_frame *top() const { return (stack_frame *)(this + 1); } - stack_frame *bottom() const { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); } + void *top() const { return (void *)(this + 1); } + void *bottom() const { return (void *)((cell)(this + 1) + untag_fixnum(length)); } }; struct tuple : public object { diff --git a/vm/sampling_profiler.cpp b/vm/sampling_profiler.cpp index c1c720634b..aa3f6a7dbe 100644 --- a/vm/sampling_profiler.cpp +++ b/vm/sampling_profiler.cpp @@ -49,31 +49,32 @@ void factor_vm::record_sample(bool prolog_p) counts, special_objects[OBJ_CURRENT_THREAD])); } +struct record_callstack_sample_iterator { + std::vector *sample_callstacks; + bool skip_p; + + record_callstack_sample_iterator(std::vector *sample_callstacks, bool prolog_p) + : sample_callstacks(sample_callstacks), skip_p(prolog_p) {} + + void operator()(void *frame_top, cell frame_size, code_block *owner, void *addr) + { + if (skip_p) + skip_p = false; + else + sample_callstacks->push_back(owner->owner); + } +}; + void factor_vm::record_callstack_sample(cell *begin, cell *end, bool prolog_p) { *begin = sample_callstacks.size(); - stack_frame *frame = ctx->bottom_frame(); - if (prolog_p) - { - FACTOR_ASSERT(frame >= ctx->callstack_top); - stack_frame *next_frame = frame_successor(frame); - while (next_frame >= ctx->callstack_top) - { - sample_callstacks.push_back(frame_code(frame)->owner); - frame = next_frame; - next_frame = frame_successor(next_frame); - } - } - else - { - while (frame >= ctx->callstack_top) - { - sample_callstacks.push_back(frame_code(frame)->owner); - frame = frame_successor(frame); - } - } + + record_callstack_sample_iterator recorder(&sample_callstacks, prolog_p); + iterate_callstack(ctx, recorder); *end = sample_callstacks.size(); + + std::reverse(sample_callstacks.begin() + *begin, sample_callstacks.end()); } void factor_vm::set_sampling_profiler(fixnum rate) diff --git a/vm/vm.hpp b/vm/vm.hpp index 7a30f0184c..bac366d2e8 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -627,22 +627,14 @@ struct factor_vm template void iterate_callstack_object(callstack *stack_, Iterator &iterator); - void check_frame(stack_frame *frame); callstack *allot_callstack(cell size); - stack_frame *second_from_top_stack_frame(context *ctx); + void *second_from_top_stack_frame(context *ctx); cell capture_callstack(context *ctx); void primitive_callstack(); void primitive_callstack_for(); - code_block *frame_code(stack_frame *frame); - code_block_type frame_type(stack_frame *frame); - cell frame_executing(stack_frame *frame); - cell frame_executing_quot(stack_frame *frame); - stack_frame *frame_successor(stack_frame *frame); - cell frame_scan(stack_frame *frame); - cell frame_offset(stack_frame *frame); - void set_frame_offset(stack_frame *frame, cell offset); + void *frame_predecessor(void *frame); void primitive_callstack_to_array(); - stack_frame *innermost_stack_frame(stack_frame *bottom, stack_frame *top); + void *innermost_stack_frame(void *bottom, void *top); void primitive_innermost_stack_frame_executing(); void primitive_innermost_stack_frame_scan(); void primitive_set_innermost_stack_frame_quot(); @@ -714,7 +706,7 @@ struct factor_vm // entry points void c_to_factor(cell quot); template Func get_entry_point(cell n); - void unwind_native_frames(cell quot, stack_frame *to); + void unwind_native_frames(cell quot, void *to); cell get_fpu_state(); void set_fpu_state(cell state);