diff --git a/ChangeLog b/ChangeLog index 21563abb46..76fc6b9bcf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Tue Dec 17 4:15:36 2008 Brent Roman + + * eval.c: streamlined rb_thread_restore_context() to ensure O(1) time + Tue Dec 15 9:15:36 2008 Brent Roman * eval.c: factored rb_eval() into many separate non-inlined diff --git a/eval.c b/eval.c index 372d71aa52..cc9234056f 100644 --- a/eval.c +++ b/eval.c @@ -10885,11 +10885,10 @@ rb_thread_switch(n) 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,void*))); -NORETURN(NOINLINE(static void stack_extend(rb_thread_t, int, VALUE *))); +NORETURN(NOINLINE(static void rb_thread_restore_context_0(rb_thread_t,int))); static void -rb_thread_restore_context_0(rb_thread_t th, int exit, void *vp) +rb_thread_restore_context_0(rb_thread_t th, int exit) { static rb_thread_t tmp; static int ex; @@ -10946,9 +10945,9 @@ static volatile int C(f), C(g), C(h), C(i), C(j); 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, void *, VALUE *))); +NORETURN(NOINLINE(static void register_stack_extend(rb_thread_t, int, VALUE *))); static void -register_stack_extend(rb_thread_t th, int exit, void *vp, VALUE *curr_bsp) +register_stack_extend(rb_thread_t th, int exit, VALUE *curr_bsp) { if (rb_dummy_false) { /* use registers as much as possible */ @@ -10962,52 +10961,68 @@ register_stack_extend(rb_thread_t th, int exit, void *vp, VALUE *curr_bsp) 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, &exit, (VALUE*)rb_ia64_bsp()); + register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp()); } - rb_thread_restore_context_0(th, exit, &exit); + rb_thread_restore_context_0(th, 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, VALUE *addr_in_prev_frame) -{ -#define STACK_PAD_SIZE 1024 - VALUE space[STACK_PAD_SIZE]; - -#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 */ - if (addr_in_prev_frame > th->stk_pos) stack_extend(th, exit, &space[0]); - } - else { - /* Stack grows upward */ - if (addr_in_prev_frame < th->stk_pos + th->stk_len) stack_extend(th, exit, &space[STACK_PAD_SIZE-1]); - } -#endif -#ifdef __ia64 - 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 *pos = th->stk_start; + +#if HAVE_ALLOCA /* use alloca to grow stack in O(1) time */ VALUE v; + volatile VALUE *space; + if (!th->stk_ptr) rb_bug("unsaved context"); - stack_extend(th, exit, &v); +# if !STACK_GROW_DIRECTION /* unknown at compile time */ + if (rb_gc_stack_grow_direction < 0) { +# endif +# if STACK_GROW_DIRECTION <= 0 + pos -= th->stk_len; + if (&v > pos) space=ALLOCA_N(VALUE, &v-pos); +# endif +# if !STACK_GROW_DIRECTION + }else +# endif +#if STACK_GROW_DIRECTION >= 0 /* stack grows upward */ + if (&v < pos + th->stk_len) space=ALLOCA_N(VALUE, pos+th->stk_len - &v); +# endif + +#else /* recursive O(n/1024) if extending stack > 1024 VALUEs */ + + volatile VALUE v[1023]; + +# if !STACK_GROW_DIRECTION /* unknown at compile time */ + if (rb_gc_stack_grow_direction < 0) { +# endif +# if STACK_GROW_DIRECTION <= 0 + pos -= th->stk_len; + if (v > pos) rb_thread_restore_context(th, exit); +# endif +# if !STACK_GROW_DIRECTION + }else +# endif +# if STACK_GROW_DIRECTION >= 0 /* stack grows upward */ + if (v < pos + th->stk_len) rb_thread_restore_context(th, exit); +# endif + if (!th->stk_ptr) rb_bug("unsaved context"); + +#endif /* stack now extended */ + + +#ifdef __ia64 + register_stack_extend(th, exit, (VALUE*)rb_ia64_bsp()); +#else + rb_thread_restore_context_0(th, exit); +#endif } static void diff --git a/version.h b/version.h index 2f6c834daa..9373924548 100644 --- a/version.h +++ b/version.h @@ -1,7 +1,7 @@ #define RUBY_VERSION "1.8.7" -#define RUBY_RELEASE_DATE "2008-12-16" +#define RUBY_RELEASE_DATE "2008-12-17" #define RUBY_VERSION_CODE 187 -#define RUBY_RELEASE_CODE 20081216 +#define RUBY_RELEASE_CODE 20081217 #define RUBY_PATCHLEVEL 72 #define RUBY_VERSION_MAJOR 1 @@ -9,7 +9,7 @@ #define RUBY_VERSION_TEENY 7 #define RUBY_RELEASE_YEAR 2008 #define RUBY_RELEASE_MONTH 12 -#define RUBY_RELEASE_DAY 16 +#define RUBY_RELEASE_DAY 17 #ifdef RUBY_EXTERN RUBY_EXTERN const char ruby_version[]; @@ -25,7 +25,7 @@ RUBY_EXTERN const char *ruby_copyright; #define RUBY_BIRTH_MONTH 2 #define RUBY_BIRTH_DAY 24 -#define RUBY_RELEASE_STR "MBARI 4 on patchlevel" +#define RUBY_RELEASE_STR "MBARI 5 on patchlevel" #define RUBY_RELEASE_NUM RUBY_PATCHLEVEL