VM: merge of slot_visitor and code_block_visitor

Looks like there is no reason for them to be separate classes and by
merging them you can simplify lots of code.
db4
Björn Lindqvist 2015-01-12 04:58:55 +00:00
parent d2aea0f606
commit 4d7bc4c169
7 changed files with 140 additions and 174 deletions

View File

@ -118,7 +118,6 @@ ifdef CONFIG
vm/nursery_collector.hpp \
vm/aging_collector.hpp \
vm/to_tenured_collector.hpp \
vm/code_block_visitor.hpp \
vm/full_collector.hpp \
vm/arrays.hpp \
vm/math.hpp \

View File

@ -1,122 +0,0 @@
namespace factor {
/* Code block visitors iterate over sets of code blocks, applying a functor to
each one. The functor returns a new code_block pointer, which may or may not
equal the old one. This is stored back to the original location.
This is used by GC's sweep and compact phases, and the implementation of the
modify-code-heap primitive.
Iteration is driven by visit_*() methods. Some of them define GC roots:
- visit_context_code_blocks()
- visit_callback_code_blocks() */
template <typename Fixup> struct code_block_visitor {
factor_vm* parent;
Fixup fixup;
code_block_visitor(factor_vm* parent, Fixup fixup)
: parent(parent), fixup(fixup) {}
code_block* visit_code_block(code_block* compiled);
void visit_object_code_block(object* obj);
void visit_embedded_code_pointers(code_block* compiled);
void visit_context_code_blocks();
void visit_uninitialized_code_blocks();
};
template <typename Fixup>
code_block* code_block_visitor<Fixup>::visit_code_block(code_block* compiled) {
return fixup.fixup_code(compiled);
}
template <typename Fixup> struct call_frame_code_block_visitor {
factor_vm* parent;
Fixup fixup;
call_frame_code_block_visitor(factor_vm* parent, Fixup fixup)
: parent(parent), fixup(fixup) {}
void operator()(cell frame_top, cell size, code_block* owner, cell addr) {
code_block* compiled =
Fixup::translated_code_block_map ? owner : fixup.fixup_code(owner);
cell fixed_addr = compiled->address_for_offset(owner->offset(addr));
*(cell*)frame_top = fixed_addr;
}
};
template <typename Fixup>
void code_block_visitor<Fixup>::visit_object_code_block(object* obj) {
switch (obj->type()) {
case WORD_TYPE: {
word* w = (word*)obj;
if (w->entry_point)
w->entry_point = visit_code_block(w->code())->entry_point();
break;
}
case QUOTATION_TYPE: {
quotation* q = (quotation*)obj;
if (q->entry_point)
q->entry_point = visit_code_block(q->code())->entry_point();
break;
}
case CALLSTACK_TYPE: {
callstack* stack = (callstack*)obj;
call_frame_code_block_visitor<Fixup> call_frame_visitor(parent, fixup);
parent->iterate_callstack_object(stack, call_frame_visitor, fixup);
break;
}
}
}
template <typename Fixup> struct embedded_code_pointers_visitor {
Fixup fixup;
explicit embedded_code_pointers_visitor(Fixup fixup) : fixup(fixup) {}
void operator()(instruction_operand op) {
relocation_type type = op.rel_type();
if (type == RT_ENTRY_POINT || type == RT_ENTRY_POINT_PIC ||
type == RT_ENTRY_POINT_PIC_TAIL)
op.store_code_block(fixup.fixup_code(op.load_code_block()));
}
};
template <typename Fixup>
void code_block_visitor<Fixup>::visit_embedded_code_pointers(
code_block* compiled) {
if (!parent->code->uninitialized_p(compiled)) {
embedded_code_pointers_visitor<Fixup> operand_visitor(fixup);
compiled->each_instruction_operand(operand_visitor);
}
}
template <typename Fixup>
void code_block_visitor<Fixup>::visit_context_code_blocks() {
call_frame_code_block_visitor<Fixup> call_frame_visitor(parent, fixup);
std::set<context*>::const_iterator begin = parent->active_contexts.begin();
std::set<context*>::const_iterator end = parent->active_contexts.end();
while (begin != end) {
parent->iterate_callstack(*begin++, call_frame_visitor, fixup);
}
}
template <typename Fixup>
void code_block_visitor<Fixup>::visit_uninitialized_code_blocks() {
std::map<code_block*, cell>* uninitialized_blocks =
&parent->code->uninitialized_blocks;
std::map<code_block*, cell>::const_iterator iter =
uninitialized_blocks->begin();
std::map<code_block*, cell>::const_iterator end = uninitialized_blocks->end();
std::map<code_block*, cell> new_uninitialized_blocks;
for (; iter != end; iter++) {
new_uninitialized_blocks.insert(
std::make_pair(fixup.fixup_code(iter->first), iter->second));
}
parent->code->uninitialized_blocks = new_uninitialized_blocks;
}
}

