Index: eval.c =================================================================== --- eval.c (revision 27134) +++ eval.c (working copy) @@ -370,8 +370,7 @@ ent = cache; end = ent + CACHE_SIZE; while (ent < end) { if (ent->mid == id && - (ent->klass == klass || - RCLASS(ent->origin)->m_tbl == RCLASS(klass)->m_tbl)) { + RCLASS(ent->origin)->m_tbl == RCLASS(klass)->m_tbl) { ent->mid = 0; } ent++; @@ -1411,7 +1410,7 @@ rb_call_inits(); ruby_class = rb_cObject; ruby_frame->self = ruby_top_self; - ruby_top_cref = NEW_CREF(rb_cObject, 0); + ruby_top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0); ruby_cref = ruby_top_cref; rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self)); #ifdef __MACOS__ @@ -4663,7 +4662,6 @@ rb_exc_raise(mesg) VALUE mesg; { - mesg = rb_make_exception(1, &mesg); rb_longjmp(TAG_RAISE, mesg); } @@ -4671,7 +4669,6 @@ rb_exc_fatal(mesg) VALUE mesg; { - mesg = rb_make_exception(1, &mesg); rb_longjmp(TAG_FATAL, mesg); } @@ -5695,7 +5692,7 @@ exc = rb_eNameError; } else if (last_call_status & CSTAT_SUPER) { - format = "super: no superclass method `%s' for %s"; + format = "super: no superclass method `%s'"; } if (!format) { format = "undefined method `%s' for %s"; @@ -6141,14 +6138,13 @@ ent = cache + EXPR1(klass, mid); if (ent->mid == mid && ent->klass == klass) { if (!ent->method) - goto nomethod; + return method_missing(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0); klass = ent->origin; id = ent->mid0; noex = ent->noex; body = ent->method; } else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) { - nomethod: if (scope == 3) { return method_missing(recv, mid, argc, argv, CSTAT_SUPER); } @@ -8877,7 +8872,7 @@ OBJSETUP(scope, tmp, T_SCOPE); scope->local_tbl = _block.scope->local_tbl; scope->local_vars = _block.scope->local_vars; - scope->flags |= SCOPE_CLONE | (_block.scope->flags & SCOPE_MALLOC); + scope->flags |= SCOPE_CLONE; _block.scope = scope; } /* modify current frame */ @@ -9271,8 +9266,8 @@ ID oid = id; again: - if ((body = rb_get_method_body(&klass, &oid, &noex)) == 0) { - print_undef(rklass, id); + if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) { + print_undef(rklass, oid); } if (nd_type(body) == NODE_ZSUPER) { @@ -9413,7 +9408,7 @@ struct METHOD *data; Data_Get_Struct(obj, struct METHOD, data); - return rb_str_new2(rb_id2name(data->id)); + return rb_str_new2(rb_id2name(data->oid)); } /* @@ -9839,7 +9834,7 @@ } } rb_str_buf_cat2(str, sharp); - rb_str_buf_cat2(str, rb_id2name(data->id)); + rb_str_buf_cat2(str, rb_id2name(data->oid)); rb_str_buf_cat2(str, ">"); return str; @@ -10219,7 +10214,6 @@ #define WAIT_TIME (1<<2) #define WAIT_JOIN (1<<3) #define WAIT_PID (1<<4) -#define WAIT_DONE (1<<5) /* +infty, for this purpose */ #define DELAY_INFTY 1E30 @@ -10662,8 +10656,9 @@ th->safe = ruby_safe_level; th->node = ruby_current_node; - if (ruby_sandbox_save != NULL) { - ruby_sandbox_save(th); + if (ruby_sandbox_save != NULL) + { + ruby_sandbox_save(th); } } @@ -10711,19 +10706,20 @@ (rb_thread_switch(ruby_setjmp(rb_thread_save_context(th), (th)->context))) NORETURN(static void rb_thread_restore_context _((rb_thread_t,int))); -NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int))); -NORETURN(NOINLINE(static void stack_extend(rb_thread_t, int))); +NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int,void*))); +NORETURN(NOINLINE(static void stack_extend(rb_thread_t, int, VALUE *))); static void -rb_thread_restore_context_0(rb_thread_t th, int exit) +rb_thread_restore_context_0(rb_thread_t th, int exit, void *vp) { static rb_thread_t tmp; static int ex; static VALUE tval; rb_trap_immediate = 0; /* inhibit interrupts from here */ - if (ruby_sandbox_restore != NULL) { - ruby_sandbox_restore(th); + if (ruby_sandbox_restore != NULL) + { + ruby_sandbox_restore(th); } ruby_frame = th->frame; ruby_scope = th->scope; @@ -10771,9 +10767,9 @@ static volatile int C(k), C(l), C(m), C(n), C(o); static volatile int C(p), C(q), C(r), C(s), C(t); int rb_dummy_false = 0; -NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, VALUE *))); +NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, void *, VALUE *))); static void -register_stack_extend(rb_thread_t th, int exit, VALUE *curr_bsp) +register_stack_extend(rb_thread_t th, int exit, void *vp, VALUE *curr_bsp) { if (rb_dummy_false) { /* use registers as much as possible */ @@ -10787,63 +10783,52 @@ E(p) = E(q) = E(r) = E(s) = E(t) = 0; } if (curr_bsp < th->bstr_pos+th->bstr_len) { - register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp()); + register_stack_extend(th, exit, &exit, (VALUE*)rb_ia64_bsp()); } - stack_extend(th, exit); + rb_thread_restore_context_0(th, exit, &exit); } #undef C #undef E #endif +# if defined(_MSC_VER) && _MSC_VER >= 1300 +__declspec(noinline) static void stack_extend(rb_thread_t, int, VALUE*); +# endif static void -stack_extend(rb_thread_t th, int exit) +stack_extend(rb_thread_t th, int exit, VALUE *addr_in_prev_frame) { #define STACK_PAD_SIZE 1024 - volatile VALUE space[STACK_PAD_SIZE], *sp = space; + VALUE space[STACK_PAD_SIZE]; -#if !STACK_GROW_DIRECTION - if (space < rb_gc_stack_start) { +#if STACK_GROW_DIRECTION < 0 + if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]); +#elif STACK_GROW_DIRECTION > 0 + if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]); +#else + if (addr_in_prev_frame < rb_gc_stack_start) { /* Stack grows downward */ -#endif -#if STACK_GROW_DIRECTION <= 0 - if (space > th->stk_pos) { -# ifdef HAVE_ALLOCA - sp = ALLOCA_N(VALUE, &space[0] - th->stk_pos); -# else - stack_extend(th, exit); -# endif - } -#endif -#if !STACK_GROW_DIRECTION + if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]); } else { /* Stack grows upward */ -#endif -#if STACK_GROW_DIRECTION >= 0 - if (&space[STACK_PAD_SIZE] < th->stk_pos + th->stk_len) { -# ifdef HAVE_ALLOCA - sp = ALLOCA_N(VALUE, th->stk_pos + th->stk_len - &space[STACK_PAD_SIZE]); -# else - stack_extend(th, exit); -# endif - } -#endif -#if !STACK_GROW_DIRECTION + if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]); } #endif - rb_thread_restore_context_0(th, exit); -} #ifdef __ia64 -#define stack_extend(th, exit) register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp()) + register_stack_extend(th, exit, space, (VALUE*)rb_ia64_bsp()); +#else + rb_thread_restore_context_0(th, exit, space); #endif +} static void rb_thread_restore_context(th, exit) rb_thread_t th; int exit; { + VALUE v; if (!th->stk_ptr) rb_bug("unsaved context"); - stack_extend(th, exit); + stack_extend(th, exit, &v); } static void @@ -10875,13 +10860,6 @@ rb_thread_die(th); th->prev->next = th->next; th->next->prev = th->prev; - -#if defined(_THREAD_SAFE) || defined(HAVE_SETITIMER) - /* if this is the last ruby thread, stop timer signals */ - if (th->next == th->prev && th->next == main_thread) { - rb_thread_stop_timer(); - } -#endif } static int @@ -11012,6 +10990,7 @@ rb_thread_t next; /* OK */ rb_thread_t th; rb_thread_t curr; + rb_thread_t th_found = 0; int found = 0; fd_set readfds; @@ -11050,7 +11029,6 @@ now = -1.0; FOREACH_THREAD_FROM(curr, th) { - th->wait_for &= ~WAIT_DONE; if (!found && th->status <= THREAD_RUNNABLE) { found = 1; } @@ -11083,12 +11061,7 @@ if (now < 0.0) now = timeofday(); th_delay = th->delay - now; if (th_delay <= 0.0) { - if (th->wait_for & WAIT_SELECT) { - need_select = 1; - } - else { - th->status = THREAD_RUNNABLE; - } + th->status = THREAD_RUNNABLE; found = 1; } else if (th_delay < delay) { @@ -11207,22 +11180,22 @@ if (n > 0) { now = -1.0; /* Some descriptors are ready. - * The corresponding threads are runnable as next. - * Mark them with WAIT_DONE. - * Don't change the status to runnable here because - * threads which don't run next should not be changed. + * Choose a thread which may run next. + * Don't change the status of threads which don't run next. */ FOREACH_THREAD_FROM(curr, th) { if ((th->wait_for&WAIT_FD) && FD_ISSET(th->fd, &readfds)) { - th->wait_for |= WAIT_DONE; + th_found = th; found = 1; + break; } if ((th->wait_for&WAIT_SELECT) && (match_fds(&readfds, &th->readfds, max) || match_fds(&writefds, &th->writefds, max) || match_fds(&exceptfds, &th->exceptfds, max))) { - th->wait_for |= WAIT_DONE; + th_found = th; found = 1; + break; } } END_FOREACH_FROM(curr, th); @@ -11238,28 +11211,27 @@ next = th; break; } - if ((th->status == THREAD_RUNNABLE || (th->wait_for & WAIT_DONE)) && th->stk_ptr) { + if ((th->status == THREAD_RUNNABLE || th == th_found) && th->stk_ptr) { if (!next || next->priority < th->priority) { + if (th == th_found) { + th_found->status = THREAD_RUNNABLE; + th_found->wait_for = 0; + if (th->wait_for&WAIT_FD) { + th_found->fd = 0; + } + else { /* th->wait_for&WAIT_SELECT */ + n = intersect_fds(&readfds, &th_found->readfds, max) + + intersect_fds(&writefds, &th_found->writefds, max) + + intersect_fds(&exceptfds, &th_found->exceptfds, max); + th_found->select_value = n; + } + } next = th; } } } END_FOREACH_FROM(curr, th); - if (next && (next->wait_for & WAIT_DONE)) { - next->status = THREAD_RUNNABLE; - if (next->wait_for&WAIT_FD) { - next->fd = 0; - } - else { /* next->wait_for&WAIT_SELECT */ - n = intersect_fds(&readfds, &next->readfds, max) + - intersect_fds(&writefds, &next->writefds, max) + - intersect_fds(&exceptfds, &next->exceptfds, max); - next->select_value = n; - } - next->wait_for = 0; - } - if (!next) { /* raise fatal error to main thread */ curr_thread->node = ruby_current_node; @@ -11269,16 +11241,15 @@ TRAP_END; } FOREACH_THREAD_FROM(curr, th) { - int wait_for = th->wait_for & ~WAIT_DONE; warn_printf("deadlock 0x%lx: %s:", th->thread, thread_status_name(th->status)); - if (wait_for & WAIT_FD) warn_printf("F(%d)", th->fd); - if (wait_for & WAIT_SELECT) warn_printf("S"); - if (wait_for & WAIT_TIME) warn_printf("T(%f)", th->delay); - if (wait_for & WAIT_JOIN) + if (th->wait_for & WAIT_FD) warn_printf("F(%d)", th->fd); + if (th->wait_for & WAIT_SELECT) warn_printf("S"); + if (th->wait_for & WAIT_TIME) warn_printf("T(%f)", th->delay); + if (th->wait_for & WAIT_JOIN) warn_printf("J(0x%lx)", th->join ? th->join->thread : 0); - if (wait_for & WAIT_PID) warn_printf("P"); - if (!wait_for) warn_printf("-"); + if (th->wait_for & WAIT_PID) warn_printf("P"); + if (!th->wait_for) warn_printf("-"); warn_printf(" %s - %s:%d\n", th==main_thread ? "(main)" : "", th->node->nd_file, nd_line(th->node)); @@ -12222,9 +12193,9 @@ th->locals = 0;\ th->thread = 0;\ if (curr_thread == 0) {\ - th->sandbox = Qnil;\ + th->sandbox = Qnil;\ } else {\ - th->sandbox = curr_thread->sandbox;\ + th->sandbox = curr_thread->sandbox;\ }\ } while (0) @@ -12247,12 +12218,6 @@ static int thread_init; -#if defined(POSIX_SIGNAL) -#define CATCH_VTALRM() posix_signal(SIGVTALRM, catch_timer) -#else -#define CATCH_VTALRM() signal(SIGVTALRM, catch_timer) -#endif - #if defined(_THREAD_SAFE) static void catch_timer(sig) @@ -12269,60 +12315,31 @@ /* cause EINTR */ } -#define PER_NANO 1000000000 - -static struct timespec * -get_ts(struct timespec *to, long ns) -{ - struct timeval tv; - -#ifdef CLOCK_REALTIME - if (clock_gettime(CLOCK_REALTIME, to) != 0) -#endif - { - gettimeofday(&tv, NULL); - to->tv_sec = tv.tv_sec; - to->tv_nsec = tv.tv_usec * 1000; - } - if ((to->tv_nsec += ns) >= PER_NANO) { - to->tv_sec += to->tv_nsec / PER_NANO; - to->tv_nsec %= PER_NANO; - } - return to; -} - -static struct timer_thread { - pthread_cond_t cond; - pthread_mutex_t lock; - pthread_t thread; -} time_thread = {PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER}; - +static pthread_t time_thread; static int timer_stopping; -#define safe_mutex_lock(lock) \ - pthread_mutex_lock(lock); \ - pthread_cleanup_push((void (*)_((void *)))pthread_mutex_unlock, lock) - static void* thread_timer(dummy) void *dummy; { - struct timer_thread *running = ((void **)dummy)[0]; - pthread_cond_t *start = ((void **)dummy)[1]; - struct timespec to; - int err; - sigset_t all_signals; sigfillset(&all_signals); pthread_sigmask(SIG_BLOCK, &all_signals, 0); - safe_mutex_lock(&running->lock); - pthread_cond_signal(start); - -#define WAIT_FOR_10MS() \ - pthread_cond_timedwait(&running->cond, &running->lock, get_ts(&to, PER_NANO/100)) - while ((err = WAIT_FOR_10MS()) == EINTR || err == ETIMEDOUT) { + for (;;) { +#ifdef HAVE_NANOSLEEP + struct timespec req, rem; + + req.tv_sec = 0; + req.tv_nsec = 10000000; + nanosleep(&req, &rem); +#else + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 10000; + select(0, NULL, NULL, NULL, &tv); +#endif if (timer_stopping) break; @@ -12333,42 +12350,16 @@ } } } - - pthread_cleanup_pop(1); - - return NULL; } void rb_thread_start_timer() { - void *args[2]; - static pthread_cond_t start = PTHREAD_COND_INITIALIZER; - - if (thread_init) return; - if (rb_thread_alone()) return; - CATCH_VTALRM(); - args[0] = &time_thread; - args[1] = &start; - safe_mutex_lock(&time_thread.lock); - if (pthread_create(&time_thread.thread, 0, thread_timer, args) == 0) { - thread_init = 1; - pthread_cond_wait(&start, &time_thread.lock); - } - pthread_cleanup_pop(1); } void rb_thread_stop_timer() { - if (!thread_init) return; - safe_mutex_lock(&time_thread.lock); - timer_stopping = 1; - pthread_cond_signal(&time_thread.cond); - thread_init = 0; - pthread_cleanup_pop(1); - pthread_join(time_thread.thread, NULL); - timer_stopping = 0; } #elif defined(HAVE_SETITIMER) static void @@ -12378,14 +12290,11 @@ { struct itimerval tval; - if (thread_init) return; - if (rb_thread_alone()) return; - CATCH_VTALRM(); + if (!thread_init) return; tval.it_interval.tv_sec = 0; tval.it_interval.tv_usec = 10000; tval.it_value = tval.it_interval; setitimer(ITIMER_VIRTUAL, &tval, NULL); - thread_init = 1; } void @@ -12398,20 +12307,11 @@ tval.it_interval.tv_usec = 0; tval.it_value = tval.it_interval; setitimer(ITIMER_VIRTUAL, &tval, NULL); - thread_init = 0; } #else /* !(_THREAD_SAFE || HAVE_SETITIMER) */ int rb_thread_tick = THREAD_TICK; #endif -#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) -#define START_TIMER() (thread_init ? (void)0 : rb_thread_start_timer()) -#define STOP_TIMER() (rb_thread_stop_timer()) -#else -#define START_TIMER() ((void)0) -#define STOP_TIMER() ((void)0) -#endif - static VALUE rb_thread_start_0(fn, arg, th) VALUE (*fn)(); @@ -12429,6 +12329,23 @@ "can't start a new thread (frozen ThreadGroup)"); } + if (!thread_init) { + thread_init = 1; +#if defined(HAVE_SETITIMER) || defined(_THREAD_SAFE) +#if defined(POSIX_SIGNAL) + posix_signal(SIGVTALRM, catch_timer); +#else + signal(SIGVTALRM, catch_timer); +#endif + +#ifdef _THREAD_SAFE + pthread_create(&time_thread, 0, thread_timer, 0); +#else + rb_thread_start_timer(); +#endif +#endif + } + if (THREAD_SAVE_CONTEXT(curr_thread)) { return thread; } @@ -12451,7 +12368,6 @@ th->priority = curr_thread->priority; th->thgroup = curr_thread->thgroup; } - START_TIMER(); PUSH_TAG(PROT_THREAD); if ((state = EXEC_TAG()) == 0) { @@ -13177,7 +13093,6 @@ main_thread = curr_thread; curr_thread->next = curr_thread; curr_thread->prev = curr_thread; - STOP_TIMER(); }