From 837fd5e494731d7d44786f29e7d6e8c27029806f Mon Sep 17 00:00:00 2001 From: ko1 Date: Thu, 26 Oct 2017 08:32:49 +0000 Subject: Use rb_execution_context_t instead of rb_thread_t to represent execution context [Feature #14038] * vm_core.h (rb_thread_t): rb_thread_t::ec is now a pointer. There are many code using `th` to represent execution context (such as cfp, VM stack and so on). To access `ec`, they need to use `th->ec->...` (adding one indirection) so that we need to replace them by passing `ec` instead of `th`. * vm_core.h (GET_EC()): introduced to access current ec. Also remove `ruby_current_thread` global variable. * cont.c (rb_context_t): introduce rb_context_t::thread_ptr instead of rb_context_t::thread_value. * cont.c (ec_set_vm_stack): added to update vm_stack explicitly. * cont.c (ec_switch): added to switch ec explicitly. * cont.c (rb_fiber_close): added to terminate fibers explicitly. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60440 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- .gdbinit | 4 +- compile.c | 2 +- cont.c | 375 ++++++++++++++++++++++++++++++++++++------------------- error.c | 4 +- eval.c | 96 +++++++------- eval_error.c | 8 +- eval_intern.h | 30 ++--- eval_jump.c | 10 +- gc.c | 18 +-- insns.def | 4 +- internal.h | 1 - iseq.c | 4 +- load.c | 12 +- proc.c | 10 +- process.c | 4 +- safe.c | 12 +- signal.c | 8 +- thread.c | 79 ++++++------ thread_pthread.c | 36 +++--- thread_win32.c | 10 +- vm.c | 254 ++++++++++++++++++------------------- vm_args.c | 10 +- vm_backtrace.c | 10 +- vm_core.h | 68 ++++++++-- vm_dump.c | 44 +++---- vm_eval.c | 62 ++++----- vm_exec.c | 10 +- vm_exec.h | 4 +- vm_insnhelper.c | 66 +++++----- vm_insnhelper.h | 4 +- vm_method.c | 6 +- vm_trace.c | 52 ++++---- 32 files changed, 742 insertions(+), 575 deletions(-) diff --git a/.gdbinit b/.gdbinit index 53c3ac2a3f..544ded74c8 100644 --- a/.gdbinit +++ b/.gdbinit @@ -1119,8 +1119,8 @@ define rb_ps_thread set $ps_thread_th = (rb_thread_t*)$ps_thread->data printf "* #\n", \ $ps_thread, $ps_thread_th, $ps_thread_th->thread_id - set $cfp = $ps_thread_th->ec.cfp - set $cfpend = (rb_control_frame_t *)($ps_thread_th->ec.vm_stack + $ps_thread_th->ec.vm_stack_size)-1 + set $cfp = $ps_thread_th->ec->cfp + set $cfpend = (rb_control_frame_t *)($ps_thread_th->ec->vm_stack + $ps_thread_th->ec.vm_stack_size)-1 while $cfp < $cfpend if $cfp->iseq if !((VALUE)$cfp->iseq & RUBY_IMMEDIATE_MASK) && (((imemo_ifunc << RUBY_FL_USHIFT) | RUBY_T_IMEMO)==$cfp->iseq->flags & ((RUBY_IMEMO_MASK << RUBY_FL_USHIFT) | RUBY_T_MASK)) diff --git a/compile.c b/compile.c index b3969ff4c4..6894ee0084 100644 --- a/compile.c +++ b/compile.c @@ -7604,7 +7604,7 @@ caller_location(VALUE *path, VALUE *realpath) { const rb_thread_t *const th = GET_THREAD(); const rb_control_frame_t *const cfp = - rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (cfp) { int line = rb_vm_get_sourceline(cfp); diff --git a/cont.c b/cont.c index df4ac789bd..2d9cf8d07f 100644 --- a/cont.c +++ b/cont.c @@ -83,8 +83,8 @@ enum context_type { struct cont_saved_vm_stack { VALUE *ptr; #ifdef CAPTURE_JUST_VALID_VM_STACK - size_t slen; /* length of stack (head of th->ec.vm_stack) */ - size_t clen; /* length of control frames (tail of th->ec.vm_stack) */ + size_t slen; /* length of stack (head of th->ec->vm_stack) */ + size_t clen; /* length of control frames (tail of th->ec->vm_stack) */ #endif }; @@ -110,7 +110,7 @@ typedef struct rb_context_struct { rb_jmpbuf_t jmpbuf; rb_ensure_entry_t *ensure_array; rb_ensure_list_t *ensure_list; - VALUE thread_value; + rb_thread_t *thread_ptr; } rb_context_t; @@ -189,15 +189,62 @@ fiber_status_name(enum fiber_status s) return NULL; } +static void +fiber_verify(const rb_fiber_t *fib) +{ +#if VM_CHECK_MODE > 0 + VM_ASSERT(fib->cont.saved_ec.fiber == fib); + + switch (fib->status) { + case FIBER_RESUMED: + VM_ASSERT(fib->cont.saved_ec.vm_stack != NULL); + break; + case FIBER_SUSPENDED: + VM_ASSERT(fib->cont.saved_ec.vm_stack != NULL); + break; + case FIBER_CREATED: + case FIBER_TERMINATED: + /* TODO */ + break; + default: + VM_UNREACHABLE(fiber_verify); + } +#endif +} + +#if VM_CHECK_MODE > 0 +void +rb_ec_verify(const rb_execution_context_t *ec) +{ + /* TODO */ +} +#endif + static void fiber_status_set(const rb_fiber_t *fib, enum fiber_status s) { if (0) fprintf(stderr, "fib: %p, status: %s -> %s\n", fib, fiber_status_name(fib->status), fiber_status_name(s)); VM_ASSERT(!FIBER_TERMINATED_P(fib)); VM_ASSERT(fib->status != s); + fiber_verify(fib); *((enum fiber_status *)&fib->status) = s; } +void +ec_set_vm_stack(rb_execution_context_t *ec, VALUE *stack, size_t size) +{ + *(VALUE **)(&ec->vm_stack) = stack; + *(size_t *)(&ec->vm_stack_size) = size; +} + +static inline void +ec_switch(rb_thread_t *th, rb_fiber_t *fib) +{ + rb_execution_context_t *ec = &fib->cont.saved_ec; + ruby_current_execution_context_ptr = th->ec = ec; + VM_ASSERT(ec->fiber->cont.self == 0 || ec->vm_stack != NULL); +} + static const rb_data_type_t cont_data_type, fiber_data_type; static VALUE rb_cContinuation; static VALUE rb_cFiber; @@ -214,13 +261,13 @@ static VALUE rb_eFiberError; NOINLINE(static VALUE cont_capture(volatile int *volatile stat)); #define THREAD_MUST_BE_RUNNING(th) do { \ - if (!(th)->ec.tag) rb_raise(rb_eThreadError, "not running thread"); \ + if (!(th)->ec->tag) rb_raise(rb_eThreadError, "not running thread"); \ } while (0) static VALUE cont_thread_value(const rb_context_t *cont) { - return cont->thread_value; + return cont->thread_ptr->self; } static void @@ -252,10 +299,9 @@ cont_mark(void *ptr) } else { /* fiber */ - const rb_thread_t *th = rb_thread_ptr(cont_thread_value(cont)); const rb_fiber_t *fib = (rb_fiber_t*)cont; - if ((th->ec.fiber != fib) && !FIBER_TERMINATED_P(fib)) { + if (!FIBER_TERMINATED_P(fib)) { rb_gc_mark_locations(cont->machine.stack, cont->machine.stack + cont->machine.stack_size); } @@ -277,7 +323,8 @@ cont_free(void *ptr) rb_context_t *cont = ptr; RUBY_FREE_ENTER("cont"); - RUBY_FREE_UNLESS_NULL(cont->saved_ec.vm_stack); + ruby_xfree(cont->saved_ec.vm_stack); + #if FIBER_USE_NATIVE if (cont->type == CONTINUATION_CONTEXT) { /* cont */ @@ -287,22 +334,19 @@ cont_free(void *ptr) else { /* fiber */ const rb_fiber_t *fib = (rb_fiber_t*)cont; - const rb_thread_t *const th = GET_THREAD(); #ifdef _WIN32 - if (th && th->ec.fiber != fib && cont->type != ROOT_FIBER_CONTEXT) { + if (cont->type != ROOT_FIBER_CONTEXT) { /* don't delete root fiber handle */ if (fib->fib_handle) { DeleteFiber(fib->fib_handle); } } #else /* not WIN32 */ - if (th && th->ec.fiber != fib) { - if (fib->ss_sp) { - if (cont->type == ROOT_FIBER_CONTEXT) { - rb_bug("Illegal root fiber parameter"); - } - munmap((void*)fib->ss_sp, fib->ss_size); + if (fib->ss_sp != NULL) { + if (cont->type == ROOT_FIBER_CONTEXT) { + rb_bug("Illegal root fiber parameter"); } + munmap((void*)fib->ss_sp, fib->ss_size); } else { /* It may reached here when finalize */ @@ -352,32 +396,21 @@ cont_memsize(const void *ptr) return size; } -static void -fiber_verify(const rb_fiber_t *fib) +rb_thread_t * +rb_fiberptr_thread_ptr(const rb_fiber_t *fib) { -#if VM_CHECK_MODE > 0 - switch (fib->status) { - case FIBER_RESUMED: - VM_ASSERT(fib->cont.saved_ec.vm_stack == NULL); - break; - case FIBER_SUSPENDED: - VM_ASSERT(fib->cont.saved_ec.vm_stack != NULL); - break; - case FIBER_CREATED: - case FIBER_TERMINATED: - /* TODO */ - break; - default: - VM_UNREACHABLE(fiber_verify); - } -#endif + return fib->cont.thread_ptr; } void rb_fiber_mark_self(const rb_fiber_t *fib) { - if (fib) + if (fib->cont.self) { rb_gc_mark(fib->cont.self); + } + else { + rb_execution_context_mark(&fib->cont.saved_ec); + } } static void @@ -387,7 +420,17 @@ fiber_mark(void *ptr) RUBY_MARK_ENTER("cont"); fiber_verify(fib); rb_gc_mark(fib->first_proc); - rb_fiber_mark_self(fib->prev); + if (fib->prev) rb_fiber_mark_self(fib->prev); + +#if !FIBER_USE_NATIVE + if (fib->status == FIBER_TERMINATED) { + /* FIBER_TERMINATED fiber should not mark machine stack */ + if (fib->cont.saved_ec.machine.stack_end != NULL) { + fib->cont.saved_ec.machine.stack_end = NULL; + } + } +#endif + cont_mark(&fib->cont); RUBY_MARK_LEAVE("cont"); } @@ -397,8 +440,7 @@ fiber_free(void *ptr) { rb_fiber_t *fib = ptr; RUBY_FREE_ENTER("fiber"); - if (fib->cont.type != ROOT_FIBER_CONTEXT && - fib->cont.saved_ec.local_storage) { + if (fib->cont.saved_ec.local_storage) { st_free_table(fib->cont.saved_ec.local_storage); } @@ -437,18 +479,18 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont) { size_t size; - SET_MACHINE_STACK_END(&th->ec.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->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; + 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->ec.machine.stack_end - th->ec.machine.stack_start; - cont->machine.stack_src = th->ec.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) { @@ -490,7 +532,7 @@ cont_save_thread(rb_context_t *cont, rb_thread_t *th) VM_ASSERT(th->status == THREAD_RUNNABLE); /* save thread context */ - *sec = th->ec; + *sec = *th->ec; /* saved_thread->machine.stack_end should be NULL */ /* because it may happen GC afterward */ @@ -507,7 +549,7 @@ cont_init(rb_context_t *cont, rb_thread_t *th) { /* save thread context */ cont_save_thread(cont, th); - cont->thread_value = th->self; + cont->thread_ptr = th; cont->saved_ec.local_storage = NULL; cont->saved_ec.local_storage_recursive_hash = Qnil; cont->saved_ec.local_storage_recursive_hash_for_trace = Qnil; @@ -527,13 +569,40 @@ cont_new(VALUE klass) return cont; } +#if 0 +void +show_vm_stack(const rb_execution_context_t *ec) +{ + VALUE *p = ec->vm_stack; + while (p < ec->cfp->sp) { + fprintf(stderr, "%3d ", (int)(p - ec->vm_stack)); + rb_obj_info_dump(*p); + p++; + } +} + +void +show_vm_pcs(const rb_control_frame_t *cfp, + const rb_control_frame_t *end_of_cfp) +{ + int i=0; + while (cfp != end_of_cfp) { + int pc = 0; + if (cfp->iseq) { + pc = cfp->pc - cfp->iseq->body->iseq_encoded; + } + fprintf(stderr, "%2d pc: %d\n", i++, pc); + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); + } +} +#endif static VALUE cont_capture(volatile int *volatile stat) { rb_context_t *volatile cont; rb_thread_t *th = GET_THREAD(); volatile VALUE contval; - rb_execution_context_t *ec = &th->ec; + const rb_execution_context_t *ec = th->ec; THREAD_MUST_BE_RUNNING(th); rb_vm_stack_to_heap(th); @@ -544,15 +613,18 @@ cont_capture(volatile int *volatile stat) cont->saved_vm_stack.slen = ec->cfp->sp - ec->vm_stack; cont->saved_vm_stack.clen = ec->vm_stack + ec->vm_stack_size - (VALUE*)ec->cfp; cont->saved_vm_stack.ptr = ALLOC_N(VALUE, cont->saved_vm_stack.slen + cont->saved_vm_stack.clen); - MEMCPY(cont->saved_vm_stack.ptr, ec->vm_stack, VALUE, cont->saved_vm_stack.slen); + MEMCPY(cont->saved_vm_stack.ptr, + ec->vm_stack, + VALUE, cont->saved_vm_stack.slen); MEMCPY(cont->saved_vm_stack.ptr + cont->saved_vm_stack.slen, - (VALUE*)ec->cfp, VALUE, cont->saved_vm_stack.clen); + (VALUE*)ec->cfp, + VALUE, + cont->saved_vm_stack.clen); #else cont->saved_vm_stack.ptr = ALLOC_N(VALUE, ec->vm_stack_size); MEMCPY(cont->saved_vm_stack.ptr, ec->vm_stack, VALUE, ec->vm_stack_size); #endif - cont->saved_ec.vm_stack = NULL; - + ec_set_vm_stack(&cont->saved_ec, NULL, 0); cont_save_machine_stack(th, cont); /* backup ensure_list to array for search in another context */ @@ -560,10 +632,10 @@ cont_capture(volatile int *volatile stat) rb_ensure_list_t *p; int size = 0; rb_ensure_entry_t *entry; - for (p=th->ec.ensure_list; p; p=p->next) + for (p=th->ec->ensure_list; p; p=p->next) size++; entry = cont->ensure_array = ALLOC_N(rb_ensure_entry_t,size+1); - for (p=th->ec.ensure_list; p; p=p->next) { + for (p=th->ec->ensure_list; p; p=p->next) { if (!p->entry.marker) p->entry.marker = rb_ary_tmp_new(0); /* dummy object */ *entry++ = p->entry; @@ -590,10 +662,8 @@ cont_capture(volatile int *volatile stat) static inline void fiber_restore_thread(rb_thread_t *th, rb_fiber_t *fib) { - th->ec = fib->cont.saved_ec; - fib->cont.saved_ec.vm_stack = NULL; - - VM_ASSERT(th->ec.vm_stack != NULL); + ec_switch(th, fib); + VM_ASSERT(th->ec->fiber == fib); } static inline void @@ -605,36 +675,44 @@ cont_restore_thread(rb_context_t *cont) if (cont->type == CONTINUATION_CONTEXT) { /* continuation */ rb_execution_context_t *sec = &cont->saved_ec; - const rb_fiber_t *fib; + rb_fiber_t *fib = NULL; - fib = th->ec.fiber = sec->fiber; - if (fib == NULL) fib = th->root_fiber; + if (sec->fiber != NULL) { + fib = sec->fiber; + } + else if (th->root_fiber) { + fib = th->root_fiber; + } - if (fib && fib->cont.saved_ec.vm_stack) { - th->ec.vm_stack_size = fib->cont.saved_ec.vm_stack_size; - th->ec.vm_stack = fib->cont.saved_ec.vm_stack; + if (fib && th->ec != &fib->cont.saved_ec) { + ec_switch(th, fib); } + + /* copy vm stack */ #ifdef CAPTURE_JUST_VALID_VM_STACK - MEMCPY(th->ec.vm_stack, cont->saved_vm_stack.ptr, VALUE, cont->saved_vm_stack.slen); - MEMCPY(th->ec.vm_stack + sec->vm_stack_size - cont->saved_vm_stack.clen, - cont->saved_vm_stack.ptr + cont->saved_vm_stack.slen, VALUE, cont->saved_vm_stack.clen); + MEMCPY(th->ec->vm_stack, + cont->saved_vm_stack.ptr, + VALUE, cont->saved_vm_stack.slen); + MEMCPY(th->ec->vm_stack + th->ec->vm_stack_size - cont->saved_vm_stack.clen, + cont->saved_vm_stack.ptr + cont->saved_vm_stack.slen, + VALUE, cont->saved_vm_stack.clen); #else - MEMCPY(th->ec.vm_stack, cont->saved_vm_stack.ptr, VALUE, sec->vm_stack_size); + MEMCPY(th->ec->vm_stack, cont->saved_vm_stack.ptr, VALUE, sec->vm_stack_size); #endif - /* other members of ec */ - th->ec.cfp = sec->cfp; - th->ec.safe_level = sec->safe_level; - th->ec.raised_flag = sec->raised_flag; - th->ec.tag = sec->tag; - th->ec.protect_tag = sec->protect_tag; - th->ec.root_lep = sec->root_lep; - th->ec.root_svar = sec->root_svar; - th->ec.ensure_list = sec->ensure_list; - th->ec.errinfo = sec->errinfo; - th->ec.trace_arg = sec->trace_arg; - - VM_ASSERT(th->ec.vm_stack != NULL); + + th->ec->cfp = sec->cfp; + th->ec->safe_level = sec->safe_level; + th->ec->raised_flag = sec->raised_flag; + th->ec->tag = sec->tag; + th->ec->protect_tag = sec->protect_tag; + th->ec->root_lep = sec->root_lep; + th->ec->root_svar = sec->root_svar; + th->ec->ensure_list = sec->ensure_list; + th->ec->errinfo = sec->errinfo; + th->ec->trace_arg = sec->trace_arg; + + VM_ASSERT(th->ec->vm_stack != NULL); } else { /* fiber */ @@ -651,7 +729,7 @@ fiber_set_stack_location(void) VALUE *ptr; SET_MACHINE_STACK_END(&ptr); - th->ec.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 @@ -762,19 +840,19 @@ fiber_setcontext(rb_fiber_t *newfib, rb_fiber_t *oldfib) /* save oldfib's machine stack / TODO: is it needed? */ if (!FIBER_TERMINATED_P(oldfib)) { STACK_GROW_DIR_DETECTION; - SET_MACHINE_STACK_END(&th->ec.machine.stack_end); + 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; + 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; + 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_ec.machine.stack_start = th->ec.machine.stack_start; + oldfib->cont.saved_ec.machine.stack_start = th->ec->machine.stack_start; /* oldfib->machine.stack_end should be NULL */ oldfib->cont.saved_ec.machine.stack_end = NULL; @@ -1128,15 +1206,15 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval) if (cont_thread_value(cont) != th->self) { rb_raise(rb_eRuntimeError, "continuation called across threads"); } - if (cont->saved_ec.protect_tag != th->ec.protect_tag) { + if (cont->saved_ec.protect_tag != th->ec->protect_tag) { rb_raise(rb_eRuntimeError, "continuation called across stack rewinding barrier"); } if (cont->saved_ec.fiber) { - if (th->ec.fiber != cont->saved_ec.fiber) { + if (th->ec->fiber != cont->saved_ec.fiber) { rb_raise(rb_eRuntimeError, "continuation called across fiber"); } } - rollback_ensure_stack(contval, th->ec.ensure_list, cont->ensure_array); + rollback_ensure_stack(contval, th->ec->ensure_list, cont->ensure_array); cont->argc = argc; cont->value = make_passing_arg(argc, argv); @@ -1270,15 +1348,13 @@ fiber_init(VALUE fibval, VALUE proc) rb_context_t *cont = &fib->cont; rb_execution_context_t *sec = &cont->saved_ec; rb_thread_t *cth = GET_THREAD(); + size_t fib_stack_size = cth->vm->default_params.fiber_vm_stack_size / sizeof(VALUE); /* initialize cont */ cont->saved_vm_stack.ptr = NULL; + ec_set_vm_stack(sec, NULL, 0); - sec->vm_stack = NULL; - sec->vm_stack_size = 0; - - sec->vm_stack_size = cth->vm->default_params.fiber_vm_stack_size / sizeof(VALUE); - sec->vm_stack = ALLOC_N(VALUE, sec->vm_stack_size); + ec_set_vm_stack(sec, ALLOC_N(VALUE, fib_stack_size), fib_stack_size); sec->cfp = (void *)(sec->vm_stack + sec->vm_stack_size); rb_vm_push_frame(sec, @@ -1324,11 +1400,12 @@ static void rb_fiber_terminate(rb_fiber_t *fib); void rb_fiber_start(void) { - rb_thread_t *th = GET_THREAD(); - rb_fiber_t *fib = th->ec.fiber; + rb_thread_t * volatile th = GET_THREAD(); + rb_fiber_t *fib = th->ec->fiber; rb_proc_t *proc; enum ruby_tag_type state; + VM_ASSERT(th->ec == ruby_current_execution_context_ptr); VM_ASSERT(FIBER_RESUMED_P(fib)); TH_PUSH_TAG(th); @@ -1339,9 +1416,9 @@ rb_fiber_start(void) GetProcPtr(fib->first_proc, proc); argv = (argc = cont->argc) > 1 ? RARRAY_CONST_PTR(args) : &args; cont->value = Qnil; - th->ec.errinfo = Qnil; - th->ec.root_lep = rb_vm_proc_local_ep(fib->first_proc); - th->ec.root_svar = Qfalse; + th->ec->errinfo = Qnil; + th->ec->root_lep = rb_vm_proc_local_ep(fib->first_proc); + th->ec->root_svar = Qfalse; EXEC_EVENT_HOOK(th, RUBY_EVENT_FIBER_SWITCH, th->self, 0, 0, 0, Qnil); cont->value = rb_vm_invoke_proc(th, proc, argc, argv, VM_BLOCK_HANDLER_NONE); @@ -1352,10 +1429,10 @@ rb_fiber_start(void) VM_ASSERT(FIBER_RESUMED_P(fib)); if (state == TAG_RAISE || state == TAG_FATAL) { - rb_threadptr_pending_interrupt_enque(th, th->ec.errinfo); + rb_threadptr_pending_interrupt_enque(th, th->ec->errinfo); } else { - VALUE err = rb_vm_make_jump_tag_but_local_jump(state, th->ec.errinfo); + VALUE err = rb_vm_make_jump_tag_but_local_jump(state, th->ec->errinfo); if (!NIL_P(err)) rb_threadptr_pending_interrupt_enque(th, err); } @@ -1369,30 +1446,54 @@ rb_fiber_start(void) static rb_fiber_t * root_fiber_alloc(rb_thread_t *th) { - rb_fiber_t *fib; - /* no need to allocate vm stack */ - fib = fiber_t_alloc(fiber_alloc(rb_cFiber)); - fib->cont.type = ROOT_FIBER_CONTEXT; + VALUE fibval = fiber_alloc(rb_cFiber); + rb_fiber_t *fib = th->ec->fiber; + + VM_ASSERT(DATA_PTR(fibval) == NULL); + VM_ASSERT(fib->cont.type == ROOT_FIBER_CONTEXT); + VM_ASSERT(fib->status == FIBER_RESUMED); + + th->root_fiber = fib; + DATA_PTR(fibval) = fib; + fib->cont.self = fibval; #if FIBER_USE_NATIVE #ifdef _WIN32 - fib->fib_handle = ConvertThreadToFiber(0); + if (fib->fib_handle == 0) { + fib->fib_handle = ConvertThreadToFiber(0); + } #endif #endif - fiber_status_set(fib, FIBER_RESUMED); /* skip CREATED */ - th->root_fiber = th->ec.fiber = fib; return fib; } +void +rb_threadptr_root_fiber_setup(rb_thread_t *th) +{ + rb_fiber_t *fib = ruby_mimmalloc(sizeof(rb_fiber_t)); + MEMZERO(fib, rb_fiber_t, 1); + fib->cont.type = ROOT_FIBER_CONTEXT; + fib->cont.saved_ec.fiber = fib; + fib->cont.thread_ptr = th; + fiber_status_set(fib, FIBER_RESUMED); /* skip CREATED */ + th->ec = &fib->cont.saved_ec; + th->root_fiber = th->ec->fiber = fib; +#if FIBER_USE_NATIVE +#ifdef _WIN32 + if (fib->fib_handle == 0) { + fib->fib_handle = ConvertThreadToFiber(0); + } +#endif +#endif +} + static inline rb_fiber_t* fiber_current(void) { rb_thread_t *th = GET_THREAD(); - if (th->ec.fiber == NULL) { - rb_fiber_t *fib = root_fiber_alloc(th); - /* Running thread object has stack management responsibility */ - fib->cont.saved_ec.vm_stack = NULL; + if (th->ec->fiber->cont.self == 0) { + root_fiber_alloc(th); } - return th->ec.fiber; + return th->ec->fiber; } static inline rb_fiber_t* @@ -1426,9 +1527,8 @@ fiber_store(rb_fiber_t *next_fib, rb_thread_t *th) { rb_fiber_t *fib; - if (th->ec.fiber != NULL) { - fib = th->ec.fiber; - cont_save_thread(&fib->cont, th); + if (th->ec->fiber != NULL) { + fib = th->ec->fiber; } else { /* create root fiber */ @@ -1475,14 +1575,14 @@ fiber_store(rb_fiber_t *next_fib, rb_thread_t *th) terminated_machine_stack.size = 0; } #endif /* not _WIN32 */ - fib = th->ec.fiber; + fib = th->ec->fiber; if (fib->cont.argc == -1) rb_exc_raise(fib->cont.value); return fib->cont.value; #else /* FIBER_USE_NATIVE */ if (ruby_setjmp(fib->cont.jmpbuf)) { /* restored */ - fib = th->ec.fiber; + fib = th->ec->fiber; if (fib->cont.argc == -1) rb_exc_raise(fib->cont.value); if (next_fib->cont.value == Qundef) { cont_restore_0(&next_fib->cont, &next_fib->cont.value); @@ -1505,7 +1605,7 @@ fiber_switch(rb_fiber_t *fib, int argc, const VALUE *argv, int is_resume) rb_context_t *cont = &fib->cont; rb_thread_t *th = GET_THREAD(); - if (th->ec.fiber == fib) { + if (th->ec->fiber == fib) { /* ignore fiber context switch * because destination fiber is same as current fiber */ @@ -1515,13 +1615,13 @@ fiber_switch(rb_fiber_t *fib, int argc, const VALUE *argv, int is_resume) if (cont_thread_value(cont) != th->self) { rb_raise(rb_eFiberError, "fiber called across threads"); } - else if (cont->saved_ec.protect_tag != th->ec.protect_tag) { + else if (cont->saved_ec.protect_tag != th->ec->protect_tag) { rb_raise(rb_eFiberError, "fiber called across stack rewinding barrier"); } else if (FIBER_TERMINATED_P(fib)) { value = rb_exc_new2(rb_eFiberError, "dead fiber called"); - if (!FIBER_TERMINATED_P(th->ec.fiber)) { + if (!FIBER_TERMINATED_P(th->ec->fiber)) { rb_exc_raise(value); VM_UNREACHABLE(fiber_switch); } @@ -1535,7 +1635,7 @@ fiber_switch(rb_fiber_t *fib, int argc, const VALUE *argv, int is_resume) cont->argc = -1; cont->value = value; #if FIBER_USE_NATIVE - fiber_setcontext(th->root_fiber, th->ec.fiber); + fiber_setcontext(th->root_fiber, th->ec->fiber); #else cont_restore_0(cont, &value); #endif @@ -1567,13 +1667,33 @@ rb_fiber_transfer(VALUE fibval, int argc, const VALUE *argv) return fiber_switch(fib, argc, argv, 0); } +void +rb_fiber_close(rb_fiber_t *fib) +{ + VALUE *vm_stack = fib->cont.saved_ec.vm_stack; + fiber_status_set(fib, FIBER_TERMINATED); + if (fib->cont.type == ROOT_FIBER_CONTEXT) { + rb_thread_recycle_stack_release(vm_stack); + } + else { + ruby_xfree(vm_stack); + } + ec_set_vm_stack(&fib->cont.saved_ec, NULL, 0); + +#if !FIBER_USE_NATIVE + /* should not mark machine stack any more */ + fib->cont.saved_ec.machine.stack_end = NULL; +#endif +} + static void rb_fiber_terminate(rb_fiber_t *fib) { VALUE value = fib->cont.value; VM_ASSERT(FIBER_RESUMED_P(fib)); - fiber_status_set(fib, FIBER_TERMINATED); + rb_fiber_close(fib); + #if FIBER_USE_NATIVE && !defined(_WIN32) /* Ruby must not switch to other thread until storing terminated_machine_stack */ terminated_machine_stack.ptr = fib->ss_sp; @@ -1583,6 +1703,7 @@ rb_fiber_terminate(rb_fiber_t *fib) fib->cont.machine.stack = NULL; fib->cont.machine.stack_size = 0; #endif + fiber_switch(return_fiber(), 1, &value, 0); } @@ -1613,8 +1734,8 @@ rb_fiber_reset_root_local_storage(VALUE thval) { rb_thread_t *th = rb_thread_ptr(thval); - if (th->root_fiber && th->root_fiber != th->ec.fiber) { - th->ec.local_storage = th->root_fiber->cont.saved_ec.local_storage; + if (th->root_fiber && th->root_fiber != th->ec->fiber) { + th->ec->local_storage = th->root_fiber->cont.saved_ec.local_storage; } } @@ -1794,7 +1915,7 @@ Init_Cont(void) #else /* not WIN32 */ pagesize = sysconf(_SC_PAGESIZE); #endif - SET_MACHINE_STACK_END(&th->ec.machine.stack_end); + SET_MACHINE_STACK_END(&th->ec->machine.stack_end); #endif rb_cFiber = rb_define_class("Fiber", rb_cObject); diff --git a/error.c b/error.c index 668bc9bfa8..cbca9a5703 100644 --- a/error.c +++ b/error.c @@ -525,7 +525,7 @@ die(void) abort(); } - +#include void rb_bug(const char *fmt, ...) { @@ -1300,7 +1300,7 @@ name_err_initialize(int argc, VALUE *argv, VALUE self) rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, - RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec.cfp)); + RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec->cfp)); if (cfp) iseqw = rb_iseqw_new(cfp->iseq); } rb_ivar_set(self, id_iseq, iseqw); diff --git a/eval.c b/eval.c index 00b5156c86..a55f2f7b10 100644 --- a/eval.c +++ b/eval.c @@ -129,7 +129,7 @@ static void ruby_finalize_1(void) { ruby_sig_finalize(); - GET_THREAD()->ec.errinfo = Qnil; + GET_THREAD()->ec->errinfo = Qnil; rb_gc_call_finalizer_at_exit(); } @@ -174,8 +174,8 @@ ruby_cleanup(volatile int ex) SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(th); }); step_0: step++; - errs[1] = th->ec.errinfo; - th->ec.safe_level = 0; + errs[1] = th->ec->errinfo; + th->ec->safe_level = 0; ruby_init_stack(&errs[STACK_UPPER(errs, 0, 1)]); SAVE_ROOT_JMPBUF(th, ruby_finalize_0()); @@ -184,7 +184,7 @@ ruby_cleanup(volatile int ex) /* protect from Thread#raise */ th->status = THREAD_KILLED; - errs[0] = th->ec.errinfo; + errs[0] = th->ec->errinfo; SAVE_ROOT_JMPBUF(th, rb_thread_terminate_all()); } else { @@ -194,7 +194,7 @@ ruby_cleanup(volatile int ex) } if (ex == 0) ex = state; } - th->ec.errinfo = errs[1]; + th->ec->errinfo = errs[1]; sysex = error_handle(ex); state = 0; @@ -203,7 +203,7 @@ ruby_cleanup(volatile int ex) if (!RTEST(err)) continue; - /* th->ec.errinfo contains a NODE while break'ing */ + /* th->ec->errinfo contains a NODE while break'ing */ if (THROW_DATA_P(err)) continue; if (rb_obj_is_kind_of(err, rb_eSystemExit)) { @@ -237,7 +237,7 @@ ruby_exec_internal(void *n) { volatile int state; rb_iseq_t *iseq = (rb_iseq_t *)n; - rb_thread_t *th = GET_THREAD(); + rb_thread_t * volatile th = GET_THREAD(); if (!n) return 0; @@ -478,7 +478,7 @@ exc_setup_message(rb_thread_t *th, VALUE mesg, VALUE *cause) int nocause = 0; if (NIL_P(mesg)) { - mesg = th->ec.errinfo; + mesg = th->ec->errinfo; if (INTERNAL_EXCEPTION_P(mesg)) TH_JUMP_TAG(th, TAG_FATAL); nocause = 1; } @@ -531,19 +531,19 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause) } if (!NIL_P(mesg)) { - th->ec.errinfo = mesg; + th->ec->errinfo = mesg; } - if (RTEST(ruby_debug) && !NIL_P(e = th->ec.errinfo) && + if (RTEST(ruby_debug) && !NIL_P(e = th->ec->errinfo) && !rb_obj_is_kind_of(e, rb_eSystemExit)) { enum ruby_tag_type state; mesg = e; TH_PUSH_TAG(th); if ((state = EXEC_TAG()) == TAG_NONE) { - th->ec.errinfo = Qnil; + th->ec->errinfo = Qnil; e = rb_obj_as_string(mesg); - th->ec.errinfo = mesg; + th->ec->errinfo = mesg; if (file && line) { e = rb_sprintf("Exception `%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n", rb_obj_class(mesg), file, line, e); @@ -559,8 +559,8 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause) warn_print_str(e); } TH_POP_TAG(); - if (state == TAG_FATAL && th->ec.errinfo == exception_error) { - th->ec.errinfo = mesg; + if (state == TAG_FATAL && th->ec->errinfo == exception_error) { + th->ec->errinfo = mesg; } else if (state) { rb_threadptr_reset_raised(th); @@ -570,14 +570,14 @@ setup_exception(rb_thread_t *th, int tag, volatile VALUE mesg, VALUE cause) if (rb_threadptr_set_raised(th)) { fatal: - th->ec.errinfo = exception_error; + th->ec->errinfo = exception_error; rb_threadptr_reset_raised(th); TH_JUMP_TAG(th, TAG_FATAL); } if (tag != TAG_FATAL) { - RUBY_DTRACE_HOOK(RAISE, rb_obj_classname(th->ec.errinfo)); - EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->ec.cfp->self, 0, 0, 0, mesg); + RUBY_DTRACE_HOOK(RAISE, rb_obj_classname(th->ec->errinfo)); + EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->ec->cfp->self, 0, 0, 0, mesg); } } @@ -797,7 +797,7 @@ void rb_raise_jump(VALUE mesg, VALUE cause) { rb_thread_t *th = GET_THREAD(); - const rb_control_frame_t *cfp = th->ec.cfp; + const rb_control_frame_t *cfp = th->ec->cfp; const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp); VALUE klass = me->owner; VALUE self = cfp->self; @@ -835,7 +835,7 @@ int rb_block_given_p(void) { rb_thread_t *th = GET_THREAD(); - if (rb_vm_frame_block_handler(th->ec.cfp) == VM_BLOCK_HANDLER_NONE) { + if (rb_vm_frame_block_handler(th->ec->cfp) == VM_BLOCK_HANDLER_NONE) { return FALSE; } else { @@ -896,10 +896,10 @@ rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1, VALUE (* r_proc) (ANYARGS), VALUE data2, ...) { enum ruby_tag_type state; - rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *volatile cfp = th->ec.cfp; + rb_thread_t * volatile th = GET_THREAD(); + rb_control_frame_t *volatile cfp = th->ec->cfp; volatile VALUE result = Qfalse; - volatile VALUE e_info = th->ec.errinfo; + volatile VALUE e_info = th->ec->errinfo; va_list args; TH_PUSH_TAG(th); @@ -911,7 +911,7 @@ rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1, /* escape from r_proc */ if (state == TAG_RETRY) { state = 0; - th->ec.errinfo = Qnil; + th->ec->errinfo = Qnil; result = Qfalse; goto retry_entry; } @@ -925,7 +925,7 @@ rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1, va_init_list(args, data2); while ((eclass = va_arg(args, VALUE)) != 0) { - if (rb_obj_is_kind_of(th->ec.errinfo, eclass)) { + if (rb_obj_is_kind_of(th->ec->errinfo, eclass)) { handle = TRUE; break; } @@ -936,9 +936,9 @@ rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1, result = Qnil; state = 0; if (r_proc) { - result = (*r_proc) (data2, th->ec.errinfo); + result = (*r_proc) (data2, th->ec->errinfo); } - th->ec.errinfo = e_info; + th->ec->errinfo = e_info; } } } @@ -993,15 +993,15 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate) { volatile VALUE result = Qnil; volatile enum ruby_tag_type state; - rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *volatile cfp = th->ec.cfp; + rb_thread_t * volatile th = GET_THREAD(); + rb_control_frame_t *volatile cfp = th->ec->cfp; struct rb_vm_protect_tag protect_tag; rb_jmpbuf_t org_jmpbuf; - protect_tag.prev = th->ec.protect_tag; + protect_tag.prev = th->ec->protect_tag; TH_PUSH_TAG(th); - th->ec.protect_tag = &protect_tag; + th->ec->protect_tag = &protect_tag; MEMCPY(&org_jmpbuf, &(th)->root_jmpbuf, rb_jmpbuf_t, 1); if ((state = TH_EXEC_TAG()) == TAG_NONE) { SAVE_ROOT_JMPBUF(th, result = (*proc) (data)); @@ -1010,7 +1010,7 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate) rb_vm_rewind_cfp(th, cfp); } MEMCPY(&(th)->root_jmpbuf, &org_jmpbuf, rb_jmpbuf_t, 1); - th->ec.protect_tag = protect_tag.prev; + th->ec->protect_tag = protect_tag.prev; TH_POP_TAG(); if (pstate != NULL) *pstate = state; @@ -1037,25 +1037,25 @@ rb_ensure(VALUE (*b_proc)(ANYARGS), VALUE data1, VALUE (*e_proc)(ANYARGS), VALUE int state; volatile VALUE result = Qnil; VALUE errinfo; - rb_thread_t *const th = GET_THREAD(); + rb_thread_t *const volatile th = GET_THREAD(); rb_ensure_list_t ensure_list; ensure_list.entry.marker = 0; ensure_list.entry.e_proc = e_proc; ensure_list.entry.data2 = data2; - ensure_list.next = th->ec.ensure_list; - th->ec.ensure_list = &ensure_list; + ensure_list.next = th->ec->ensure_list; + th->ec->ensure_list = &ensure_list; TH_PUSH_TAG(th); if ((state = EXEC_TAG()) == TAG_NONE) { result = (*b_proc) (data1); } TH_POP_TAG(); - errinfo = th->ec.errinfo; + errinfo = th->ec->errinfo; if (!NIL_P(errinfo) && !RB_TYPE_P(errinfo, T_OBJECT)) { - th->ec.errinfo = Qnil; + th->ec->errinfo = Qnil; } - th->ec.ensure_list=ensure_list.next; + th->ec->ensure_list=ensure_list.next; (*ensure_list.entry.e_proc)(ensure_list.entry.data2); - th->ec.errinfo = errinfo; + th->ec->errinfo = errinfo; if (state) TH_JUMP_TAG(th, state); return result; @@ -1102,7 +1102,7 @@ frame_called_id(rb_control_frame_t *cfp) ID rb_frame_this_func(void) { - return frame_func_id(GET_THREAD()->ec.cfp); + return frame_func_id(GET_THREAD()->ec->cfp); } /*! @@ -1119,15 +1119,15 @@ rb_frame_this_func(void) ID rb_frame_callee(void) { - return frame_called_id(GET_THREAD()->ec.cfp); + return frame_called_id(GET_THREAD()->ec->cfp); } static rb_control_frame_t * previous_frame(rb_thread_t *th) { - rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec.cfp); + rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec->cfp); /* check if prev_cfp can be accessible */ - if ((void *)(th->ec.vm_stack + th->ec.vm_stack_size) == (void *)(prev_cfp)) { + if ((void *)(th->ec->vm_stack + th->ec->vm_stack_size) == (void *)(prev_cfp)) { return 0; } return prev_cfp; @@ -1159,7 +1159,7 @@ ID rb_frame_last_func(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; ID mid; while (!(mid = frame_func_id(cfp)) && @@ -1439,7 +1439,7 @@ rb_mod_refine(VALUE module, VALUE klass) id_refined_class, id_defined_at; VALUE refinements, activated_refinements; rb_thread_t *th = GET_THREAD(); - VALUE block_handler = rb_vm_frame_block_handler(th->ec.cfp); + VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp); if (block_handler == VM_BLOCK_HANDLER_NONE) { rb_raise(rb_eArgError, "no block given"); @@ -1724,7 +1724,7 @@ top_using(VALUE self, VALUE module) static const VALUE * errinfo_place(rb_thread_t *th) { - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; rb_control_frame_t *end_cfp = RUBY_VM_END_CONTROL_FRAME(th); while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) { @@ -1751,7 +1751,7 @@ get_thread_errinfo(rb_thread_t *th) return *ptr; } else { - return th->ec.errinfo; + return th->ec->errinfo; } } @@ -1777,7 +1777,7 @@ VALUE rb_errinfo(void) { rb_thread_t *th = GET_THREAD(); - return th->ec.errinfo; + return th->ec->errinfo; } /*! Sets the current exception (\c $!) to the given value @@ -1794,7 +1794,7 @@ rb_set_errinfo(VALUE err) if (!NIL_P(err) && !rb_obj_is_kind_of(err, rb_eException)) { rb_raise(rb_eTypeError, "assigning non-exception to $!"); } - GET_THREAD()->ec.errinfo = err; + GET_THREAD()->ec->errinfo = err; } static VALUE diff --git a/eval_error.c b/eval_error.c index fe6bae1145..274b2f8ec6 100644 --- a/eval_error.c +++ b/eval_error.c @@ -69,7 +69,7 @@ set_backtrace(VALUE info, VALUE bt) static void error_print(rb_thread_t *th) { - rb_threadptr_error_print(th, th->ec.errinfo); + rb_threadptr_error_print(th, th->ec->errinfo); } static void @@ -167,7 +167,7 @@ void rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo) { volatile VALUE errat = Qundef; - volatile int raised_flag = th->ec.raised_flag; + volatile int raised_flag = th->ec->raised_flag; volatile VALUE eclass = Qundef, emesg = Qundef; if (NIL_P(errinfo)) @@ -202,7 +202,7 @@ rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo) } error: TH_POP_TAG(); - th->ec.errinfo = errinfo; + th->ec->errinfo = errinfo; rb_thread_raised_set(th, raised_flag); } @@ -304,7 +304,7 @@ error_handle(int ex) warn_print("unexpected throw\n"); break; case TAG_RAISE: { - VALUE errinfo = th->ec.errinfo; + VALUE errinfo = th->ec->errinfo; if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) { status = sysexit_status(errinfo); } diff --git a/eval_intern.h b/eval_intern.h index 217eddc02c..229b34bf1a 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -14,10 +14,10 @@ vm_passed_block_handler_set(rb_thread_t *th, VALUE block_handler) static inline void pass_passed_block_handler(rb_thread_t *th) { - VALUE block_handler = rb_vm_frame_block_handler(th->ec.cfp); + VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp); vm_block_handler_verify(block_handler); vm_passed_block_handler_set(th, block_handler); - VM_ENV_FLAGS_SET(th->ec.cfp->ep, VM_FRAME_FLAG_PASSED); + VM_ENV_FLAGS_SET(th->ec->cfp->ep, VM_FRAME_FLAG_PASSED); } #define PASS_PASSED_BLOCK_HANDLER_TH(th) pass_passed_block_handler(th) @@ -133,16 +133,16 @@ LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *); struct rb_vm_tag _tag; \ _tag.state = TAG_NONE; \ _tag.tag = Qundef; \ - _tag.prev = _th->ec.tag; + _tag.prev = _th->ec->tag; #define TH_POP_TAG() \ - _th->ec.tag = _tag.prev; \ + _th->ec->tag = _tag.prev; \ } while (0) #define TH_TMPPOP_TAG() \ - _th->ec.tag = _tag.prev + _th->ec->tag = _tag.prev -#define TH_REPUSH_TAG() (void)(_th->ec.tag = &_tag) +#define TH_REPUSH_TAG() (void)(_th->ec->tag = &_tag) #define PUSH_TAG() TH_PUSH_TAG(GET_THREAD()) #define POP_TAG() TH_POP_TAG() @@ -174,12 +174,12 @@ LONG WINAPI rb_w32_stack_overflow_handler(struct _EXCEPTION_POINTERS *); #undef RB_OBJ_WRITE #define RB_OBJ_WRITE(a, slot, b) UNALIGNED_MEMBER_ACCESS(rb_obj_write((VALUE)(a), (VALUE *)(slot), (VALUE)(b), __FILE__, __LINE__)) -/* clear th->ec.tag->state, and return the value */ +/* clear th->ec->tag->state, and return the value */ static inline int rb_threadptr_tag_state(rb_thread_t *th) { - enum ruby_tag_type state = th->ec.tag->state; - th->ec.tag->state = TAG_NONE; + enum ruby_tag_type state = th->ec->tag->state; + th->ec->tag->state = TAG_NONE; return state; } @@ -187,8 +187,8 @@ NORETURN(static inline void rb_threadptr_tag_jump(rb_thread_t *, enum ruby_tag_t static inline void rb_threadptr_tag_jump(rb_thread_t *th, enum ruby_tag_type st) { - th->ec.tag->state = st; - ruby_longjmp(th->ec.tag->buf, 1); + th->ec->tag->state = st; + ruby_longjmp(th->ec->tag->buf, 1); } /* @@ -282,10 +282,10 @@ enum { }; int rb_threadptr_set_raised(rb_thread_t *th); int rb_threadptr_reset_raised(rb_thread_t *th); -#define rb_thread_raised_set(th, f) ((th)->ec.raised_flag |= (f)) -#define rb_thread_raised_reset(th, f) ((th)->ec.raised_flag &= ~(f)) -#define rb_thread_raised_p(th, f) (((th)->ec.raised_flag & (f)) != 0) -#define rb_thread_raised_clear(th) ((th)->ec.raised_flag = 0) +#define rb_thread_raised_set(th, f) ((th)->ec->raised_flag |= (f)) +#define rb_thread_raised_reset(th, f) ((th)->ec->raised_flag &= ~(f)) +#define rb_thread_raised_p(th, f) (((th)->ec->raised_flag & (f)) != 0) +#define rb_thread_raised_clear(th) ((th)->ec->raised_flag = 0) int rb_threadptr_stack_check(rb_thread_t *th); VALUE rb_f_eval(int argc, const VALUE *argv, VALUE self); diff --git a/eval_jump.c b/eval_jump.c index 22722719b5..bc3c857c2c 100644 --- a/eval_jump.c +++ b/eval_jump.c @@ -116,26 +116,26 @@ rb_exec_end_proc(void) enum ruby_tag_type state; volatile int safe = rb_safe_level(); rb_thread_t *th = GET_THREAD(); - volatile VALUE errinfo = th->ec.errinfo; + volatile VALUE errinfo = th->ec->errinfo; TH_PUSH_TAG(th); if ((state = EXEC_TAG()) == TAG_NONE) { again: - exec_end_procs_chain(&ephemeral_end_procs, &th->ec.errinfo); - exec_end_procs_chain(&end_procs, &th->ec.errinfo); + exec_end_procs_chain(&ephemeral_end_procs, &th->ec->errinfo); + exec_end_procs_chain(&end_procs, &th->ec->errinfo); } else { VAR_INITIALIZED(th); TH_TMPPOP_TAG(); error_handle(state); - if (!NIL_P(th->ec.errinfo)) errinfo = th->ec.errinfo; + if (!NIL_P(th->ec->errinfo)) errinfo = th->ec->errinfo; TH_REPUSH_TAG(); goto again; } TH_POP_TAG(); rb_set_safe_level_force(safe); - th->ec.errinfo = errinfo; + th->ec->errinfo = errinfo; } void diff --git a/gc.c b/gc.c index 2b9d5b1029..f2afe8499e 100644 --- a/gc.c +++ b/gc.c @@ -1812,7 +1812,7 @@ rb_objspace_set_event_hook(const rb_event_flag_t event) static void gc_event_hook_body(rb_thread_t *th, rb_objspace_t *objspace, const rb_event_flag_t event, VALUE data) { - EXEC_EVENT_HOOK(th, event, th->ec.cfp->self, 0, 0, 0, data); + EXEC_EVENT_HOOK(th, event, th->ec->cfp->self, 0, 0, 0, data); } #define gc_event_hook_available_p(objspace) ((objspace)->flags.has_hook) @@ -2784,16 +2784,16 @@ run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table) long finished; int safe; } saved; - rb_thread_t *const th = GET_THREAD(); + rb_thread_t *const volatile th = GET_THREAD(); #define RESTORE_FINALIZER() (\ - th->ec.cfp = saved.cfp, \ + th->ec->cfp = saved.cfp, \ rb_set_safe_level_force(saved.safe), \ rb_set_errinfo(saved.errinfo)) saved.safe = rb_safe_level(); saved.errinfo = rb_errinfo(); saved.objid = nonspecial_obj_id(obj); - saved.cfp = th->ec.cfp; + saved.cfp = th->ec->cfp; saved.finished = 0; TH_PUSH_TAG(th); @@ -4001,7 +4001,7 @@ ruby_get_stack_grow_direction(volatile VALUE *addr) size_t ruby_stack_length(VALUE **p) { - rb_execution_context_t *ec = &GET_THREAD()->ec; + 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; @@ -4019,7 +4019,7 @@ ruby_stack_length(VALUE **p) static int stack_check(rb_thread_t *th, int water_mark) { - rb_execution_context_t *ec = &th->ec; + rb_execution_context_t *ec = th->ec; int ret; SET_STACK_END; ret = STACK_LENGTH > STACK_LEVEL_MAX - water_mark; @@ -4784,7 +4784,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; + rb_execution_context_t *ec = th->ec; #if PRINT_ROOT_TICKS tick_t start_tick = tick(); @@ -4831,7 +4831,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->ec); + mark_current_machine_context(objspace, th->ec); MARK_CHECKPOINT("encodings"); rb_gc_mark_encodings(); @@ -7712,7 +7712,7 @@ rb_memerror(void) rb_thread_raised_set(th, RAISED_NOMEMORY); exc = ruby_vm_special_exception_copy(exc); } - th->ec.errinfo = exc; + th->ec->errinfo = exc; TH_JUMP_TAG(th, TAG_RAISE); } diff --git a/insns.def b/insns.def index ef229ddef4..e7e4ffd5ec 100644 --- a/insns.def +++ b/insns.def @@ -1678,8 +1678,8 @@ opt_call_c_function reg_cfp = (funcptr)(th, reg_cfp); if (reg_cfp == 0) { - VALUE err = th->ec.errinfo; - th->ec.errinfo = Qnil; + VALUE err = th->ec->errinfo; + th->ec->errinfo = Qnil; THROW_EXCEPTION(err); } diff --git a/internal.h b/internal.h index 25fcf238f4..fb1f64bb9e 100644 --- a/internal.h +++ b/internal.h @@ -1721,7 +1721,6 @@ VALUE rb_uninterruptible(VALUE (*b_proc)(ANYARGS), VALUE data); VALUE rb_mutex_owned_p(VALUE self); /* thread_pthread.c, thread_win32.c */ -void Init_native_thread(void); int rb_divert_reserved_fd(int fd); /* transcode.c */ diff --git a/iseq.c b/iseq.c index ccea4f1549..6b3379430c 100644 --- a/iseq.c +++ b/iseq.c @@ -663,7 +663,7 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, c } if (!node) { - rb_exc_raise(th->ec.errinfo); + rb_exc_raise(th->ec->errinfo); } else { INITIALIZED VALUE label = parent ? @@ -870,7 +870,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self) parser = rb_parser_new(); rb_parser_set_context(parser, NULL, FALSE); node = rb_parser_compile_file_path(parser, file, f, NUM2INT(line)); - if (!node) exc = GET_THREAD()->ec.errinfo; + if (!node) exc = GET_THREAD()->ec->errinfo; rb_io_close(f); if (!node) rb_exc_raise(exc); diff --git a/load.c b/load.c index d2ed55fed2..04882b9d1f 100644 --- a/load.c +++ b/load.c @@ -587,7 +587,7 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap) rb_thread_t *volatile th0 = th; #endif - th->ec.errinfo = Qnil; /* ensure */ + th->ec->errinfo = Qnil; /* ensure */ if (!wrap) { th->top_wrapper = 0; @@ -631,11 +631,11 @@ rb_load_internal0(rb_thread_t *th, VALUE fname, int wrap) * rb_iseq_load_iseq case */ VALUE exc = rb_vm_make_jump_tag_but_local_jump(state, Qundef); if (NIL_P(exc)) return state; - th->ec.errinfo = exc; + th->ec->errinfo = exc; return TAG_RAISE; } - if (!NIL_P(th->ec.errinfo)) { + if (!NIL_P(th->ec->errinfo)) { /* exception during load */ return TAG_RAISE; } @@ -648,7 +648,7 @@ rb_load_internal(VALUE fname, int wrap) rb_thread_t *curr_th = GET_THREAD(); int state = rb_load_internal0(curr_th, fname, wrap); if (state) { - if (state == TAG_RAISE) rb_exc_raise(curr_th->ec.errinfo); + if (state == TAG_RAISE) rb_exc_raise(curr_th->ec->errinfo); TH_JUMP_TAG(curr_th, state); } } @@ -963,7 +963,7 @@ rb_require_internal(VALUE fname, int safe) { volatile int result = -1; rb_thread_t *th = GET_THREAD(); - volatile VALUE errinfo = th->ec.errinfo; + volatile VALUE errinfo = th->ec->errinfo; enum ruby_tag_type state; struct { int safe; @@ -1024,7 +1024,7 @@ rb_require_internal(VALUE fname, int safe) return state; } - th->ec.errinfo = errinfo; + th->ec->errinfo = errinfo; RUBY_DTRACE_HOOK(REQUIRE_RETURN, RSTRING_PTR(fname)); diff --git a/proc.c b/proc.c index e8f2d411cd..3d943ba6f5 100644 --- a/proc.c +++ b/proc.c @@ -333,7 +333,7 @@ VALUE rb_binding_new(void) { rb_thread_t *th = GET_THREAD(); - return rb_vm_make_binding(th, th->ec.cfp); + return rb_vm_make_binding(th, th->ec->cfp); } /* @@ -698,7 +698,7 @@ proc_new(VALUE klass, int8_t is_lambda) { VALUE procval; rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; VALUE block_handler; if ((block_handler = rb_vm_frame_block_handler(cfp)) == VM_BLOCK_HANDLER_NONE) { @@ -1049,7 +1049,7 @@ rb_block_arity(void) { int min, max; rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; VALUE block_handler = rb_vm_frame_block_handler(cfp); struct rb_block block; @@ -1082,7 +1082,7 @@ int rb_block_min_max_arity(int *max) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; VALUE block_handler = rb_vm_frame_block_handler(cfp); struct rb_block block; @@ -1911,7 +1911,7 @@ rb_mod_define_method(int argc, VALUE *argv, VALUE mod) body = rb_block_lambda(); #else rb_thread_t *th = GET_THREAD(); - VALUE block_handler = rb_vm_frame_block_handler(th->ec.cfp); + VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp); if (block_handler == VM_BLOCK_HANDLER_NONE) rb_raise(rb_eArgError, proc_without_block); switch (vm_block_handler_type(block_handler)) { diff --git a/process.c b/process.c index d915478122..ff289435bf 100644 --- a/process.c +++ b/process.c @@ -3765,7 +3765,7 @@ rb_f_exit_bang(int argc, VALUE *argv, VALUE obj) void rb_exit(int status) { - if (GET_THREAD()->ec.tag) { + if (GET_THREAD()->ec->tag) { VALUE args[2]; args[0] = INT2NUM(status); @@ -3851,7 +3851,7 @@ rb_f_abort(int argc, const VALUE *argv) rb_check_arity(argc, 0, 1); if (argc == 0) { rb_thread_t *th = GET_THREAD(); - VALUE errinfo = th->ec.errinfo; + VALUE errinfo = th->ec->errinfo; if (!NIL_P(errinfo)) { rb_threadptr_error_print(th, errinfo); } diff --git a/safe.c b/safe.c index 2e1ac8b529..d1368d7f5f 100644 --- a/safe.c +++ b/safe.c @@ -34,13 +34,13 @@ ruby_safe_level_2_warning(void) int rb_safe_level(void) { - return GET_THREAD()->ec.safe_level; + return GET_THREAD()->ec->safe_level; } void rb_set_safe_level_force(int safe) { - GET_THREAD()->ec.safe_level = safe; + GET_THREAD()->ec->safe_level = safe; } void @@ -48,11 +48,11 @@ rb_set_safe_level(int level) { rb_thread_t *th = GET_THREAD(); - if (level > th->ec.safe_level) { + if (level > th->ec->safe_level) { if (level > SAFE_LEVEL_MAX) { rb_raise(rb_eArgError, "$SAFE=2 to 4 are obsolete"); } - th->ec.safe_level = level; + th->ec->safe_level = level; } } @@ -66,7 +66,7 @@ static void safe_setter(VALUE val) { rb_thread_t *th = GET_THREAD(); - int current_level = th->ec.safe_level; + int current_level = th->ec->safe_level; int level = NUM2INT(val); if (level == current_level) { @@ -84,7 +84,7 @@ safe_setter(VALUE val) /* block parameters */ rb_vm_stack_to_heap(th); - th->ec.safe_level = level; + th->ec->safe_level = level; } void diff --git a/signal.c b/signal.c index 78e31e92b0..3aaa988c25 100644 --- a/signal.c +++ b/signal.c @@ -838,13 +838,13 @@ check_stack_overflow(int sig, const uintptr_t addr, const ucontext_t *ctx) * the fault page can be the next. */ if (sp_page == fault_page || sp_page == fault_page + 1 || sp_page <= fault_page && fault_page <= bp_page) { - rb_thread_t *th = ruby_current_thread; + rb_thread_t *th = ruby_current_thread(); int crit = FALSE; - if ((uintptr_t)th->ec.tag->buf / pagesize <= fault_page + 1) { + if ((uintptr_t)th->ec->tag->buf / pagesize <= fault_page + 1) { /* drop the last tag if it is close to the fault, * otherwise it can cause stack overflow again at the same * place. */ - th->ec.tag = th->ec.tag->prev; + th->ec->tag = th->ec->tag->prev; crit = TRUE; } reset_sigmask(sig); @@ -856,7 +856,7 @@ static void check_stack_overflow(int sig, const void *addr) { int ruby_stack_overflowed_p(const rb_thread_t *, const void *); - rb_thread_t *th = ruby_current_thread; + rb_thread_t *th = GET_THREAD(); if (ruby_stack_overflowed_p(th, addr)) { reset_sigmask(sig); rb_threadptr_stack_overflow(th, FALSE); diff --git a/thread.c b/thread.c index 1815d9971b..caa8686b6f 100644 --- a/thread.c +++ b/thread.c @@ -139,8 +139,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)->ec.machine.regs); \ - SET_MACHINE_STACK_END(&(th)->ec.machine.stack_end); \ + setjmp((th)->ec->machine.regs); \ + SET_MACHINE_STACK_END(&(th)->ec->machine.stack_end); \ } while (0) #define GVL_UNLOCK_BEGIN() do { \ @@ -526,9 +526,9 @@ thread_cleanup_func_before_exec(void *th_ptr) { rb_thread_t *th = th_ptr; th->status = THREAD_KILLED; - th->ec.machine.stack_start = th->ec.machine.stack_end = NULL; + th->ec->machine.stack_start = th->ec->machine.stack_end = NULL; #ifdef __ia64 - th->ec.machine.register_stack_start = th->ec.machine.register_stack_end = NULL; + th->ec->machine.register_stack_start = th->ec->machine.register_stack_end = NULL; #endif } @@ -581,9 +581,9 @@ thread_do_start(rb_thread_t *th, VALUE args) if (!th->first_func) { rb_proc_t *proc; GetProcPtr(th->first_proc, proc); - th->ec.errinfo = Qnil; - th->ec.root_lep = rb_vm_proc_local_ep(th->first_proc); - th->ec.root_svar = Qfalse; + th->ec->errinfo = Qnil; + th->ec->root_lep = rb_vm_proc_local_ep(th->first_proc); + th->ec->root_svar = Qfalse; EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_BEGIN, th->self, 0, 0, 0, Qundef); th->value = rb_vm_invoke_proc(th, proc, (int)RARRAY_LEN(args), RARRAY_CONST_PTR(args), @@ -614,9 +614,9 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s ruby_thread_set_native(th); - th->ec.machine.stack_start = stack_start; + th->ec->machine.stack_start = stack_start; #ifdef __ia64 - th->ec.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); @@ -630,7 +630,7 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s SAVE_ROOT_JMPBUF(th, thread_do_start(th, args)); } else { - errinfo = th->ec.errinfo; + errinfo = th->ec->errinfo; if (state == TAG_FATAL) { /* fatal error within this thread, need to stop whole script */ } @@ -696,8 +696,7 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s rb_threadptr_unlock_all_locking_mutexes(th); rb_check_deadlock(th->vm); - rb_thread_recycle_stack_release(th->ec.vm_stack); - th->ec.vm_stack = NULL; + rb_fiber_close(th->ec->fiber); } native_mutex_lock(&th->vm->thread_destruct_lock); /* make sure vm->running_thread never point me after this point.*/ @@ -923,8 +922,8 @@ thread_join(rb_thread_t *target_th, double delay) thread_debug("thread_join: success (thid: %"PRI_THREAD_ID")\n", thread_id_str(target_th)); - if (target_th->ec.errinfo != Qnil) { - VALUE err = target_th->ec.errinfo; + if (target_th->ec->errinfo != Qnil) { + VALUE err = target_th->ec->errinfo; if (FIXNUM_P(err)) { switch (err) { @@ -935,7 +934,7 @@ thread_join(rb_thread_t *target_th, double delay) rb_bug("thread_join: Fixnum (%d) should not reach here.", FIX2INT(err)); } } - else if (THROW_DATA_P(target_th->ec.errinfo)) { + else if (THROW_DATA_P(target_th->ec->errinfo)) { rb_bug("thread_join: THROW_DATA should not reach here."); } else { @@ -1437,7 +1436,7 @@ rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd) { volatile VALUE val = Qundef; /* shouldn't be used */ rb_vm_t *vm = GET_VM(); - rb_thread_t *th = GET_THREAD(); + rb_thread_t *volatile th = GET_THREAD(); volatile int saved_errno = 0; enum ruby_tag_type state; struct waiting_fd wfd; @@ -1858,7 +1857,7 @@ static VALUE rb_thread_s_handle_interrupt(VALUE self, VALUE mask_arg) { VALUE mask; - rb_thread_t *th = GET_THREAD(); + rb_thread_t * volatile th = GET_THREAD(); volatile VALUE r = Qnil; enum ruby_tag_type state; @@ -2008,7 +2007,7 @@ rb_threadptr_to_kill(rb_thread_t *th) rb_threadptr_pending_interrupt_clear(th); th->status = THREAD_RUNNABLE; th->to_kill = 1; - th->ec.errinfo = INT2FIX(TAG_FATAL); + th->ec->errinfo = INT2FIX(TAG_FATAL); TH_JUMP_TAG(th, TAG_FATAL); } @@ -2031,7 +2030,7 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) rb_atomic_t interrupt; int postponed_job_interrupt = 0; - if (th->ec.raised_flag) return; + if (th->ec->raised_flag) return; while ((interrupt = threadptr_get_interrupts(th)) != 0) { int sig; @@ -2095,7 +2094,7 @@ rb_threadptr_execute_interrupts(rb_thread_t *th, int blocking_timing) if (th->status == THREAD_RUNNABLE) th->running_time_us += TIME_QUANTUM_USEC; - EXEC_EVENT_HOOK(th, RUBY_INTERNAL_EVENT_SWITCH, th->ec.cfp->self, + EXEC_EVENT_HOOK(th, RUBY_INTERNAL_EVENT_SWITCH, th->ec->cfp->self, 0, 0, 0, Qundef); rb_thread_schedule_limits(limits_us); @@ -2172,20 +2171,20 @@ rb_threadptr_signal_exit(rb_thread_t *th) int rb_threadptr_set_raised(rb_thread_t *th) { - if (th->ec.raised_flag & RAISED_EXCEPTION) { + if (th->ec->raised_flag & RAISED_EXCEPTION) { return 1; } - th->ec.raised_flag |= RAISED_EXCEPTION; + th->ec->raised_flag |= RAISED_EXCEPTION; return 0; } int rb_threadptr_reset_raised(rb_thread_t *th) { - if (!(th->ec.raised_flag & RAISED_EXCEPTION)) { + if (!(th->ec->raised_flag & RAISED_EXCEPTION)) { return 0; } - th->ec.raised_flag &= ~RAISED_EXCEPTION; + th->ec->raised_flag &= ~RAISED_EXCEPTION; return 1; } @@ -2822,8 +2821,8 @@ rb_thread_status(VALUE thread) rb_thread_t *target_th = rb_thread_ptr(thread); if (rb_threadptr_dead(target_th)) { - if (!NIL_P(target_th->ec.errinfo) && - !FIXNUM_P(target_th->ec.errinfo)) { + if (!NIL_P(target_th->ec->errinfo) && + !FIXNUM_P(target_th->ec->errinfo)) { return Qnil; } else { @@ -2907,7 +2906,7 @@ rb_thread_stop_p(VALUE thread) static VALUE rb_thread_safe_level(VALUE thread) { - return INT2NUM(rb_thread_ptr(thread)->ec.safe_level); + return INT2NUM(rb_thread_ptr(thread)->ec->safe_level); } /* @@ -2994,11 +2993,11 @@ static VALUE threadptr_local_aref(rb_thread_t *th, ID id) { if (id == recursive_key) { - return th->ec.local_storage_recursive_hash; + return th->ec->local_storage_recursive_hash; } else { st_data_t val; - st_table *local_storage = th->ec.local_storage; + st_table *local_storage = th->ec->local_storage; if (local_storage != NULL && st_lookup(local_storage, id, &val)) { return (VALUE)val; @@ -3102,10 +3101,10 @@ rb_thread_fetch(int argc, VALUE *argv, VALUE self) id = rb_check_id(&key); if (id == recursive_key) { - return target_th->ec.local_storage_recursive_hash; + return target_th->ec->local_storage_recursive_hash; } - else if (id && target_th->ec.local_storage && - st_lookup(target_th->ec.local_storage, id, &val)) { + else if (id && target_th->ec->local_storage && + st_lookup(target_th->ec->local_storage, id, &val)) { return val; } else if (block_given) { @@ -3123,11 +3122,11 @@ static VALUE threadptr_local_aset(rb_thread_t *th, ID id, VALUE val) { if (id == recursive_key) { - th->ec.local_storage_recursive_hash = val; + th->ec->local_storage_recursive_hash = val; return val; } else { - st_table *local_storage = th->ec.local_storage; + st_table *local_storage = th->ec->local_storage; if (NIL_P(val)) { if (!local_storage) return Qnil; @@ -3136,7 +3135,7 @@ threadptr_local_aset(rb_thread_t *th, ID id, VALUE val) } else { if (local_storage == NULL) { - th->ec.local_storage = local_storage = st_init_numtable(); + th->ec->local_storage = local_storage = st_init_numtable(); } st_insert(local_storage, id, val); return val; @@ -3249,7 +3248,7 @@ static VALUE rb_thread_key_p(VALUE self, VALUE key) { ID id = rb_check_id(&key); - st_table *local_storage = rb_thread_ptr(self)->ec.local_storage; + st_table *local_storage = rb_thread_ptr(self)->ec->local_storage; if (!id || local_storage == NULL) { return Qfalse; @@ -3292,7 +3291,7 @@ rb_thread_alone(void) static VALUE rb_thread_keys(VALUE self) { - st_table *local_storage = rb_thread_ptr(self)->ec.local_storage; + st_table *local_storage = rb_thread_ptr(self)->ec->local_storage; VALUE ary = rb_ary_new(); if (local_storage) { @@ -4481,13 +4480,13 @@ rb_thread_shield_destroy(VALUE self) static VALUE threadptr_recursive_hash(rb_thread_t *th) { - return th->ec.local_storage_recursive_hash; + return th->ec->local_storage_recursive_hash; } static void threadptr_recursive_hash_set(rb_thread_t *th, VALUE hash) { - th->ec.local_storage_recursive_hash = hash; + th->ec->local_storage_recursive_hash = hash; } ID rb_frame_last_func(void); @@ -4982,7 +4981,7 @@ rb_check_deadlock(rb_vm_t *vm) static void update_coverage(VALUE data, const rb_trace_arg_t *trace_arg) { - VALUE coverage = rb_iseq_coverage(GET_THREAD()->ec.cfp->iseq); + VALUE coverage = rb_iseq_coverage(GET_THREAD()->ec->cfp->iseq); if (RB_TYPE_P(coverage, T_ARRAY) && !RBASIC_CLASS(coverage)) { long arg = FIX2INT(trace_arg->data); switch (arg % 16) { diff --git a/thread_pthread.c b/thread_pthread.c index 83eb721a76..968d7e1f86 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -446,10 +446,8 @@ ruby_thread_set_native(rb_thread_t *th) static void native_thread_init(rb_thread_t *th); void -Init_native_thread(void) +Init_native_thread(rb_thread_t *th) { - rb_thread_t *th = GET_THREAD(); - pthread_key_create(&ruby_native_thread_key, NULL); th->thread_id = pthread_self(); fill_thread_id_str(th); @@ -827,8 +825,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->ec.machine.stack_start = native_main_thread.stack_start; - th->ec.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 @@ -837,11 +835,11 @@ native_thread_init_stack(rb_thread_t *th) if (get_stack(&start, &size) == 0) { uintptr_t diff = (uintptr_t)start - (uintptr_t)&curr; - th->ec.machine.stack_start = (VALUE *)&curr; - th->ec.machine.stack_maxsize = size - diff; + th->ec->machine.stack_start = (VALUE *)&curr; + th->ec->machine.stack_maxsize = size - diff; } #elif defined get_stack_of - if (!th->ec.machine.stack_maxsize) { + if (!th->ec->machine.stack_maxsize) { native_mutex_lock(&th->interrupt_lock); native_mutex_unlock(&th->interrupt_lock); } @@ -850,9 +848,9 @@ native_thread_init_stack(rb_thread_t *th) #endif } #ifdef __ia64 - 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; + 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; } @@ -880,7 +878,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->ec.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 @@ -1002,10 +1000,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->ec.machine.stack_maxsize = stack_size - space; + th->ec->machine.stack_maxsize = stack_size - space; #ifdef __ia64 - th->ec.machine.stack_maxsize /= 2; - th->ec.machine.register_stack_maxsize = th->ec.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 @@ -1028,8 +1026,8 @@ native_thread_create(rb_thread_t *th) #ifdef get_stack_of if (!err) { get_stack_of(th->thread_id, - &th->ec.machine.stack_start, - &th->ec.machine.stack_maxsize); + &th->ec->machine.stack_start, + &th->ec->machine.stack_maxsize); } native_mutex_unlock(&th->interrupt_lock); #endif @@ -1745,8 +1743,8 @@ ruby_stack_overflowed_p(const rb_thread_t *th, const void *addr) else #endif if (th) { - size = th->ec.machine.stack_maxsize; - base = (char *)th->ec.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 683fafc5ba..2e101b4368 100644 --- a/thread_win32.c +++ b/thread_win32.c @@ -140,10 +140,8 @@ ruby_thread_set_native(rb_thread_t *th) } void -Init_native_thread(void) +Init_native_thread(rb_thread_t *th) { - rb_thread_t *th = GET_THREAD(); - ruby_native_thread_key = TlsAlloc(); ruby_thread_set_native(th); DuplicateHandle(GetCurrentProcess(), @@ -546,8 +544,8 @@ native_thread_init_stack(rb_thread_t *th) size = end - base; space = size / 5; if (space > 1024*1024) space = 1024*1024; - th->ec.machine.stack_start = (VALUE *)end - 1; - th->ec.machine.stack_maxsize = size - space; + th->ec->machine.stack_start = (VALUE *)end - 1; + th->ec->machine.stack_maxsize = size - space; } #ifndef InterlockedExchangePointer @@ -575,7 +573,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->ec.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 7c8bba9af4..c6f670bdc7 100644 --- a/vm.c +++ b/vm.c @@ -88,8 +88,8 @@ rb_vm_frame_block_handler(const rb_control_frame_t *cfp) static int VM_CFP_IN_HEAP_P(const rb_thread_t *th, const rb_control_frame_t *cfp) { - const VALUE *start = th->ec.vm_stack; - const VALUE *end = (VALUE *)th->ec.vm_stack + th->ec.vm_stack_size; + const VALUE *start = th->ec->vm_stack; + const VALUE *end = (VALUE *)th->ec->vm_stack + th->ec->vm_stack_size; VM_ASSERT(start != NULL); if (start <= (VALUE *)cfp && (VALUE *)cfp < end) { @@ -138,7 +138,9 @@ vm_ep_in_heap_p_(const rb_execution_context_t *ec, const VALUE *ep) int rb_vm_ep_in_heap_p(const VALUE *ep) { - return vm_ep_in_heap_p_(&GET_THREAD()->ec, ep); + rb_thread_t *th = GET_THREAD(); + if (th->ec->vm_stack == NULL) return TRUE; + return vm_ep_in_heap_p_(th->ec, ep); } #endif @@ -317,8 +319,8 @@ VALUE rb_mRubyVMFrozenCore; #define ruby_vm_redefined_flag GET_VM()->redefined_flag VALUE ruby_vm_const_missing_count = 0; -rb_thread_t *ruby_current_thread = 0; -rb_vm_t *ruby_current_vm = 0; +rb_vm_t *ruby_current_vm_ptr = NULL; +rb_execution_context_t *ruby_current_execution_context_ptr = NULL; rb_event_flag_t ruby_vm_event_flags; rb_serial_t ruby_vm_global_method_state = 1; rb_serial_t ruby_vm_global_constant_state = 1; @@ -450,7 +452,7 @@ vm_set_top_stack(rb_thread_t *th, const rb_iseq_t *iseq) vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH, th->top_self, VM_BLOCK_HANDLER_NONE, (VALUE)vm_cref_new_toplevel(th), /* cref or me */ - iseq->body->iseq_encoded, th->ec.cfp->sp, + iseq->body->iseq_encoded, th->ec->cfp->sp, iseq->body->local_table_size, iseq->body->stack_max); } @@ -461,7 +463,7 @@ vm_set_eval_stack(rb_thread_t * th, const rb_iseq_t *iseq, const rb_cref_t *cref vm_block_self(base_block), VM_GUARDED_PREV_EP(vm_block_ep(base_block)), (VALUE)cref, /* cref or me */ iseq->body->iseq_encoded, - th->ec.cfp->sp, iseq->body->local_table_size, + th->ec->cfp->sp, iseq->body->local_table_size, iseq->body->stack_max); } @@ -478,7 +480,7 @@ vm_set_main_stack(rb_thread_t *th, const rb_iseq_t *iseq) /* save binding */ if (iseq->body->local_table_size > 0) { - vm_bind_update_env(toplevel_binding, bind, vm_make_env_object(th, th->ec.cfp)); + vm_bind_update_env(toplevel_binding, bind, vm_make_env_object(th, th->ec->cfp)); } } @@ -532,7 +534,7 @@ void rb_vm_pop_cfunc_frame(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp); EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, cfp->self, me->def->original_id, me->called_id, me->owner, Qnil); @@ -544,11 +546,11 @@ void rb_vm_rewind_cfp(rb_thread_t *th, rb_control_frame_t *cfp) { /* check skipped frame */ - while (th->ec.cfp != cfp) { + while (th->ec->cfp != cfp) { #if VMDEBUG - printf("skipped frame: %s\n", vm_frametype_name(th->ec.cfp)); + printf("skipped frame: %s\n", vm_frametype_name(th->ec->cfp)); #endif - if (VM_FRAME_TYPE(th->ec.cfp) != VM_FRAME_MAGIC_CFUNC) { + if (VM_FRAME_TYPE(th->ec->cfp) != VM_FRAME_MAGIC_CFUNC) { rb_vm_pop_frame(th); } else { /* unlikely path */ @@ -730,7 +732,7 @@ vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp) void rb_vm_stack_to_heap(rb_thread_t *th) { - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; while ((cfp = rb_vm_get_binding_creatable_next_cfp(th, cfp)) != 0) { vm_make_env_object(th, cfp); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); @@ -812,7 +814,7 @@ rb_proc_create_from_captured(VALUE klass, VALUE procval = rb_proc_alloc(klass); rb_proc_t *proc = RTYPEDDATA_DATA(procval); - VM_ASSERT(VM_EP_IN_HEAP_P(&GET_THREAD()->ec, captured->ep)); + VM_ASSERT(VM_EP_IN_HEAP_P(GET_THREAD()->ec, captured->ep)); /* copy block */ RB_OBJ_WRITE(procval, &proc->block.as.captured.self, captured->self); @@ -854,7 +856,7 @@ rb_proc_create(VALUE klass, const struct rb_block *block, VALUE procval = rb_proc_alloc(klass); rb_proc_t *proc = RTYPEDDATA_DATA(procval); - VM_ASSERT(VM_EP_IN_HEAP_P(&GET_THREAD()->ec, vm_block_ep(block))); + VM_ASSERT(VM_EP_IN_HEAP_P(GET_THREAD()->ec, vm_block_ep(block))); rb_vm_block_copy(procval, &proc->block, block); vm_block_type_set(&proc->block, block->type); proc->safe_level = safe_level; @@ -879,13 +881,13 @@ rb_vm_make_proc_lambda(rb_thread_t *th, const struct rb_captured_block *captured rb_control_frame_t *cfp = VM_CAPTURED_BLOCK_TO_CFP(captured); vm_make_env_object(th, cfp); } - VM_ASSERT(VM_EP_IN_HEAP_P(&th->ec, captured->ep)); + VM_ASSERT(VM_EP_IN_HEAP_P(th->ec, captured->ep)); VM_ASSERT(imemo_type_p(captured->code.val, imemo_iseq) || imemo_type_p(captured->code.val, imemo_ifunc)); procval = rb_proc_create_from_captured(klass, captured, imemo_type(captured->code.val) == imemo_iseq ? block_type_iseq : block_type_ifunc, - (int8_t)th->ec.safe_level, FALSE, is_lambda); + (int8_t)th->ec->safe_level, FALSE, is_lambda); return procval; } @@ -959,7 +961,7 @@ rb_binding_add_dynavars(VALUE bindval, rb_binding_t *bind, int dyncount, const I ALLOCV_END(idtmp); vm_set_eval_stack(th, iseq, 0, base_block); - vm_bind_update_env(bindval, bind, envval = vm_make_env_object(th, th->ec.cfp)); + vm_bind_update_env(bindval, bind, envval = vm_make_env_object(th, th->ec->cfp)); rb_vm_pop_frame(th); env = (const rb_env_t *)envval; @@ -977,7 +979,7 @@ invoke_block(rb_thread_t *th, const rb_iseq_t *iseq, VALUE self, const struct rb VM_GUARDED_PREV_EP(captured->ep), (VALUE)cref, /* cref or method */ iseq->body->iseq_encoded + opt_pc, - th->ec.cfp->sp + arg_size, + th->ec->cfp->sp + arg_size, iseq->body->local_table_size - arg_size, iseq->body->stack_max); return vm_exec(th); @@ -994,13 +996,13 @@ invoke_bmethod(rb_thread_t *th, const rb_iseq_t *iseq, VALUE self, const struct VM_GUARDED_PREV_EP(captured->ep), (VALUE)me, iseq->body->iseq_encoded + opt_pc, - th->ec.cfp->sp + arg_size, + th->ec->cfp->sp + arg_size, iseq->body->local_table_size - arg_size, iseq->body->stack_max); RUBY_DTRACE_METHOD_ENTRY_HOOK(th, me->owner, me->def->original_id); EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, self, me->def->original_id, me->called_id, me->owner, Qnil); - VM_ENV_FLAGS_SET(th->ec.cfp->ep, VM_FRAME_FLAG_FINISH); + VM_ENV_FLAGS_SET(th->ec->cfp->ep, VM_FRAME_FLAG_FINISH); ret = vm_exec(th); EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, self, me->def->original_id, me->called_id, me->owner, ret); RUBY_DTRACE_METHOD_RETURN_HOOK(th, me->owner, me->def->original_id); @@ -1015,7 +1017,7 @@ invoke_iseq_block_from_c(rb_thread_t *th, const struct rb_captured_block *captur const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq); int i, opt_pc; VALUE type = VM_FRAME_MAGIC_BLOCK | (is_lambda ? VM_FRAME_FLAG_LAMBDA : 0); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; VALUE *sp = cfp->sp; const rb_callable_method_entry_t *me = th->passed_bmethod_me; th->passed_bmethod_me = NULL; @@ -1075,7 +1077,7 @@ invoke_block_from_c_bh(rb_thread_t *th, VALUE block_handler, static inline VALUE check_block_handler(rb_thread_t *th) { - VALUE block_handler = VM_CF_BLOCK_HANDLER(th->ec.cfp); + VALUE block_handler = VM_CF_BLOCK_HANDLER(th->ec->cfp); vm_block_handler_verify(block_handler); if (UNLIKELY(block_handler == VM_BLOCK_HANDLER_NONE)) { rb_vm_localjump_error("no block given", Qnil, 0); @@ -1145,16 +1147,16 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, { VALUE val = Qundef; enum ruby_tag_type state; - volatile int stored_safe = th->ec.safe_level; + volatile int stored_safe = th->ec->safe_level; TH_PUSH_TAG(th); if ((state = EXEC_TAG()) == TAG_NONE) { - th->ec.safe_level = proc->safe_level; + th->ec->safe_level = proc->safe_level; val = invoke_block_from_c_proc(th, proc, self, argc, argv, passed_block_handler, proc->is_lambda); } TH_POP_TAG(); - th->ec.safe_level = stored_safe; + th->ec->safe_level = stored_safe; if (state) { TH_JUMP_TAG(th, state); @@ -1216,14 +1218,14 @@ static VALUE vm_svar_get(VALUE key) { rb_thread_t *th = GET_THREAD(); - return vm_cfp_svar_get(th, th->ec.cfp, key); + return vm_cfp_svar_get(th, th->ec->cfp, key); } static void vm_svar_set(VALUE key, VALUE val) { rb_thread_t *th = GET_THREAD(); - vm_cfp_svar_set(th, th->ec.cfp, key, val); + vm_cfp_svar_set(th, th->ec->cfp, key, val); } VALUE @@ -1256,7 +1258,7 @@ VALUE rb_sourcefilename(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (cfp) { return rb_iseq_path(cfp->iseq); @@ -1270,7 +1272,7 @@ const char * rb_sourcefile(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (cfp) { return RSTRING_PTR(rb_iseq_path(cfp->iseq)); @@ -1284,7 +1286,7 @@ int rb_sourceline(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (cfp) { return rb_vm_get_sourceline(cfp); @@ -1298,7 +1300,7 @@ VALUE rb_source_location(int *pline) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (cfp) { if (pline) *pline = rb_vm_get_sourceline(cfp); @@ -1322,7 +1324,7 @@ rb_cref_t * rb_vm_cref(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (cfp == NULL) { return NULL; @@ -1335,7 +1337,7 @@ rb_cref_t * rb_vm_cref_replace_with_duplicated_cref(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); rb_cref_t *cref = vm_cref_replace_with_duplicated_cref(cfp->ep); return cref; } @@ -1344,7 +1346,7 @@ const rb_cref_t * rb_vm_cref_in_context(VALUE self, VALUE cbase) { rb_thread_t *th = GET_THREAD(); - const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); const rb_cref_t *cref; if (cfp->self != self) return NULL; if (!vm_env_cref_by_cref(cfp->ep)) return NULL; @@ -1369,7 +1371,7 @@ VALUE rb_vm_cbase(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (cfp == 0) { rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread"); @@ -1445,7 +1447,7 @@ rb_vm_make_jump_tag_but_local_jump(int state, VALUE val) return Qnil; } if (val == Qundef) { - val = GET_THREAD()->ec.tag->retval; + val = GET_THREAD()->ec->tag->retval; } return make_localjump_error(mesg, val, state); } @@ -1474,7 +1476,7 @@ next_not_local_frame(rb_control_frame_t *cfp) static void vm_iter_break(rb_thread_t *th, VALUE val) { - rb_control_frame_t *cfp = next_not_local_frame(th->ec.cfp); + rb_control_frame_t *cfp = next_not_local_frame(th->ec->cfp); const VALUE *ep = VM_CF_PREV_EP(cfp); const rb_control_frame_t *target_cfp = rb_vm_search_cf_from_ep(th, cfp, ep); @@ -1484,7 +1486,7 @@ vm_iter_break(rb_thread_t *th, VALUE val) } #endif - th->ec.errinfo = (VALUE)THROW_DATA_NEW(val, target_cfp, TAG_BREAK); + th->ec->errinfo = (VALUE)THROW_DATA_NEW(val, target_cfp, TAG_BREAK); TH_JUMP_TAG(th, TAG_BREAK); } @@ -1670,33 +1672,33 @@ hook_before_rewind(rb_thread_t *th, const rb_control_frame_t *cfp, int will_fini if (state == TAG_RAISE && RBASIC_CLASS(err) == rb_eSysStackError) { return; } - switch (VM_FRAME_TYPE(th->ec.cfp)) { + switch (VM_FRAME_TYPE(th->ec->cfp)) { case VM_FRAME_MAGIC_METHOD: RUBY_DTRACE_METHOD_RETURN_HOOK(th, 0, 0); - EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_RETURN, th->ec.cfp->self, 0, 0, 0, frame_return_value(err)); + EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_RETURN, th->ec->cfp->self, 0, 0, 0, frame_return_value(err)); THROW_DATA_CONSUMED_SET(err); break; case VM_FRAME_MAGIC_BLOCK: - if (VM_FRAME_BMETHOD_P(th->ec.cfp)) { - EXEC_EVENT_HOOK(th, RUBY_EVENT_B_RETURN, th->ec.cfp->self, 0, 0, 0, frame_return_value(err)); + if (VM_FRAME_BMETHOD_P(th->ec->cfp)) { + EXEC_EVENT_HOOK(th, RUBY_EVENT_B_RETURN, th->ec->cfp->self, 0, 0, 0, frame_return_value(err)); if (!will_finish_vm_exec) { /* kick RUBY_EVENT_RETURN at invoke_block_from_c() for bmethod */ - EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_RETURN, th->ec.cfp->self, - rb_vm_frame_method_entry(th->ec.cfp)->def->original_id, - rb_vm_frame_method_entry(th->ec.cfp)->called_id, - rb_vm_frame_method_entry(th->ec.cfp)->owner, + EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_RETURN, th->ec->cfp->self, + rb_vm_frame_method_entry(th->ec->cfp)->def->original_id, + rb_vm_frame_method_entry(th->ec->cfp)->called_id, + rb_vm_frame_method_entry(th->ec->cfp)->owner, frame_return_value(err)); } THROW_DATA_CONSUMED_SET(err); } else { - EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_B_RETURN, th->ec.cfp->self, 0, 0, 0, frame_return_value(err)); + EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_B_RETURN, th->ec->cfp->self, 0, 0, 0, frame_return_value(err)); THROW_DATA_CONSUMED_SET(err); } break; case VM_FRAME_MAGIC_CLASS: - EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_END, th->ec.cfp->self, 0, 0, 0, Qnil); + EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_END, th->ec->cfp->self, 0, 0, 0, Qnil); break; } } @@ -1794,7 +1796,7 @@ vm_exec(rb_thread_t *th) if ((state = EXEC_TAG()) == TAG_NONE) { vm_loop_start: result = vm_exec_core(th, initial); - VM_ASSERT(th->ec.tag == &_tag); + VM_ASSERT(th->ec->tag == &_tag); if ((state = _tag.state) != TAG_NONE) { err = (struct vm_throw_data *)result; _tag.state = TAG_NONE; @@ -1811,27 +1813,27 @@ vm_exec(rb_thread_t *th) VALUE type; const rb_control_frame_t *escape_cfp; - err = (struct vm_throw_data *)th->ec.errinfo; + err = (struct vm_throw_data *)th->ec->errinfo; rb_thread_raised_reset(th, RAISED_STACKOVERFLOW); exception_handler: cont_pc = cont_sp = 0; catch_iseq = NULL; - while (th->ec.cfp->pc == 0 || th->ec.cfp->iseq == 0) { - if (UNLIKELY(VM_FRAME_TYPE(th->ec.cfp) == VM_FRAME_MAGIC_CFUNC)) { - EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->ec.cfp->self, - rb_vm_frame_method_entry(th->ec.cfp)->def->original_id, - rb_vm_frame_method_entry(th->ec.cfp)->called_id, - rb_vm_frame_method_entry(th->ec.cfp)->owner, Qnil); + while (th->ec->cfp->pc == 0 || th->ec->cfp->iseq == 0) { + if (UNLIKELY(VM_FRAME_TYPE(th->ec->cfp) == VM_FRAME_MAGIC_CFUNC)) { + EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->ec->cfp->self, + rb_vm_frame_method_entry(th->ec->cfp)->def->original_id, + rb_vm_frame_method_entry(th->ec->cfp)->called_id, + rb_vm_frame_method_entry(th->ec->cfp)->owner, Qnil); RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, - rb_vm_frame_method_entry(th->ec.cfp)->owner, - rb_vm_frame_method_entry(th->ec.cfp)->def->original_id); + rb_vm_frame_method_entry(th->ec->cfp)->owner, + rb_vm_frame_method_entry(th->ec->cfp)->def->original_id); } rb_vm_pop_frame(th); } - cfp = th->ec.cfp; + cfp = th->ec->cfp; epc = cfp->pc - cfp->iseq->body->iseq_encoded; escape_cfp = NULL; @@ -1858,10 +1860,10 @@ vm_exec(rb_thread_t *th) } } if (catch_iseq == NULL) { - th->ec.errinfo = Qnil; + th->ec->errinfo = Qnil; result = THROW_DATA_VAL(err); THROW_DATA_CATCH_FRAME_SET(err, cfp + 1); - hook_before_rewind(th, th->ec.cfp, TRUE, state, err); + hook_before_rewind(th, th->ec->cfp, TRUE, state, err); rb_vm_pop_frame(th); goto finish_vme; } @@ -1873,9 +1875,9 @@ vm_exec(rb_thread_t *th) #if OPT_STACK_CACHING initial = THROW_DATA_VAL(err); #else - *th->ec.cfp->sp++ = THROW_DATA_VAL(err); + *th->ec->cfp->sp++ = THROW_DATA_VAL(err); #endif - th->ec.errinfo = Qnil; + th->ec->errinfo = Qnil; goto vm_loop_start; } } @@ -1914,7 +1916,7 @@ vm_exec(rb_thread_t *th) escape_cfp = THROW_DATA_CATCH_FRAME(err); if (cfp == escape_cfp) { cfp->pc = cfp->iseq->body->iseq_encoded + entry->cont; - th->ec.errinfo = Qnil; + th->ec->errinfo = Qnil; goto vm_loop_start; } } @@ -1944,11 +1946,11 @@ vm_exec(rb_thread_t *th) #if OPT_STACK_CACHING initial = THROW_DATA_VAL(err); #else - *th->ec.cfp->sp++ = THROW_DATA_VAL(err); + *th->ec->cfp->sp++ = THROW_DATA_VAL(err); #endif } - th->ec.errinfo = Qnil; - VM_ASSERT(th->ec.tag->state == TAG_NONE); + th->ec->errinfo = Qnil; + VM_ASSERT(th->ec->tag->state == TAG_NONE); goto vm_loop_start; } } @@ -1998,16 +2000,16 @@ vm_exec(rb_thread_t *th) catch_iseq->body->stack_max); state = 0; - th->ec.tag->state = TAG_NONE; - th->ec.errinfo = Qnil; + th->ec->tag->state = TAG_NONE; + th->ec->errinfo = Qnil; goto vm_loop_start; } else { - hook_before_rewind(th, th->ec.cfp, FALSE, state, err); + hook_before_rewind(th, th->ec->cfp, FALSE, state, err); - if (VM_FRAME_FINISHED_P(th->ec.cfp)) { + if (VM_FRAME_FINISHED_P(th->ec->cfp)) { rb_vm_pop_frame(th); - th->ec.errinfo = (VALUE)err; + th->ec->errinfo = (VALUE)err; TH_TMPPOP_TAG(); TH_JUMP_TAG(th, state); } @@ -2064,7 +2066,7 @@ rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, ID *cal int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, ID *called_idp, VALUE *klassp) { - return rb_vm_control_frame_id_and_class(th->ec.cfp, idp, called_idp, klassp); + return rb_vm_control_frame_id_and_class(th->ec->cfp, idp, called_idp, klassp); } int @@ -2076,7 +2078,7 @@ rb_frame_method_id_and_class(ID *idp, VALUE *klassp) VALUE rb_thread_current_status(const rb_thread_t *th) { - const rb_control_frame_t *cfp = th->ec.cfp; + const rb_control_frame_t *cfp = th->ec->cfp; const rb_callable_method_entry_t *me; VALUE str = Qnil; @@ -2102,7 +2104,7 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename) { rb_thread_t *th = GET_THREAD(); - const rb_control_frame_t *reg_cfp = th->ec.cfp; + const rb_control_frame_t *reg_cfp = th->ec->cfp; const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); VALUE val; @@ -2216,7 +2218,7 @@ ruby_vm_destruct(rb_vm_t *vm) } /* after freeing objspace, you *can't* use ruby_xfree() */ ruby_mimfree(vm); - ruby_current_vm = 0; + ruby_current_vm_ptr = NULL; } RUBY_FREE_LEAVE("vm"); return 0; @@ -2366,11 +2368,14 @@ rb_thread_recycle_stack_release(VALUE *stack) ruby_xfree(stack); } -void rb_fiber_mark_self(rb_fiber_t *fib); - void rb_execution_context_mark(const rb_execution_context_t *ec) { +#if VM_CHECK_MODE > 0 + void rb_ec_verify(const rb_execution_context_t *ec); /* cont.c */ + rb_ec_verify(ec); +#endif + /* mark VM stack */ if (ec->vm_stack) { VALUE *p = ec->vm_stack; @@ -2394,8 +2399,7 @@ 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) { + if (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) + @@ -2407,16 +2411,16 @@ rb_execution_context_mark(const rb_execution_context_t *ec) rb_mark_tbl(ec->local_storage); RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash); RUBY_MARK_UNLESS_NULL(ec->local_storage_recursive_hash_for_trace); - rb_fiber_mark_self(ec->fiber); } +void rb_fiber_mark_self(rb_fiber_t *fib); + void rb_thread_mark(void *ptr) { rb_thread_t *th = ptr; RUBY_MARK_ENTER("thread"); - - rb_execution_context_mark(&th->ec); + rb_fiber_mark_self(th->ec->fiber); /* mark ruby objects */ RUBY_MARK_UNLESS_NULL(th->first_proc); @@ -2444,11 +2448,6 @@ thread_free(void *ptr) rb_thread_t *th = ptr; RUBY_FREE_ENTER("thread"); - if (th->ec.vm_stack != NULL) { - rb_thread_recycle_stack_release(th->ec.vm_stack); - th->ec.vm_stack = NULL; - } - if (th->locking_mutex != Qfalse) { rb_bug("thread_free: locking_mutex must be NULL (%p:%p)", (void *)th, (void *)th->locking_mutex); } @@ -2456,10 +2455,13 @@ thread_free(void *ptr) rb_bug("thread_free: keeping_mutexes must be NULL (%p:%p)", (void *)th, (void *)th->keeping_mutexes); } - if (th->ec.local_storage) { - st_free_table(th->ec.local_storage); + if (th->ec->local_storage) { + st_free_table(th->ec->local_storage); } + if (th->ec == ruby_current_execution_context_ptr) + ruby_current_execution_context_ptr = NULL; + if (th->vm && th->vm->main_thread == th) { RUBY_GC_INFO("main thread\n"); } @@ -2471,8 +2473,6 @@ thread_free(void *ptr) #endif ruby_xfree(ptr); } - if (ruby_current_thread == th) - ruby_current_thread = NULL; RUBY_FREE_LEAVE("thread"); } @@ -2484,10 +2484,10 @@ thread_memsize(const void *ptr) size_t size = sizeof(rb_thread_t); if (!th->root_fiber) { - size += th->ec.vm_stack_size * sizeof(VALUE); + size += th->ec->vm_stack_size * sizeof(VALUE); } - if (th->ec.local_storage) { - size += st_memsize(th->ec.local_storage); + if (th->ec->local_storage) { + size += st_memsize(th->ec->local_storage); } return size; } @@ -2524,35 +2524,39 @@ thread_alloc(VALUE klass) return obj; } +void rb_threadptr_root_fiber_setup(rb_thread_t *th); + static void th_init(rb_thread_t *th, VALUE self) { th->self = self; + rb_threadptr_root_fiber_setup(th); /* allocate thread stack */ #ifdef USE_SIGALTSTACK /* altstack of main thread is reallocated in another place */ th->altstack = malloc(rb_sigaltstack_size()); #endif - /* th->ec.vm_stack_size is word number. - * th->vm->default_params.thread_vm_stack_size is byte size. - */ - th->ec.vm_stack_size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE); - th->ec.vm_stack = thread_recycle_stack(th->ec.vm_stack_size); + { + /* vm_stack_size is word number. + * th->vm->default_params.thread_vm_stack_size is byte size. */ + size_t size = th->vm->default_params.thread_vm_stack_size / sizeof(VALUE); + ec_set_vm_stack(th->ec, thread_recycle_stack(size), size); + } - th->ec.cfp = (void *)(th->ec.vm_stack + th->ec.vm_stack_size); + th->ec->cfp = (void *)(th->ec->vm_stack + th->ec->vm_stack_size); vm_push_frame(th, 0 /* dummy iseq */, VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL | VM_FRAME_FLAG_FINISH | VM_FRAME_FLAG_CFRAME /* dummy frame */, Qnil /* dummy self */, VM_BLOCK_HANDLER_NONE /* dummy block ptr */, 0 /* dummy cref/me */, - 0 /* dummy pc */, th->ec.vm_stack, 0, 0); + 0 /* dummy pc */, th->ec->vm_stack, 0, 0); th->status = THREAD_RUNNABLE; th->last_status = Qnil; - th->ec.errinfo = Qnil; - th->ec.root_svar = Qfalse; - th->ec.local_storage_recursive_hash = Qnil; - th->ec.local_storage_recursive_hash_for_trace = Qnil; + th->ec->errinfo = Qnil; + th->ec->root_svar = Qfalse; + th->ec->local_storage_recursive_hash = Qnil; + th->ec->local_storage_recursive_hash_for_trace = Qnil; #ifdef NON_SCALAR_THREAD_ID th->thread_id_string[0] = '\0'; #endif @@ -2575,7 +2579,7 @@ ruby_thread_init(VALUE self) th->top_wrapper = 0; th->top_self = rb_vm_top_self(); - th->ec.root_svar = Qfalse; + th->ec->root_svar = Qfalse; return self; } @@ -2617,11 +2621,11 @@ vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval, int is_single #define REWIND_CFP(expr) do { \ rb_thread_t *th__ = GET_THREAD(); \ - VALUE *const curr_sp = (th__->ec.cfp++)->sp; \ - VALUE *const saved_sp = th__->ec.cfp->sp; \ - th__->ec.cfp->sp = curr_sp; \ + VALUE *const curr_sp = (th__->ec->cfp++)->sp; \ + VALUE *const saved_sp = th__->ec->cfp->sp; \ + th__->ec->cfp->sp = curr_sp; \ expr; \ - (th__->ec.cfp--)->sp = saved_sp; \ + (th__->ec->cfp--)->sp = saved_sp; \ } while (0) static VALUE @@ -3065,7 +3069,7 @@ Init_VM(void) /* VM bootstrap: phase 2 */ { - rb_vm_t *vm = ruby_current_vm; + rb_vm_t *vm = ruby_current_vm_ptr; rb_thread_t *th = GET_THREAD(); VALUE filename = rb_fstring_cstr("
"); const rb_iseq_t *iseq = rb_iseq_new(0, filename, filename, Qnil, 0, ISEQ_TYPE_TOP); @@ -3087,12 +3091,12 @@ Init_VM(void) rb_vm_living_threads_insert(vm, th); rb_gc_register_mark_object((VALUE)iseq); - th->ec.cfp->iseq = iseq; - th->ec.cfp->pc = iseq->body->iseq_encoded; - th->ec.cfp->self = th->top_self; + th->ec->cfp->iseq = iseq; + th->ec->cfp->pc = iseq->body->iseq_encoded; + th->ec->cfp->self = th->top_self; - VM_ENV_FLAGS_UNSET(th->ec.cfp->ep, VM_FRAME_FLAG_CFRAME); - VM_STACK_ENV_WRITE(th->ec.cfp->ep, VM_ENV_DATA_INDEX_ME_CREF, (VALUE)vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE, FALSE, NULL, FALSE)); + VM_ENV_FLAGS_UNSET(th->ec->cfp->ep, VM_FRAME_FLAG_CFRAME); + VM_STACK_ENV_WRITE(th->ec->cfp->ep, VM_ENV_DATA_INDEX_ME_CREF, (VALUE)vm_cref_new(rb_cObject, METHOD_VISI_PRIVATE, FALSE, NULL, FALSE)); /* * The Binding of the top level scope @@ -3110,7 +3114,7 @@ void rb_vm_set_progname(VALUE filename) { rb_thread_t *th = GET_VM()->main_thread; - rb_control_frame_t *cfp = (void *)(th->ec.vm_stack + th->ec.vm_stack_size); + rb_control_frame_t *cfp = (void *)(th->ec->vm_stack + th->ec->vm_stack_size); --cfp; rb_iseq_pathobj_set(cfp->iseq, rb_str_dup(filename), rb_iseq_realpath(cfp->iseq)); @@ -3129,15 +3133,15 @@ Init_BareVM(void) exit(EXIT_FAILURE); } MEMZERO(th, rb_thread_t, 1); - rb_thread_set_current_raw(th); - vm_init2(vm); + vm->objspace = rb_objspace_alloc(); - ruby_current_vm = vm; + ruby_current_vm_ptr = vm; - Init_native_thread(); + Init_native_thread(th); th->vm = vm; th_init(th, 0); + rb_thread_set_current_raw(th); ruby_thread_init_stack(th); } @@ -3293,7 +3297,7 @@ vm_analysis_operand(int insn, int n, VALUE op) HASH_ASET(ihash, INT2FIX(n), ophash); } /* intern */ - valstr = rb_insn_operand_intern(GET_THREAD()->ec.cfp->iseq, insn, n, op, 0, 0, 0, 0); + valstr = rb_insn_operand_intern(GET_THREAD()->ec->cfp->iseq, insn, n, op, 0, 0, 0, 0); /* set count */ if ((cv = rb_hash_aref(ophash, valstr)) == Qnil) { @@ -3406,7 +3410,7 @@ vm_collect_usage_operand(int insn, int n, VALUE op) if (RUBY_DTRACE_INSN_OPERAND_ENABLED()) { VALUE valstr; - valstr = rb_insn_operand_intern(GET_THREAD()->ec.cfp->iseq, insn, n, op, 0, 0, 0, 0); + valstr = rb_insn_operand_intern(GET_THREAD()->ec->cfp->iseq, insn, n, op, 0, 0, 0, 0); RUBY_DTRACE_INSN_OPERAND(RSTRING_PTR(valstr), rb_insns_name(insn)); RB_GC_GUARD(valstr); diff --git a/vm_args.c b/vm_args.c index c15ce788bd..6eff1a4939 100644 --- a/vm_args.c +++ b/vm_args.c @@ -508,7 +508,7 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, int given_argc; struct args_info args_body, *args; VALUE keyword_hash = Qnil; - VALUE * const orig_sp = th->ec.cfp->sp; + VALUE * const orig_sp = th->ec->cfp->sp; unsigned int i; /* @@ -528,7 +528,7 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, for (i=calling->argc; ibody->param.size; i++) { locals[i] = Qnil; } - th->ec.cfp->sp = &locals[i]; + th->ec->cfp->sp = &locals[i]; /* setup args */ args = &args_body; @@ -587,7 +587,7 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, } else { if (arg_setup_type == arg_setup_block) { - CHECK_VM_STACK_OVERFLOW(th->ec.cfp, min_argc); + CHECK_VM_STACK_OVERFLOW(th->ec->cfp, min_argc); given_argc = min_argc; args_extend(args, min_argc); } @@ -683,7 +683,7 @@ setup_parameters_complex(rb_thread_t * const th, const rb_iseq_t * const iseq, } #endif - th->ec.cfp->sp = orig_sp; + th->ec->cfp->sp = orig_sp; return opt_pc; } @@ -696,7 +696,7 @@ raise_argument_error(rb_thread_t *th, const rb_iseq_t *iseq, const VALUE exc) vm_push_frame(th, iseq, VM_FRAME_MAGIC_DUMMY | VM_ENV_FLAG_LOCAL, Qnil /* self */, VM_BLOCK_HANDLER_NONE /* specval*/, Qfalse /* me or cref */, iseq->body->iseq_encoded, - th->ec.cfp->sp, 0, 0 /* stack_max */); + th->ec->cfp->sp, 0, 0 /* stack_max */); at = rb_threadptr_backtrace_object(th); rb_vm_pop_frame(th); } diff --git a/vm_backtrace.c b/vm_backtrace.c index aab62ea072..54ffc6baec 100644 --- a/vm_backtrace.c +++ b/vm_backtrace.c @@ -427,7 +427,7 @@ backtrace_each(rb_thread_t *th, void (*iter_cfunc)(void *arg, const rb_control_frame_t *cfp, ID mid), void *arg) { - rb_control_frame_t *last_cfp = th->ec.cfp; + rb_control_frame_t *last_cfp = th->ec->cfp; rb_control_frame_t *start_cfp = RUBY_VM_END_CONTROL_FRAME(th); rb_control_frame_t *cfp; ptrdiff_t size, i; @@ -439,7 +439,7 @@ backtrace_each(rb_thread_t *th, * top frame * ... * 2nd frame <- lev:0 - * current frame <- th->ec.cfp + * current frame <- th->ec->cfp */ start_cfp = @@ -1172,12 +1172,12 @@ VALUE rb_debug_inspector_open(rb_debug_inspector_func_t func, void *data) { rb_debug_inspector_t dbg_context; - rb_thread_t *th = GET_THREAD(); + rb_thread_t * volatile th = GET_THREAD(); enum ruby_tag_type state; volatile VALUE MAYBE_UNUSED(result); dbg_context.th = th; - dbg_context.cfp = dbg_context.th->ec.cfp; + dbg_context.cfp = dbg_context.th->ec->cfp; dbg_context.backtrace = rb_threadptr_backtrace_location_ary(th, 0, 0); dbg_context.backtrace_size = RARRAY_LEN(dbg_context.backtrace); dbg_context.contexts = collect_caller_bindings(th); @@ -1247,7 +1247,7 @@ rb_profile_frames(int start, int limit, VALUE *buff, int *lines) { int i; rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->ec.cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(th); + rb_control_frame_t *cfp = th->ec->cfp, *end_cfp = RUBY_VM_END_CONTROL_FRAME(th); const rb_callable_method_entry_t *cme; for (i=0; iec.vm_stack + (th)->ec.vm_stack_size)) + ((rb_control_frame_t *)((th)->ec->vm_stack + (th)->ec->vm_stack_size)) #define RUBY_VM_VALID_CONTROL_FRAME_P(cfp, ecfp) \ ((void *)(ecfp) > (void *)(cfp)) #define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp) \ @@ -1469,7 +1471,7 @@ extern void rb_vmdebug_stack_dump_raw(rb_thread_t *, rb_control_frame_t *); extern void rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp, const VALUE *_pc); extern void rb_vmdebug_debug_print_post(rb_thread_t *th, rb_control_frame_t *cfp); -#define SDR() rb_vmdebug_stack_dump_raw(GET_THREAD(), GET_THREAD()->ec.cfp) +#define SDR() rb_vmdebug_stack_dump_raw(GET_THREAD(), GET_THREAD()->ec->cfp) #define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_THREAD(), (cfp)) void rb_vm_bugreport(const void *); NORETURN(void rb_bug_context(const void *, const char *fmt, ...)); @@ -1569,19 +1571,62 @@ VALUE rb_catch_protect(VALUE t, rb_block_call_func *func, VALUE data, enum ruby_ /* for thread */ #if RUBY_VM_THREAD_MODEL == 2 - RUBY_SYMBOL_EXPORT_BEGIN -extern rb_thread_t *ruby_current_thread; -extern rb_vm_t *ruby_current_vm; +extern rb_vm_t *ruby_current_vm_ptr; +extern rb_execution_context_t *ruby_current_execution_context_ptr; extern rb_event_flag_t ruby_vm_event_flags; RUBY_SYMBOL_EXPORT_END -#define GET_VM() ruby_current_vm -#define GET_THREAD() ruby_current_thread +#define GET_VM() ruby_current_vm() +#define GET_THREAD() ruby_current_thread() +#define GET_EC() ruby_current_execution_context() + +rb_thread_t *rb_fiberptr_thread_ptr(const rb_fiber_t *fib); + +static inline rb_thread_t * +rb_ec_thread_ptr(const rb_execution_context_t *ec) +{ + return rb_fiberptr_thread_ptr(ec->fiber); +} + +static inline rb_vm_t * +rb_ec_vm_ptr(const rb_execution_context_t *ec) +{ + const rb_thread_t *th = rb_fiberptr_thread_ptr(ec->fiber); + if (th) { + return rb_fiberptr_thread_ptr(ec->fiber)->vm; + } + else { + return NULL; + } +} + +static inline rb_execution_context_t * +ruby_current_execution_context(void) +{ + return ruby_current_execution_context_ptr; +} + +static inline rb_thread_t * +ruby_current_thread(void) +{ + const rb_execution_context_t *ec = GET_EC(); + return rb_ec_thread_ptr(ec); +} + +static inline rb_vm_t * +ruby_current_vm(void) +{ + VM_ASSERT(ruby_current_vm_ptr == NULL || + ruby_current_execution_context_ptr == NULL || + rb_ec_thread_ptr(GET_EC()) == NULL || + rb_ec_vm_ptr(GET_EC()) == ruby_current_vm_ptr); + return ruby_current_vm_ptr; +} -#define rb_thread_set_current_raw(th) (void)(ruby_current_thread = (th)) +#define rb_thread_set_current_raw(th) (void)(ruby_current_execution_context_ptr = (th)->ec) #define rb_thread_set_current(th) do { \ if ((th)->vm->running_thread != (th)) { \ (th)->running_time_us = 0; \ @@ -1622,11 +1667,14 @@ void rb_threadptr_pending_interrupt_enque(rb_thread_t *th, VALUE v); int rb_threadptr_pending_interrupt_active_p(rb_thread_t *th); void rb_threadptr_error_print(rb_thread_t *volatile th, volatile VALUE errinfo); void rb_execution_context_mark(const rb_execution_context_t *ec); +void rb_fiber_close(rb_fiber_t *fib); +void Init_native_thread(rb_thread_t *th); #define RUBY_VM_CHECK_INTS(th) ruby_vm_check_ints(th) static inline void ruby_vm_check_ints(rb_thread_t *th) { + VM_ASSERT(th->ec == ruby_current_execution_context_ptr); if (UNLIKELY(RUBY_VM_INTERRUPTED_ANY(th))) { rb_threadptr_execute_interrupts(th, 0); } @@ -1669,7 +1717,7 @@ ruby_exec_event_hook_orig(rb_thread_t *const th, const rb_event_flag_t flag, struct rb_trace_arg_struct trace_arg; trace_arg.event = flag; trace_arg.th = th; - trace_arg.cfp = th->ec.cfp; + trace_arg.cfp = th->ec->cfp; trace_arg.self = self; trace_arg.id = id; trace_arg.called_id = called_id; diff --git a/vm_dump.c b/vm_dump.c index 79bb20c253..938a31f806 100644 --- a/vm_dump.c +++ b/vm_dump.c @@ -22,14 +22,14 @@ #define MAX_POSBUF 128 #define VM_CFP_CNT(th, cfp) \ - ((rb_control_frame_t *)((th)->ec.vm_stack + (th)->ec.vm_stack_size) - \ + ((rb_control_frame_t *)((th)->ec->vm_stack + (th)->ec->vm_stack_size) - \ (rb_control_frame_t *)(cfp)) static void control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) { ptrdiff_t pc = -1; - ptrdiff_t ep = cfp->ep - th->ec.vm_stack; + ptrdiff_t ep = cfp->ep - th->ec->vm_stack; char ep_in_heap = ' '; char posbuf[MAX_POSBUF+1]; int line = 0; @@ -39,7 +39,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) const rb_callable_method_entry_t *me; - if (ep < 0 || (size_t)ep > th->ec.vm_stack_size) { + if (ep < 0 || (size_t)ep > th->ec->vm_stack_size) { ep = (ptrdiff_t)cfp->ep; ep_in_heap = 'p'; } @@ -112,14 +112,14 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) } fprintf(stderr, "c:%04"PRIdPTRDIFF" ", - ((rb_control_frame_t *)(th->ec.vm_stack + th->ec.vm_stack_size) - cfp)); + ((rb_control_frame_t *)(th->ec->vm_stack + th->ec->vm_stack_size) - cfp)); if (pc == -1) { fprintf(stderr, "p:---- "); } else { fprintf(stderr, "p:%04"PRIdPTRDIFF" ", pc); } - fprintf(stderr, "s:%04"PRIdPTRDIFF" ", cfp->sp - th->ec.vm_stack); + fprintf(stderr, "s:%04"PRIdPTRDIFF" ", cfp->sp - th->ec->vm_stack); fprintf(stderr, ep_in_heap == ' ' ? "e:%06"PRIdPTRDIFF" " : "E:%06"PRIxPTRDIFF" ", ep % 10000); fprintf(stderr, "%-6s", magic); if (line) { @@ -145,12 +145,12 @@ rb_vmdebug_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp) VALUE *p, *st, *t; fprintf(stderr, "-- stack frame ------------\n"); - for (p = st = th->ec.vm_stack; p < sp; p++) { + for (p = st = th->ec->vm_stack; p < sp; p++) { fprintf(stderr, "%04ld (%p): %08"PRIxVALUE, (long)(p - st), p, *p); t = (VALUE *)*p; - if (th->ec.vm_stack <= t && t < sp) { - fprintf(stderr, " (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF(t) - th->ec.vm_stack)); + if (th->ec->vm_stack <= t && t < sp) { + fprintf(stderr, " (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF(t) - th->ec->vm_stack)); } if (p == ep) @@ -162,7 +162,7 @@ rb_vmdebug_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp) fprintf(stderr, "-- Control frame information " "-----------------------------------------------\n"); - while ((void *)cfp < (void *)(th->ec.vm_stack + th->ec.vm_stack_size)) { + while ((void *)cfp < (void *)(th->ec->vm_stack + th->ec->vm_stack_size)) { control_frame_dump(th, cfp); cfp++; } @@ -173,7 +173,7 @@ void rb_vmdebug_stack_dump_raw_current(void) { rb_thread_t *th = GET_THREAD(); - rb_vmdebug_stack_dump_raw(th, th->ec.cfp); + rb_vmdebug_stack_dump_raw(th, th->ec->cfp); } void @@ -213,7 +213,7 @@ void rb_vmdebug_stack_dump_th(VALUE thval) { rb_thread_t *target_th = rb_thread_ptr(thval); - rb_vmdebug_stack_dump_raw(target_th, target_th->ec.cfp); + rb_vmdebug_stack_dump_raw(target_th, target_th->ec->cfp); } #if VMDEBUG > 2 @@ -285,11 +285,11 @@ vm_stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp) break; } fprintf(stderr, " stack %2d: %8s (%"PRIdPTRDIFF")\n", i, StringValueCStr(rstr), - (ptr - th->ec.vm_stack)); + (ptr - th->ec->vm_stack)); } } else if (VM_FRAME_FINISHED_P(cfp)) { - if ((th)->ec.vm_stack + (th)->ec.vm_stack_size > (VALUE *)(cfp + 1)) { + if ((th)->ec->vm_stack + (th)->ec->vm_stack_size > (VALUE *)(cfp + 1)) { vm_stack_dump_each(th, cfp + 1); } else { @@ -305,22 +305,22 @@ vm_stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp) void rb_vmdebug_debug_print_register(rb_thread_t *th) { - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; ptrdiff_t pc = -1; - ptrdiff_t ep = cfp->ep - th->ec.vm_stack; + ptrdiff_t ep = cfp->ep - th->ec->vm_stack; ptrdiff_t cfpi; if (VM_FRAME_RUBYFRAME_P(cfp)) { pc = cfp->pc - cfp->iseq->body->iseq_encoded; } - if (ep < 0 || (size_t)ep > th->ec.vm_stack_size) { + if (ep < 0 || (size_t)ep > th->ec->vm_stack_size) { ep = -1; } - cfpi = ((rb_control_frame_t *)(th->ec.vm_stack + th->ec.vm_stack_size)) - cfp; + cfpi = ((rb_control_frame_t *)(th->ec->vm_stack + th->ec->vm_stack_size)) - cfp; fprintf(stderr, " [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n", - pc, (cfp->sp - th->ec.vm_stack), ep, cfpi); + pc, (cfp->sp - th->ec->vm_stack), ep, cfpi); } void @@ -342,7 +342,7 @@ rb_vmdebug_debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp, const VALUE printf(" "); } printf("| "); - if(0)printf("[%03ld] ", (long)(cfp->sp - th->ec.vm_stack)); + if(0)printf("[%03ld] ", (long)(cfp->sp - th->ec->vm_stack)); /* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(th, cfp)); */ if (pc >= 0) { @@ -377,7 +377,7 @@ rb_vmdebug_debug_print_post(rb_thread_t *th, rb_control_frame_t *cfp #if VMDEBUG > 2 /* stack_dump_thobj(th); */ - vm_stack_dump_each(th, th->ec.cfp); + vm_stack_dump_each(th, th->ec->cfp); #if OPT_STACK_CACHING { @@ -397,7 +397,7 @@ VALUE rb_vmdebug_thread_dump_state(VALUE self) { rb_thread_t *th = rb_thread_ptr(self); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; fprintf(stderr, "Thread state dump:\n"); fprintf(stderr, "pc : %p, sp : %p\n", (void *)cfp->pc, (void *)cfp->sp); @@ -1085,6 +1085,6 @@ rb_vmdebug_stack_dump_all_threads(void) #else fprintf(stderr, "th: %p, native_id: %p\n", th, (void *)th->thread_id); #endif - rb_vmdebug_stack_dump_raw(th, th->ec.cfp); + rb_vmdebug_stack_dump_raw(th, th->ec->cfp); } } diff --git a/vm_eval.c b/vm_eval.c index 31344cd305..8f07843c88 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -74,7 +74,7 @@ vm_call0_cfunc_with_frame(rb_thread_t* th, struct rb_calling_info *calling, cons RUBY_DTRACE_CMETHOD_ENTRY_HOOK(th, me->owner, me->def->original_id); EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->def->original_id, mid, me->owner, Qnil); { - rb_control_frame_t *reg_cfp = th->ec.cfp; + rb_control_frame_t *reg_cfp = th->ec->cfp; vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL, recv, block_handler, (VALUE)me, @@ -113,7 +113,7 @@ vm_call0_body(rb_thread_t* th, struct rb_calling_info *calling, const struct rb_ switch (cc->me->def->type) { case VM_METHOD_TYPE_ISEQ: { - rb_control_frame_t *reg_cfp = th->ec.cfp; + rb_control_frame_t *reg_cfp = th->ec->cfp; int i; CHECK_VM_STACK_OVERFLOW(reg_cfp, calling->argc + 1); @@ -124,7 +124,7 @@ vm_call0_body(rb_thread_t* th, struct rb_calling_info *calling, const struct rb_ } vm_call_iseq_setup(th, reg_cfp, calling, ci, cc); - VM_ENV_FLAGS_SET(th->ec.cfp->ep, VM_FRAME_FLAG_FINISH); + VM_ENV_FLAGS_SET(th->ec->cfp->ep, VM_FRAME_FLAG_FINISH); return vm_exec(th); /* CHECK_INTS in this function */ } case VM_METHOD_TYPE_NOTIMPLEMENTED: @@ -211,10 +211,10 @@ rb_vm_call(rb_thread_t *th, VALUE recv, VALUE id, int argc, const VALUE *argv, c static inline VALUE vm_call_super(rb_thread_t *th, int argc, const VALUE *argv) { - VALUE recv = th->ec.cfp->self; + VALUE recv = th->ec->cfp->self; VALUE klass; ID id; - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp); if (VM_FRAME_RUBYFRAME_P(cfp)) { @@ -247,7 +247,7 @@ rb_current_receiver(void) { rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp; - if (!th || !(cfp = th->ec.cfp)) + if (!th || !(cfp = th->ec->cfp)) rb_raise(rb_eRuntimeError, "no self, no life"); return cfp->self; } @@ -348,7 +348,7 @@ check_funcall_respond_to(rb_thread_t *th, VALUE klass, VALUE recv, ID mid) static int check_funcall_callable(rb_thread_t *th, const rb_callable_method_entry_t *me) { - return rb_method_call_status(th, me, CALL_FCALL, th->ec.cfp->self) == MISSING_NONE; + return rb_method_call_status(th, me, CALL_FCALL, th->ec->cfp->self) == MISSING_NONE; } static VALUE @@ -585,7 +585,7 @@ static inline VALUE rb_call(VALUE recv, ID mid, int argc, const VALUE *argv, call_type scope) { rb_thread_t *th = GET_THREAD(); - return rb_call0(recv, mid, argc, argv, scope, th->ec.cfp->self); + return rb_call0(recv, mid, argc, argv, scope, th->ec->cfp->self); } NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, @@ -850,7 +850,7 @@ rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE pas static VALUE * current_vm_stack_arg(rb_thread_t *th, const VALUE *argv) { - rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec.cfp); + rb_control_frame_t *prev_cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec->cfp); if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, prev_cfp)) return NULL; if (prev_cfp->sp + 1 != argv) return NULL; return prev_cfp->sp + 1; @@ -869,7 +869,7 @@ send_internal(int argc, const VALUE *argv, VALUE recv, call_type scope) self = Qundef; } else { - self = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec.cfp)->self; + self = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec->cfp)->self; } if (argc == 0) { @@ -1112,7 +1112,7 @@ rb_iterate0(VALUE (* it_proc) (VALUE), VALUE data1, { enum ruby_tag_type state; volatile VALUE retval = Qnil; - rb_control_frame_t *const cfp = th->ec.cfp; + rb_control_frame_t *const cfp = th->ec->cfp; TH_PUSH_TAG(th); state = TH_EXEC_TAG(); @@ -1134,15 +1134,15 @@ rb_iterate0(VALUE (* it_proc) (VALUE), VALUE data1, retval = (*it_proc) (data1); } else if (state == TAG_BREAK || state == TAG_RETRY) { - const struct vm_throw_data *const err = (struct vm_throw_data *)th->ec.errinfo; + const struct vm_throw_data *const err = (struct vm_throw_data *)th->ec->errinfo; const rb_control_frame_t *const escape_cfp = THROW_DATA_CATCH_FRAME(err); if (cfp == escape_cfp) { rb_vm_rewind_cfp(th, cfp); state = 0; - th->ec.tag->state = TAG_NONE; - th->ec.errinfo = Qnil; + th->ec->tag->state = TAG_NONE; + th->ec->errinfo = Qnil; if (state == TAG_RETRY) goto iter_retry; retval = THROW_DATA_VAL(err); @@ -1296,7 +1296,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_ base_block = &bind->block; } else { - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (cfp != 0) { block.as.captured = *VM_CFP_TO_CAPTURED_BLOCK(cfp); @@ -1318,7 +1318,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_ iseq = rb_iseq_compile_with_option(src, fname, realpath, INT2FIX(line), base_block, Qnil); if (!iseq) { - rb_exc_raise(adjust_backtrace_in_eval(th, th->ec.errinfo)); + rb_exc_raise(adjust_backtrace_in_eval(th, th->ec->errinfo)); } /* TODO: what the code checking? */ @@ -1340,7 +1340,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_ /* save new env */ if (bind && iseq->body->local_table_size > 0) { - vm_bind_update_env(scope, bind, vm_make_env_object(th, th->ec.cfp)); + vm_bind_update_env(scope, bind, vm_make_env_object(th, th->ec->cfp)); } } @@ -1357,7 +1357,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_ if (state) { if (state == TAG_RAISE) { - adjust_backtrace_in_eval(th, th->ec.errinfo); + adjust_backtrace_in_eval(th, th->ec->errinfo); } TH_JUMP_TAG(th, state); } @@ -1546,7 +1546,7 @@ static VALUE yield_under(VALUE under, VALUE self, int argc, const VALUE *argv) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; VALUE block_handler = VM_CF_BLOCK_HANDLER(cfp); VALUE new_block_handler = 0; const struct rb_captured_block *captured = NULL; @@ -1580,7 +1580,7 @@ yield_under(VALUE under, VALUE self, int argc, const VALUE *argv) new_captured.self = self; ep = captured->ep; - VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(th->ec.cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler); + VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(th->ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler); } cref = vm_cref_push(th, under, ep, TRUE); @@ -1591,7 +1591,7 @@ VALUE rb_yield_refine_block(VALUE refinement, VALUE refinements) { rb_thread_t *th = GET_THREAD(); - VALUE block_handler = VM_CF_BLOCK_HANDLER(th->ec.cfp); + VALUE block_handler = VM_CF_BLOCK_HANDLER(th->ec->cfp); if (vm_block_handler_type(block_handler) != block_handler_type_iseq) { rb_bug("rb_yield_refine_block: an iseq block is required"); @@ -1603,7 +1603,7 @@ rb_yield_refine_block(VALUE refinement, VALUE refinements) const VALUE *ep = captured->ep; rb_cref_t *cref = vm_cref_push(th, refinement, ep, TRUE); CREF_REFINEMENTS_SET(cref, refinements); - VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(th->ec.cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler); + VM_FORCE_WRITE_SPECIAL_CONST(&VM_CF_LEP(th->ec->cfp)[VM_ENV_DATA_INDEX_SPECVAL], new_block_handler); new_captured.self = refinement; return vm_yield_with_cref(th, 0, NULL, cref, FALSE); } @@ -1875,7 +1875,7 @@ void rb_throw_obj(VALUE tag, VALUE value) { rb_thread_t *th = GET_THREAD(); - struct rb_vm_tag *tt = th->ec.tag; + struct rb_vm_tag *tt = th->ec->tag; while (tt) { if (tt->tag == tag) { @@ -1892,7 +1892,7 @@ rb_throw_obj(VALUE tag, VALUE value) rb_exc_raise(rb_class_new_instance(numberof(desc), desc, rb_eUncaughtThrow)); } - th->ec.errinfo = (VALUE)THROW_DATA_NEW(tag, NULL, TAG_THROW); + th->ec->errinfo = (VALUE)THROW_DATA_NEW(tag, NULL, TAG_THROW); TH_JUMP_TAG(th, TAG_THROW); } @@ -1986,7 +1986,7 @@ vm_catch_protect(VALUE tag, rb_block_call_func *func, VALUE data, { enum ruby_tag_type state; VALUE val = Qnil; /* OK */ - rb_control_frame_t *volatile saved_cfp = th->ec.cfp; + rb_control_frame_t *volatile saved_cfp = th->ec->cfp; TH_PUSH_TAG(th); @@ -1996,10 +1996,10 @@ vm_catch_protect(VALUE tag, rb_block_call_func *func, VALUE data, /* call with argc=1, argv = [tag], block = Qnil to insure compatibility */ val = (*func)(tag, data, 1, (const VALUE *)&tag, Qnil); } - else if (state == TAG_THROW && THROW_DATA_VAL((struct vm_throw_data *)th->ec.errinfo) == tag) { + else if (state == TAG_THROW && THROW_DATA_VAL((struct vm_throw_data *)th->ec->errinfo) == tag) { rb_vm_rewind_cfp(th, saved_cfp); - val = th->ec.tag->retval; - th->ec.errinfo = Qnil; + val = th->ec->tag->retval; + th->ec->errinfo = Qnil; state = 0; } TH_POP_TAG(); @@ -2081,7 +2081,7 @@ rb_f_local_variables(void) struct local_var_list vars; rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = - vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec.cfp)); + vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->ec->cfp)); unsigned int i; local_var_list_init(&vars); @@ -2137,7 +2137,7 @@ VALUE rb_f_block_given_p(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); if (cfp != NULL && VM_CF_BLOCK_HANDLER(cfp) != VM_BLOCK_HANDLER_NONE) { @@ -2152,7 +2152,7 @@ VALUE rb_current_realfilepath(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); if (cfp != 0) return rb_iseq_realpath(cfp->iseq); return Qnil; diff --git a/vm_exec.c b/vm_exec.c index 9537687da4..004265fbbb 100644 --- a/vm_exec.c +++ b/vm_exec.c @@ -84,7 +84,7 @@ vm_exec_core(rb_thread_t *th, VALUE initial) #undef RESTORE_REGS #define RESTORE_REGS() \ { \ - VM_REG_CFP = th->ec.cfp; \ + VM_REG_CFP = th->ec->cfp; \ reg_pc = reg_cfp->pc; \ } @@ -102,7 +102,7 @@ vm_exec_core(rb_thread_t *th, VALUE initial) return (VALUE)insns_address_table; } #endif - reg_cfp = th->ec.cfp; + reg_cfp = th->ec->cfp; reg_pc = reg_cfp->pc; #if OPT_STACK_CACHING @@ -142,7 +142,7 @@ rb_vm_get_insns_address_table(void) static VALUE vm_exec_core(rb_thread_t *th, VALUE initial) { - register rb_control_frame_t *reg_cfp = th->ec.cfp; + register rb_control_frame_t *reg_cfp = th->ec->cfp; while (1) { reg_cfp = ((rb_insn_func_t) (*GET_PC()))(th, reg_cfp); @@ -158,8 +158,8 @@ vm_exec_core(rb_thread_t *th, VALUE initial) return ret; } else { - VALUE err = th->ec.errinfo; - th->ec.errinfo = Qnil; + VALUE err = th->ec->errinfo; + th->ec->errinfo = Qnil; return err; } } diff --git a/vm_exec.h b/vm_exec.h index 12dd277330..e44ed1bbaf 100644 --- a/vm_exec.h +++ b/vm_exec.h @@ -157,11 +157,11 @@ default: \ #endif -#define VM_SP_CNT(th, sp) ((sp) - (th)->ec.vm_stack) +#define VM_SP_CNT(th, sp) ((sp) - (th)->ec->vm_stack) #if OPT_CALL_THREADED_CODE #define THROW_EXCEPTION(exc) do { \ - th->ec.errinfo = (VALUE)(exc); \ + th->ec->errinfo = (VALUE)(exc); \ return 0; \ } while (0) #else diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 3e3e7d5d6d..e291a86d12 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -35,14 +35,14 @@ static void threadptr_stack_overflow(rb_thread_t *th, int setup) { VALUE mesg = th->vm->special_exceptions[ruby_error_sysstack]; - th->ec.raised_flag = RAISED_STACKOVERFLOW; + th->ec->raised_flag = RAISED_STACKOVERFLOW; if (setup) { VALUE at = rb_threadptr_backtrace_object(th); mesg = ruby_vm_special_exception_copy(mesg); rb_ivar_set(mesg, idBt, at); rb_ivar_set(mesg, idBt_locations, at); } - th->ec.errinfo = mesg; + th->ec->errinfo = mesg; TH_JUMP_TAG(th, TAG_RAISE); } @@ -57,8 +57,8 @@ void rb_threadptr_stack_overflow(rb_thread_t *th, int crit) { if (crit || rb_during_gc()) { - th->ec.raised_flag = RAISED_STACKOVERFLOW; - th->ec.errinfo = th->vm->special_exceptions[ruby_error_stackfatal]; + th->ec->raised_flag = RAISED_STACKOVERFLOW; + th->ec->errinfo = th->vm->special_exceptions[ruby_error_stackfatal]; TH_JUMP_TAG(th, TAG_RAISE); } #ifdef USE_SIGALTSTACK @@ -266,7 +266,7 @@ vm_push_frame(rb_thread_t *th, int local_size, int stack_max) { - return vm_push_frame_(&th->ec, iseq, type, self, specval, cref_or_me, pc, sp, local_size, stack_max); + return vm_push_frame_(th->ec, iseq, type, self, specval, cref_or_me, pc, sp, local_size, stack_max); } rb_control_frame_t * @@ -293,7 +293,7 @@ vm_pop_frame(rb_thread_t *th, rb_control_frame_t *cfp, const VALUE *ep) if (VM_CHECK_MODE >= 4) rb_gc_verify_internal_consistency(); if (VMDEBUG == 2) SDR(); - th->ec.cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); + th->ec->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); return flags & VM_FRAME_FLAG_FINISH; } @@ -301,7 +301,7 @@ vm_pop_frame(rb_thread_t *th, rb_control_frame_t *cfp, const VALUE *ep) void rb_vm_pop_frame(rb_thread_t *th) { - vm_pop_frame(th, th->ec.cfp, th->ec.cfp->ep); + vm_pop_frame(th, th->ec->cfp, th->ec->cfp->ep); } /* method dispatch */ @@ -406,11 +406,11 @@ lep_svar(rb_thread_t *th, const VALUE *lep) { VALUE svar; - if (lep && (th == NULL || th->ec.root_lep != lep)) { + if (lep && (th == NULL || th->ec->root_lep != lep)) { svar = lep[VM_ENV_DATA_INDEX_ME_CREF]; } else { - svar = th->ec.root_svar; + svar = th->ec->root_svar; } VM_ASSERT(svar == Qfalse || vm_svar_valid_p(svar)); @@ -423,11 +423,11 @@ lep_svar_write(rb_thread_t *th, const VALUE *lep, const struct vm_svar *svar) { VM_ASSERT(vm_svar_valid_p((VALUE)svar)); - if (lep && (th == NULL || th->ec.root_lep != lep)) { + if (lep && (th == NULL || th->ec->root_lep != lep)) { vm_env_write(lep, VM_ENV_DATA_INDEX_ME_CREF, (VALUE)svar); } else { - RB_OBJ_WRITE(th->self, &th->ec.root_svar, svar); + RB_OBJ_WRITE(th->self, &th->ec->root_svar, svar); } } @@ -757,7 +757,7 @@ vm_cref_push(rb_thread_t *th, VALUE klass, const VALUE *ep, int pushed_by_eval) prev_cref = vm_env_cref(ep); } else { - rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->ec->cfp); if (cfp) { prev_cref = vm_env_cref(cfp->ep); @@ -830,7 +830,7 @@ vm_get_ev_const(rb_thread_t *th, VALUE orig_klass, ID id, int is_defined) if (orig_klass == Qnil) { /* in current lexical scope */ - const rb_cref_t *root_cref = rb_vm_get_cref(th->ec.cfp->ep); + const rb_cref_t *root_cref = rb_vm_get_cref(th->ec->cfp->ep); const rb_cref_t *cref; VALUE klass = Qnil; @@ -876,10 +876,10 @@ vm_get_ev_const(rb_thread_t *th, VALUE orig_klass, ID id, int is_defined) /* search self */ if (root_cref && !NIL_P(CREF_CLASS(root_cref))) { - klass = vm_get_iclass(th->ec.cfp, CREF_CLASS(root_cref)); + klass = vm_get_iclass(th->ec->cfp, CREF_CLASS(root_cref)); } else { - klass = CLASS_OF(th->ec.cfp->self); + klass = CLASS_OF(th->ec->cfp->self); } if (is_defined) { @@ -1066,16 +1066,16 @@ vm_throw_continue(rb_thread_t *th, VALUE err) /* continue throw */ if (FIXNUM_P(err)) { - th->ec.tag->state = FIX2INT(err); + th->ec->tag->state = FIX2INT(err); } else if (SYMBOL_P(err)) { - th->ec.tag->state = TAG_THROW; + th->ec->tag->state = TAG_THROW; } else if (THROW_DATA_P(err)) { - th->ec.tag->state = THROW_DATA_STATE((struct vm_throw_data *)err); + th->ec->tag->state = THROW_DATA_STATE((struct vm_throw_data *)err); } else { - th->ec.tag->state = TAG_RAISE; + th->ec->tag->state = TAG_RAISE; } return err; } @@ -1230,7 +1230,7 @@ vm_throw_start(rb_thread_t *const th, rb_control_frame_t *const reg_cfp, enum ru rb_bug("isns(throw): unsupport throw type"); } - th->ec.tag->state = state; + th->ec->tag->state = state; return (VALUE)THROW_DATA_NEW(throwobj, escape_cfp, state); } @@ -1554,8 +1554,8 @@ vm_base_ptr(const rb_control_frame_t *cfp) #if VM_DEBUG_BP_CHECK if (bp != cfp->bp_check) { fprintf(stderr, "bp_check: %ld, bp: %ld\n", - (long)(cfp->bp_check - GET_THREAD()->ec.vm_stack), - (long)(bp - GET_THREAD()->ec.vm_stack)); + (long)(cfp->bp_check - GET_THREAD()->ec->vm_stack), + (long)(bp - GET_THREAD()->ec->vm_stack)); rb_bug("vm_base_ptr: unreachable"); } #endif @@ -1624,7 +1624,7 @@ vm_callee_setup_arg(rb_thread_t *th, struct rb_calling_info *calling, const stru const rb_iseq_t *iseq, VALUE *argv, int param_size, int local_size) { if (LIKELY(simple_iseq_p(iseq) && !(ci->flag & VM_CALL_KW_SPLAT))) { - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; CALLER_SETUP_ARG(cfp, calling, ci); /* splat arg */ @@ -1707,7 +1707,7 @@ vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_ } vm_pop_frame(th, cfp, cfp->ep); - cfp = th->ec.cfp; + cfp = th->ec->cfp; sp_orig = sp = cfp->sp; @@ -1873,7 +1873,7 @@ static inline int vm_cfp_consistent_p(rb_thread_t *th, const rb_control_frame_t *reg_cfp) { const int ov_flags = RAISED_STACKOVERFLOW; - if (LIKELY(reg_cfp == th->ec.cfp + 1)) return TRUE; + if (LIKELY(reg_cfp == th->ec->cfp + 1)) return TRUE; if (rb_thread_raised_p(th, ov_flags)) { rb_thread_raised_reset(th, ov_flags); return TRUE; @@ -1883,7 +1883,7 @@ vm_cfp_consistent_p(rb_thread_t *th, const rb_control_frame_t *reg_cfp) #define CHECK_CFP_CONSISTENCY(func) \ (LIKELY(vm_cfp_consistent_p(th, reg_cfp)) ? (void)0 : \ - rb_bug(func ": cfp consistency error (%p, %p)", reg_cfp, th->ec.cfp+1)) + rb_bug(func ": cfp consistency error (%p, %p)", reg_cfp, th->ec->cfp+1)) static inline const rb_method_cfunc_t * @@ -1930,7 +1930,7 @@ vm_call_cfunc_with_frame(rb_thread_t *th, rb_control_frame_t *reg_cfp, struct rb vm_push_frame(th, NULL, VM_FRAME_MAGIC_CFUNC | VM_FRAME_FLAG_CFRAME | VM_ENV_FLAG_LOCAL, recv, block_handler, (VALUE)me, - 0, th->ec.cfp->sp, 0, 0); + 0, th->ec->cfp->sp, 0, 0); if (len >= 0) rb_check_arity(argc, len, len); @@ -2564,7 +2564,7 @@ vm_yield_with_cfunc(rb_thread_t *th, self, VM_GUARDED_PREV_EP(captured->ep), (VALUE)me, - 0, th->ec.cfp->sp, 0, 0); + 0, th->ec->cfp->sp, 0, 0); val = (*ifunc->func)(arg, ifunc->data, argc, argv, blockarg); rb_vm_pop_frame(th); @@ -2609,7 +2609,7 @@ static int vm_callee_setup_block_arg(rb_thread_t *th, struct rb_calling_info *calling, const struct rb_call_info *ci, const rb_iseq_t *iseq, VALUE *argv, const enum arg_setup_type arg_setup_type) { if (simple_iseq_p(iseq)) { - rb_control_frame_t *cfp = th->ec.cfp; + rb_control_frame_t *cfp = th->ec->cfp; VALUE arg0; CALLER_SETUP_ARG(cfp, calling, ci); /* splat arg */ @@ -2694,7 +2694,7 @@ vm_invoke_symbol_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, { VALUE val; int argc; - CALLER_SETUP_ARG(th->ec.cfp, calling, ci); + CALLER_SETUP_ARG(th->ec->cfp, calling, ci); argc = calling->argc; val = vm_yield_with_symbol(th, symbol, argc, STACK_ADDR_FROM_TOP(argc), VM_BLOCK_HANDLER_NONE); POPN(argc); @@ -2708,7 +2708,7 @@ vm_invoke_ifunc_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, { VALUE val; int argc; - CALLER_SETUP_ARG(th->ec.cfp, calling, ci); + CALLER_SETUP_ARG(th->ec->cfp, calling, ci); argc = calling->argc; val = vm_yield_with_cfunc(th, captured, captured->self, argc, STACK_ADDR_FROM_TOP(argc), VM_BLOCK_HANDLER_NONE); POPN(argc); /* TODO: should put before C/yield? */ @@ -2773,7 +2773,7 @@ static VALUE vm_make_proc_with_iseq(const rb_iseq_t *blockiseq) { rb_thread_t *th = GET_THREAD(); - const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); struct rb_captured_block *captured; if (cfp == 0) { @@ -3313,7 +3313,7 @@ vm_once_dispatch(ISEQ iseq, IC ic, rb_thread_t *th) val = is->once.value = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is); /* is->once.running_thread is cleared by vm_once_clear() */ is->once.running_thread = RUNNING_THREAD_ONCE_DONE; /* success */ - rb_iseq_add_mark_object(th->ec.cfp->iseq, val); + rb_iseq_add_mark_object(th->ec->cfp->iseq, val); return val; } else if (is->once.running_thread == th) { diff --git a/vm_insnhelper.h b/vm_insnhelper.h index 065496912e..62df3ee11d 100644 --- a/vm_insnhelper.h +++ b/vm_insnhelper.h @@ -54,7 +54,7 @@ RUBY_SYMBOL_EXPORT_END #define VM_REG_EP (VM_REG_CFP->ep) #define RESTORE_REGS() do { \ - VM_REG_CFP = th->ec.cfp; \ + VM_REG_CFP = th->ec->cfp; \ } while (0) #define REG_A reg_a @@ -102,7 +102,7 @@ enum vm_regan_acttype { #define SET_SV(x) (*GET_SP() = (x)) /* set current stack value as x */ -#define GET_SP_COUNT() (VM_REG_SP - th->ec.vm_stack) +#define GET_SP_COUNT() (VM_REG_SP - th->ec->vm_stack) /* instruction sequence C struct */ #define GET_ISEQ() (GET_CFP()->iseq) diff --git a/vm_method.c b/vm_method.c index 2320b54aed..9b2dd1fc8a 100644 --- a/vm_method.c +++ b/vm_method.c @@ -264,7 +264,7 @@ method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, def->body.attr.id = (ID)(VALUE)opts; - cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (cfp && (line = rb_vm_get_sourceline(cfp))) { VALUE location = rb_ary_new3(2, rb_iseq_path(cfp->iseq), INT2FIX(line)); @@ -1089,7 +1089,7 @@ static rb_method_visibility_t rb_scope_visibility_get(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (!vm_env_cref_by_cref(cfp->ep)) { return METHOD_VISI_PUBLIC; @@ -1103,7 +1103,7 @@ static int rb_scope_module_func_check(void) { rb_thread_t *th = GET_THREAD(); - rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); + rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec->cfp); if (!vm_env_cref_by_cref(cfp->ep)) { return FALSE; diff --git a/vm_trace.c b/vm_trace.c index fe07967606..c143cc3d65 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -304,31 +304,31 @@ rb_threadptr_exec_event_hooks_orig(rb_trace_arg_t *trace_arg, int pop_p) rb_thread_t *th = trace_arg->th; if (trace_arg->event & RUBY_INTERNAL_EVENT_MASK) { - if (th->ec.trace_arg && (th->ec.trace_arg->event & RUBY_INTERNAL_EVENT_MASK)) { + if (th->ec->trace_arg && (th->ec->trace_arg->event & RUBY_INTERNAL_EVENT_MASK)) { /* skip hooks because this thread doing INTERNAL_EVENT */ } else { - rb_trace_arg_t *prev_trace_arg = th->ec.trace_arg; + rb_trace_arg_t *prev_trace_arg = th->ec->trace_arg; th->vm->trace_running++; - th->ec.trace_arg = trace_arg; + th->ec->trace_arg = trace_arg; exec_hooks_unprotected(th, &th->event_hooks, trace_arg); exec_hooks_unprotected(th, &th->vm->event_hooks, trace_arg); - th->ec.trace_arg = prev_trace_arg; + th->ec->trace_arg = prev_trace_arg; th->vm->trace_running--; } } else { - if (th->ec.trace_arg == NULL && /* check reentrant */ + if (th->ec->trace_arg == NULL && /* check reentrant */ trace_arg->self != rb_mRubyVMFrozenCore /* skip special methods. TODO: remove it. */) { - const VALUE errinfo = th->ec.errinfo; - const VALUE old_recursive = th->ec.local_storage_recursive_hash; + const VALUE errinfo = th->ec->errinfo; + const VALUE old_recursive = th->ec->local_storage_recursive_hash; int state = 0; - th->ec.local_storage_recursive_hash = th->ec.local_storage_recursive_hash_for_trace; - th->ec.errinfo = Qnil; + th->ec->local_storage_recursive_hash = th->ec->local_storage_recursive_hash_for_trace; + th->ec->errinfo = Qnil; th->vm->trace_running++; - th->ec.trace_arg = trace_arg; + th->ec->trace_arg = trace_arg; { /* thread local traces */ state = exec_hooks_protected(th, &th->event_hooks, trace_arg); @@ -338,19 +338,19 @@ rb_threadptr_exec_event_hooks_orig(rb_trace_arg_t *trace_arg, int pop_p) state = exec_hooks_protected(th, &th->vm->event_hooks, trace_arg); if (state) goto terminate; - th->ec.errinfo = errinfo; + th->ec->errinfo = errinfo; } terminate: - th->ec.trace_arg = NULL; + th->ec->trace_arg = NULL; th->vm->trace_running--; - th->ec.local_storage_recursive_hash_for_trace = th->ec.local_storage_recursive_hash; - th->ec.local_storage_recursive_hash = old_recursive; + th->ec->local_storage_recursive_hash_for_trace = th->ec->local_storage_recursive_hash; + th->ec->local_storage_recursive_hash = old_recursive; if (state) { if (pop_p) { - if (VM_FRAME_FINISHED_P(th->ec.cfp)) { - th->ec.tag = th->ec.tag->prev; + if (VM_FRAME_FINISHED_P(th->ec->cfp)) { + th->ec->tag = th->ec->tag->prev; } rb_vm_pop_frame(th); } @@ -379,12 +379,12 @@ rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg) VALUE result = Qnil; rb_thread_t *volatile th = GET_THREAD(); enum ruby_tag_type state; - const int tracing = th->ec.trace_arg ? 1 : 0; + const int volatile tracing = th->ec->trace_arg ? 1 : 0; rb_trace_arg_t dummy_trace_arg; dummy_trace_arg.event = 0; if (!tracing) th->vm->trace_running++; - if (!th->ec.trace_arg) th->ec.trace_arg = &dummy_trace_arg; + if (!th->ec->trace_arg) th->ec->trace_arg = &dummy_trace_arg; raised = rb_threadptr_reset_raised(th); @@ -398,7 +398,7 @@ rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg) rb_threadptr_set_raised(th); } - if (th->ec.trace_arg == &dummy_trace_arg) th->ec.trace_arg = 0; + if (th->ec->trace_arg == &dummy_trace_arg) th->ec->trace_arg = 0; if (!tracing) th->vm->trace_running--; if (state) { @@ -706,7 +706,7 @@ tpptr(VALUE tpval) static rb_trace_arg_t * get_trace_arg(void) { - rb_trace_arg_t *trace_arg = GET_THREAD()->ec.trace_arg; + rb_trace_arg_t *trace_arg = GET_THREAD()->ec->trace_arg; if (trace_arg == 0) { rb_raise(rb_eRuntimeError, "access from outside"); } @@ -1310,7 +1310,7 @@ static VALUE tracepoint_inspect(VALUE self) { rb_tp_t *tp = tpptr(self); - rb_trace_arg_t *trace_arg = GET_THREAD()->ec.trace_arg; + rb_trace_arg_t *trace_arg = GET_THREAD()->ec->trace_arg; if (trace_arg) { switch (trace_arg->event) { @@ -1591,12 +1591,12 @@ rb_postponed_job_register_one(unsigned int flags, rb_postponed_job_func_t func, void rb_postponed_job_flush(rb_vm_t *vm) { - rb_thread_t *th = GET_THREAD(); + rb_thread_t * volatile th = GET_THREAD(); const unsigned long block_mask = POSTPONED_JOB_INTERRUPT_MASK|TRAP_INTERRUPT_MASK; - unsigned long saved_mask = th->interrupt_mask & block_mask; - VALUE saved_errno = th->ec.errinfo; + volatile unsigned long saved_mask = th->interrupt_mask & block_mask; + VALUE volatile saved_errno = th->ec->errinfo; - th->ec.errinfo = Qnil; + th->ec->errinfo = Qnil; /* mask POSTPONED_JOB dispatch */ th->interrupt_mask |= block_mask; { @@ -1614,5 +1614,5 @@ rb_postponed_job_flush(rb_vm_t *vm) } /* restore POSTPONED_JOB mask */ th->interrupt_mask &= ~(saved_mask ^ block_mask); - th->ec.errinfo = saved_errno; + th->ec->errinfo = saved_errno; } -- cgit v1.2.3