6 void factorvm::check_frame(stack_frame *frame)
9 check_code_pointer((cell)frame->xt);
10 assert(frame->size != 0);
14 callstack *factorvm::allot_callstack(cell size)
16 callstack *stack = allot<callstack>(callstack_size(size));
17 stack->length = tag_fixnum(size);
21 stack_frame *factorvm::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 *factorvm::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 inline void factorvm::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));
65 PRIMITIVE_GETVM()->primitive_callstack();
68 inline void factorvm::primitive_set_callstack()
70 callstack *stack = untag_check<callstack>(dpop());
72 set_callstack(stack_chain->callstack_bottom,
74 untag_fixnum(stack->length),
77 /* We cannot return here ... */
78 critical_error("Bug in set_callstack()",0);
81 PRIMITIVE(set_callstack)
83 PRIMITIVE_GETVM()->primitive_set_callstack();
86 code_block *factorvm::frame_code(stack_frame *frame)
89 return (code_block *)frame->xt - 1;
92 cell factorvm::frame_type(stack_frame *frame)
94 return frame_code(frame)->type;
97 cell factorvm::frame_executing(stack_frame *frame)
99 code_block *compiled = frame_code(frame);
100 if(compiled->literals == F || !stack_traces_p())
104 array *literals = untag<array>(compiled->literals);
105 cell executing = array_nth(literals,0);
106 check_data_pointer((object *)executing);
111 stack_frame *factorvm::frame_successor(stack_frame *frame)
114 return (stack_frame *)((cell)frame - frame->size);
117 /* Allocates memory */
118 cell factorvm::frame_scan(stack_frame *frame)
120 switch(frame_type(frame))
124 cell quot = frame_executing(frame);
129 char *return_addr = (char *)FRAME_RETURN_ADDRESS(frame);
130 char *quot_xt = (char *)(frame_code(frame) + 1);
132 return tag_fixnum(quot_code_offset_to_scan(
133 quot,(cell)(return_addr - quot_xt)));
139 critical_error("Bad frame type",frame_type(frame));
147 struct stack_frame_accumulator {
148 growable_array frames;
150 stack_frame_accumulator(factorvm *vm) : frames(vm) {}
152 void operator()(stack_frame *frame, factorvm *myvm)
154 gc_root<object> executing(myvm->frame_executing(frame),myvm);
155 gc_root<object> scan(myvm->frame_scan(frame),myvm);
157 frames.add(executing.value());
158 frames.add(scan.value());
164 inline void factorvm::primitive_callstack_to_array()
166 gc_root<callstack> callstack(dpop(),this);
168 stack_frame_accumulator accum(this);
169 iterate_callstack_object(callstack.untagged(),accum);
172 dpush(accum.frames.elements.value());
175 PRIMITIVE(callstack_to_array)
177 PRIMITIVE_GETVM()->primitive_callstack_to_array();
180 stack_frame *factorvm::innermost_stack_frame(callstack *stack)
182 stack_frame *top = stack->top();
183 stack_frame *bottom = stack->bottom();
184 stack_frame *frame = bottom - 1;
186 while(frame >= top && frame_successor(frame) >= top)
187 frame = frame_successor(frame);
192 stack_frame *factorvm::innermost_stack_frame_quot(callstack *callstack)
194 stack_frame *inner = innermost_stack_frame(callstack);
195 tagged<quotation>(frame_executing(inner)).untag_check(this);
199 /* Some primitives implementing a limited form of callstack mutation.
200 Used by the single stepper. */
201 inline void factorvm::primitive_innermost_stack_frame_executing()
203 dpush(frame_executing(innermost_stack_frame(untag_check<callstack>(dpop()))));
206 PRIMITIVE(innermost_stack_frame_executing)
208 PRIMITIVE_GETVM()->primitive_innermost_stack_frame_executing();
211 inline void factorvm::primitive_innermost_stack_frame_scan()
213 dpush(frame_scan(innermost_stack_frame_quot(untag_check<callstack>(dpop()))));
216 PRIMITIVE(innermost_stack_frame_scan)
218 PRIMITIVE_GETVM()->primitive_innermost_stack_frame_scan();
221 inline void factorvm::primitive_set_innermost_stack_frame_quot()
223 gc_root<callstack> callstack(dpop(),this);
224 gc_root<quotation> quot(dpop(),this);
226 callstack.untag_check(this);
227 quot.untag_check(this);
229 jit_compile(quot.value(),true);
231 stack_frame *inner = innermost_stack_frame_quot(callstack.untagged());
232 cell offset = (char *)FRAME_RETURN_ADDRESS(inner) - (char *)inner->xt;
233 inner->xt = quot->xt;
234 FRAME_RETURN_ADDRESS(inner) = (char *)quot->xt + offset;
237 PRIMITIVE(set_innermost_stack_frame_quot)
239 PRIMITIVE_GETVM()->primitive_set_innermost_stack_frame_quot();
242 /* called before entry into Factor code. */
243 void factorvm::save_callstack_bottom(stack_frame *callstack_bottom)
245 stack_chain->callstack_bottom = callstack_bottom;
248 VM_ASM_API void save_callstack_bottom(stack_frame *callstack_bottom, factorvm *myvm)
251 return VM_PTR->save_callstack_bottom(callstack_bottom);