void visit_callstack_object(callstack* stack);
void visit_callstack(context* ctx);
void visit_context(context *ctx);
- void visit_code_block_objects(code_block* compiled);
- void visit_embedded_literals(code_block* compiled);
void visit_object_code_block(object* obj);
void visit_context_code_blocks();
void visit_uninitialized_code_blocks();
- void visit_embedded_code_pointers(code_block* compiled);
void visit_object(object* obj);
void visit_mark_stack(std::vector<cell>* mark_stack);
- void visit_instruction_operands(code_block* block, cell rel_base);
+
template <typename SourceGeneration>
cell visit_card(SourceGeneration* gen, cell index, cell start);
template <typename SourceGeneration>
void visit_cards(SourceGeneration* gen, card mask, card unmask);
- void visit_code_heap_roots(std::set<code_block*>* remembered_set);
+
template <typename TargetGeneration>
void cheneys_algorithm(TargetGeneration* gen, cell scan);
+
+ // Visits the data pointers in code blocks in the remembered set.
+ void visit_code_heap_roots(std::set<code_block*>* remembered_set);
+
+ // Visits pointers embedded in instructions in code blocks.
+ void visit_instruction_operands(code_block* block, cell rel_base);
+ void visit_embedded_code_pointers(code_block* compiled);
+ void visit_embedded_literals(code_block* compiled);
+
+ // Visits data pointers in code blocks.
+ void visit_code_block_objects(code_block* compiled);
};
template <typename Fixup>
}
auto callback_slot_visitor = [&](code_block* stub, cell size) {
+ (void)size;
visit_handle(&stub->owner);
};
- parent->callbacks->allocator->iterate(callback_slot_visitor);
+ parent->callbacks->allocator->iterate(callback_slot_visitor, no_fixup());
FACTOR_FOR_EACH(parent->code->uninitialized_blocks) {
iter->second = visit_pointer(iter->second);
}
- FACTOR_FOR_EACH(parent->sample_callstacks) {
- visit_handle(&*iter);
- }
-
FACTOR_FOR_EACH(parent->samples) {
visit_handle(&iter->thread);
}
}
// 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.
+// visit spill slots which references objects in the heap.
// So for each call frame:
-// - scrub some uninitialized locations
// - trace roots in spill slots
template <typename Fixup> struct call_frame_slot_visitor {
slot_visitor<Fixup>* visitor;
- // NULL in case we're a visitor for a callstack object.
- context* ctx;
-
- void scrub_stack(cell stack, uint8_t* bitmap, cell base, uint32_t count) {
- for (cell loc = 0; loc < count; loc++) {
- if (bitmap_p(bitmap, base + loc)) {
-#ifdef DEBUG_GC_MAPS
- FACTOR_PRINT("scrubbing stack location " << loc);
-#endif
- *((cell*)stack - loc) = 0;
- }
- }
- }
- call_frame_slot_visitor(slot_visitor<Fixup>* visitor, context* ctx)
- : visitor(visitor), ctx(ctx) {}
+ call_frame_slot_visitor(slot_visitor<Fixup>* visitor)
+ : visitor(visitor) {}
// frame top -> [return address]
// [spill area]
// [size]
void operator()(cell frame_top, cell size, code_block* owner, cell addr) {
+ (void)size;
cell return_address = owner->offset(addr);
code_block* compiled =
cell* stack_pointer = (cell*)frame_top;
uint8_t* bitmap = info->gc_info_bitmap();
- if (ctx) {
- // Scrub vacant stack locations.
- scrub_stack(ctx->datastack,
- bitmap,
- info->callsite_scrub_d(callsite),
- info->scrub_d_count);
- scrub_stack(ctx->retainstack,
- bitmap,
- info->callsite_scrub_r(callsite),
- info->scrub_r_count);
- }
-
// Subtract old value of base pointer from every derived pointer.
for (cell spill_slot = 0; spill_slot < info->derived_root_count;
spill_slot++) {
for (cell spill_slot = 0; spill_slot < info->gc_root_count; spill_slot++) {
if (bitmap_p(bitmap, callsite_gc_roots + spill_slot)) {
-#ifdef DEBUG_GC_MAPS
+ #ifdef DEBUG_GC_MAPS
FACTOR_PRINT("visiting GC root " << spill_slot);
-#endif
+ #endif
visitor->visit_handle(stack_pointer + spill_slot);
}
}
template <typename Fixup>
void slot_visitor<Fixup>::visit_callstack_object(callstack* stack) {
- call_frame_slot_visitor<Fixup> call_frame_visitor(this, NULL);
+ call_frame_slot_visitor<Fixup> call_frame_visitor(this);
parent->iterate_callstack_object(stack, call_frame_visitor, fixup);
}
template <typename Fixup>
void slot_visitor<Fixup>::visit_callstack(context* ctx) {
- call_frame_slot_visitor<Fixup> call_frame_visitor(this, ctx);
+ call_frame_slot_visitor<Fixup> call_frame_visitor(this);
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);
cell ds_ptr = ctx->datastack;
// Clear out the space not visited with a known pattern. That makes
// it easier to see if uninitialized reads are made.
ctx->fill_stack_seg(ds_ptr, ds_seg, 0xbaadbadd);
- ctx->fill_stack_seg(rs_ptr, rs_seg, 0xdaabdaab);
+ ctx->fill_stack_seg(rs_ptr, rs_seg, 0xdaabdabb);
}
template <typename Fixup>
template <typename Fixup> struct call_frame_code_block_visitor {
Fixup fixup;
- call_frame_code_block_visitor(Fixup fixup)
- : fixup(fixup) {}
+ call_frame_code_block_visitor(Fixup fixup) : fixup(fixup) {}
void operator()(cell frame_top, cell size, code_block* owner, cell addr) {
- code_block* compiled =
+ (void)size;
+ code_block* compiled =
Fixup::translated_code_block_map ? owner : fixup.fixup_code(owner);
cell fixed_addr = compiled->address_for_offset(owner->offset(addr));
break;
}
};
+ if (parent->code->uninitialized_p(block))
+ return;
block->each_instruction_operand(visit_func);
}