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;
93 cell factorvm::frame_type(stack_frame *frame)
95 return frame_code(frame)->type;
98 cell factorvm::frame_executing(stack_frame *frame)
100 code_block *compiled = frame_code(frame);
101 if(compiled->literals == F || !stack_traces_p())
105 array *literals = untag<array>(compiled->literals);
106 cell executing = array_nth(literals,0);
107 check_data_pointer((object *)executing);
112 stack_frame *factorvm::frame_successor(stack_frame *frame)
115 return (stack_frame *)((cell)frame - frame->size);
118 /* Allocates memory */
119 cell factorvm::frame_scan(stack_frame *frame)
121 switch(frame_type(frame))
125 cell quot = frame_executing(frame);
130 char *return_addr = (char *)FRAME_RETURN_ADDRESS(frame);
131 char *quot_xt = (char *)(frame_code(frame) + 1);
133 return tag_fixnum(quot_code_offset_to_scan(
134 quot,(cell)(return_addr - quot_xt)));
140 critical_error("Bad frame type",frame_type(frame));
148 struct stack_frame_accumulator {
149 growable_array frames;
151 stack_frame_accumulator(factorvm *vm) : frames(vm) {}
153 void operator()(stack_frame *frame, factorvm *myvm)
155 gc_root<object> executing(myvm->frame_executing(frame),myvm);
156 gc_root<object> scan(myvm->frame_scan(frame),myvm);
158 frames.add(executing.value());
159 frames.add(scan.value());
165 inline void factorvm::primitive_callstack_to_array()
167 gc_root<callstack> callstack(dpop(),this);
169 stack_frame_accumulator accum(this);
170 iterate_callstack_object(callstack.untagged(),accum);
173 dpush(accum.frames.elements.value());
176 PRIMITIVE(callstack_to_array)
178 PRIMITIVE_GETVM()->primitive_callstack_to_array();
181 stack_frame *factorvm::innermost_stack_frame(callstack *stack)
183 stack_frame *top = stack->top();
184 stack_frame *bottom = stack->bottom();
185 stack_frame *frame = bottom - 1;
187 while(frame >= top && frame_successor(frame) >= top)
188 frame = frame_successor(frame);
193 stack_frame *factorvm::innermost_stack_frame_quot(callstack *callstack)
195 stack_frame *inner = innermost_stack_frame(callstack);
196 tagged<quotation>(frame_executing(inner)).untag_check(this);
200 /* Some primitives implementing a limited form of callstack mutation.
201 Used by the single stepper. */
202 inline void factorvm::primitive_innermost_stack_frame_executing()
204 dpush(frame_executing(innermost_stack_frame(untag_check<callstack>(dpop()))));
207 PRIMITIVE(innermost_stack_frame_executing)
209 PRIMITIVE_GETVM()->primitive_innermost_stack_frame_executing();
212 inline void factorvm::primitive_innermost_stack_frame_scan()
214 dpush(frame_scan(innermost_stack_frame_quot(untag_check<callstack>(dpop()))));
217 PRIMITIVE(innermost_stack_frame_scan)
219 PRIMITIVE_GETVM()->primitive_innermost_stack_frame_scan();
222 inline void factorvm::primitive_set_innermost_stack_frame_quot()
224 gc_root<callstack> callstack(dpop(),this);
225 gc_root<quotation> quot(dpop(),this);
227 callstack.untag_check(this);
228 quot.untag_check(this);
230 jit_compile(quot.value(),true);
232 stack_frame *inner = innermost_stack_frame_quot(callstack.untagged());
233 cell offset = (char *)FRAME_RETURN_ADDRESS(inner) - (char *)inner->xt;
234 inner->xt = quot->xt;
235 FRAME_RETURN_ADDRESS(inner) = (char *)quot->xt + offset;
238 PRIMITIVE(set_innermost_stack_frame_quot)
240 PRIMITIVE_GETVM()->primitive_set_innermost_stack_frame_quot();
243 /* called before entry into Factor code. */
244 void factorvm::save_callstack_bottom(stack_frame *callstack_bottom)
246 stack_chain->callstack_bottom = callstack_bottom;
249 VM_ASM_API void save_callstack_bottom(stack_frame *callstack_bottom, factorvm *myvm)
252 return VM_PTR->save_callstack_bottom(callstack_bottom);