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
parent
d2aea0f606
commit
4d7bc4c169
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
10
vm/image.cpp
10
vm/image.cpp
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue