renaming: contain? -> any?, deep-contains? -> deep-any?, pad-left -> pad-head, pad...
[factor/jcg.git] / vm / callstack.c
blobae3f52411287ce2e088d7c75d6b25858d31c9bb0
1 #include "master.h"
3 /* called before entry into Factor code. */
4 F_FASTCALL void save_callstack_bottom(F_STACK_FRAME *callstack_bottom)
6 stack_chain->callstack_bottom = callstack_bottom;
9 void iterate_callstack(CELL top, CELL bottom, CALLSTACK_ITER iterator)
11 F_STACK_FRAME *frame = (F_STACK_FRAME *)bottom - 1;
13 while((CELL)frame >= top)
15 F_STACK_FRAME *next = frame_successor(frame);
16 iterator(frame);
17 frame = next;
21 void iterate_callstack_object(F_CALLSTACK *stack, CALLSTACK_ITER iterator)
23 CELL top = (CELL)FIRST_STACK_FRAME(stack);
24 CELL bottom = top + untag_fixnum_fast(stack->length);
26 iterate_callstack(top,bottom,iterator);
29 F_CALLSTACK *allot_callstack(CELL size)
31 F_CALLSTACK *callstack = allot_object(
32 CALLSTACK_TYPE,
33 callstack_size(size));
34 callstack->length = tag_fixnum(size);
35 return callstack;
38 F_STACK_FRAME *fix_callstack_top(F_STACK_FRAME *top, F_STACK_FRAME *bottom)
40 F_STACK_FRAME *frame = bottom - 1;
42 while(frame >= top)
43 frame = frame_successor(frame);
45 return frame + 1;
48 /* We ignore the topmost frame, the one calling 'callstack',
49 so that set-callstack doesn't get stuck in an infinite loop.
51 This means that if 'callstack' is called in tail position, we
52 will have popped a necessary frame... however this word is only
53 called by continuation implementation, and user code shouldn't
54 be calling it at all, so we leave it as it is for now. */
55 F_STACK_FRAME *capture_start(void)
57 F_STACK_FRAME *frame = stack_chain->callstack_bottom - 1;
58 while(frame >= stack_chain->callstack_top
59 && frame_successor(frame) >= stack_chain->callstack_top)
61 frame = frame_successor(frame);
63 return frame + 1;
66 void primitive_callstack(void)
68 F_STACK_FRAME *top = capture_start();
69 F_STACK_FRAME *bottom = stack_chain->callstack_bottom;
71 F_FIXNUM size = (CELL)bottom - (CELL)top;
72 if(size < 0)
73 size = 0;
75 F_CALLSTACK *callstack = allot_callstack(size);
76 memcpy(FIRST_STACK_FRAME(callstack),top,size);
77 dpush(tag_object(callstack));
80 void primitive_set_callstack(void)
82 F_CALLSTACK *stack = untag_callstack(dpop());
84 set_callstack(stack_chain->callstack_bottom,
85 FIRST_STACK_FRAME(stack),
86 untag_fixnum_fast(stack->length),
87 memcpy);
89 /* We cannot return here ... */
90 critical_error("Bug in set_callstack()",0);
93 F_CODE_BLOCK *frame_code(F_STACK_FRAME *frame)
95 return (F_CODE_BLOCK *)frame->xt - 1;
98 CELL frame_type(F_STACK_FRAME *frame)
100 return frame_code(frame)->type;
103 CELL frame_executing(F_STACK_FRAME *frame)
105 F_CODE_BLOCK *compiled = frame_code(frame);
106 if(compiled->literals == F)
107 return F;
108 else
110 F_ARRAY *array = untag_object(compiled->literals);
111 return array_nth(array,0);
115 F_STACK_FRAME *frame_successor(F_STACK_FRAME *frame)
117 if(frame->size == 0)
118 critical_error("Stack frame has zero size",(CELL)frame);
119 return (F_STACK_FRAME *)((CELL)frame - frame->size);
122 CELL frame_scan(F_STACK_FRAME *frame)
124 if(frame_type(frame) == QUOTATION_TYPE)
126 CELL quot = frame_executing(frame);
127 if(quot == F)
128 return F;
129 else
131 XT return_addr = FRAME_RETURN_ADDRESS(frame);
132 XT quot_xt = (XT)(frame_code(frame) + 1);
134 return tag_fixnum(quot_code_offset_to_scan(
135 quot,(CELL)(return_addr - quot_xt)));
138 else
139 return F;
142 /* C doesn't have closures... */
143 static CELL frame_count;
145 void count_stack_frame(F_STACK_FRAME *frame)
147 frame_count += 2;
150 static CELL frame_index;
151 static F_ARRAY *array;
153 void stack_frame_to_array(F_STACK_FRAME *frame)
155 set_array_nth(array,frame_index++,frame_executing(frame));
156 set_array_nth(array,frame_index++,frame_scan(frame));
159 void primitive_callstack_to_array(void)
161 F_CALLSTACK *stack = untag_callstack(dpop());
163 frame_count = 0;
164 iterate_callstack_object(stack,count_stack_frame);
166 REGISTER_UNTAGGED(stack);
167 array = allot_array_internal(ARRAY_TYPE,frame_count);
168 UNREGISTER_UNTAGGED(stack);
170 frame_index = 0;
171 iterate_callstack_object(stack,stack_frame_to_array);
173 dpush(tag_object(array));
176 F_STACK_FRAME *innermost_stack_frame(F_CALLSTACK *callstack)
178 F_STACK_FRAME *top = FIRST_STACK_FRAME(callstack);
179 CELL bottom = (CELL)top + untag_fixnum_fast(callstack->length);
181 F_STACK_FRAME *frame = (F_STACK_FRAME *)bottom - 1;
183 while(frame >= top && frame_successor(frame) >= top)
184 frame = frame_successor(frame);
186 return frame;
189 /* Some primitives implementing a limited form of callstack mutation.
190 Used by the single stepper. */
191 void primitive_innermost_stack_frame_quot(void)
193 F_STACK_FRAME *inner = innermost_stack_frame(
194 untag_callstack(dpop()));
195 type_check(QUOTATION_TYPE,frame_executing(inner));
197 dpush(frame_executing(inner));
200 void primitive_innermost_stack_frame_scan(void)
202 F_STACK_FRAME *inner = innermost_stack_frame(
203 untag_callstack(dpop()));
204 type_check(QUOTATION_TYPE,frame_executing(inner));
206 dpush(frame_scan(inner));
209 void primitive_set_innermost_stack_frame_quot(void)
211 F_CALLSTACK *callstack = untag_callstack(dpop());
212 F_QUOTATION *quot = untag_quotation(dpop());
214 REGISTER_UNTAGGED(callstack);
215 REGISTER_UNTAGGED(quot);
217 jit_compile(tag_object(quot),true);
219 UNREGISTER_UNTAGGED(quot);
220 UNREGISTER_UNTAGGED(callstack);
222 F_STACK_FRAME *inner = innermost_stack_frame(callstack);
223 type_check(QUOTATION_TYPE,frame_executing(inner));
225 CELL offset = FRAME_RETURN_ADDRESS(inner) - inner->xt;
227 inner->xt = quot->xt;
229 FRAME_RETURN_ADDRESS(inner) = quot->xt + offset;