reset_retainstack();
}
-void context::scrub_stacks(gc_info* info, cell index) {
- uint8_t* bitmap = info->gc_info_bitmap();
-
- {
- cell base = info->callsite_scrub_d(index);
-
- for (cell loc = 0; loc < info->scrub_d_count; loc++) {
- if (bitmap_p(bitmap, base + loc)) {
-#ifdef DEBUG_GC_MAPS
- std::cout << "scrubbing datastack location " << loc << std::endl;
-#endif
- *((cell*)datastack - loc) = 0;
- }
- }
- }
-
- {
- cell base = info->callsite_scrub_r(index);
-
- for (cell loc = 0; loc < info->scrub_r_count; loc++) {
- if (bitmap_p(bitmap, base + loc)) {
-#ifdef DEBUG_GC_MAPS
- std::cout << "scrubbing retainstack location " << loc << std::endl;
-#endif
- *((cell*)retainstack - loc) = 0;
- }
- }
- }
-}
-
context::~context() {
delete datastack_seg;
delete retainstack_seg;
FACTOR_ASSERT(!data->high_fragmentation_p());
}
-/* primitive_minor_gc() is invoked by inline GC checks, and it needs to fill in
- uninitialized stack locations before actually calling the GC. See the
- comment in compiler.cfg.stacks.uninitialized for details. */
-
-struct call_frame_scrubber {
- factor_vm* parent;
- context* ctx;
-
- call_frame_scrubber(factor_vm* parent, context* ctx)
- : parent(parent), ctx(ctx) {}
-
- void operator()(void* frame_top, cell frame_size, code_block* owner,
- void* addr) {
- cell return_address = owner->offset(addr);
-
- gc_info* info = owner->block_gc_info();
-
- FACTOR_ASSERT(return_address < owner->size());
- cell index = info->return_address_index(return_address);
- if (index != (cell)-1)
- ctx->scrub_stacks(info, index);
- }
-};
-
-void factor_vm::scrub_context(context* ctx) {
- call_frame_scrubber scrubber(this, ctx);
- iterate_callstack(ctx, scrubber);
-}
-
-void factor_vm::scrub_contexts() {
- std::set<context*>::const_iterator begin = active_contexts.begin();
- std::set<context*>::const_iterator end = active_contexts.end();
- while (begin != end) {
- scrub_context(*begin);
- begin++;
- }
-}
-
void factor_vm::primitive_minor_gc() {
- scrub_contexts();
-
gc(collect_nursery_op, 0, /* requested size */
true /* trace contexts? */);
}
void visit_roots();
void visit_callstack_object(callstack* stack);
void visit_callstack(context* ctx);
+ void visit_context(context *ctx);
void visit_contexts();
void visit_code_block_objects(code_block* compiled);
void visit_embedded_literals(code_block* compiled);
parent->special_objects + special_object_count);
}
+/* primitive_minor_gc() is invoked by inline GC checks, and it needs to fill in
+ uninitialized stack locations before actually calling the GC. See the
+ documentation in compiler.cfg.stacks.vacant for details.
+
+ So for each call frame:
+
+ - scrub some uninitialized locations
+ - trace some overinitialized locations
+ - trace roots in spill slots
+*/
template <typename Fixup> struct call_frame_slot_visitor {
factor_vm* parent;
slot_visitor<Fixup>* visitor;
cell* stack_pointer = (cell*)frame_top;
uint8_t* bitmap = info->gc_info_bitmap();
- /* Subtract old value of base pointer from every derived pointer. */
- for (cell spill_slot = 0; spill_slot < info->derived_root_count;
- spill_slot++) {
- uint32_t base_pointer = info->lookup_base_pointer(callsite, spill_slot);
- if (base_pointer != (uint32_t)-1) {
+ /* Scrub vacant stack locations. */
+ cell callsite_scrub_d = info->callsite_scrub_d(callsite);
+ for (cell loc = 0; loc < info->scrub_d_count; loc++) {
+ if (bitmap_p(bitmap, callsite_scrub_d + loc)) {
#ifdef DEBUG_GC_MAPS
- std::cout << "visiting derived root " << spill_slot
- << " with base pointer " << base_pointer << std::endl;
+ std::cout << "scrubbing datastack location " << loc << std::endl;
#endif
- stack_pointer[spill_slot] -= stack_pointer[base_pointer];
+ *((cell*)ctx->datastack - loc) = 0;
+ }
+ }
+
+ cell callsite_scrub_r = info->callsite_scrub_r(callsite);
+ for (cell loc = 0; loc < info->scrub_r_count; loc++) {
+ if (bitmap_p(bitmap, callsite_scrub_r + loc)) {
+#ifdef DEBUG_GC_MAPS
+ std::cout << "scrubbing retainstack location " << loc << std::endl;
+#endif
+ *((cell*)ctx->retainstack - loc) = 0;
}
}
- /* Trace all overinitialized stack locations. */
+ /* Trace overinitialized stack locations. */
cell callsite_check_d = info->callsite_check_d(callsite);
for (uint32_t loc = 0; loc < info->check_d_count; loc++) {
if (bitmap_p(bitmap, callsite_check_d + loc)) {
}
}
+ /* Subtract old value of base pointer from every derived pointer. */
+ for (cell spill_slot = 0; spill_slot < info->derived_root_count;
+ spill_slot++) {
+ uint32_t base_pointer = info->lookup_base_pointer(callsite, spill_slot);
+ if (base_pointer != (uint32_t)-1) {
+#ifdef DEBUG_GC_MAPS
+ std::cout << "visiting derived root " << spill_slot
+ << " with base pointer " << base_pointer << std::endl;
+#endif
+ stack_pointer[spill_slot] -= stack_pointer[base_pointer];
+ }
+ }
+
/* Update all GC roots, including base pointers. */
cell callsite_gc_roots = info->callsite_gc_roots(callsite);
parent->iterate_callstack(ctx, call_frame_visitor, fixup);
}
+template <typename Fixup>
+void slot_visitor<Fixup>::visit_context(context* ctx) {
+ /* Callstack is visited first because it scrubs the data and retain
+ stacks. */
+ visit_callstack(ctx);
+
+ visit_stack_elements(ctx->datastack_seg, (cell*)ctx->datastack);
+ visit_stack_elements(ctx->retainstack_seg, (cell*)ctx->retainstack);
+ visit_object_array(ctx->context_objects,
+ ctx->context_objects + context_object_count);
+
+}
+
template <typename Fixup> void slot_visitor<Fixup>::visit_contexts() {
std::set<context*>::const_iterator begin = parent->active_contexts.begin();
std::set<context*>::const_iterator end = parent->active_contexts.end();
while (begin != end) {
- context* ctx = *begin;
-
- visit_stack_elements(ctx->datastack_seg, (cell*)ctx->datastack);
- visit_stack_elements(ctx->retainstack_seg, (cell*)ctx->retainstack);
- visit_object_array(ctx->context_objects,
- ctx->context_objects + context_object_count);
- visit_callstack(ctx);
+ visit_context(*begin);
begin++;
}
}