cell factor_vm::frame_scan(stack_frame *frame)
{
- switch(frame_type(frame))
- {
- case code_block_unoptimized:
- {
- tagged<object> obj(frame_executing(frame));
- if(obj.type_p(WORD_TYPE))
- obj = obj.as<word>()->def;
-
- if(obj.type_p(QUOTATION_TYPE))
- return tag_fixnum(quot_code_offset_to_scan(obj.value(),frame_offset(frame)));
- else
- return false_object;
- }
- case code_block_optimized:
- return false_object;
- default:
- critical_error("Bad frame type",frame_type(frame));
- return false_object;
- }
+ return frame_code(frame)->scan(this, FRAME_RETURN_ADDRESS(frame,this));
}
struct stack_frame_accumulator {
/* This is a little tricky. The iterator may allocate memory, so we
keep the callstack in a GC root and use relative offsets */
+template<typename Iterator>
+void factor_vm::iterate_callstack_object_reversed(callstack *stack_, Iterator &iterator)
+{
+ data_root<callstack> stack(stack_,this);
+ fixnum frame_length = factor::untag_fixnum(stack->length);
+ fixnum frame_offset = 0;
+
+ while(frame_offset < frame_length)
+ {
+ void *frame_top = stack->frame_top_at(frame_offset);
+ void *addr = frame_return_address(frame_top);
+
+ code_block *owner = code->code_block_for_address(addr);
+ cell frame_size = owner->stack_frame_size_for_address(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;
+ FACTOR_ASSERT(owner->entry_point() == frame->entry_point);
+ FACTOR_ASSERT(frame_size == frame->size);
+#endif
+
+ iterator(owner, addr);
+ frame_offset += frame_size;
+ }
+}
+
template<typename Iterator> void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator)
{
data_root<callstack> stack(stack_,this);
}
}
-inline void factor_vm::verify_callstack(context *ctx, cell pc)
+template<typename Iterator>
+void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator)
{
- if (pc == 0)
- {
- std::cout << "null return address" << std::endl;
+ if (ctx->callstack_top == ctx->callstack_bottom)
return;
- }
- unsigned char *frame_top = (unsigned char*)ctx->callstack_top;
- cell addr = pc;
+ char *frame_top = (char*)ctx->callstack_top;
- while(frame_top < (unsigned char*)ctx->callstack_bottom)
+ while (frame_top < (char*)ctx->callstack_bottom)
{
- std::cout << std::endl;
- std::cout << "address " << (void*)addr << std::endl;
- code_block *owner = code->code_block_for_address(addr);
- std::cout << "owner " << (void*)owner->entry_point() << " ";
- print_obj(owner->owner);
- std::cout << std::endl;
- cell frame_size = owner->stack_frame_size_for_address(addr);
- std::cout << "frame size " << (void*)frame_size << std::endl;
+ 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);
+
+#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;
+ FACTOR_ASSERT(owner->entry_point() == frame->entry_point);
+ FACTOR_ASSERT(frame_size == frame->size);
+#endif
+
frame_top += frame_size;
- stack_frame *frame = (stack_frame*)frame_top - 1;
- if (owner->entry_point() != frame->entry_point)
- {
- std::cout << "unexpected frame owner " << (void*)frame->entry_point << " ";
- print_obj(((code_block*)frame->entry_point - 1)->owner);
- std::cout << std::endl;
- }
- if (frame_size != frame->size)
- std::cout << "unexpected frame size " << frame->size << std::endl;
- // XXX x86
- addr = *(cell*)frame_top;
+ iterator(owner, addr);
}
}
-inline void factor_vm::verify_callstack(context *ctx)
-{
- /*
- std::cout << std::endl << std::endl
- << "callstack " << (void*)ctx->callstack_top
- << " to " << (void*)ctx->callstack_bottom << std::endl;
-
- // XXX x86-centric
- cell return_address = *((cell*)ctx->callstack_top);
- verify_callstack(ctx, return_address);
- */
-}
-
-template<typename Iterator> void factor_vm::iterate_callstack(context *ctx, Iterator &iterator)
+template<typename Iterator>
+void factor_vm::iterate_callstack(context *ctx, Iterator &iterator)
{
stack_frame *frame = ctx->callstack_bottom - 1;
namespace factor
{
+cell code_block::scan(factor_vm *vm, void *addr) const
+{
+ switch(type())
+ {
+ case code_block_unoptimized:
+ {
+ tagged<object> obj(owner);
+ if(obj.type_p(WORD_TYPE))
+ obj = obj.as<word>()->def;
+
+ if(obj.type_p(QUOTATION_TYPE))
+ return tag_fixnum(vm->quot_code_offset_to_scan(obj.value(),offset(addr)));
+ else
+ return false_object;
+ }
+ case code_block_optimized:
+ return false_object;
+ default:
+ critical_error("Bad frame type",type());
+ return false_object;
+ }
+}
+
cell factor_vm::compute_entry_point_address(cell obj)
{
switch(tagged<object>(obj).type())
}
}
}
+
+ cell offset(void *addr) const
+ {
+ return (char*)addr - (char*)entry_point();
+ }
+
+ cell scan(factor_vm *vm, void *addr) const;
};
VM_C_API void undefined_symbol(void);
#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;
+}
+
+inline static void set_frame_return_address(void *frame_top, cell return_address)
+{
+ *(cell*)frame_top = return_address;
+}
+
#define CALLSTACK_BOTTOM(ctx) (stack_frame *)(ctx->callstack_seg->end - sizeof(cell) * 5)
inline static void flush_icache(cell start, cell len) {}
factor_vm *parent;
explicit stack_frame_printer(factor_vm *parent_) : parent(parent_) {}
- void operator()(stack_frame *frame)
+ void operator()(code_block *owner, void *addr)
{
- std::cout << "frame: " << std::hex << (cell)frame << std::dec << std::endl;
+ std::cout << std::endl;
std::cout << "executing: ";
- parent->print_obj(parent->frame_executing(frame));
+ parent->print_obj(owner->owner);
std::cout << std::endl;
std::cout << "scan: ";
- parent->print_obj(parent->frame_scan(frame));
+ parent->print_obj(owner->scan(parent, addr));
std::cout << std::endl;
std::cout << "word/quot addr: ";
- std::cout << std::hex << (cell)parent->frame_executing(frame) << std::dec;
+ std::cout << std::hex << (cell)owner->owner << std::dec;
std::cout << std::endl;
std::cout << "word/quot xt: ";
- std::cout << std::hex << (cell)frame->entry_point << std::dec;
+ std::cout << std::hex << (cell)owner->entry_point() << std::dec;
std::cout << std::endl;
std::cout << "return address: ";
- std::cout << std::hex << (cell)FRAME_RETURN_ADDRESS(frame,parent) << std::dec;
+ std::cout << std::hex << (cell)addr << std::dec;
std::cout << std::endl;
}
};
if (ctx)
{
stack_frame_printer printer(this);
- verify_callstack(ctx);
- iterate_callstack(ctx,printer);
+ iterate_callstack_reversed(ctx,printer);
}
else
std::cout << "*** Context not initialized" << std::endl;
{
call_frame_scrubber scrubber(this,ctx);
iterate_callstack(ctx,scrubber);
- verify_callstack(ctx);
}
void factor_vm::scrub_contexts()
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 slot_visitor<Fixup>::visit_callstack(context *ctx)
{
call_frame_slot_visitor<Fixup> call_frame_visitor(parent,this);
- parent->verify_callstack(ctx);
parent->iterate_callstack(ctx,call_frame_visitor);
}
std::set<context *>::const_iterator end = active_contexts.end();
while(begin != end)
{
- verify_callstack(*begin);
iterate_callstack(*begin++,iter);
}
}
// callstack
template<typename Iterator> void iterate_callstack_object(callstack *stack_, Iterator &iterator);
+ template<typename Iterator> void iterate_callstack_object_reversed(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 primitive_innermost_stack_frame_scan();
void primitive_set_innermost_stack_frame_quot();
void primitive_callstack_bounds();
- void verify_callstack(context *ctx);
- void verify_callstack(context *ctx, cell pc);
+ template<typename Iterator> void iterate_callstack_reversed(context *ctx, Iterator &iterator);
template<typename Iterator> void iterate_callstack(context *ctx, Iterator &iterator);
// cpu-*