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>(callstack_object_size(size));
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);
ctx->push(capture_callstack(other_ctx));
}
-code_block *factor_vm::frame_code(stack_frame *frame)
-{
- 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)
+void *factor_vm::frame_predecessor(void *frame_top)
{
- 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 {
}
-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.
void factor_vm::primitive_innermost_stack_frame_executing()
{
callstack *stack = untag_check<callstack>(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<callstack>(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()
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()
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;
}
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;
: 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();
}
};
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);
}
// 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;
datastack += sizeof(cell);
replace(tagged);
}
-
- stack_frame *bottom_frame()
- {
- return callstack_bottom - 1;
- }
};
VM_C_API context *new_context(factor_vm *parent);
#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:
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;
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;
*(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) {}
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]);
void *func = entry_point_word->entry_point;
{
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);
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 {
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)
{
*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)
template<typename Iterator>
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();
// entry points
void c_to_factor(cell quot);
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();
void set_fpu_state(cell state);