From: Narihiro Nakamura Date: 2011-07-05T21:08:41+09:00 Subject: [ruby-dev:44040] Re: [ruby-core:37707] [Ruby 1.9 - Bug #3781] FIBER_USE_NATIVE が有効だと落ちるスクリプトがある nariです。 kosakiさん、パッチのレビュー、ありがとうございます。 指摘された箇所を直してみました。 # configure.inをいじるのは初めてだったのでその辺りは大分不安です。 diff --git a/configure.in b/configure.in index 7f74fd1..6b08b2e 100644 --- a/configure.in +++ b/configure.in @@ -1227,6 +1227,63 @@ if test $rb_cv_stack_end_address != no; then AC_DEFINE_UNQUOTED(STACK_END_ADDRESS, $rb_cv_stack_end_address) fi +AC_CACHE_CHECK(for gc_mark and gc_children stack frame approximate size(word), rb_cv_gc_mark_stackframe_word, +[save_CFLAGS="$CFLAGS" +CFLAGS="-O0" +AC_TRY_RUN([ +int word; +void *stack_start; + +void +set_stackframe_word() +{ + int dumy = 42; + int diff; + + if (stack_start < (void *)&dumy) { + diff = (int)((void *)&dumy - stack_start); + } + else { + diff = (int)(stack_start - (void *)&dumy); + } + word = (diff/sizeof(void *)); + if ((diff % sizeof(void *)) != 0) { + word++; + } +} + +void +gc_mark_children(void *p1, void *p2, int lev) +{ + void *obj = p2; + + set_stackframe_word(p1,p2,lev); +} + +void +gc_mark(void *p1, void *p2, int lev) +{ + void *obj = p2; + + gc_mark_children(p1,p2,lev++); +} + +int +main() { + int dumy = 42; + + stack_start = (void *)&dumy; + gc_mark(0, 0, 255); + return word; +} +], + [rb_cv_gc_mark_stackframe_word="$?"], + [rb_cv_gc_mark_stackframe_word="$?"], + [rb_cv_gc_mark_stackframe_word="30"]) +CFLAGS="$save_CFLAGS"]) +AC_DEFINE_UNQUOTED(GC_MARK_STACKFRAME_WORD, $rb_cv_gc_mark_stackframe_word) + + dnl Checks for library functions. AC_TYPE_GETGROUPS AC_TYPE_SIGNAL diff --git a/gc.c b/gc.c index d5b8dfd..bde9c53 100644 --- a/gc.c +++ b/gc.c @@ -1277,7 +1277,8 @@ ruby_get_stack_grow_direction(volatile VALUE *addr) } #endif -#define GC_WATER_MARK 512 +#define GC_LEVEL_MAX 250 +#define STACKFRAME_FOR_GC_MARK (GC_LEVEL_MAX * GC_MARK_STACKFRAME_WORD) size_t ruby_stack_length(VALUE **p) @@ -1289,28 +1290,30 @@ ruby_stack_length(VALUE **p) } static int -stack_check(void) +stack_check(int water_mark) { int ret; rb_thread_t *th = GET_THREAD(); SET_STACK_END; - ret = STACK_LENGTH > STACK_LEVEL_MAX - GC_WATER_MARK; + ret = STACK_LENGTH > STACK_LEVEL_MAX - water_mark; #ifdef __ia64 if (!ret) { ret = (VALUE*)rb_ia64_bsp() - th->machine_register_stack_start > - th->machine_register_stack_maxsize/sizeof(VALUE) - GC_WATER_MARK; + th->machine_register_stack_maxsize/sizeof(VALUE) - water_mark; } #endif return ret; } +#define STACKFRAME_FOR_CALL_CFUNC 512 + int ruby_stack_check(void) { #if defined(POSIX_SIGNAL) && defined(SIGSEGV) && defined(HAVE_SIGALTSTACK) return 0; #else - return stack_check(); + return stack_check(STACKFRAME_FOR_CALL_CFUNC); #endif } @@ -1600,8 +1603,6 @@ rb_gc_mark_maybe(VALUE obj) } } -#define GC_LEVEL_MAX 250 - static void gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev) { @@ -1614,7 +1615,7 @@ gc_mark(rb_objspace_t *objspace, VALUE ptr, int lev) obj->as.basic.flags |= FL_MARK; objspace->heap.live_num++; - if (lev > GC_LEVEL_MAX || (lev == 0 && stack_check())) { + if (lev > GC_LEVEL_MAX || (lev == 0 && stack_check(STACKFRAME_FOR_GC_MARK))) { if (!mark_stack_overflow) { if (mark_stack_ptr - mark_stack < MARK_STACK_MAX) { *mark_stack_ptr = ptr; -- Narihiro Nakamura (nari)