vm: replace remaining stack_frame-based logic

db4
Joe Groff 2011-12-06 17:53:52 -08:00
parent d74f194b07
commit 604ceb957c
13 changed files with 82 additions and 170 deletions

View File

@ -3,14 +3,6 @@
namespace factor 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 *factor_vm::allot_callstack(cell size)
{ {
callstack *stack = allot<callstack>(callstack_object_size(size)); callstack *stack = allot<callstack>(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 will have popped a necessary frame... however this word is only
called by continuation implementation, and user code shouldn't called by continuation implementation, and user code shouldn't
be calling it at all, so we leave it as it is for now. */ 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(); void *frame_top = ctx->callstack_top;
while(frame >= ctx->callstack_top for (unsigned i = 0; i < 2; ++i)
&& frame_successor(frame) >= ctx->callstack_top
&& frame_successor(frame_successor(frame)) >= ctx->callstack_top)
{ {
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) cell factor_vm::capture_callstack(context *ctx)
{ {
stack_frame *top = second_from_top_stack_frame(ctx); void *top = second_from_top_stack_frame(ctx);
stack_frame *bottom = ctx->callstack_bottom; void *bottom = ctx->callstack_bottom;
fixnum size = std::max((fixnum)0,(fixnum)bottom - (fixnum)top); 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)); 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); void *addr = frame_return_address((void*)frame_top);
return (code_block *)frame->entry_point - 1; 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);
code_block_type factor_vm::frame_type(stack_frame *frame) return (void*)((char*)frame_top + frame_size);
{
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));
} }
struct stack_frame_accumulator { 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; /* if (top < bottom)
{
while(frame >= top && frame_successor(frame) >= top) void *pred = frame_predecessor(top);
frame = frame_successor(frame); if (pred < bottom)
return pred;
return frame; else
return top;
}
else */
return top;
} }
/* Some primitives implementing a limited form of callstack mutation. /* 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() void factor_vm::primitive_innermost_stack_frame_executing()
{ {
callstack *stack = untag_check<callstack>(ctx->pop()); callstack *stack = untag_check<callstack>(ctx->pop());
stack_frame *frame = innermost_stack_frame(stack->bottom(), stack->top()); void *frame = innermost_stack_frame(stack->bottom(), stack->top());
ctx->push(frame_executing_quot(frame)); 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() void factor_vm::primitive_innermost_stack_frame_scan()
{ {
callstack *stack = untag_check<callstack>(ctx->pop()); callstack *stack = untag_check<callstack>(ctx->pop());
stack_frame *frame = innermost_stack_frame(stack->bottom(), stack->top()); void *frame = innermost_stack_frame(stack->bottom(), stack->top());
ctx->push(frame_scan(frame)); 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() 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); jit_compile_quot(quot.value(),true);
stack_frame *inner = innermost_stack_frame(stack->bottom(), stack->top()); void *inner = innermost_stack_frame(stack->bottom(), stack->top());
cell offset = frame_offset(inner); void *addr = frame_return_address(inner);
inner->entry_point = quot->entry_point; code_block *block = code->code_block_for_address((cell)addr);
set_frame_offset(inner,offset); cell offset = block->offset(addr);
set_frame_return_address(inner, (char*)quot->entry_point + offset);
} }
void factor_vm::primitive_callstack_bounds() void factor_vm::primitive_callstack_bounds()

View File

@ -27,16 +27,6 @@ inline void factor_vm::iterate_callstack_object(callstack *stack_,
code_block *owner = code->code_block_for_address((cell)fixed_addr); code_block *owner = code->code_block_for_address((cell)fixed_addr);
cell frame_size = owner->stack_frame_size_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); iterator(frame_top, frame_size, owner, fixed_addr);
frame_offset += frame_size; 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); 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 void *fixed_addr_for_iter = Fixup::translated_code_block_map
? fixed_addr ? fixed_addr
: addr; : addr;

View File

@ -49,9 +49,6 @@ struct call_frame_code_block_visitor {
: fixup.fixup_code(owner); : fixup.fixup_code(owner);
void *fixed_addr = compiled->address_for_offset(owner->offset(addr)); void *fixed_addr = compiled->address_for_offset(owner->offset(addr));
set_frame_return_address(frame_top, fixed_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();
} }
}; };

View File

@ -508,14 +508,13 @@ struct find_symbol_at_address_visitor {
image load. It finds the symbol and library, and throws an error. */ image load. It finds the symbol and library, and throws an error. */
void factor_vm::undefined_symbol() void factor_vm::undefined_symbol()
{ {
stack_frame *frame = innermost_stack_frame(ctx->callstack_bottom, void *frame = innermost_stack_frame(ctx->callstack_bottom, ctx->callstack_top);
ctx->callstack_top); void *return_address = frame_return_address(frame);
code_block *compiled = frame_code(frame); code_block *compiled = code->code_block_for_address((cell)return_address);
cell return_address = (cell)FRAME_RETURN_ADDRESS(frame, this); find_symbol_at_address_visitor visitor(this, (cell)return_address);
find_symbol_at_address_visitor visitor(this, return_address);
compiled->each_instruction_operand(visitor); compiled->each_instruction_operand(visitor);
if (!to_boolean(visitor.symbol)) 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 else
general_error(ERROR_UNDEFINED_SYMBOL,visitor.symbol,visitor.library); general_error(ERROR_UNDEFINED_SYMBOL,visitor.symbol,visitor.library);
} }

View File

