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();
50 delete retainstack_seg;
54 /* called on startup */
55 void factor_vm::init_contexts(cell datastack_size_, cell retainstack_size_, cell callstack_size_)
57 datastack_size = datastack_size_;
58 retainstack_size = retainstack_size_;
59 callstack_size = callstack_size_;
62 spare_ctx = new_context();
65 void factor_vm::delete_contexts()
68 std::vector<context *>::const_iterator iter = unused_contexts.begin();
69 std::vector<context *>::const_iterator end = unused_contexts.end();
77 context *factor_vm::new_context()
81 if(unused_contexts.empty())
83 new_context = new context(datastack_size,
89 new_context = unused_contexts.back();
90 unused_contexts.pop_back();
95 active_contexts.insert(new_context);
100 void factor_vm::delete_context(context *old_context)
102 unused_contexts.push_back(old_context);
103 active_contexts.erase(old_context);
106 void factor_vm::begin_callback()
109 spare_ctx = new_context();
110 callback_ids.push_back(callback_id++);
113 void begin_callback(factor_vm *parent)
115 parent->begin_callback();
118 void factor_vm::end_callback()
120 callback_ids.pop_back();
124 void end_callback(factor_vm *parent)
126 parent->end_callback();
129 void factor_vm::primitive_current_callback()
131 ctx->push(tag_fixnum(callback_ids.back()));
134 void factor_vm::primitive_context_object()
136 fixnum n = untag_fixnum(ctx->peek());
137 ctx->replace(ctx->context_objects[n]);
140 void factor_vm::primitive_set_context_object()
142 fixnum n = untag_fixnum(ctx->pop());
143 cell value = ctx->pop();
144 ctx->context_objects[n] = value;
147 bool factor_vm::stack_to_array(cell bottom, cell top)
149 fixnum depth = (fixnum)(top - bottom + sizeof(cell));
155 array *a = allot_uninitialized_array<array>(depth / sizeof(cell));
156 memcpy(a + 1,(void*)bottom,depth);
157 ctx->push(tag<array>(a));
162 void factor_vm::primitive_datastack()
164 if(!stack_to_array(ctx->datastack_seg->start,ctx->datastack))
165 general_error(ERROR_DS_UNDERFLOW,false_object,false_object,NULL);
168 void factor_vm::primitive_retainstack()
170 if(!stack_to_array(ctx->retainstack_seg->start,ctx->retainstack))
171 general_error(ERROR_RS_UNDERFLOW,false_object,false_object,NULL);
174 /* returns pointer to top of stack */
175 cell factor_vm::array_to_stack(array *array, cell bottom)
177 cell depth = array_capacity(array) * sizeof(cell);
178 memcpy((void*)bottom,array + 1,depth);
179 return bottom + depth - sizeof(cell);
182 void factor_vm::primitive_set_datastack()
184 ctx->datastack = array_to_stack(untag_check<array>(ctx->pop()),ctx->datastack_seg->start);
187 void factor_vm::primitive_set_retainstack()
189 ctx->retainstack = array_to_stack(untag_check<array>(ctx->pop()),ctx->retainstack_seg->start);
192 /* Used to implement call( */
193 void factor_vm::primitive_check_datastack()
195 fixnum out = to_fixnum(ctx->pop());
196 fixnum in = to_fixnum(ctx->pop());
197 fixnum height = out - in;
198 array *saved_datastack = untag_check<array>(ctx->pop());
199 fixnum saved_height = array_capacity(saved_datastack);
200 fixnum current_height = (ctx->datastack - ctx->datastack_seg->start + sizeof(cell)) / sizeof(cell);
201 if(current_height - height != saved_height)
202 ctx->push(false_object);
205 cell *ds_bot = (cell *)ctx->datastack_seg->start;
206 for(fixnum i = 0; i < saved_height - in; i++)
208 if(ds_bot[i] != array_nth(saved_datastack,i))
210 ctx->push(false_object);
214 ctx->push(true_object);
218 void factor_vm::primitive_load_locals()
220 fixnum count = untag_fixnum(ctx->pop());
221 memcpy((cell *)(ctx->retainstack + sizeof(cell)),
222 (cell *)(ctx->datastack - sizeof(cell) * (count - 1)),
223 sizeof(cell) * count);
224 ctx->datastack -= sizeof(cell) * count;
225 ctx->retainstack += sizeof(cell) * count;
228 void factor_vm::primitive_current_context()
230 ctx->push(allot_alien(ctx));
233 void factor_vm::primitive_start_context()
235 cell quot = ctx->pop();
237 unwind_native_frames(quot,ctx->callstack_bottom);
240 void factor_vm::primitive_delete_context()
242 context *old_context = (context *)pinned_alien_offset(ctx->pop());
243 delete_context(old_context);