]> gitweb.factorcode.org Git - factor.git/blob - vm/callstack.hpp
vm: iterate_callstack_reversed in slot_visitor
[factor.git] / vm / callstack.hpp
1 namespace factor
2 {
3
4 inline static cell callstack_object_size(cell size)
5 {
6         return sizeof(callstack) + size;
7 }
8
9 /* This is a little tricky. The iterator may allocate memory, so we
10 keep the callstack in a GC root and use relative offsets */
11 template<typename Iterator, typename Fixup>
12 void factor_vm::iterate_callstack_object_reversed(callstack *stack_,
13         Iterator &iterator, Fixup &fixup)
14 {
15         data_root<callstack> stack(stack_,this);
16         fixnum frame_length = factor::untag_fixnum(stack->length);
17         fixnum frame_offset = 0;
18
19         while(frame_offset < frame_length)
20         {
21                 void *frame_top = stack->frame_top_at(frame_offset);
22                 void *addr = frame_return_address(frame_top);
23
24                 void *fixed_addr = (void*)fixup.translate_code((code_block*)addr);
25                 code_block *owner = code->code_block_for_address((cell)fixed_addr);
26                 cell frame_size = owner->stack_frame_size_for_address((cell)fixed_addr);
27
28 #ifdef FACTOR_DEBUG
29                 // check our derived owner and frame size against the ones stored in the frame
30                 // by the function prolog
31                 stack_frame *frame = (stack_frame*)((char*)frame_top + frame_size) - 1;
32                 void *fixed_entry_point =
33                         (void*)fixup.translate_code((code_block*)frame->entry_point);
34                 FACTOR_ASSERT(owner->entry_point() == fixed_entry_point);
35                 FACTOR_ASSERT(frame_size == frame->size);
36 #endif
37
38                 iterator(frame_top, owner, fixed_addr);
39                 frame_offset += frame_size;
40         }
41 }
42
43 template<typename Iterator> void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator)
44 {
45         data_root<callstack> stack(stack_,this);
46         fixnum frame_offset = factor::untag_fixnum(stack->length) - sizeof(stack_frame);
47
48         while(frame_offset >= 0)
49         {
50                 stack_frame *frame = stack->frame_at(frame_offset);
51                 frame_offset -= frame->size;
52                 iterator(frame);
53         }
54 }
55
56 template<typename Iterator>
57 void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator)
58 {
59         if (ctx->callstack_top == ctx->callstack_bottom)
60                 return;
61
62         char *frame_top = (char*)ctx->callstack_top;
63
64         while (frame_top < (char*)ctx->callstack_bottom)
65         {
66                 void *addr = frame_return_address((void*)frame_top);
67                 FACTOR_ASSERT(addr != 0);
68
69                 code_block *owner = code->code_block_for_address((cell)addr);
70                 cell frame_size = owner->stack_frame_size_for_address((cell)addr);
71
72 #ifdef FACTOR_DEBUG
73                 // check our derived owner and frame size against the ones stored in the frame
74                 // by the function prolog
75                 stack_frame *frame = (stack_frame*)(frame_top + frame_size) - 1;
76                 FACTOR_ASSERT(owner->entry_point() == frame->entry_point);
77                 FACTOR_ASSERT(frame_size == frame->size);
78 #endif
79
80                 iterator(frame_top, owner, addr);
81                 frame_top += frame_size;
82         }
83 }
84
85 template<typename Iterator>
86 void factor_vm::iterate_callstack(context *ctx, Iterator &iterator)
87 {
88         stack_frame *frame = ctx->callstack_bottom - 1;
89
90         while(frame >= ctx->callstack_top)
91         {
92                 iterator(frame);
93                 frame = frame_successor(frame);
94         }
95 }
96
97 }