]> gitweb.factorcode.org Git - factor.git/blob - vm/callstack.hpp
vm: reversed callstack iteration
[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>
12 void factor_vm::iterate_callstack_object_reversed(callstack *stack_, Iterator &iterator)
13 {
14         data_root<callstack> stack(stack_,this);
15         fixnum frame_length = factor::untag_fixnum(stack->length);
16         fixnum frame_offset = 0;
17
18         while(frame_offset < frame_length)
19         {
20                 void *frame_top = stack->frame_top_at(frame_offset);
21                 void *addr = frame_return_address(frame_top);
22
23                 code_block *owner = code->code_block_for_address(addr);
24                 cell frame_size = owner->stack_frame_size_for_address(addr);
25
26 #ifdef FACTOR_DEBUG
27                 // check our derived owner and frame size against the ones stored in the frame
28                 // by the function prolog
29                 stack_frame *frame = (stack_frame*)((char*)frame_top + frame_size) - 1;
30                 FACTOR_ASSERT(owner->entry_point() == frame->entry_point);
31                 FACTOR_ASSERT(frame_size == frame->size);
32 #endif
33
34                 iterator(owner, addr);
35                 frame_offset += frame_size;
36         }
37 }
38
39 template<typename Iterator> void factor_vm::iterate_callstack_object(callstack *stack_, Iterator &iterator)
40 {
41         data_root<callstack> stack(stack_,this);
42         fixnum frame_offset = factor::untag_fixnum(stack->length) - sizeof(stack_frame);
43
44         while(frame_offset >= 0)
45         {
46                 stack_frame *frame = stack->frame_at(frame_offset);
47                 frame_offset -= frame->size;
48                 iterator(frame);
49         }
50 }
51
52 template<typename Iterator>
53 void factor_vm::iterate_callstack_reversed(context *ctx, Iterator &iterator)
54 {
55         if (ctx->callstack_top == ctx->callstack_bottom)
56                 return;
57
58         char *frame_top = (char*)ctx->callstack_top;
59
60         while (frame_top < (char*)ctx->callstack_bottom)
61         {
62                 void *addr = frame_return_address((void*)frame_top);
63                 FACTOR_ASSERT(addr != 0);
64
65                 code_block *owner = code->code_block_for_address((cell)addr);
66                 cell frame_size = owner->stack_frame_size_for_address((cell)addr);
67
68 #ifdef FACTOR_DEBUG
69                 // check our derived owner and frame size against the ones stored in the frame
70                 // by the function prolog
71                 stack_frame *frame = (stack_frame*)(frame_top + frame_size) - 1;
72                 FACTOR_ASSERT(owner->entry_point() == frame->entry_point);
73                 FACTOR_ASSERT(frame_size == frame->size);
74 #endif
75
76                 frame_top += frame_size;
77                 iterator(owner, addr);
78         }
79 }
80
81 template<typename Iterator>
82 void factor_vm::iterate_callstack(context *ctx, Iterator &iterator)
83 {
84         stack_frame *frame = ctx->callstack_bottom - 1;
85
86         while(frame >= ctx->callstack_top)
87         {
88                 iterator(frame);
89                 frame = frame_successor(frame);
90         }
91 }
92
93 }