From 4f0c9a5cc49cf36f15af85f644982fbb847f0dca Mon Sep 17 00:00:00 2001 From: ko1 Date: Sun, 10 Sep 2017 15:49:45 +0000 Subject: [PATCH] move th->machine to ec->machine. * vm_core.h: move rb_thread_t::machine to rb_execution_context_t::machine. * vm_core.h, gc.c (rb_gc_mark_machine_stack): accept ec instead of th. it enables to call this func from rb_execution_context_mark() in vm.c. * cont.c (fiber_setcontext): catch up this fix. fiber_restore_thread() restores machine stack information too. * gc.c: catch up structure layout changes. * thread.c: ditto. * thread_pthread.c: ditto. * thread_win32.c: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59825 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- cont.c | 77 ++++++++++++++++++++++++------------------------ gc.c | 38 +++++++++++++----------- thread.c | 12 ++++---- thread_pthread.c | 32 ++++++++++---------- thread_win32.c | 6 ++-- vm.c | 17 ++++++----- vm_core.h | 28 +++++++++--------- 7 files changed, 106 insertions(+), 104 deletions(-) diff --git a/cont.c b/cont.c index c89f7404f6..6b0c771efd 100644 --- a/cont.c +++ b/cont.c @@ -430,18 +430,18 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont) { size_t size; - SET_MACHINE_STACK_END(&th->machine.stack_end); + SET_MACHINE_STACK_END(&th->ec.machine.stack_end); #ifdef __ia64 th->machine.register_stack_end = rb_ia64_bsp(); #endif - if (th->machine.stack_start > th->machine.stack_end) { - size = cont->machine.stack_size = th->machine.stack_start - th->machine.stack_end; - cont->machine.stack_src = th->machine.stack_end; + if (th->ec.machine.stack_start > th->ec.machine.stack_end) { + size = cont->machine.stack_size = th->ec.machine.stack_start - th->ec.machine.stack_end; + cont->machine.stack_src = th->ec.machine.stack_end; } else { - size = cont->machine.stack_size = th->machine.stack_end - th->machine.stack_start; - cont->machine.stack_src = th->machine.stack_start; + size = cont->machine.stack_size = th->ec.machine.stack_end - th->ec.machine.stack_start; + cont->machine.stack_src = th->ec.machine.stack_start; } if (cont->machine.stack) { @@ -485,13 +485,15 @@ cont_save_thread(rb_context_t *cont, rb_thread_t *th) /* save thread context */ sth->ec = th->ec; +#if FIBER_USE_NATIVE /* saved_thread->machine.stack_(start|end) should be NULL */ /* because it may happen GC afterward */ - sth->machine.stack_start = 0; - sth->machine.stack_end = 0; + sth->ec.machine.stack_start = NULL; + sth->ec.machine.stack_end = NULL; #ifdef __ia64 - sth->machine.register_stack_start = 0; - sth->machine.register_stack_end = 0; + sth->ec.machine.register_stack_start = NULL; + sth->ec.machine.register_stack_end = NULL; +#endif #endif } @@ -501,7 +503,6 @@ cont_init(rb_context_t *cont, rb_thread_t *th) /* save thread context */ cont_save_thread(cont, th); cont->saved_thread.self = th->self; - cont->saved_thread.machine.stack_maxsize = th->machine.stack_maxsize; cont->saved_thread.ec.local_storage = NULL; cont->saved_thread.ec.local_storage_recursive_hash = Qnil; @@ -651,7 +652,7 @@ fiber_set_stack_location(void) VALUE *ptr; SET_MACHINE_STACK_END(&ptr); - th->machine.stack_start = (void*)(((VALUE)ptr & RB_PAGE_MASK) + STACK_UPPER((void *)&ptr, 0, RB_PAGE_SIZE)); + th->ec.machine.stack_start = (void*)(((VALUE)ptr & RB_PAGE_MASK) + STACK_UPPER((void *)&ptr, 0, RB_PAGE_SIZE)); } static VOID CALLBACK @@ -730,7 +731,7 @@ fiber_initialize_machine_stack_context(rb_fiber_t *fib, size_t size) rb_raise(rb_eFiberError, "can't create fiber"); } } - sth->machine.stack_maxsize = size; + sth->ec.machine.stack_maxsize = size; #else /* not WIN32 */ ucontext_t *context = &fib->context; char *ptr; @@ -744,8 +745,8 @@ fiber_initialize_machine_stack_context(rb_fiber_t *fib, size_t size) fib->ss_sp = ptr; fib->ss_size = size; makecontext(context, rb_fiber_start, 0); - sth->machine.stack_start = (VALUE*)(ptr + STACK_DIR_UPPER(0, size)); - sth->machine.stack_maxsize = size - RB_PAGE_SIZE; + sth->ec.machine.stack_start = (VALUE*)(ptr + STACK_DIR_UPPER(0, size)); + sth->ec.machine.stack_maxsize = size - RB_PAGE_SIZE; #endif #ifdef __ia64 sth->machine.register_stack_maxsize = sth->machine.stack_maxsize; @@ -757,33 +758,31 @@ NOINLINE(static void fiber_setcontext(rb_fiber_t *newfib, rb_fiber_t *oldfib)); static void fiber_setcontext(rb_fiber_t *newfib, rb_fiber_t *oldfib) { - rb_thread_t *th = GET_THREAD(), *sth = &newfib->cont.saved_thread; + rb_thread_t *th = GET_THREAD(); + + /* save oldfib's machine stack / TODO: is it needd? */ + if (!FIBER_TERMINATED_P(oldfib)) { + STACK_GROW_DIR_DETECTION; + SET_MACHINE_STACK_END(&th->ec.machine.stack_end); + if (STACK_DIR_UPPER(0, 1)) { + oldfib->cont.machine.stack_size = th->ec.machine.stack_start - th->ec.machine.stack_end; + oldfib->cont.machine.stack = th->ec.machine.stack_end; + } + else { + oldfib->cont.machine.stack_size = th->ec.machine.stack_end - th->ec.machine.stack_start; + oldfib->cont.machine.stack = th->ec.machine.stack_start; + } + } + + /* exchange machine_stack_start between oldfib and newfib */ + oldfib->cont.saved_thread.ec.machine.stack_start = th->ec.machine.stack_start; + + /* oldfib->machine.stack_end should be NULL */ + oldfib->cont.saved_thread.ec.machine.stack_end = NULL; /* restore thread context */ fiber_restore_thread(th, newfib); - th->machine.stack_maxsize = sth->machine.stack_maxsize; - if (sth->machine.stack_end && (newfib != oldfib)) { - rb_bug("fiber_setcontext: sth->machine.stack_end has non zero value"); - } - /* save oldfib's machine stack */ - if (!FIBER_TERMINATED_P(oldfib)) { - STACK_GROW_DIR_DETECTION; - SET_MACHINE_STACK_END(&th->machine.stack_end); - if (STACK_DIR_UPPER(0, 1)) { - oldfib->cont.machine.stack_size = th->machine.stack_start - th->machine.stack_end; - oldfib->cont.machine.stack = th->machine.stack_end; - } - else { - oldfib->cont.machine.stack_size = th->machine.stack_end - th->machine.stack_start; - oldfib->cont.machine.stack = th->machine.stack_start; - } - } - /* exchange machine_stack_start between oldfib and newfib */ - oldfib->cont.saved_thread.machine.stack_start = th->machine.stack_start; - th->machine.stack_start = sth->machine.stack_start; - /* oldfib->machine.stack_end should be NULL */ - oldfib->cont.saved_thread.machine.stack_end = 0; #ifndef _WIN32 if (!newfib->context.uc_stack.ss_sp && th->root_fiber != newfib) { rb_bug("non_root_fiber->context.uc_stac.ss_sp should not be NULL"); @@ -1791,7 +1790,7 @@ Init_Cont(void) #else /* not WIN32 */ pagesize = sysconf(_SC_PAGESIZE); #endif - SET_MACHINE_STACK_END(&th->machine.stack_end); + SET_MACHINE_STACK_END(&th->ec.machine.stack_end); #endif rb_cFiber = rb_define_class("Fiber", rb_cObject); diff --git a/gc.c b/gc.c index 11f31693c0..7f6c1a7a79 100644 --- a/gc.c +++ b/gc.c @@ -3967,14 +3967,14 @@ init_mark_stack(mark_stack_t *stack) /* Marking */ #ifdef __ia64 -#define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine.stack_end), th->machine.register_stack_end = rb_ia64_bsp()) +#define SET_STACK_END (SET_MACHINE_STACK_END(&ec->machine.stack_end), ec->machine.register_stack_end = rb_ia64_bsp()) #else -#define SET_STACK_END SET_MACHINE_STACK_END(&th->machine.stack_end) +#define SET_STACK_END SET_MACHINE_STACK_END(&ec->machine.stack_end) #endif -#define STACK_START (th->machine.stack_start) -#define STACK_END (th->machine.stack_end) -#define STACK_LEVEL_MAX (th->machine.stack_maxsize/sizeof(VALUE)) +#define STACK_START (ec->machine.stack_start) +#define STACK_END (ec->machine.stack_end) +#define STACK_LEVEL_MAX (ec->machine.stack_maxsize/sizeof(VALUE)) #if STACK_GROW_DIRECTION < 0 # define STACK_LENGTH (size_t)(STACK_START - STACK_END) @@ -4000,7 +4000,7 @@ ruby_get_stack_grow_direction(volatile VALUE *addr) size_t ruby_stack_length(VALUE **p) { - rb_thread_t *th = GET_THREAD(); + rb_execution_context_t *ec = &GET_THREAD()->ec; SET_STACK_END; if (p) *p = STACK_UPPER(STACK_END, STACK_START, STACK_END); return STACK_LENGTH; @@ -4018,13 +4018,14 @@ ruby_stack_length(VALUE **p) static int stack_check(rb_thread_t *th, int water_mark) { + rb_execution_context_t *ec = &th->ec; int ret; SET_STACK_END; 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) - water_mark; + ret = (VALUE*)rb_ia64_bsp() - ec->machine.register_stack_start > + ec->machine.register_stack_maxsize/sizeof(VALUE) - water_mark; } #endif return ret; @@ -4235,11 +4236,11 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl) ((start) = STACK_END, (end) = STACK_START) : ((start) = STACK_START, (end) = STACK_END+(appendix))) #endif -static void mark_stack_locations(rb_objspace_t *objspace, rb_thread_t *th, +static void mark_stack_locations(rb_objspace_t *objspace, const rb_execution_context_t *ec, const VALUE *stack_start, const VALUE *stack_end); static void -mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th) +mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec) { union { rb_jmp_buf j; @@ -4259,29 +4260,29 @@ mark_current_machine_context(rb_objspace_t *objspace, rb_thread_t *th) mark_locations_array(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v)); - mark_stack_locations(objspace, th, stack_start, stack_end); + mark_stack_locations(objspace, ec, stack_start, stack_end); } void -rb_gc_mark_machine_stack(rb_thread_t *th) +rb_gc_mark_machine_stack(const rb_execution_context_t *ec) { - rb_objspace_t *objspace = rb_objspace_of(th->vm); + rb_objspace_t *objspace = &rb_objspace; VALUE *stack_start, *stack_end; GET_STACK_BOUNDS(stack_start, stack_end, 0); - mark_stack_locations(objspace, th, stack_start, stack_end); + mark_stack_locations(objspace, ec, stack_start, stack_end); } static void -mark_stack_locations(rb_objspace_t *objspace, rb_thread_t *th, +mark_stack_locations(rb_objspace_t *objspace, const rb_execution_context_t *ec, const VALUE *stack_start, const VALUE *stack_end) { gc_mark_locations(objspace, stack_start, stack_end); #ifdef __ia64 gc_mark_locations(objspace, - th->machine.register_stack_start, - th->machine.register_stack_end); + ec->machine.register_stack_start, + ec->machine.register_stack_end); #endif #if defined(__mc68000__) gc_mark_locations(objspace, @@ -4774,6 +4775,7 @@ gc_mark_roots(rb_objspace_t *objspace, const char **categoryp) { struct gc_list *list; rb_thread_t *th = GET_THREAD(); + rb_execution_context_t *ec = &th->ec; #if PRINT_ROOT_TICKS tick_t start_tick = tick(); @@ -4820,7 +4822,7 @@ gc_mark_roots(rb_objspace_t *objspace, const char **categoryp) mark_tbl(objspace, finalizer_table); MARK_CHECKPOINT("machine_context"); - mark_current_machine_context(objspace, th); + mark_current_machine_context(objspace, &th->ec); MARK_CHECKPOINT("encodings"); rb_gc_mark_encodings(); diff --git a/thread.c b/thread.c index 766b3d4100..d706ee469b 100644 --- a/thread.c +++ b/thread.c @@ -138,8 +138,8 @@ static inline void blocking_region_end(rb_thread_t *th, struct rb_blocking_regio do { \ FLUSH_REGISTER_WINDOWS; \ RB_GC_SAVE_MACHINE_REGISTER_STACK(th); \ - setjmp((th)->machine.regs); \ - SET_MACHINE_STACK_END(&(th)->machine.stack_end); \ + setjmp((th)->ec.machine.regs); \ + SET_MACHINE_STACK_END(&(th)->ec.machine.stack_end); \ } while (0) #define GVL_UNLOCK_BEGIN() do { \ @@ -525,9 +525,9 @@ thread_cleanup_func_before_exec(void *th_ptr) { rb_thread_t *th = th_ptr; th->status = THREAD_KILLED; - th->machine.stack_start = th->machine.stack_end = 0; + th->ec.machine.stack_start = th->ec.machine.stack_end = NULL; #ifdef __ia64 - th->machine.register_stack_start = th->machine.register_stack_end = 0; + th->ec.machine.register_stack_start = th->ec.machine.register_stack_end = NULL; #endif } @@ -613,9 +613,9 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s ruby_thread_set_native(th); - th->machine.stack_start = stack_start; + th->ec.machine.stack_start = stack_start; #ifdef __ia64 - th->machine.register_stack_start = register_stack_start; + th->ec.machine.register_stack_start = register_stack_start; #endif thread_debug("thread start: %p\n", (void *)th); diff --git a/thread_pthread.c b/thread_pthread.c index 242b48f15d..675a2ddbae 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -832,8 +832,8 @@ native_thread_init_stack(rb_thread_t *th) rb_nativethread_id_t curr = pthread_self(); if (pthread_equal(curr, native_main_thread.id)) { - th->machine.stack_start = native_main_thread.stack_start; - th->machine.stack_maxsize = native_main_thread.stack_maxsize; + th->ec.machine.stack_start = native_main_thread.stack_start; + th->ec.machine.stack_maxsize = native_main_thread.stack_maxsize; } else { #ifdef STACKADDR_AVAILABLE @@ -841,11 +841,11 @@ native_thread_init_stack(rb_thread_t *th) size_t size; if (get_stack(&start, &size) == 0) { - th->machine.stack_start = start; - th->machine.stack_maxsize = size; + th->ec.machine.stack_start = start; + th->ec.machine.stack_maxsize = size; } #elif defined get_stack_of - if (!th->machine.stack_maxsize) { + if (!th->ec.machine.stack_maxsize) { native_mutex_lock(&th->interrupt_lock); native_mutex_unlock(&th->interrupt_lock); } @@ -854,9 +854,9 @@ native_thread_init_stack(rb_thread_t *th) #endif } #ifdef __ia64 - th->machine.register_stack_start = native_main_thread.register_stack_start; - th->machine.stack_maxsize /= 2; - th->machine.register_stack_maxsize = th->machine.stack_maxsize; + th->ec.machine.register_stack_start = native_main_thread.register_stack_start; + th->ec.machine.stack_maxsize /= 2; + th->ec.machine.register_stack_maxsize = th->ec.machine.stack_maxsize; #endif return 0; } @@ -884,7 +884,7 @@ thread_start_func_1(void *th_ptr) native_thread_init(th); /* run */ #if defined USE_NATIVE_THREAD_INIT - thread_start_func_2(th, th->machine.stack_start, rb_ia64_bsp()); + thread_start_func_2(th, th->ec.machine.stack_start, rb_ia64_bsp()); #else thread_start_func_2(th, &stack_start, rb_ia64_bsp()); #endif @@ -1006,10 +1006,10 @@ native_thread_create(rb_thread_t *th) const size_t stack_size = th->vm->default_params.thread_machine_stack_size; const size_t space = space_size(stack_size); - th->machine.stack_maxsize = stack_size - space; + th->ec.machine.stack_maxsize = stack_size - space; #ifdef __ia64 - th->machine.stack_maxsize /= 2; - th->machine.register_stack_maxsize = th->machine.stack_maxsize; + th->ec.machine.stack_maxsize /= 2; + th->ec.machine.register_stack_maxsize = th->ec.machine.stack_maxsize; #endif #ifdef HAVE_PTHREAD_ATTR_INIT @@ -1032,8 +1032,8 @@ native_thread_create(rb_thread_t *th) #ifdef get_stack_of if (!err) { get_stack_of(th->thread_id, - &th->machine.stack_start, - &th->machine.stack_maxsize); + &th->ec.machine.stack_start, + &th->ec.machine.stack_maxsize); } native_mutex_unlock(&th->interrupt_lock); #endif @@ -1745,8 +1745,8 @@ ruby_stack_overflowed_p(const rb_thread_t *th, const void *addr) else #endif if (th) { - size = th->machine.stack_maxsize; - base = (char *)th->machine.stack_start - STACK_DIR_UPPER(0, size); + size = th->ec.machine.stack_maxsize; + base = (char *)th->ec.machine.stack_start - STACK_DIR_UPPER(0, size); } else { return 0; diff --git a/thread_win32.c b/thread_win32.c index 5b42310679..683fafc5ba 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -546,8 +546,8 @@ native_thread_init_stack(rb_thread_t *th) size = end - base; space = size / 5; if (space > 1024*1024) space = 1024*1024; - th->machine.stack_start = (VALUE *)end - 1; - th->machine.stack_maxsize = size - space; + th->ec.machine.stack_start = (VALUE *)end - 1; + th->ec.machine.stack_maxsize = size - space; } #ifndef InterlockedExchangePointer @@ -575,7 +575,7 @@ thread_start_func_1(void *th_ptr) thread_debug("thread created (th: %p, thid: %p, event: %p)\n", th, th->thread_id, th->native_thread_data.interrupt_event); - thread_start_func_2(th, th->machine.stack_start, rb_ia64_bsp()); + thread_start_func_2(th, th->ec.machine.stack_start, rb_ia64_bsp()); w32_close_handle(thread_id); thread_debug("thread deleted (th: %p)\n", th); diff --git a/vm.c b/vm.c index 5569b87182..9054293b64 100644 --- a/vm.c +++ b/vm.c @@ -2390,6 +2390,15 @@ rb_execution_context_mark(const rb_execution_context_t *ec) } } + /* mark machine stack */ + if (&GET_THREAD()->ec != ec && + ec->machine.stack_start && ec->machine.stack_end) { + rb_gc_mark_machine_stack(ec); + rb_gc_mark_locations((VALUE *)&ec->machine.regs, + (VALUE *)(&ec->machine.regs) + + sizeof(ec->machine.regs) / sizeof(VALUE)); + } + RUBY_MARK_UNLESS_NULL(ec->errinfo); RUBY_MARK_UNLESS_NULL(ec->root_svar); rb_mark_tbl(ec->local_storage); @@ -2406,14 +2415,6 @@ rb_thread_mark(void *ptr) rb_execution_context_mark(&th->ec); - /* mark machine stack */ - if (GET_THREAD() != th && th->machine.stack_start && th->machine.stack_end) { - rb_gc_mark_machine_stack(th); - rb_gc_mark_locations((VALUE *)&th->machine.regs, - (VALUE *)(&th->machine.regs) + - sizeof(th->machine.regs) / sizeof(VALUE)); - } - /* mark ruby objects */ RUBY_MARK_UNLESS_NULL(th->first_proc); if (th->first_proc) RUBY_MARK_UNLESS_NULL(th->first_args); diff --git a/vm_core.h b/vm_core.h index a2ca6342cf..67f9641c25 100644 --- a/vm_core.h +++ b/vm_core.h @@ -767,6 +767,19 @@ typedef struct rb_execution_context_struct { rb_ensure_list_t *ensure_list; rb_fiber_t *fiber; + + /* for GC */ + struct { + VALUE *stack_start; + VALUE *stack_end; + size_t stack_maxsize; +#ifdef __ia64 + VALUE *register_stack_start; + VALUE *register_stack_end; + size_t register_stack_maxsize; +#endif + jmp_buf regs; + } machine; } rb_execution_context_t; typedef struct rb_thread_struct { @@ -829,19 +842,6 @@ typedef struct rb_thread_struct { VALUE first_args; VALUE (*first_func)(ANYARGS); - /* for GC */ - struct { - VALUE *stack_start; - VALUE *stack_end; - size_t stack_maxsize; -#ifdef __ia64 - VALUE *register_stack_start; - VALUE *register_stack_end; - size_t register_stack_maxsize; -#endif - jmp_buf regs; - } machine; - /* statistics data for profiler */ VALUE stat_insn_usage; @@ -1543,7 +1543,7 @@ void rb_vm_register_special_exception_str(enum ruby_special_exceptions sp, VALUE #define rb_vm_register_special_exception(sp, e, m) \ rb_vm_register_special_exception_str(sp, e, rb_usascii_str_new_static((m), (long)rb_strlen_lit(m))) -void rb_gc_mark_machine_stack(rb_thread_t *th); +void rb_gc_mark_machine_stack(const rb_execution_context_t *ec); int rb_autoloading_value(VALUE mod, ID id, VALUE* value);