6 void factor_vm::check_frame(stack_frame *frame)
9 check_code_pointer((cell)frame->entry_point);
10 FACTOR_ASSERT(frame->size != 0);
14 callstack *factor_vm::allot_callstack(cell size)
16 callstack *stack = allot<callstack>(callstack_object_size(size));
17 stack->length = tag_fixnum(size);
21 /* We ignore the two topmost frames, the 'callstack' primitive
22 frame itself, and the frame calling the 'callstack' primitive,
23 so that set-callstack doesn't get stuck in an infinite loop.
25 This means that if 'callstack' is called in tail position, we
26 will have popped a necessary frame... however this word is only
27 called by continuation implementation, and user code shouldn't
28 be calling it at all, so we leave it as it is for now. */
29 stack_frame *factor_vm::second_from_top_stack_frame(context *ctx)
31 stack_frame *frame = ctx->bottom_frame();
32 while(frame >= ctx->callstack_top
33 && frame_successor(frame) >= ctx->callstack_top
34 && frame_successor(frame_successor(frame)) >= ctx->callstack_top)
36 frame = frame_successor(frame);
41 cell factor_vm::capture_callstack(context *ctx)
43 stack_frame *top = second_from_top_stack_frame(ctx);
44 stack_frame *bottom = ctx->callstack_bottom;
46 fixnum size = std::max((fixnum)0,(fixnum)bottom - (fixnum)top);
48 callstack *stack = allot_callstack(size);
49 memcpy(stack->top(),top,size);
50 return tag<callstack>(stack);
53 void factor_vm::primitive_callstack()
55 ctx->push(capture_callstack(ctx));
58 void factor_vm::primitive_callstack_for()
60 context *other_ctx = (context *)pinned_alien_offset(ctx->pop());
61 ctx->push(capture_callstack(other_ctx));
64 code_block *factor_vm::frame_code(stack_frame *frame)
67 return (code_block *)frame->entry_point - 1;
70 code_block_type factor_vm::frame_type(stack_frame *frame)
72 return frame_code(frame)->type();
75 cell factor_vm::frame_executing(stack_frame *frame)
77 return frame_code(frame)->owner;
80 cell factor_vm::frame_executing_quot(stack_frame *frame)
82 return frame_code(frame)->owner_quot();
85 stack_frame *factor_vm::frame_successor(stack_frame *frame)
88 return (stack_frame *)((cell)frame - frame->size);
91 cell factor_vm::frame_offset(stack_frame *frame)
93 char *return_address = (char *)FRAME_RETURN_ADDRESS(frame,this);
94 FACTOR_ASSERT(return_address != 0);
95 return frame_code(frame)->offset(return_address);
98 void factor_vm::set_frame_offset(stack_frame *frame, cell offset)
100 char *entry_point = (char *)frame_code(frame)->entry_point();
101 FRAME_RETURN_ADDRESS(frame,this) = entry_point + offset;
104 cell factor_vm::frame_scan(stack_frame *frame)
106 return frame_code(frame)->scan(this, FRAME_RETURN_ADDRESS(frame,this));
109 struct stack_frame_accumulator {
111 growable_array frames;
113 explicit stack_frame_accumulator(factor_vm *parent_)
114 : parent(parent_), frames(parent_) {}
116 void operator()(void *frame_top, cell frame_size, code_block *owner, void *addr)
118 data_root<object> executing_quot(owner->owner_quot(),parent);
119 data_root<object> executing(owner->owner,parent);
120 data_root<object> scan(owner->scan(parent, addr),parent);
122 frames.add(executing.value());
123 frames.add(executing_quot.value());
124 frames.add(scan.value());
128 struct stack_frame_in_array { cell cells[3]; };
130 void factor_vm::primitive_callstack_to_array()
132 data_root<callstack> callstack(ctx->pop(),this);
134 stack_frame_accumulator accum(this);
135 iterate_callstack_object(callstack.untagged(),accum);
137 /* The callstack iterator visits frames in reverse order (top to bottom) */
139 (stack_frame_in_array*)accum.frames.elements->data(),
140 (stack_frame_in_array*)(accum.frames.elements->data() + accum.frames.count));
144 ctx->push(accum.frames.elements.value());
148 stack_frame *factor_vm::innermost_stack_frame(stack_frame *bottom, stack_frame *top)
150 stack_frame *frame = bottom - 1;
152 while(frame >= top && frame_successor(frame) >= top)
153 frame = frame_successor(frame);
158 /* Some primitives implementing a limited form of callstack mutation.
159 Used by the single stepper. */
160 void factor_vm::primitive_innermost_stack_frame_executing()
162 callstack *stack = untag_check<callstack>(ctx->pop());
163 stack_frame *frame = innermost_stack_frame(stack->bottom(), stack->top());
164 ctx->push(frame_executing_quot(frame));
167 void factor_vm::primitive_innermost_stack_frame_scan()
169 callstack *stack = untag_check<callstack>(ctx->pop());
170 stack_frame *frame = innermost_stack_frame(stack->bottom(), stack->top());
171 ctx->push(frame_scan(frame));
174 void factor_vm::primitive_set_innermost_stack_frame_quot()
176 data_root<callstack> stack(ctx->pop(),this);
177 data_root<quotation> quot(ctx->pop(),this);
179 stack.untag_check(this);
180 quot.untag_check(this);
182 jit_compile_quot(quot.value(),true);
184 stack_frame *inner = innermost_stack_frame(stack->bottom(), stack->top());
185 cell offset = frame_offset(inner);
186 inner->entry_point = quot->entry_point;
187 set_frame_offset(inner,offset);
190 void factor_vm::primitive_callstack_bounds()
192 ctx->push(allot_alien((void*)ctx->callstack_seg->start));
193 ctx->push(allot_alien((void*)ctx->callstack_seg->end));