diff --git a/vm/builtin/data.cpp b/vm/builtin/data.cpp
index 567ca0d265..94aea31dc8 100644
--- a/vm/builtin/data.cpp
+++ b/vm/builtin/data.cpp
@@ -29,9 +29,9 @@ namespace rubinius {
return data;
}
- void Data::finalize(STATE) {
- FreeFunctor f = this->free();
- if(f) f(data());
+ void Data::finalize(STATE, Data* data) {
+ FreeFunctor f = data->free();
+ if(f) f(data->data());
}
void Data::Info::mark(Object* t, ObjectMark& mark) {
diff --git a/vm/builtin/data.hpp b/vm/builtin/data.hpp
index 145a5e6039..3d48986c18 100644
--- a/vm/builtin/data.hpp
+++ b/vm/builtin/data.hpp
@@ -35,7 +35,7 @@ namespace rubinius {
/** New Data instance. */
static Data* create(STATE, void* data, MarkFunctor mark, FreeFunctor free);
- void finalize(STATE);
+ static void finalize(STATE, Data* data);
RDataExposed* exposed() {
return &exposed_;
diff --git a/vm/builtin/dir.cpp b/vm/builtin/dir.cpp
index 32a3ae55bb..9166b6c98a 100644
--- a/vm/builtin/dir.cpp
+++ b/vm/builtin/dir.cpp
@@ -24,7 +24,7 @@ namespace rubinius {
Dir* d = state->new_object
(G(dir));
d->os_ = 0;
- state->om->needs_finalization(d);
+ state->om->needs_finalization(d, (FinalizerFunction)&Dir::finalize);
return d;
}
@@ -39,10 +39,10 @@ namespace rubinius {
return dir;
}
- void Dir::finalize(STATE) {
- if(os_) {
- closedir(os_);
- os_ = 0;
+ void Dir::finalize(STATE, Dir* dir) {
+ if(dir->os_) {
+ closedir(dir->os_);
+ dir->os_ = 0;
}
}
diff --git a/vm/builtin/dir.hpp b/vm/builtin/dir.hpp
index 20061b4a01..fbecc42c08 100644
--- a/vm/builtin/dir.hpp
+++ b/vm/builtin/dir.hpp
@@ -29,7 +29,7 @@ namespace rubinius {
static Dir* create(STATE);
- void finalize(STATE);
+ static void finalize(STATE, Dir* dir);
// Ruby.primitive :dir_allocate
static Dir* allocate(STATE, Object* self);
diff --git a/vm/builtin/fiber.cpp b/vm/builtin/fiber.cpp
index 4f7ebd6176..9a456a0c4a 100644
--- a/vm/builtin/fiber.cpp
+++ b/vm/builtin/fiber.cpp
@@ -37,7 +37,7 @@ namespace rubinius {
fib->stack_ = state->stack_start();
fib->context_ = new ucontext_t;
- state->om->needs_finalization(fib);
+ state->om->needs_finalization(fib, (FinalizerFunction)&Fiber::finalize);
state->current_fiber.set(fib);
}
@@ -98,7 +98,7 @@ namespace rubinius {
fib->stack_ = malloc(stack_size);
fib->context_ = new ucontext_t;
- state->om->needs_finalization(fib);
+ state->om->needs_finalization(fib, (FinalizerFunction)&Fiber::finalize);
ucontext_t* ctx = fib->ucontext();
@@ -189,10 +189,10 @@ namespace rubinius {
#endif
}
- void Fiber::finalize(STATE) {
+ void Fiber::finalize(STATE, Fiber* fib) {
#ifdef FIBER_ENABLED
- delete context_;
- if(stack_ && !root_) free(stack_);
+ delete fib->context_;
+ if(fib->stack_ && !fib->root_) free(fib->stack_);
#endif
}
diff --git a/vm/builtin/fiber.hpp b/vm/builtin/fiber.hpp
index c19b08fa85..94c8c171d8 100644
--- a/vm/builtin/fiber.hpp
+++ b/vm/builtin/fiber.hpp
@@ -92,7 +92,7 @@ namespace rubinius {
// Ruby.primitive :fiber_s_yield
static Object* s_yield(STATE, Arguments& args, CallFrame* calling_environment);
- void finalize(STATE);
+ static void finalize(STATE, Fiber* fib);
public: /* TypeInfo */
diff --git a/vm/builtin/io.cpp b/vm/builtin/io.cpp
index 52344c7580..0e163d45c6 100644
--- a/vm/builtin/io.cpp
+++ b/vm/builtin/io.cpp
@@ -43,7 +43,7 @@ namespace rubinius {
// Don't bother to add finalization for stdio
if(fd >= 3) {
- state->om->needs_finalization(io);
+ state->om->needs_finalization(io, (FinalizerFunction)&IO::finalize);
}
return io;
@@ -60,7 +60,7 @@ namespace rubinius {
// Ensure the instance's class is set (i.e. for subclasses of IO)
io->klass(state, as(self));
- state->om->needs_finalization(io);
+ state->om->needs_finalization(io, (FinalizerFunction)&IO::finalize);
return io;
}
@@ -385,15 +385,15 @@ namespace rubinius {
mode(state, Fixnum::from((m & ~O_ACCMODE) | O_WRONLY));
}
- void IO::finalize(STATE) {
- if(descriptor_->nil_p()) return;
+ void IO::finalize(STATE, IO* io) {
+ if(io->descriptor()->nil_p()) return;
- native_int fd = descriptor_->to_native();
+ native_int fd = io->descriptor()->to_native();
// don't close stdin, stdout, stderr (0, 1, 2)
if(fd >= 3) {
::close(fd);
- descriptor(state, Fixnum::from(-1));
+ io->descriptor(state, Fixnum::from(-1));
}
}
diff --git a/vm/builtin/io.hpp b/vm/builtin/io.hpp
index 368240d243..c00a7cc571 100644
--- a/vm/builtin/io.hpp
+++ b/vm/builtin/io.hpp
@@ -43,7 +43,7 @@ namespace rubinius {
void unsafe_set_descriptor(native_int fd);
void force_read_only(STATE);
void force_write_only(STATE);
- void finalize(STATE);
+ static void finalize(STATE, IO* io);
/* Class primitives */
diff --git a/vm/builtin/memorypointer.cpp b/vm/builtin/memorypointer.cpp
index 4f96335c79..b3a0325a4e 100644
--- a/vm/builtin/memorypointer.cpp
+++ b/vm/builtin/memorypointer.cpp
@@ -58,16 +58,17 @@ namespace rubinius {
autorelease = val->true_p() ? true : false;
if(autorelease && !set_finalizer) {
- state->om->needs_finalization(this);
+ state->om->needs_finalization(this,
+ (FinalizerFunction)&MemoryPointer::finalize);
set_finalizer = true;
}
return val;
}
- void MemoryPointer::finalize(STATE) {
- if(autorelease && pointer) {
- ::free(pointer);
+ void MemoryPointer::finalize(STATE, MemoryPointer* ptr) {
+ if(ptr->autorelease && ptr->pointer) {
+ ::free(ptr->pointer);
}
}
diff --git a/vm/builtin/memorypointer.hpp b/vm/builtin/memorypointer.hpp
index 077b3b9754..8c8da039d6 100644
--- a/vm/builtin/memorypointer.hpp
+++ b/vm/builtin/memorypointer.hpp
@@ -17,7 +17,7 @@ namespace rubinius {
static MemoryPointer* create(STATE, void* ptr);
- void finalize(STATE);
+ static void finalize(STATE, MemoryPointer* ptr);
// Ruby.primitive :memorypointer_address
Integer* get_address(STATE);
diff --git a/vm/gc/finalize.hpp b/vm/gc/finalize.hpp
index 33b1bcdead..9185eed2ba 100644
--- a/vm/gc/finalize.hpp
+++ b/vm/gc/finalize.hpp
@@ -1,5 +1,7 @@
namespace rubinius {
+ typedef void (*FinalizerFunction)(STATE, Object*);
+
struct FinalizeObject {
public:
enum FinalizationStatus {
@@ -11,11 +13,13 @@ namespace rubinius {
public:
FinalizeObject()
: queue_count(0)
+ , finalizer(0)
{}
Object* object;
FinalizationStatus status;
int queue_count;
+ FinalizerFunction finalizer;
void queued() {
status = eQueued;
diff --git a/vm/objectmemory.cpp b/vm/objectmemory.cpp
index 9abcf2b43d..6d3a064c21 100644
--- a/vm/objectmemory.cpp
+++ b/vm/objectmemory.cpp
@@ -452,10 +452,11 @@ namespace rubinius {
code_manager_.add_resource(cr);
}
- void ObjectMemory::needs_finalization(Object* obj) {
+ void ObjectMemory::needs_finalization(Object* obj, FinalizerFunction func) {
FinalizeObject fi;
fi.object = obj;
fi.status = FinalizeObject::eLive;
+ fi.finalizer = func;
// Makes a copy of fi.
finalize_.push_back(fi);
@@ -466,16 +467,8 @@ namespace rubinius {
i != to_finalize_.end(); ) {
FinalizeObject* fi = *i;
- if(IO* io = try_as(fi->object)) {
- io->finalize(state);
- } else if(Fiber* fib = try_as(fi->object)) {
- fib->finalize(state);
- } else if(MemoryPointer* ptr = try_as(fi->object)) {
- ptr->finalize(state);
- } else if(Data* data = try_as(fi->object)) {
- data->finalize(state);
- } else if(Dir* dir = try_as(fi->object)) {
- dir->finalize(state);
+ if(fi->finalizer) {
+ (*fi->finalizer)(state, fi->object);
} else {
std::cerr << "Unsupported object to be finalized: "
<< fi->object->to_s(state)->c_str() << "\n";
diff --git a/vm/objectmemory.hpp b/vm/objectmemory.hpp
index e46f84b2b9..1cb9d843bb 100644
--- a/vm/objectmemory.hpp
+++ b/vm/objectmemory.hpp
@@ -193,7 +193,7 @@ namespace rubinius {
int mature_bytes_allocated();
- void needs_finalization(Object* obj);
+ void needs_finalization(Object* obj, FinalizerFunction func = 0);
void run_finalizers(STATE);
void find_referers(Object* obj, ObjectArray& result);