6 context::context(cell datastack_size, cell retainstack_size, cell callstack_size) :
8 callstack_bottom(NULL),
12 datastack_seg(new segment(datastack_size,false)),
13 retainstack_seg(new segment(retainstack_size,false)),
14 callstack_seg(new segment(callstack_size,false))
19 void context::reset_datastack()
21 datastack = datastack_seg->start - sizeof(cell);
24 void context::reset_retainstack()
26 retainstack = retainstack_seg->start - sizeof(cell);
29 void context::reset_callstack()
31 callstack_top = callstack_bottom = CALLSTACK_BOTTOM(this);
34 void context::reset_context_objects()
36 memset_cell(context_objects,false_object,context_object_count * sizeof(cell));
44 reset_context_objects();
47 void context::fix_stacks()
49 if(datastack + sizeof(cell) < datastack_seg->start
50 || datastack + stack_reserved >= datastack_seg->end)
53 if(retainstack + sizeof(cell) < retainstack_seg->start
54 || retainstack + stack_reserved >= retainstack_seg->end)
61 delete retainstack_seg;
65 /* called on startup */
66 void factor_vm::init_contexts(cell datastack_size_, cell retainstack_size_, cell callstack_size_)
68 datastack_size = datastack_size_;
69 retainstack_size = retainstack_size_;
70 callstack_size = callstack_size_;
73 spare_ctx = new_context();
76 void factor_vm::delete_contexts()
79 std::vector<context *>::const_iterator iter = unused_contexts.begin();
80 std::vector<context *>::const_iterator end = unused_contexts.end();
88 context *factor_vm::new_context()
92 if(unused_contexts.empty())
94 new_context = new context(datastack_size,
100 new_context = unused_contexts.back();
101 unused_contexts.pop_back();
104 new_context->reset();
106 active_contexts.insert(new_context);
111 context *new_context(factor_vm *parent)
113 return parent->new_context();
116 void factor_vm::delete_context(context *old_context)
118 unused_contexts.push_back(old_context);
119 active_contexts.erase(old_context);
122 void factor_vm::begin_callback()
125 spare_ctx = new_context();
126 callback_ids.push_back(callback_id++);
129 void begin_callback(factor_vm *parent)
131 parent->begin_callback();
134 void factor_vm::end_callback()
136 callback_ids.pop_back();
140 void end_callback(factor_vm *parent)
142 parent->end_callback();
145 void factor_vm::primitive_current_callback()
147 ctx->push(tag_fixnum(callback_ids.back()));
150 void factor_vm::primitive_context_object()
152 fixnum n = untag_fixnum(ctx->peek());
153 ctx->replace(ctx->context_objects[n]);
156 void factor_vm::primitive_set_context_object()
158 fixnum n = untag_fixnum(ctx->pop());
159 cell value = ctx->pop();
160 ctx->context_objects[n] = value;
163 bool factor_vm::stack_to_array(cell bottom, cell top)
165 fixnum depth = (fixnum)(top - bottom + sizeof(cell));
171 array *a = allot_uninitialized_array<array>(depth / sizeof(cell));
172 memcpy(a + 1,(void*)bottom,depth);
173 ctx->push(tag<array>(a));
178 void factor_vm::primitive_datastack()
180 if(!stack_to_array(ctx->datastack_seg->start,ctx->datastack))
181 general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object);
184 void factor_vm::primitive_retainstack()
186 if(!stack_to_array(ctx->retainstack_seg->start,ctx->retainstack))
187 general_error(ERROR_RETAINSTACK_UNDERFLOW,false_object,false_object);
190 /* returns pointer to top of stack */
191 cell factor_vm::array_to_stack(array *array, cell bottom)
193 cell depth = array_capacity(array) * sizeof(cell);
194 memcpy((void*)bottom,array + 1,depth);
195 return bottom + depth - sizeof(cell);
198 void factor_vm::primitive_set_datastack()
200 ctx->datastack = array_to_stack(untag_check<array>(ctx->pop()),ctx->datastack_seg->start);
203 void factor_vm::primitive_set_retainstack()
205 ctx->retainstack = array_to_stack(untag_check<array>(ctx->pop()),ctx->retainstack_seg->start);
208 /* Used to implement call( */
209 void factor_vm::primitive_check_datastack()
211 fixnum out = to_fixnum(ctx->pop());
212 fixnum in = to_fixnum(ctx->pop());
213 fixnum height = out - in;
214 array *saved_datastack = untag_check<array>(ctx->pop());
215 fixnum saved_height = array_capacity(saved_datastack);
216 fixnum current_height = (ctx->datastack - ctx->datastack_seg->start + sizeof(cell)) / sizeof(cell);
217 if(current_height - height != saved_height)
218 ctx->push(false_object);
221 cell *ds_bot = (cell *)ctx->datastack_seg->start;
222 for(fixnum i = 0; i < saved_height - in; i++)
224 if(ds_bot[i] != array_nth(saved_datastack,i))
226 ctx->push(false_object);
230 ctx->push(true_object);
234 void factor_vm::primitive_load_locals()
236 fixnum count = untag_fixnum(ctx->pop());
237 memcpy((cell *)(ctx->retainstack + sizeof(cell)),
238 (cell *)(ctx->datastack - sizeof(cell) * (count - 1)),
239 sizeof(cell) * count);
240 ctx->datastack -= sizeof(cell) * count;
241 ctx->retainstack += sizeof(cell) * count;
244 void factor_vm::primitive_context()
246 ctx->push(allot_alien(ctx));
249 void factor_vm::primitive_delete_context()
251 context *old_context = (context *)pinned_alien_offset(ctx->pop());
252 delete_context(old_context);