ruby-changes:6413
From: shyouhei <ko1@a...>
Date: Mon, 7 Jul 2008 15:02:04 +0900 (JST)
Subject: [ruby-changes:6413] Ruby:r17928 (ruby_1_8_6): merge revision(s) 17832:
shyouhei 2008-07-07 15:01:50 +0900 (Mon, 07 Jul 2008) New Revision: 17928 Modified files: branches/ruby_1_8_6/eval.c branches/ruby_1_8_6/gc.c branches/ruby_1_8_6/node.h branches/ruby_1_8_6/version.h Log: merge revision(s) 17832: * eval.c (rb_longjmp): duplicate the thrown exception to set backtrace if it was frozen. clear all raised flags. * eval.c (stack_check): leave clearing flag to rb_longjmp. * eval.c (rb_thread_set_raised, rb_thread_reset_raised): use generic flags. * eval.c (Init_Proc), gc.c (Init_GC): freeze preallocated special exceptions. * gc.c (rb_memerror): use thread raised flag instead of static flag, and raise nomem_error without backtrace if failed to make backtrace. [ruby-dev:34724] * gc.c (ruby_xmalloc): increase malloc_increase only if malloc succeeds. failed malloc size can be huge. it may increase malloc_limit too big which cause less GC and memory full. (ruby_xrealloc): ditto. http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17928 Index: ruby_1_8_6/version.h =================================================================== --- ruby_1_8_6/version.h (revision 17927) +++ ruby_1_8_6/version.h (revision 17928) @@ -2,7 +2,7 @@ #define RUBY_RELEASE_DATE "2008-07-07" #define RUBY_VERSION_CODE 186 #define RUBY_RELEASE_CODE 20080707 -#define RUBY_PATCHLEVEL 267 +#define RUBY_PATCHLEVEL 268 #define RUBY_VERSION_MAJOR 1 #define RUBY_VERSION_MINOR 8 Index: ruby_1_8_6/eval.c =================================================================== --- ruby_1_8_6/eval.c (revision 17927) +++ ruby_1_8_6/eval.c (revision 17928) @@ -1442,9 +1442,6 @@ static void rb_thread_cleanup _((void)); static void rb_thread_wait_other_threads _((void)); -static int thread_set_raised(); -static int thread_reset_raised(); - static int thread_no_ensure _((void)); static VALUE exception_error; @@ -1463,8 +1460,10 @@ int ex; { int status = EXIT_FAILURE; + rb_thread_t th = curr_thread; - if (thread_set_raised()) return EXIT_FAILURE; + if (rb_thread_set_raised(th)) + return EXIT_FAILURE; switch (ex & TAG_MASK) { case 0: status = EXIT_SUCCESS; @@ -1517,7 +1516,7 @@ rb_bug("Unknown longjmp status %d", ex); break; } - thread_reset_raised(); + rb_thread_reset_raised(th); return status; } @@ -2710,6 +2709,7 @@ NODE *node_save; VALUE srcfile; char *event_name; + rb_thread_t th = curr_thread; if (!trace_func) return; if (tracing) return; @@ -2741,7 +2741,7 @@ } } PUSH_TAG(PROT_NONE); - raised = thread_reset_raised(); + raised = rb_thread_reset_raised(th); if ((state = EXEC_TAG()) == 0) { srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)"); event_name = get_event_name(event); @@ -2753,7 +2753,7 @@ klass), Qundef, 0); } - if (raised) thread_set_raised(); + if (raised) rb_thread_set_raised(th); POP_TAG(); POP_FRAME(); @@ -4569,8 +4569,9 @@ VALUE mesg; { VALUE at; + rb_thread_t th = curr_thread; - if (thread_set_raised()) { + if (rb_thread_set_raised(th)) { ruby_errinfo = exception_error; JUMP_TAG(TAG_FATAL); } @@ -4584,6 +4585,9 @@ at = get_backtrace(mesg); if (NIL_P(at)) { at = make_backtrace(); + if (OBJ_FROZEN(mesg)) { + mesg = rb_obj_dup(mesg); + } set_backtrace(mesg, at); } } @@ -4609,7 +4613,7 @@ ruby_errinfo = mesg; } else if (status) { - thread_reset_raised(); + rb_thread_reset_raised(th); JUMP_TAG(status); } } @@ -4624,11 +4628,20 @@ if (!prot_tag) { error_print(); } - thread_reset_raised(); + rb_thread_raised_clear(th); JUMP_TAG(tag); } void +rb_exc_jump(mesg) + VALUE mesg; +{ + rb_thread_raised_clear(rb_curr_thread); + ruby_errinfo = mesg; + JUMP_TAG(TAG_RAISE); +} + +void rb_exc_raise(mesg) VALUE mesg; { @@ -5544,18 +5557,11 @@ static void stack_check() { - static int overflowing = 0; + rb_thread_t th = rb_curr_thread; - if (!overflowing && ruby_stack_check()) { - int state; - overflowing = 1; - PUSH_TAG(PROT_NONE); - if ((state = EXEC_TAG()) == 0) { - rb_exc_raise(sysstack_error); - } - POP_TAG(); - overflowing = 0; - JUMP_TAG(state); + if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) && ruby_stack_check()) { + rb_thread_raised_set(th, RAISED_STACKOVERFLOW); + rb_exc_raise(sysstack_error); } } @@ -9710,11 +9716,14 @@ rb_global_variable(&exception_error); exception_error = rb_exc_new2(rb_eFatal, "exception reentered"); + OBJ_TAINT(exception_error); + OBJ_FREEZE(exception_error); rb_eSysStackError = rb_define_class("SystemStackError", rb_eStandardError); rb_global_variable(&sysstack_error); sysstack_error = rb_exc_new2(rb_eSysStackError, "stack level too deep"); OBJ_TAINT(sysstack_error); + OBJ_FREEZE(sysstack_error); rb_cProc = rb_define_class("Proc", rb_cObject); rb_undef_alloc_func(rb_cProc); @@ -9886,10 +9895,9 @@ # endif #endif -#define THREAD_RAISED 0x200 /* temporary flag */ #define THREAD_TERMINATING 0x400 /* persistent flag */ -#define THREAD_NO_ENSURE 0x800 /* persistent flag */ -#define THREAD_FLAGS_MASK 0xc00 /* mask for persistent flags */ +#define THREAD_NO_ENSURE 0x800 /* persistent flag */ +#define THREAD_FLAGS_MASK 0xfc00 /* mask for persistent flags */ #define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next; #define END_FOREACH_FROM(f,x) } while (x != f) @@ -9941,19 +9949,25 @@ (dst)->join = (src)->join, \ 0) -static int -thread_set_raised() +int +rb_thread_set_raised(th) + rb_thread_t th; { - if (curr_thread->flags & THREAD_RAISED) return 1; - curr_thread->flags |= THREAD_RAISED; + if (th->flags & RAISED_EXCEPTION) { + return 1; + } + th->flags |= RAISED_EXCEPTION; return 0; } -static int -thread_reset_raised() +int +rb_thread_reset_raised(th) + rb_thread_t th; { - if (!(curr_thread->flags & THREAD_RAISED)) return 0; - curr_thread->flags &= ~THREAD_RAISED; + if (!(th->flags & RAISED_EXCEPTION)) { + return 0; + } + th->flags &= ~RAISED_EXCEPTION; return 1; } @@ -11091,7 +11105,7 @@ if (!rb_thread_dead(th)) return Qfalse; } - if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED)) { + if (!NIL_P(th->errinfo) && (th->flags & RAISED_EXCEPTION)) { VALUE oldbt = get_backtrace(th->errinfo); VALUE errat = make_backtrace(); VALUE errinfo = rb_obj_dup(th->errinfo); @@ -12020,7 +12034,7 @@ } if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) { - th->flags |= THREAD_RAISED; + th->flags |= RAISED_EXCEPTION; if (state == TAG_FATAL) { /* fatal error within this thread, need to stop whole script */ main_thread->errinfo = ruby_errinfo; @@ -12238,7 +12252,7 @@ rb_thread_t th = rb_thread_check(thread); if (rb_thread_dead(th)) { - if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED)) + if (!NIL_P(th->errinfo) && (th->flags & RAISED_EXCEPTION)) return Qnil; return Qfalse; } Index: ruby_1_8_6/gc.c =================================================================== --- ruby_1_8_6/gc.c (revision 17927) +++ ruby_1_8_6/gc.c (revision 17928) @@ -74,16 +74,22 @@ static VALUE nomem_error; static void garbage_collect(); +NORETURN(void rb_exc_jump _((VALUE))); + void rb_memerror() { - static int recurse = 0; + rb_thread_t th = rb_curr_thread; - if (!nomem_error || (recurse > 0 && rb_safe_level() < 4)) { + if (!nomem_error || + (rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) { fprintf(stderr, "[FATAL] failed to allocate memory\n"); exit(1); } - recurse++; + if (rb_thread_raised_p(th, RAISED_NOMEMORY)) { + rb_exc_jump(nomem_error); + } + rb_thread_raised_set(th, RAISED_NOMEMORY); rb_exc_raise(nomem_error); } @@ -97,9 +103,8 @@ rb_raise(rb_eNoMemError, "negative allocation size (or too big)"); } if (size == 0) size = 1; - malloc_increase += size; - if (malloc_increase > malloc_limit) { + if ((malloc_increase+size) > malloc_limit) { garbage_collect(); } RUBY_CRITICAL(mem = malloc(size)); @@ -110,6 +115,7 @@ rb_memerror(); } } + malloc_increase += size; return mem; } @@ -138,7 +144,6 @@ } if (!ptr) return xmalloc(size); if (size == 0) size = 1; - malloc_increase += size; RUBY_CRITICAL(mem = realloc(ptr, size)); if (!mem) { garbage_collect(); @@ -147,6 +152,7 @@ rb_memerror(); } } + malloc_increase += size; return mem; } @@ -2064,6 +2070,8 @@ rb_global_variable(&nomem_error); nomem_error = rb_exc_new2(rb_eNoMemError, "failed to allocate memory"); + OBJ_TAINT(nomem_error); + OBJ_FREEZE(nomem_error); rb_define_method(rb_mKernel, "hash", rb_obj_id, 0); rb_define_method(rb_mKernel, "__id__", rb_obj_id, 0); Index: ruby_1_8_6/node.h =================================================================== --- ruby_1_8_6/node.h (revision 17927) +++ ruby_1_8_6/node.h (revision 17928) @@ -468,6 +468,19 @@ extern rb_thread_t rb_curr_thread; extern rb_thread_t rb_main_thread; +enum { + RAISED_EXCEPTION = 0x1000, + RAISED_STACKOVERFLOW = 0x2000, + RAISED_NOMEMORY = 0x4000, + RAISED_MASK = 0xf000 +}; +int rb_thread_set_raised(rb_thread_t th); +int rb_thread_reset_raised(rb_thread_t th); +#define rb_thread_raised_set(th, f) ((th)->flags |= (f)) +#define rb_thread_raised_reset(th, f) ((th)->flags &= ~(f)) +#define rb_thread_raised_p(th, f) (((th)->flags & (f)) != 0) +#define rb_thread_raised_clear(th) ((th)->flags = 0) + #if defined(__cplusplus) } /* extern "C" { */ #endif -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/