revert_thread_scheduler_optimizations.diff   [plain text]


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();
 }