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 code_block *compiled = frame_code(frame);
90 if(compiled->literals == F || !stack_traces_p())
94 array *literals = untag<array>(compiled->literals);
95 cell executing = array_nth(literals,0);
96 check_data_pointer((object *)executing);
101 stack_frame *factor_vm::frame_successor(stack_frame *frame)
104 return (stack_frame *)((cell)frame - frame->size);
107 /* Allocates memory */
108 cell factor_vm::frame_scan(stack_frame *frame)
110 switch(frame_type(frame))
114 cell quot = frame_executing(frame);
119 char *return_addr = (char *)FRAME_RETURN_ADDRESS(frame);
120 char *quot_xt = (char *)(frame_code(frame) + 1);
122 return tag_fixnum(quot_code_offset_to_scan(
123 quot,(cell)(return_addr - quot_xt)));
129 critical_error("Bad frame type",frame_type(frame));
137 struct stack_frame_accumulator {
138 growable_array frames;
140 stack_frame_accumulator(factor_vm *vm) : frames(vm) {}
142 void operator()(stack_frame *frame, factor_vm *myvm)
144 gc_root<object> executing(myvm->frame_executing(frame),myvm);
145 gc_root<object> scan(myvm->frame_scan(frame),myvm);
147 frames.add(executing.value());
148 frames.add(scan.value());
154 void factor_vm::primitive_callstack_to_array()
156 gc_root<callstack> callstack(dpop(),this);
158 stack_frame_accumulator accum(this);
159 iterate_callstack_object(callstack.untagged(),accum);
162 dpush(accum.frames.elements.value());
165 stack_frame *factor_vm::innermost_stack_frame(callstack *stack)
167 stack_frame *top = stack->top();
168 stack_frame *bottom = stack->bottom();
169 stack_frame *frame = bottom - 1;
171 while(frame >= top && frame_successor(frame) >= top)
172 frame = frame_successor(frame);
177 stack_frame *factor_vm::innermost_stack_frame_quot(callstack *callstack)
179 stack_frame *inner = innermost_stack_frame(callstack);
180 tagged<quotation>(frame_executing(inner)).untag_check(this);
184 /* Some primitives implementing a limited form of callstack mutation.
185 Used by the single stepper. */
186 void factor_vm::primitive_innermost_stack_frame_executing()
188 dpush(frame_executing(innermost_stack_frame(untag_check<callstack>(dpop()))));
191 void factor_vm::primitive_innermost_stack_frame_scan()
193 dpush(frame_scan(innermost_stack_frame_quot(untag_check<callstack>(dpop()))));
196 void factor_vm::primitive_set_innermost_stack_frame_quot()
198 gc_root<callstack> callstack(dpop(),this);
199 gc_root<quotation> quot(dpop(),this);
201 callstack.untag_check(this);
202 quot.untag_check(this);
204 jit_compile(quot.value(),true);
206 stack_frame *inner = innermost_stack_frame_quot(callstack.untagged());
207 cell offset = (char *)FRAME_RETURN_ADDRESS(inner) - (char *)inner->xt;
208 inner->xt = quot->xt;
209 FRAME_RETURN_ADDRESS(inner) = (char *)quot->xt + offset;
212 /* called before entry into Factor code. */
213 void factor_vm::save_callstack_bottom(stack_frame *callstack_bottom)
215 stack_chain->callstack_bottom = callstack_bottom;
218 VM_ASM_API void save_callstack_bottom(stack_frame *callstack_bottom, factor_vm *myvm)
221 return VM_PTR->save_callstack_bottom(callstack_bottom);