6 context::context(cell ds_size, cell rs_size) :
8 callstack_bottom(NULL),
12 datastack_region(new segment(ds_size,false)),
13 retainstack_region(new segment(rs_size,false)),
15 current_callback_save(0),
22 context *factor_vm::alloc_context()
28 new_context = unused_contexts;
29 unused_contexts = unused_contexts->next;
32 new_context = new context(ds_size,rs_size);
37 void factor_vm::dealloc_context(context *old_context)
39 old_context->next = unused_contexts;
40 unused_contexts = old_context;
43 /* called on entry into a compiled callback */
44 void factor_vm::nest_stacks(stack_frame *magic_frame)
46 context *new_ctx = alloc_context();
48 new_ctx->callstack_bottom = (stack_frame *)-1;
49 new_ctx->callstack_top = (stack_frame *)-1;
51 new_ctx->magic_frame = magic_frame;
53 /* save per-callback special_objects */
54 new_ctx->current_callback_save = special_objects[OBJ_CURRENT_CALLBACK];
55 new_ctx->catchstack_save = special_objects[OBJ_CATCHSTACK];
57 new_ctx->reset_datastack();
58 new_ctx->reset_retainstack();
64 void nest_stacks(stack_frame *magic_frame, factor_vm *parent)
66 return parent->nest_stacks(magic_frame);
69 /* called when leaving a compiled callback */
70 void factor_vm::unnest_stacks()
72 /* restore per-callback special_objects */
73 special_objects[OBJ_CURRENT_CALLBACK] = ctx->current_callback_save;
74 special_objects[OBJ_CATCHSTACK] = ctx->catchstack_save;
76 context *old_ctx = ctx;
78 dealloc_context(old_ctx);
81 void unnest_stacks(factor_vm *parent)
83 return parent->unnest_stacks();
86 /* called on startup */
87 void factor_vm::init_stacks(cell ds_size_, cell rs_size_)
92 unused_contexts = NULL;
95 bool factor_vm::stack_to_array(cell bottom, cell top)
97 fixnum depth = (fixnum)(top - bottom + sizeof(cell));
103 array *a = allot_uninitialized_array<array>(depth / sizeof(cell));
104 memcpy(a + 1,(void*)bottom,depth);
105 ctx->push(tag<array>(a));
110 void factor_vm::primitive_datastack()
112 if(!stack_to_array(ctx->datastack_region->start,ctx->datastack))
113 general_error(ERROR_DS_UNDERFLOW,false_object,false_object,NULL);
116 void factor_vm::primitive_retainstack()
118 if(!stack_to_array(ctx->retainstack_region->start,ctx->retainstack))
119 general_error(ERROR_RS_UNDERFLOW,false_object,false_object,NULL);
122 /* returns pointer to top of stack */
123 cell factor_vm::array_to_stack(array *array, cell bottom)
125 cell depth = array_capacity(array) * sizeof(cell);
126 memcpy((void*)bottom,array + 1,depth);
127 return bottom + depth - sizeof(cell);
130 void factor_vm::primitive_set_datastack()
132 ctx->datastack = array_to_stack(untag_check<array>(ctx->pop()),ctx->datastack_region->start);
135 void factor_vm::primitive_set_retainstack()
137 ctx->retainstack = array_to_stack(untag_check<array>(ctx->pop()),ctx->retainstack_region->start);
140 /* Used to implement call( */
141 void factor_vm::primitive_check_datastack()
143 fixnum out = to_fixnum(ctx->pop());
144 fixnum in = to_fixnum(ctx->pop());
145 fixnum height = out - in;
146 array *saved_datastack = untag_check<array>(ctx->pop());
147 fixnum saved_height = array_capacity(saved_datastack);
148 fixnum current_height = (ctx->datastack - ctx->datastack_region->start + sizeof(cell)) / sizeof(cell);
149 if(current_height - height != saved_height)
150 ctx->push(false_object);
153 cell *ds_bot = (cell *)ctx->datastack_region->start;
154 for(fixnum i = 0; i < saved_height - in; i++)
156 if(ds_bot[i] != array_nth(saved_datastack,i))
158 ctx->push(false_object);
162 ctx->push(true_object);
166 void factor_vm::primitive_load_locals()
168 fixnum count = untag_fixnum(ctx->pop());
169 memcpy((cell *)(ctx->retainstack + sizeof(cell)),
170 (cell *)(ctx->datastack - sizeof(cell) * (count - 1)),
171 sizeof(cell) * count);
172 ctx->datastack -= sizeof(cell) * count;
173 ctx->retainstack += sizeof(cell) * count;