View File

@ -67,12 +67,9 @@ struct object_compaction_updater {
starts(&parent->data->tenured->starts) {}
void operator()(object* old_address, object* new_address, cell size) {
slot_visitor<compaction_fixup> slot_forwarder(parent, fixup);
slot_forwarder.visit_slots(new_address);
code_block_visitor<compaction_fixup> code_forwarder(parent, fixup);
code_forwarder.visit_object_code_block(new_address);
slot_visitor<compaction_fixup> forwarder(parent, fixup);
forwarder.visit_slots(new_address);
forwarder.visit_object_code_block(new_address);
starts->record_object_start_offset(new_address);
}
};
@ -125,19 +122,16 @@ template <typename Fixup> struct code_block_compaction_relocation_visitor {
template <typename Fixup> struct code_block_compaction_updater {
factor_vm* parent;
Fixup fixup;
slot_visitor<Fixup> data_forwarder;
code_block_visitor<Fixup> code_forwarder;
slot_visitor<Fixup> forwarder;
code_block_compaction_updater(
factor_vm* parent, Fixup fixup, slot_visitor<Fixup> data_forwarder,
code_block_visitor<Fixup> code_forwarder)
factor_vm* parent, Fixup fixup, slot_visitor<Fixup> forwarder)
: parent(parent),
fixup(fixup),
data_forwarder(data_forwarder),
code_forwarder(code_forwarder) {}
forwarder(forwarder) { }
void operator()(code_block* old_address, code_block* new_address, cell size) {
data_forwarder.visit_code_block_objects(new_address);
forwarder.visit_code_block_objects(new_address);
code_block_compaction_relocation_visitor<Fixup> visitor(parent, old_address,
fixup);
@ -195,10 +189,9 @@ void factor_vm::collect_compact_impl(bool trace_contexts_p) {
compaction_fixup fixup(data_forwarding_map, code_forwarding_map, &data_finger,
&code_finger);
slot_visitor<compaction_fixup> data_forwarder(this, fixup);
code_block_visitor<compaction_fixup> code_forwarder(this, fixup);
slot_visitor<compaction_fixup> forwarder(this, fixup);
code_forwarder.visit_uninitialized_code_blocks();
forwarder.visit_uninitialized_code_blocks();
/* Object start offsets get recomputed by the object_compaction_updater */
data->tenured->starts.clear_object_start_offsets();
@ -214,14 +207,14 @@ void factor_vm::collect_compact_impl(bool trace_contexts_p) {
pointers inside code blocks. */
{
code_block_compaction_updater<compaction_fixup> code_block_updater(
this, fixup, data_forwarder, code_forwarder);
this, fixup, forwarder);
code->allocator->compact(code_block_updater, fixup, &code_finger);
}
data_forwarder.visit_roots();
forwarder.visit_roots();
if (trace_contexts_p) {
data_forwarder.visit_contexts();
code_forwarder.visit_context_code_blocks();
forwarder.visit_contexts();
forwarder.visit_context_code_blocks();
}
}
@ -270,13 +263,13 @@ struct code_compaction_fixup {
};
struct object_grow_heap_updater {
code_block_visitor<code_compaction_fixup> code_forwarder;
slot_visitor<code_compaction_fixup> forwarder;
explicit object_grow_heap_updater(
code_block_visitor<code_compaction_fixup> code_forwarder)
: code_forwarder(code_forwarder) {}
slot_visitor<code_compaction_fixup> forwarder)
: forwarder(forwarder) {}
void operator()(object* obj) { code_forwarder.visit_object_code_block(obj); }
void operator()(object* obj) { forwarder.visit_object_code_block(obj); }
};
/* Compact just the code heap, after growing the data heap */
@ -288,22 +281,21 @@ void factor_vm::collect_compact_code_impl(bool trace_contexts_p) {
const code_block* code_finger = (code_block*)code->allocator->start;
code_compaction_fixup fixup(code_forwarding_map, &code_finger);
slot_visitor<code_compaction_fixup> data_forwarder(this, fixup);
code_block_visitor<code_compaction_fixup> code_forwarder(this, fixup);
slot_visitor<code_compaction_fixup> forwarder(this, fixup);
code_forwarder.visit_uninitialized_code_blocks();
forwarder.visit_uninitialized_code_blocks();
if (trace_contexts_p)
code_forwarder.visit_context_code_blocks();
forwarder.visit_context_code_blocks();
/* Update code heap references in data heap */
object_grow_heap_updater object_updater(code_forwarder);
object_grow_heap_updater object_updater(forwarder);
each_object(object_updater);
/* Slide everything in the code heap up, and update code heap
pointers inside code blocks. */
code_block_compaction_updater<code_compaction_fixup> code_block_updater(
this, fixup, data_forwarder, code_forwarder);
this, fixup, forwarder);
code->allocator->compact(code_block_updater, fixup, &code_finger);
update_code_roots_for_compaction();

View File

@ -25,21 +25,18 @@ void factor_vm::collect_mark_impl(bool trace_contexts_p) {
workhorse(this, this->data->tenured, full_policy(this));
slot_visitor<gc_workhorse<tenured_space, full_policy> >
data_visitor(this, workhorse);
code_block_visitor<gc_workhorse<tenured_space, full_policy> >
code_visitor(this, workhorse);
visitor(this, workhorse);
mark_stack.clear();
code->allocator->state.clear_mark_bits();
data->tenured->state.clear_mark_bits();
data_visitor.visit_roots();
visitor.visit_roots();
if (trace_contexts_p) {
data_visitor.visit_contexts();
code_visitor.visit_context_code_blocks();
code_visitor.visit_uninitialized_code_blocks();
visitor.visit_contexts();
visitor.visit_context_code_blocks();
visitor.visit_uninitialized_code_blocks();
}
while (!mark_stack.empty()) {
@ -48,15 +45,15 @@ void factor_vm::collect_mark_impl(bool trace_contexts_p) {
if (ptr & 1) {
code_block* compiled = (code_block*)(ptr - 1);
data_visitor.visit_code_block_objects(compiled);
data_visitor.visit_embedded_literals(compiled);
code_visitor.visit_embedded_code_pointers(compiled);
visitor.visit_code_block_objects(compiled);
visitor.visit_embedded_literals(compiled);
visitor.visit_embedded_code_pointers(compiled);
} else {
object* obj = (object*)ptr;
data_visitor.visit_slots(obj);
visitor.visit_slots(obj);
if (obj->type() == ALIEN_TYPE)
((alien*)obj)->update_address();
code_visitor.visit_object_code_block(obj);
visitor.visit_object_code_block(obj);
}
}
data->reset_tenured();

View File

@ -80,19 +80,17 @@ struct startup_fixup {
struct start_object_updater {
factor_vm* parent;
startup_fixup fixup;
slot_visitor<startup_fixup> data_visitor;
code_block_visitor<startup_fixup> code_visitor;
slot_visitor<startup_fixup> visitor;
start_object_updater(factor_vm* parent, startup_fixup fixup)
: parent(parent),
fixup(fixup),
data_visitor(slot_visitor<startup_fixup>(parent, fixup)),
code_visitor(code_block_visitor<startup_fixup>(parent, fixup)) {}
visitor(slot_visitor<startup_fixup>(parent, fixup)) { }
void operator()(object* obj, cell size) {
parent->data->tenured->starts.record_object_start_offset(obj);
data_visitor.visit_slots(obj);
visitor.visit_slots(obj);
switch (obj->type()) {
case ALIEN_TYPE: {
@ -110,7 +108,7 @@ struct start_object_updater {
break;
}
default: {
code_visitor.visit_object_code_block(obj);
visitor.visit_object_code_block(obj);
break;
}
}

View File

@ -137,7 +137,6 @@ namespace factor { struct factor_vm; }
#include "nursery_collector.hpp"
#include "aging_collector.hpp"
#include "to_tenured_collector.hpp"
#include "code_block_visitor.hpp"
#include "full_collector.hpp"
#include "arrays.hpp"
#include "math.hpp"

View File

@ -103,7 +103,18 @@ of the become primitive.
Iteration is driven by visit_*() methods. Some of them define GC roots:
- visit_roots()
- visit_contexts() */
- visit_contexts()
Code block visitors iterate over sets of code blocks, applying a functor to
each one. The functor returns a new code_block pointer, which may or may not
equal the old one. This is stored back to the original location.
This is used by GC's sweep and compact phases, and the implementation of the
modify-code-heap primitive.
Iteration is driven by visit_*() methods. Some of them define GC roots:
- visit_context_code_blocks()
- visit_callback_code_blocks() */
template <typename Fixup> struct slot_visitor {
factor_vm* parent;
@ -130,6 +141,10 @@ template <typename Fixup> struct slot_visitor {
void visit_embedded_literals(code_block* compiled);
void visit_sample_callstacks();
void visit_sample_threads();
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);
};
template <typename Fixup>
@ -431,4 +446,92 @@ void slot_visitor<Fixup>::visit_embedded_literals(code_block* compiled) {
}
}
template <typename Fixup> struct call_frame_code_block_visitor {
factor_vm* parent;
Fixup fixup;
call_frame_code_block_visitor(factor_vm* parent, Fixup fixup)
: parent(parent), fixup(fixup) {}
void operator()(cell frame_top, cell size, code_block* owner, cell addr) {
code_block* compiled =
Fixup::translated_code_block_map ? owner : fixup.fixup_code(owner);
cell fixed_addr = compiled->address_for_offset(owner->offset(addr));
*(cell*)frame_top = fixed_addr;
}
};
template <typename Fixup>
void slot_visitor<Fixup>::visit_object_code_block(object* obj) {
switch (obj->type()) {
case WORD_TYPE: {
word* w = (word*)obj;
if (w->entry_point)
w->entry_point = fixup.fixup_code(w->code())->entry_point();
break;
}
case QUOTATION_TYPE: {
quotation* q = (quotation*)obj;
if (q->entry_point)
q->entry_point = fixup.fixup_code(q->code())->entry_point();
break;
}
case CALLSTACK_TYPE: {
callstack* stack = (callstack*)obj;
call_frame_code_block_visitor<Fixup> call_frame_visitor(parent, fixup);
parent->iterate_callstack_object(stack, call_frame_visitor, fixup);
break;
}
}
}
template <typename Fixup>
void slot_visitor<Fixup>::visit_context_code_blocks() {
call_frame_code_block_visitor<Fixup> call_frame_visitor(parent, fixup);
std::set<context*>::const_iterator begin = parent->active_contexts.begin();
std::set<context*>::const_iterator end = parent->active_contexts.end();
while (begin != end) {
parent->iterate_callstack(*begin++, call_frame_visitor, fixup);
}
}
template <typename Fixup>
void slot_visitor<Fixup>::visit_uninitialized_code_blocks() {
std::map<code_block*, cell>* uninitialized_blocks =
&parent->code->uninitialized_blocks;
std::map<code_block*, cell>::const_iterator iter =
uninitialized_blocks->begin();
std::map<code_block*, cell>::const_iterator end = uninitialized_blocks->end();
std::map<code_block*, cell> new_uninitialized_blocks;
for (; iter != end; iter++) {
new_uninitialized_blocks.insert(
std::make_pair(fixup.fixup_code(iter->first), iter->second));
}
parent->code->uninitialized_blocks = new_uninitialized_blocks;
}
template <typename Fixup> struct embedded_code_pointers_visitor {
Fixup fixup;
explicit embedded_code_pointers_visitor(Fixup fixup) : fixup(fixup) {}
void operator()(instruction_operand op) {
relocation_type type = op.rel_type();
if (type == RT_ENTRY_POINT || type == RT_ENTRY_POINT_PIC ||
type == RT_ENTRY_POINT_PIC_TAIL)
op.store_code_block(fixup.fixup_code(op.load_code_block()));
}
};
template <typename Fixup>
void slot_visitor<Fixup>::visit_embedded_code_pointers(code_block* compiled) {
if (!parent->code->uninitialized_p(compiled)) {
embedded_code_pointers_visitor<Fixup> operand_visitor(fixup);
compiled->each_instruction_operand(operand_visitor);
}
}
}