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 \
+++ /dev/null
-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;
-}
-
-}
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);
}
};
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);
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();
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();
}
}
};
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 */
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();
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()) {
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();
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: {
break;
}
default: {
- code_visitor.visit_object_code_block(obj);
+ visitor.visit_object_code_block(obj);
break;
}
}
#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"
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;
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>
}
}
+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);
+ }
+}
+
}