6 void factor_vm::check_frame(stack_frame *frame)
9 check_code_pointer((cell)frame->xt);
10 assert(frame->size != 0);
14 callstack *factor_vm::allot_callstack(cell size)
16 callstack *stack = allot<callstack>(callstack_size(size));
17 stack->length = tag_fixnum(size);
21 stack_frame *factor_vm::fix_callstack_top(stack_frame *top, stack_frame *bottom)
23 stack_frame *frame = bottom - 1;
26 frame = frame_successor(frame);
31 /* We ignore the topmost frame, the one calling 'callstack',
32 so that set-callstack doesn't get stuck in an infinite loop.
34 This means that if 'callstack' is called in tail position, we
35 will have popped a necessary frame... however this word is only
36 called by continuation implementation, and user code shouldn't
37 be calling it at all, so we leave it as it is for now. */
38 stack_frame *factor_vm::capture_start()
40 stack_frame *frame = stack_chain->callstack_bottom - 1;
41 while(frame >= stack_chain->callstack_top
42 && frame_successor(frame) >= stack_chain->callstack_top)
44 frame = frame_successor(frame);
49 void factor_vm::primitive_callstack()
51 stack_frame *top = capture_start();
52 stack_frame *bottom = stack_chain->callstack_bottom;
54 fixnum size = (cell)bottom - (cell)top;
58 callstack *stack = allot_callstack(size);
59 memcpy(stack->top(),top,size);
60 dpush(tag<callstack>(stack));
63 void factor_vm::primitive_set_callstack()
65 callstack *stack = untag_check<callstack>(dpop());
67 set_callstack(stack_chain->callstack_bottom,
69 untag_fixnum(stack->length),
72 /* We cannot return here ... */
73 critical_error("Bug in set_callstack()",0);
76 code_block *factor_vm::frame_code(stack_frame *frame)
79 return (code_block *)frame->xt - 1;
82 cell factor_vm::frame_type(stack_frame *frame)
84 return frame_code(frame)->type();
87 cell factor_vm::frame_executing(stack_frame *frame)
89 return frame_code(frame)->owner;
92 stack_frame *factor_vm::frame_successor(stack_frame *frame)
95 return (stack_frame *)((cell)frame - frame->size);
98 /* Allocates memory */
99 cell factor_vm::frame_scan(stack_frame *frame)
101 switch(frame_type(frame))
105 cell quot = frame_executing(frame);
110 char *return_addr = (char *)FRAME_RETURN_ADDRESS(frame,this);
111 char *quot_xt = (char *)(frame_code(frame) + 1);
113 return tag_fixnum(quot_code_offset_to_scan(
114 quot,(cell)(return_addr - quot_xt)));
120 critical_error("Bad frame type",frame_type(frame));
128 struct stack_frame_accumulator {
130 growable_array frames;
132 explicit stack_frame_accumulator(factor_vm *myvm_) : myvm(myvm_), frames(myvm_) {}
134 void operator()(stack_frame *frame)
136 gc_root<object> executing(myvm->frame_executing(frame),myvm);
137 gc_root<object> scan(myvm->frame_scan(frame),myvm);
139 frames.add(executing.value());
140 frames.add(scan.value());
146 void factor_vm::primitive_callstack_to_array()
148 gc_root<callstack> callstack(dpop(),this);
150 stack_frame_accumulator accum(this);
151 iterate_callstack_object(callstack.untagged(),accum);
154 dpush(accum.frames.elements.value());
157 stack_frame *factor_vm::innermost_stack_frame(callstack *stack)
159 stack_frame *top = stack->top();
160 stack_frame *bottom = stack->bottom();
161 stack_frame *frame = bottom - 1;
163 while(frame >= top && frame_successor(frame) >= top)
164 frame = frame_successor(frame);
169 stack_frame *factor_vm::innermost_stack_frame_quot(callstack *callstack)
171 stack_frame *inner = innermost_stack_frame(callstack);
172 tagged<quotation>(frame_executing(inner)).untag_check(this);
176 /* Some primitives implementing a limited form of callstack mutation.
177 Used by the single stepper. */
178 void factor_vm::primitive_innermost_stack_frame_executing()
180 dpush(frame_executing(innermost_stack_frame(untag_check<callstack>(dpop()))));
183 void factor_vm::primitive_innermost_stack_frame_scan()
185 dpush(frame_scan(innermost_stack_frame_quot(untag_check<callstack>(dpop()))));
188 void factor_vm::primitive_set_innermost_stack_frame_quot()
190 gc_root<callstack> callstack(dpop(),this);
191 gc_root<quotation> quot(dpop(),this);
193 callstack.untag_check(this);
194 quot.untag_check(this);
196 jit_compile(quot.value(),true);
198 stack_frame *inner = innermost_stack_frame_quot(callstack.untagged());
199 cell offset = (char *)FRAME_RETURN_ADDRESS(inner,this) - (char *)inner->xt;
200 inner->xt = quot->xt;
201 FRAME_RETURN_ADDRESS(inner,this) = (char *)quot->xt + offset;
204 /* called before entry into Factor code. */
205 void factor_vm::save_callstack_bottom(stack_frame *callstack_bottom)
207 stack_chain->callstack_bottom = callstack_bottom;
210 VM_ASM_API void save_callstack_bottom(stack_frame *callstack_bottom, factor_vm *myvm)
212 return myvm->save_callstack_bottom(callstack_bottom);