@ -20,8 +20,8 @@ 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
/* Factor callstack pointers */ /* Factor callstack pointers */
stack_frame *callstack_top; void *callstack_top;
stack_frame *callstack_bottom; void *callstack_bottom;
/* current datastack top pointer */ /* current datastack top pointer */
cell datastack; cell datastack;
@ -73,11 +73,6 @@ struct context {
datastack += sizeof(cell); datastack += sizeof(cell);
replace(tagged); replace(tagged);
} }
stack_frame *bottom_frame()
{
return callstack_bottom - 1;
}
}; };
VM_C_API context *new_context(factor_vm *parent); VM_C_API context *new_context(factor_vm *parent);

View File

@ -7,7 +7,7 @@ namespace factor
#define FACTOR_CPU_STRING "ppc.32" #define FACTOR_CPU_STRING "ppc.32"
#endif #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: /* In the instruction sequence:

View File

@ -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 the signal handler to do its thing, and launch the handler without going
through the resumable subprimitive. */ through the resumable subprimitive. */
signal_resumable = false; signal_resumable = false;
stack_frame *frame = ctx->bottom_frame(); void *frame_top = (void*)ctx->callstack_top;
while((cell)frame >= *sp while(frame_top < ctx->callstack_bottom
&& frame >= ctx->callstack_top && (cell)frame_top < ctx->callstack_seg->start + stack_reserved)
&& (cell)frame >= ctx->callstack_seg->start + stack_reserved)
{ {
frame = frame_successor(frame); frame_top = frame_predecessor(frame_top);
} }
cell newsp = (cell)(frame+1); *sp = (cell)frame_top;
*sp = newsp; ctx->callstack_top = frame_top;
ctx->callstack_top = (stack_frame*)newsp;
*pc = handler; *pc = handler;
} else { } else {
signal_resumable = true; signal_resumable = true;

View File

@ -1,8 +1,6 @@
namespace factor namespace factor
{ {
#define FRAME_RETURN_ADDRESS(frame,vm) *(void **)(vm->frame_successor(frame) + 1)
inline static void* frame_return_address(void *frame_top) inline static void* frame_return_address(void *frame_top)
{ {
return *(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; *(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) {} inline static void flush_icache(cell start, cell len) {}

View File

@ -26,7 +26,7 @@ template<typename Func> Func factor_vm::get_entry_point(cell n)
return (Func)entry_point_word->entry_point; 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<word> entry_point_word(special_objects[UNWIND_NATIVE_FRAMES_WORD]); tagged<word> entry_point_word(special_objects[UNWIND_NATIVE_FRAMES_WORD]);
void *func = entry_point_word->entry_point; void *func = entry_point_word->entry_point;

View File

@ -2,7 +2,7 @@ namespace factor
{ {
typedef void (* c_to_factor_func_type)(cell quot); 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 cell (* get_fpu_state_func_type)();
typedef void (* set_fpu_state_func_type)(cell state); typedef void (* set_fpu_state_func_type)(cell state);

View File

@ -349,30 +349,18 @@ struct dll : public object {
void *handle; 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 { struct callstack : public object {
static const cell type_number = CALLSTACK_TYPE; static const cell type_number = CALLSTACK_TYPE;
/* tagged */ /* tagged */
cell length; cell length;
stack_frame *frame_at(cell offset) const
{
return (stack_frame *)((char *)(this + 1) + offset);
}
void *frame_top_at(cell offset) const void *frame_top_at(cell offset) const
{ {
return (void *)((char *)(this + 1) + offset); return (void *)((char *)(this + 1) + offset);
} }
stack_frame *top() const { return (stack_frame *)(this + 1); } void *top() const { return (void *)(this + 1); }
stack_frame *bottom() const { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); } void *bottom() const { return (void *)((cell)(this + 1) + untag_fixnum(length)); }
}; };
struct tuple : public object { struct tuple : public object {

View File

@ -49,31 +49,32 @@ void factor_vm::record_sample(bool prolog_p)
counts, special_objects[OBJ_CURRENT_THREAD])); counts, special_objects[OBJ_CURRENT_THREAD]));
} }
struct record_callstack_sample_iterator {
std::vector<cell> *sample_callstacks;
bool skip_p;
record_callstack_sample_iterator(std::vector<cell> *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) void factor_vm::record_callstack_sample(cell *begin, cell *end, bool prolog_p)
{ {
*begin = sample_callstacks.size(); *begin = sample_callstacks.size();
stack_frame *frame = ctx->bottom_frame();
if (prolog_p) record_callstack_sample_iterator recorder(&sample_callstacks, prolog_p);
{ iterate_callstack(ctx, recorder);
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);
}
}
*end = sample_callstacks.size(); *end = sample_callstacks.size();
std::reverse(sample_callstacks.begin() + *begin, sample_callstacks.end());
} }
void factor_vm::set_sampling_profiler(fixnum rate) void factor_vm::set_sampling_profiler(fixnum rate)

View File

@ -627,22 +627,14 @@ struct factor_vm
template<typename Iterator> template<typename Iterator>
void iterate_callstack_object(callstack *stack_, Iterator &iterator); void iterate_callstack_object(callstack *stack_, Iterator &iterator);
void check_frame(stack_frame *frame);
callstack *allot_callstack(cell size); 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); cell capture_callstack(context *ctx);
void primitive_callstack(); void primitive_callstack();
void primitive_callstack_for(); void primitive_callstack_for();
code_block *frame_code(stack_frame *frame); void *frame_predecessor(void *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 primitive_callstack_to_array(); 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_executing();
void primitive_innermost_stack_frame_scan(); void primitive_innermost_stack_frame_scan();
void primitive_set_innermost_stack_frame_quot(); void primitive_set_innermost_stack_frame_quot();
@ -714,7 +706,7 @@ struct factor_vm
// entry points // entry points
void c_to_factor(cell quot); void c_to_factor(cell quot);
template<typename Func> Func get_entry_point(cell n); template<typename Func> 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(); cell get_fpu_state();
void set_fpu_state(cell state); void set_fpu_state(cell state);