static void 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->trace_arg && (th->trace_arg->event & RUBY_INTERNAL_EVENT_MASK)) { /* skip hooks because this thread doing INTERNAL_EVENT */ } else { rb_trace_arg_t *prev_trace_arg = th->trace_arg; th->trace_arg = trace_arg; exec_hooks_unprotected(th, &th->event_hooks, trace_arg); exec_hooks_unprotected(th, &th->vm->event_hooks, trace_arg); th->trace_arg = prev_trace_arg; } } else { if (th->trace_arg == 0 && /* check reentrant */ trace_arg->self != rb_mRubyVMFrozenCore /* skip special methods. TODO: remove it. */) { const VALUE errinfo = th->errinfo; const int outer_state = th->state; int state = 0; th->state = 0; th->errinfo = Qnil; th->vm->trace_running++; th->trace_arg = trace_arg; { /* thread local traces */ state = exec_hooks_protected(th, &th->event_hooks, trace_arg); if (state) goto terminate; /* vm global traces */ state = exec_hooks_protected(th, &th->vm->event_hooks, trace_arg); if (state) goto terminate; th->errinfo = errinfo; } terminate: th->trace_arg = 0; th->vm->trace_running--; if (state) { if (pop_p) { if (VM_FRAME_TYPE_FINISH_P(th->cfp)) { th->tag = th->tag->prev; } th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); } TH_JUMP_TAG(th, state); } th->state = outer_state; } } }
static void vm_iter_break(rb_thread_t *th) { rb_control_frame_t *cfp = th->cfp; VALUE *dfp = GC_GUARDED_PTR_REF(*cfp->dfp); th->state = TAG_BREAK; th->errinfo = (VALUE)NEW_THROW_OBJECT(Qnil, (VALUE)dfp, TAG_BREAK); TH_JUMP_TAG(th, TAG_BREAK); }
static void rb_threadptr_exec_event_hooks_orig(rb_trace_arg_t *trace_arg, int pop_p) { rb_thread_t *th = trace_arg->th; if (th->trace_arg == 0 && trace_arg->self != rb_mRubyVMFrozenCore /* skip special methods. TODO: remove it. */) { const int vm_tracing = th->vm->trace_running; const VALUE errinfo = th->errinfo; const int outer_state = th->state; int state = 0; th->state = 0; th->vm->trace_running++; th->trace_arg = trace_arg; { rb_hook_list_t *list; /* thread local traces */ list = &th->event_hooks; if (list->events & trace_arg->event) { state = exec_hooks(th, list, trace_arg, TRUE); if (state) goto terminate; } /* vm global traces */ list = &th->vm->event_hooks; if (list->events & trace_arg->event) { state = exec_hooks(th, list, trace_arg, !vm_tracing); if (state) goto terminate; } th->errinfo = errinfo; } terminate: th->trace_arg = 0; th->vm->trace_running--; if (state) { if (pop_p) { if (VM_FRAME_TYPE_FINISH_P(th->cfp)) { th->tag = th->tag->prev; } th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); } TH_JUMP_TAG(th, state); } th->state = outer_state; } }
static inline VALUE vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp, int num, ID id, ID oid, VALUE recv, VALUE klass, VALUE flag, const NODE *mn, const rb_block_t *blockptr) { VALUE val = 0; int state = 0; EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass); TH_PUSH_TAG(th); if (th->event_flags & RUBY_EVENT_C_RETURN) { state = TH_EXEC_TAG(); } else { _th->tag = _tag.prev; } if (state == 0) { rb_control_frame_t *cfp = vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1); cfp->method_id = oid; cfp->method_class = klass; reg_cfp->sp -= num + 1; val = call_cfunc(mn->nd_cfnc, recv, mn->nd_argc, num, reg_cfp->sp + 1); if (reg_cfp != th->cfp + 1) { rb_bug("cfp consistency error - send"); } vm_pop_frame(th); } TH_POP_TAG(); EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass); if (state) TH_JUMP_TAG(th, state); return val; }
VALUE rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1, VALUE (* bl_proc) (ANYARGS), VALUE data2) { int state; volatile VALUE retval = Qnil; NODE *node = NEW_IFUNC(bl_proc, data2); rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = th->cfp; TH_PUSH_TAG(th); state = TH_EXEC_TAG(); if (state == 0) { iter_retry: { rb_block_t *blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(th->cfp); blockptr->iseq = (void *)node; blockptr->proc = 0; th->passed_block = blockptr; } retval = (*it_proc) (data1); } else { VALUE err = th->errinfo; if (state == TAG_BREAK) { VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err); VALUE *cdfp = cfp->dfp; if (cdfp == escape_dfp) { state = 0; th->state = 0; th->errinfo = Qnil; th->cfp = cfp; } else{ /* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */ } } else if (state == TAG_RETRY) { VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err); VALUE *cdfp = cfp->dfp; if (cdfp == escape_dfp) { state = 0; th->state = 0; th->errinfo = Qnil; th->cfp = cfp; goto iter_retry; } } } TH_POP_TAG(); switch (state) { case 0: break; default: TH_JUMP_TAG(th, state); } return retval; }