-namespace factor
-{
+namespace factor {
-inline static cell callstack_object_size(cell size)
-{
- return sizeof(callstack) + size;
+inline static cell callstack_object_size(cell size) {
+ return sizeof(callstack) + size;
}
-/* 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(callstack *stack_, Iterator &iterator)
-{
- data_root<callstack> stack(stack_,this);
- fixnum frame_offset = factor::untag_fixnum(stack->length) - sizeof(stack_frame);
+// This is a little tricky. The iterator may allocate memory, so we
+// keep the callstack in a GC root and use relative offsets
+// Allocates memory
+template <typename Iterator, typename Fixup>
+inline void factor_vm::iterate_callstack_object(callstack* stack_,
+ Iterator& iterator,
+ Fixup& fixup) {
+ data_root<callstack> stack(stack_, this);
+ fixnum frame_length = untag_fixnum(stack->length);
+ fixnum frame_offset = 0;
- while(frame_offset >= 0)
- {
- stack_frame *frame = stack->frame_at(frame_offset);
- frame_offset -= frame->size;
- iterator(frame);
- }
-}
+ while (frame_offset < frame_length) {
+ cell frame_top = stack->frame_top_at(frame_offset);
+ cell addr = *(cell*)frame_top;
+ cell fixed_addr = Fixup::translated_code_block_map
+ ? (cell)fixup.translate_code((code_block*)addr)
+ : addr;
+ code_block* owner = code->code_block_for_address(fixed_addr);
-inline void factor_vm::verify_callstack(context *ctx, cell pc)
-{
- if (pc == 0)
- {
- std::cout << "null return address" << std::endl;
- return;
- }
+ cell frame_size = owner->stack_frame_size_for_address(fixed_addr);
- unsigned char *frame_top = (unsigned char*)ctx->callstack_top;
- cell addr = pc;
+ iterator(frame_top, frame_size, owner, fixed_addr);
+ frame_offset += frame_size;
+ }
+ FACTOR_ASSERT(frame_offset == frame_length);
+}
- while(frame_top < (unsigned 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;
- 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;
- }
+// Allocates memory
+template <typename Iterator>
+inline void factor_vm::iterate_callstack_object(callstack* stack,
+ Iterator& iterator) {
+ no_fixup none;
+ iterate_callstack_object(stack, iterator, none);
}
-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;
+// Iterates the callstack from innermost to outermost
+// callframe. Allocates memory
+template <typename Iterator, typename Fixup>
+void factor_vm::iterate_callstack(context* ctx, Iterator& iterator,
+ Fixup& fixup) {
- // XXX x86-centric
- cell return_address = *((cell*)ctx->callstack_top);
- verify_callstack(ctx, return_address);
- */
-}
+ cell top = ctx->callstack_top;
+ cell bottom = ctx->callstack_bottom;
+ // When we are translating the code block maps, all callstacks must
+ // be empty.
+ FACTOR_ASSERT(!Fixup::translated_code_block_map || top == bottom);
+
+ while (top < bottom) {
+ cell addr = *(cell*)top;
+ FACTOR_ASSERT(addr != 0);
-template<typename Iterator> void factor_vm::iterate_callstack(context *ctx, Iterator &iterator)
-{
- stack_frame *frame = ctx->callstack_bottom - 1;
+ // Only the address is valid, if the code heap has been compacted,
+ // owner might not point to a real code block.
+ code_block* owner = code->code_block_for_address(addr);
+ code_block* fixed_owner = fixup.translate_code(owner);
+
+ cell delta = addr - (cell)owner - sizeof(code_block);
+ cell natural_frame_size = fixed_owner->stack_frame_size();
+ cell size = LEAF_FRAME_SIZE;
+ if (natural_frame_size > 0 && delta > 0)
+ size = natural_frame_size;
+
+ iterator(top, size, owner, addr);
+ top += size;
+ }
+ FACTOR_ASSERT(top == bottom);
+}
- while(frame >= ctx->callstack_top)
- {
- iterator(frame);
- frame = frame_successor(frame);
- }
+// Allocates memory
+template <typename Iterator>
+inline void factor_vm::iterate_callstack(context* ctx, Iterator& iterator) {
+ no_fixup none;
+ iterate_callstack(ctx, iterator, none);
}
}