diff options
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | configure.in | 57 | ||||
-rw-r--r-- | gc.c | 17 |
3 files changed, 76 insertions, 8 deletions
@@ -1,3 +1,13 @@ +Thu Jul 7 23:35:31 2011 Narihiro Nakamura <authornari@gmail.com> + + * gc.c: change water_mark value value that may call + gc_mark(lev <= GC_LEVEL_MAX) in gc_mark(). + In ruby_stack_check(), water_mark is a value that may call some + C function. Fixes Bug #3781 + + * configure.in: define GC_MARK_STACKFRAME_WORD that approximate + size of gc_mark() and gc_mark_children() stackframes. + Thu Jul 7 17:55:05 2011 NAKAMURA Usaku <usa@ruby-lang.org> * test/testunit/test_parallel.rb (TestParallelWorker#teardown): wait diff --git a/configure.in b/configure.in index 2185174851..81bc57eeb2 100644 --- a/configure.in +++ b/configure.in @@ -1230,6 +1230,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 @@ -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; |