Permalink
Browse files

Add new Immix GC as the mature GC

  • Loading branch information...
1 parent 0649d9d commit 45be183889b9daac5e1115c1db3a697ca26a2e55 Evan Phoenix committed Mar 9, 2009
@@ -178,6 +178,14 @@ namespace rubinius {
}
}
+ void Tuple::Info::visit(Object* obj, ObjectVisitor& visit) {
+ Tuple* tup = as<Tuple>(obj);
+
+ for(size_t i = 0; i < tup->num_fields(); i++) {
+ visit.call(tup->field[i]);
+ }
+ }
+
void Tuple::Info::show(STATE, Object* self, int level) {
Tuple* tup = as<Tuple>(self);
size_t size = tup->num_fields();
@@ -58,6 +58,7 @@ namespace rubinius {
virtual void mark(Object* t, ObjectMark& mark);
virtual void show(STATE, Object* self, int level);
virtual void show_simple(STATE, Object* self, int level);
+ virtual void visit(Object*, ObjectVisitor& visit);
};
};
};
@@ -96,6 +96,7 @@ namespace rubinius {
virtual void set_field(STATE, Object*, size_t, Object*);
virtual Object* get_field(STATE, Object*, size_t);
virtual void auto_mark(Object*, ObjectMark&);
+ virtual void auto_visit(Object*, ObjectVisitor&);
};
};
}
@@ -359,6 +359,21 @@ def generate_marks(cpp)
return str
end
+ def generate_visits(cpp)
+ str = ''
+
+ str << generate_visits(cpp.super) if cpp.super
+
+ cpp.fields.each do |name, type, idx|
+ str << <<-EOF
+ visit.call(target->#{name}());
+ EOF
+ end
+
+ return str
+
+ end
+
def generate_mark
marks = generate_marks(self).rstrip
@@ -376,6 +391,23 @@ def generate_mark
str
end
+ def generate_visit
+ marks = generate_visits(self).rstrip
+
+ str = ''
+
+ str << <<-EOF unless marks.empty?
+void #{@name}::Info::auto_visit(Object* _t, ObjectVisitor& visit) {
+ #{@name}* target = as<#{@name}>(_t);
+
+#{marks}
+}
+
+ EOF
+
+ str
+ end
+
def kind_of_code(what)
case @name
when "Fixnum"
@@ -654,6 +686,7 @@ def write_if_new(path)
parser.classes.each do |n, cpp|
f.puts cpp.generate_typechecks
f.puts cpp.generate_mark
+ f.puts cpp.generate_visit
end
end
View
@@ -51,15 +51,8 @@ namespace rubinius {
void GarbageCollector::scan_object(Object* obj) {
Object* slot;
- // If this object's refs are weak, then add it to the weak_refs
- // vector and don't look at it otherwise.
- if(obj->RefsAreWeak) {
- if(!weak_refs) {
- weak_refs = new ObjectArray(0);
- }
-
- weak_refs->push_back(obj);
- return;
+ if(watched_p(obj)) {
+ std::cout << "detected " << obj << " during scan_object.\n";
}
if(obj->klass() && obj->klass()->reference_p()) {
@@ -72,6 +65,17 @@ namespace rubinius {
if(slot) obj->ivars(object_memory->state, slot);
}
+ // If this object's refs are weak, then add it to the weak_refs
+ // vector and don't look at it otherwise.
+ if(obj->RefsAreWeak) {
+ if(!weak_refs) {
+ weak_refs = new ObjectArray(0);
+ }
+
+ weak_refs->push_back(obj);
+ return;
+ }
+
TypeInfo* ti = object_memory->type_info[obj->obj_type];
assert(ti);
@@ -147,6 +151,153 @@ namespace rubinius {
call_frame = call_frame->previous;
}
+ }
+
+ void GarbageCollector::visit_variable_scope(VariableScope* scope, ObjectVisitor& visit) {
+ scope->update(visit.call(scope->self()),
+ visit.call(scope->module()),
+ visit.call(scope->block()));
+
+ for(int i = 0; i < scope->number_of_locals(); i++) {
+ Object* local = scope->get_local(i);
+ if(local->reference_p()) {
+ scope->set_local(i, visit.call(local));
+ }
+ }
+
+ VariableScope* parent = scope->parent();
+ if(parent && parent->reference_p()) {
+ if(parent->stack_allocated_p()) {
+ saw_variable_scope(parent);
+ } else {
+ scope->update_parent((VariableScope*)visit.call(parent));
+ }
+ }
+ }
+
+ void GarbageCollector::visit_call_frame(CallFrame* top_call_frame, ObjectVisitor& visit) {
+ CallFrame* call_frame = top_call_frame;
+ while(call_frame) {
+ if(call_frame->name && call_frame->name->reference_p()) {
+ call_frame->name = (Symbol*)visit.call(call_frame->name);
+ }
+
+ if(call_frame->cm && call_frame->cm->reference_p()) {
+ call_frame->cm = (CompiledMethod*)visit.call(call_frame->cm);
+ }
+
+ for(int i = 0; i < call_frame->stack_size; i++) {
+ Object* obj = call_frame->stk[i];
+ if(obj && obj->reference_p()) {
+ call_frame->stk[i] = visit.call(obj);
+ }
+ }
+
+ if(call_frame->top_scope) {
+ if(call_frame->top_scope->stack_allocated_p()) {
+ visit_variable_scope(call_frame->top_scope, visit);
+ } else {
+ call_frame->top_scope = (VariableScope*)visit.call(call_frame->top_scope);
+ }
+ }
+
+ if(call_frame->scope) {
+ if(call_frame->scope->stack_allocated_p()) {
+ visit_variable_scope(call_frame->scope, visit);
+ } else {
+ call_frame->scope = (VariableScope*)visit.call(call_frame->scope);
+ }
+ }
+
+ call_frame = call_frame->previous;
+ }
+ }
+
+ void GarbageCollector::visit_roots(Roots& roots, ObjectVisitor& visit) {
+ Root* root = static_cast<Root*>(roots.head());
+ while(root) {
+ Object* tmp = root->get();
+ if(tmp->reference_p()) {
+ visit.call(tmp);
+ }
+
+ root = static_cast<Root*>(root->next());
+ }
+ }
+
+ void GarbageCollector::visit_call_frames_list(CallFrameLocationList& call_frames,
+ ObjectVisitor& visit) {
+
+ // Walk all the call frames
+ for(CallFrameLocationList::const_iterator i = call_frames.begin();
+ i != call_frames.end();
+ i++) {
+ CallFrame** loc = *i;
+ visit_call_frame(*loc, visit);
+ }
+ }
+
+ class UnmarkVisitor : public ObjectVisitor {
+ std::vector<Object*> stack_;
+ ObjectMemory* object_memory_;
+
+ public:
+
+ UnmarkVisitor(ObjectMemory* om)
+ : object_memory_(om)
+ {}
+
+ Object* call(Object* obj) {
+ if(watched_p(obj)) {
+ std::cout << "detected " << obj << " during unmarking.\n";
+ }
+
+ if(obj->reference_p() && obj->marked_p()) {
+ obj->clear_mark();
+ stack_.push_back(obj);
+ }
+
+ return obj;
+ }
+
+ /* Understands how to read the inside of an object and find all references
+ * located within. It copies the objects pointed to, but does not follow into
+ * those further (ie, not recursive) */
+ void visit_object(Object* obj) {
+ if(obj->klass() && obj->klass()->reference_p()) {
+ call(obj->klass());
+ }
+
+ if(obj->ivars() && obj->ivars()->reference_p()) {
+ call(obj->ivars());
+ }
+
+ TypeInfo* ti = object_memory_->type_info[obj->obj_type];
+ assert(ti);
+
+ ti->visit(obj, *this);
+ }
+
+ void drain_stack() {
+ while(!stack_.empty()) {
+ Object* obj = stack_.back();
+ stack_.pop_back();
+
+ if(watched_p(obj)) {
+ std::cout << "detected " << obj << " in unmarking stack.\n";
+ }
+
+ visit_object(obj);
+ }
+ }
+ };
+
+ void GarbageCollector::unmark_all(Roots &roots, CallFrameLocationList& call_frames) {
+ UnmarkVisitor visit(object_memory);
+
+ visit_roots(roots, visit);
+ visit_call_frames_list(call_frames, visit);
+ visit.drain_stack();
}
}
View
@@ -13,9 +13,14 @@ namespace rubinius {
typedef std::vector<Object*> ObjectArray;
+ class ObjectVisitor {
+ public:
+ virtual ~ObjectVisitor() { }
+ virtual Object* call(Object*) = 0;
+ };
class GarbageCollector {
- public:
+ public:
ObjectMemory* object_memory;
ObjectArray* weak_refs;
@@ -28,12 +33,19 @@ namespace rubinius {
void walk_call_frame(CallFrame* top_call_frame);
void saw_variable_scope(VariableScope* scope);
+ void visit_variable_scope(VariableScope* scope, ObjectVisitor& visit);
+ void visit_call_frame(CallFrame* top, ObjectVisitor& visit);
+
Object* mark_object(Object* obj) {
if(!obj || !obj->reference_p()) return obj;
Object* tmp = saw_object(obj);
if(tmp) return tmp;
return obj;
}
+
+ void visit_roots(Roots& roots, ObjectVisitor& visit);
+ void visit_call_frames_list(CallFrameLocationList& call_frames, ObjectVisitor& visit);
+ void unmark_all(Roots &roots, CallFrameLocationList& call_frames);
};
}
View
@@ -29,6 +29,10 @@ namespace rubinius {
Object* BakerGC::saw_object(Object* obj) {
Object* copy;
+ if(watched_p(obj)) {
+ std::cout << "detected " << obj << " during baker collection\n";
+ }
+
if(!obj->reference_p()) return obj;
if(obj->zone != YoungObjectZone) return obj;
@@ -56,6 +60,10 @@ namespace rubinius {
ctx->post_copy(as<MethodContext>(obj));
}
+ if(watched_p(copy)) {
+ std::cout << "detected " << copy << " during baker collection (2)\n";
+ }
+
obj->set_forward(object_memory->state, copy);
return copy;
}
@@ -102,7 +110,7 @@ namespace rubinius {
assert(tmp->zone == MatureObjectZone);
assert(!tmp->forwarded_p());
- /* Remove the Remember bit, since we're clearing the set. */
+ // Remove the Remember bit, since we're clearing the set.
tmp->Remember = 0;
scan_object(tmp);
}
@@ -153,6 +161,9 @@ namespace rubinius {
tmp = *oi;
assert(tmp->zone == MatureObjectZone);
scan_object(tmp);
+ if(watched_p(tmp)) {
+ std::cout << "detected " << tmp << " during scan of promoted objects.\n";
+ }
}
delete cur;
View
@@ -15,12 +15,14 @@
#include "call_frame_list.hpp"
+#include "object_watch.hpp"
+
namespace rubinius {
class ObjectMemory;
class BakerGC : public GarbageCollector {
- public:
+ public:
/* Fields */
Heap heap_a;
@@ -60,6 +62,10 @@ namespace rubinius {
obj = (Object*)current->allocate(bytes);
}
+ if(watched_p(obj)) {
+ std::cout << "detected " << obj << " during baker allocation.\n";
+ }
+
obj->init_header(YoungObjectZone, bytes);
#ifdef RBX_GC_STATS
Oops, something went wrong. Retry.

0 comments on commit 45be183

Please sign in to comment.