cell factor_vm::frame_executing_quot(stack_frame *frame)
{
- tagged<object> executing(frame_executing(frame));
- code_block *compiled = frame_code(frame);
- if(!compiled->optimized_p() && executing->type() == WORD_TYPE)
- executing = executing.as<word>()->def;
- return executing.value();
+ return frame_code(frame)->owner_quot();
}
stack_frame *factor_vm::frame_successor(stack_frame *frame)
factor_vm *parent;
growable_array frames;
- explicit stack_frame_accumulator(factor_vm *parent_) : parent(parent_), frames(parent_) {}
+ explicit stack_frame_accumulator(factor_vm *parent_)
+ : parent(parent_), frames(parent_) {}
- void operator()(stack_frame *frame)
+ void operator()(void *frame_top, cell frame_size, code_block *owner, void *addr)
{
- data_root<object> executing_quot(parent->frame_executing_quot(frame),parent);
- data_root<object> executing(parent->frame_executing(frame),parent);
- data_root<object> scan(parent->frame_scan(frame),parent);
+ data_root<object> executing_quot(owner->owner_quot(),parent);
+ data_root<object> executing(owner->owner,parent);
+ data_root<object> scan(owner->scan(parent, addr),parent);
frames.add(executing.value());
frames.add(executing_quot.value());
}
};
+struct stack_frame_in_array { cell cells[3]; };
+
void factor_vm::primitive_callstack_to_array()
{
data_root<callstack> callstack(ctx->pop(),this);
stack_frame_accumulator accum(this);
- iterate_callstack_object(callstack.untagged(),accum);
+ iterate_callstack_object_reversed(callstack.untagged(),accum);
+
+ /* The callstack iterator visits frames in reverse order (top to bottom) */
+ std::reverse(
+ (stack_frame_in_array*)accum.frames.elements->data(),
+ (stack_frame_in_array*)(accum.frames.elements->data() + accum.frames.count));
+
accum.frames.trim();
ctx->push(accum.frames.elements.value());
+
}
stack_frame *factor_vm::innermost_stack_frame(stack_frame *bottom, stack_frame *top)
/* 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, typename Fixup>
-void factor_vm::iterate_callstack_object_reversed(callstack *stack_,
+inline void factor_vm::iterate_callstack_object_reversed(callstack *stack_,
Iterator &iterator, Fixup &fixup)
{
data_root<callstack> stack(stack_,this);
}
template<typename Iterator>
-void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator)
+inline void factor_vm::iterate_callstack_object_reversed(callstack *stack_, Iterator &iterator)
+{
+ no_fixup none;
+ iterate_callstack_object_reversed(stack_, iterator, none);
+}
+
+template<typename Iterator>
+inline void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator)
{
data_root<callstack> stack(stack_,this);
fixnum frame_offset = factor::untag_fixnum(stack->length) - sizeof(stack_frame);
}
template<typename Iterator, typename Fixup>
-void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator, Fixup &fixup)
+inline void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator, Fixup &fixup)
{
if (ctx->callstack_top == ctx->callstack_bottom)
return;
}
template<typename Iterator>
-void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator)
+inline void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator)
{
- if (ctx->callstack_top == ctx->callstack_bottom)
- return;
-
- char *frame_top = (char*)ctx->callstack_top;
-
- while (frame_top < (char*)ctx->callstack_bottom)
- {
- 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
-
- iterator(frame_top, frame_size, owner, addr);
- frame_top += frame_size;
- }
+ no_fixup none;
+ iterate_callstack_reversed(ctx, iterator, none);
}
+
}
namespace factor
{
+cell code_block::owner_quot() const
+{
+ tagged<object> executing(owner);
+ if (!optimized_p() && executing->type() == WORD_TYPE)
+ executing = executing.as<word>()->def;
+ return executing.value();
+}
+
cell code_block::scan(factor_vm *vm, void *addr) const
{
switch(type())
}
cell scan(factor_vm *vm, void *addr) const;
+ cell owner_quot() const;
};
VM_C_API void undefined_symbol(void);
void iterate_callstack_object(callstack *stack_, Iterator &iterator);
template<typename Iterator, typename Fixup>
- void iterate_callstack_object_reversed(callstack *stack_,
- Iterator &iterator, Fixup &fixup);
+ void iterate_callstack_object_reversed(callstack *stack_, Iterator &iterator,
+ Fixup &fixup);
+ template<typename Iterator>
+ void iterate_callstack_object_reversed(callstack *stack_, Iterator &iterator);
void check_frame(stack_frame *frame);
callstack *allot_callstack(cell size);
void primitive_set_innermost_stack_frame_quot();
void primitive_callstack_bounds();
- template<typename Iterator>
- void iterate_callstack_reversed(context *ctx, Iterator &iterator);
-
template<typename Iterator, typename Fixup>
void iterate_callstack_reversed(context *ctx, Iterator &iterator, Fixup &fixup);
+ template<typename Iterator>
+ void iterate_callstack_reversed(context *ctx, Iterator &iterator);
// cpu-*
void dispatch_signal_handler(cell *sp, cell *pc, cell newpc);