3 void reset_datastack(void)
8 void reset_retainstack(void)
13 #define RESERVED (64 * CELLS)
17 if(ds
+ CELLS
< ds_bot
|| ds
+ RESERVED
>= ds_top
) reset_datastack();
18 if(rs
+ CELLS
< rs_bot
|| rs
+ RESERVED
>= rs_top
) reset_retainstack();
21 /* called before entry into foreign C code. Note that ds and rs might
22 be stored in registers, so callbacks must save and restore the correct values */
23 void save_stacks(void)
27 stack_chain
->datastack
= ds
;
28 stack_chain
->retainstack
= rs
;
32 F_CONTEXT
*alloc_context(void)
38 context
= unused_contexts
;
39 unused_contexts
= unused_contexts
->next
;
43 context
= safe_malloc(sizeof(F_CONTEXT
));
44 context
->datastack_region
= alloc_segment(ds_size
);
45 context
->retainstack_region
= alloc_segment(rs_size
);
51 void dealloc_context(F_CONTEXT
*context
)
53 context
->next
= unused_contexts
;
54 unused_contexts
= context
;
57 /* called on entry into a compiled callback */
58 void nest_stacks(void)
60 F_CONTEXT
*new_stacks
= alloc_context();
62 new_stacks
->callstack_bottom
= (F_STACK_FRAME
*)-1;
63 new_stacks
->callstack_top
= (F_STACK_FRAME
*)-1;
65 /* note that these register values are not necessarily valid stack
66 pointers. they are merely saved non-volatile registers, and are
67 restored in unnest_stacks(). consider this scenario:
68 - factor code calls C function
69 - C function saves ds/cs registers (since they're non-volatile)
70 - C function clobbers them
71 - C function calls Factor callback
72 - Factor callback returns
73 - C function restores registers
74 - C function returns to Factor code */
75 new_stacks
->datastack_save
= ds
;
76 new_stacks
->retainstack_save
= rs
;
78 /* save per-callback userenv */
79 new_stacks
->current_callback_save
= userenv
[CURRENT_CALLBACK_ENV
];
80 new_stacks
->catchstack_save
= userenv
[CATCHSTACK_ENV
];
82 new_stacks
->next
= stack_chain
;
83 stack_chain
= new_stacks
;
89 /* called when leaving a compiled callback */
90 void unnest_stacks(void)
92 ds
= stack_chain
->datastack_save
;
93 rs
= stack_chain
->retainstack_save
;
95 /* restore per-callback userenv */
96 userenv
[CURRENT_CALLBACK_ENV
] = stack_chain
->current_callback_save
;
97 userenv
[CATCHSTACK_ENV
] = stack_chain
->catchstack_save
;
99 F_CONTEXT
*old_stacks
= stack_chain
;
100 stack_chain
= old_stacks
->next
;
101 dealloc_context(old_stacks
);
104 /* called on startup */
105 void init_stacks(CELL ds_size_
, CELL rs_size_
)
110 unused_contexts
= NULL
;
113 bool stack_to_array(CELL bottom
, CELL top
)
115 F_FIXNUM depth
= (F_FIXNUM
)(top
- bottom
+ CELLS
);
121 F_ARRAY
*a
= allot_array_internal(ARRAY_TYPE
,depth
/ CELLS
);
122 memcpy(a
+ 1,(void*)bottom
,depth
);
123 dpush(tag_object(a
));
128 void primitive_datastack(void)
130 if(!stack_to_array(ds_bot
,ds
))
131 general_error(ERROR_DS_UNDERFLOW
,F
,F
,NULL
);
134 void primitive_retainstack(void)
136 if(!stack_to_array(rs_bot
,rs
))
137 general_error(ERROR_RS_UNDERFLOW
,F
,F
,NULL
);
140 /* returns pointer to top of stack */
141 CELL
array_to_stack(F_ARRAY
*array
, CELL bottom
)
143 CELL depth
= array_capacity(array
) * CELLS
;
144 memcpy((void*)bottom
,array
+ 1,depth
);
145 return bottom
+ depth
- CELLS
;
148 void primitive_set_datastack(void)
150 ds
= array_to_stack(untag_array(dpop()),ds_bot
);
153 void primitive_set_retainstack(void)
155 rs
= array_to_stack(untag_array(dpop()),rs_bot
);
158 void primitive_getenv(void)
160 F_FIXNUM e
= untag_fixnum_fast(dpeek());
164 void primitive_setenv(void)
166 F_FIXNUM e
= untag_fixnum_fast(dpop());
171 void primitive_exit(void)
173 exit(to_fixnum(dpop()));
176 void primitive_micros(void)
178 box_unsigned_8(current_micros());
181 void primitive_sleep(void)
183 sleep_micros(to_cell(dpop()));
186 void primitive_set_slot(void)
188 F_FIXNUM slot
= untag_fixnum_fast(dpop());
191 set_slot(obj
,slot
,value
);
194 void primitive_load_locals(void)
196 F_FIXNUM count
= untag_fixnum_fast(dpop());
197 memcpy((CELL
*)(rs
+ CELLS
),(CELL
*)(ds
- CELLS
* (count
- 1)),CELLS
* count
);