Revision: 2921 http://trac.macosforge.org/projects/ruby/changeset/2921 Author: lsansonetti@apple.com Date: 2009-10-29 16:36:01 -0700 (Thu, 29 Oct 2009) Log Message: ----------- call pending ObjectSpace finalizers before exiting Modified Paths: -------------- MacRuby/trunk/eval.c MacRuby/trunk/gc.c MacRuby/trunk/vm.cpp MacRuby/trunk/vm.h Modified: MacRuby/trunk/eval.c =================================================================== --- MacRuby/trunk/eval.c 2009-10-29 23:35:15 UTC (rev 2920) +++ MacRuby/trunk/eval.c 2009-10-29 23:36:01 UTC (rev 2921) @@ -97,7 +97,6 @@ rb_vm_finalize(); ruby_sig_finalize(); //GET_THREAD()->errinfo = Qnil; - rb_gc_call_finalizer_at_exit(); } void Modified: MacRuby/trunk/gc.c =================================================================== --- MacRuby/trunk/gc.c 2009-10-29 23:35:15 UTC (rev 2920) +++ MacRuby/trunk/gc.c 2009-10-29 23:36:01 UTC (rev 2921) @@ -726,11 +726,6 @@ * */ -typedef struct { - VALUE klass; - VALUE finalizers; -} rb_vm_finalizer_t; - static VALUE rb_cFinalizer; static void *finalizer_key = NULL; // only used for its address @@ -742,13 +737,10 @@ static void rb_objc_finalizer_finalize(void *rcv, SEL sel) { - rb_vm_set_multithreaded(true); rb_vm_finalizer_t *f = (rb_vm_finalizer_t *)rcv; - for (int i = 0, count = RARRAY_LEN(f->finalizers); i < count; i++) { - VALUE b = RARRAY_AT(f->finalizers, i); - VALUE objid = rb_obj_id((VALUE)rcv, 0); - rb_vm_call(b, selCall, 1, &objid, false); - } + rb_vm_set_multithreaded(true); + rb_vm_call_finalizer(f); + rb_vm_unregister_finalizer(f); if (rb_objc_finalizer_finalize_super != NULL) { ((void(*)(void *, SEL))rb_objc_finalizer_finalize_super)(rcv, sel); } @@ -764,6 +756,7 @@ &finalizer_key); if (finalizer != NULL) { rb_ary_clear(finalizer->finalizers); + rb_vm_unregister_finalizer(finalizer); rb_objc_set_associative_ref((void *)obj, &finalizer_key, NULL); } return obj; @@ -802,8 +795,10 @@ finalizer = (rb_vm_finalizer_t *) rb_objc_newobj(sizeof(rb_vm_finalizer_t *)); finalizer->klass = rb_cFinalizer; + finalizer->objid = rb_obj_id(obj, 0); GC_WB(&finalizer->finalizers, rb_ary_new()); rb_objc_set_associative_ref((void *)obj, &finalizer_key, finalizer); + rb_vm_register_finalizer(finalizer); } rb_ary_push(finalizer->finalizers, block); @@ -818,13 +813,6 @@ // TODO } -void -rb_gc_call_finalizer_at_exit(void) -{ - // This should magically trigger -[__Finalizer finalize]. - auto_collect(__auto_zone, AUTO_COLLECT_FULL_COLLECTION, NULL); -} - /* * call-seq: * ObjectSpace._id2ref(object_id) -> an_object Modified: MacRuby/trunk/vm.cpp =================================================================== --- MacRuby/trunk/vm.cpp 2009-10-29 23:35:15 UTC (rev 2920) +++ MacRuby/trunk/vm.cpp 2009-10-29 23:36:01 UTC (rev 2921) @@ -256,6 +256,12 @@ #endif } +RoxorCore::~RoxorCore(void) +{ + call_all_finalizers(); + // TODO +} + RoxorVM::RoxorVM(void) { current_top_object = Qnil; @@ -3715,6 +3721,73 @@ } extern "C" +void +rb_vm_register_finalizer(rb_vm_finalizer_t *finalizer) +{ + GET_CORE()->register_finalizer(finalizer); +} + +extern "C" +void +rb_vm_unregister_finalizer(rb_vm_finalizer_t *finalizer) +{ + GET_CORE()->unregister_finalizer(finalizer); +} + +void +RoxorCore::register_finalizer(rb_vm_finalizer_t *finalizer) +{ + lock(); + finalizers.push_back(finalizer); + unlock(); +} + +void +RoxorCore::unregister_finalizer(rb_vm_finalizer_t *finalizer) +{ + lock(); + std::vector<rb_vm_finalizer_t *>::iterator i = std::find(finalizers.begin(), + finalizers.end(), finalizer); + if (i != finalizers.end()) { + finalizers.erase(i); + } + unlock(); +} + +static void +call_finalizer(rb_vm_finalizer_t *finalizer) +{ + for (int i = 0, count = RARRAY_LEN(finalizer->finalizers); i < count; i++) { + VALUE b = RARRAY_AT(finalizer->finalizers, i); + try { + rb_vm_call(b, selCall, 1, &finalizer->objid, false); + } + catch (...) { + // Do nothing. + } + } + rb_ary_clear(finalizer->finalizers); +} + +extern "C" +void +rb_vm_call_finalizer(rb_vm_finalizer_t *finalizer) +{ + call_finalizer(finalizer); +} + +void +RoxorCore::call_all_finalizers(void) +{ + for (std::vector<rb_vm_finalizer_t *>::iterator i = finalizers.begin(); + i != finalizers.end(); + ++i) { + call_finalizer(*i); + } + finalizers.clear(); +} + +extern "C" void * rb_vm_create_vm(void) { @@ -4332,4 +4405,7 @@ printf("functions all=%ld compiled=%ld\n", RoxorCompiler::module->size(), GET_CORE()->get_functions_compiled()); #endif + + delete RoxorCore::shared; + RoxorCore::shared = NULL; } Modified: MacRuby/trunk/vm.h =================================================================== --- MacRuby/trunk/vm.h 2009-10-29 23:35:15 UTC (rev 2920) +++ MacRuby/trunk/vm.h 2009-10-29 23:36:01 UTC (rev 2921) @@ -447,6 +447,16 @@ void rb_vm_set_current_scope(VALUE mod, rb_vm_scope_t scope); +typedef struct { + VALUE klass; + VALUE objid; + VALUE finalizers; +} rb_vm_finalizer_t; + +void rb_vm_register_finalizer(rb_vm_finalizer_t *finalizer); +void rb_vm_unregister_finalizer(rb_vm_finalizer_t *finalizer); +void rb_vm_call_finalizer(rb_vm_finalizer_t *finalizer); + VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line); VALUE rb_iseq_eval(VALUE iseq); VALUE rb_iseq_new(NODE *node, VALUE filename); @@ -548,6 +558,11 @@ // Running threads. VALUE threads; + // Finalizers. They are automatically called during garbage collection + // but we still need to keep a list of them, because the list may not + // be empty when we exit and we need to call the remaining finalizers. + std::vector<rb_vm_finalizer_t *> finalizers; + // State. bool running; bool multithreaded; @@ -604,6 +619,7 @@ public: RoxorCore(void); + ~RoxorCore(void); ACCESSOR(running, bool); ACCESSOR(multithreaded, bool); @@ -744,6 +760,10 @@ size_t get_sizeof(const char *type); bool is_large_struct_type(const Type *type); + void register_finalizer(rb_vm_finalizer_t *finalizer); + void unregister_finalizer(rb_vm_finalizer_t *finalizer); + void call_all_finalizers(void); + private: bool register_bs_boxed(bs_element_type_t type, void *value); void register_bs_class(bs_element_class_t *bs_class);
participants (1)
-
source_changes@macosforge.org