From: nobu@... Date: 2004-09-27T13:41:36+09:00 Subject: [ruby-dev:24359] Re: finalizer なかだです。 At Mon, 27 Sep 2004 12:59:00 +0900, Tanaka Akira wrote in [ruby-dev:24354]: > > これってどうなるのが正しいんでしょうね。 > > これまでの経験の結果、finalizer の実行を gc から直接行なうのが良くない、 > という考えに至りました。 > > finalizer の実行は、rb_eval などのユーザのコードが動いてもおかしくない > タイミングまで遅延する挙動をデフォルトにするほうがよいのではないでしょ > うか。 > > そうすれば、メモリ確保のタイミングでユーザのコードが動いて配列の長さや > ら何やらが変わってしまうことを考慮せずに済みます。 なるほど。全ノードごとにコストが増えるのは避けたいので、stack checkと同じタイミングに入れてみました。 Index: eval.c =================================================================== RCS file: /cvs/ruby/src/ruby/eval.c,v retrieving revision 1.703 diff -U2 -p -d -r1.703 eval.c --- eval.c 24 Sep 2004 16:58:50 -0000 1.703 +++ eval.c 27 Sep 2004 04:32:29 -0000 @@ -5467,4 +5467,5 @@ rb_call0(klass, recv, id, oid, argc, arg CHECK_INTS; /* better than nothing */ stack_check(); + rb_gc_finalize_deferred(); } PUSH_ITER(itr); Index: gc.c =================================================================== RCS file: /cvs/ruby/src/ruby/gc.c,v retrieving revision 1.185 diff -U2 -p -d -r1.185 gc.c --- gc.c 24 Sep 2004 05:53:42 -0000 1.185 +++ gc.c 27 Sep 2004 04:30:24 -0000 @@ -994,4 +994,39 @@ static void obj_free _((VALUE)); static void +finalize_list(p) + RVALUE *p; +{ + while (p) { + RVALUE *tmp = p->as.free.next; + run_final((VALUE)p); + if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */ + p->as.free.flags = 0; + p->as.free.next = freelist; + freelist = p; + } + p = tmp; + } +} + +static void +free_unused_heaps() +{ + int i, j; + + for (i = j = 1; j < heaps_used; i++) { + if (heaps[i].limit == 0) { + free(heaps[i].slot); + heaps_used--; + } + else { + if (i != j) { + heaps[j] = heaps[i]; + } + j++; + } + } +} + +static void gc_sweep() { @@ -1065,33 +1100,8 @@ gc_sweep() /* clear finalization list */ if (final_list) { - RVALUE *tmp; - - if (rb_prohibit_interrupt) { - deferred_final_list = final_list; - return; - } - - for (p = final_list; p; p = tmp) { - tmp = p->as.free.next; - run_final((VALUE)p); - if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */ - p->as.free.flags = 0; - p->as.free.next = freelist; - freelist = p; - } - } - } - for (i = j = 1; j < heaps_used; i++) { - if (heaps[i].limit == 0) { - free(heaps[i].slot); - heaps_used--; - } - else { - if (i != j) { - heaps[j] = heaps[i]; - } - j++; - } + deferred_final_list = final_list; + return; } + free_unused_heaps(); } @@ -1775,4 +1785,16 @@ run_final(obj) void +rb_gc_finalize_deferred() +{ + RVALUE *p = deferred_final_list; + + deferred_final_list = 0; + if (p) { + finalize_list(p); + free_unused_heaps(); + } +} + +void rb_gc_call_finalizer_at_exit() { @@ -1782,12 +1804,5 @@ rb_gc_call_finalizer_at_exit() /* run finalizers */ if (need_call_final) { - if (deferred_final_list) { - p = deferred_final_list; - while (p) { - RVALUE *tmp = p; - p = p->as.free.next; - run_final((VALUE)tmp); - } - } + finalize_list(deferred_final_list); for (i = 0; i < heaps_used; i++) { p = heaps[i].slot; pend = p + heaps[i].limit; -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