From bd26be2b3479a0e4ce75179d56de9d6d10be528b Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 26 Nov 2013 09:42:04 +0000 Subject: * vm_trace.c: skip "exception check" and "reentrant check (only normal events) for internal events. Reentrant check for internal events are remaining. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43855 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- vm_trace.c | 133 +++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 82 insertions(+), 51 deletions(-) (limited to 'vm_trace.c') diff --git a/vm_trace.c b/vm_trace.c index 369bd7c4f1..3a88811286 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -251,15 +251,50 @@ clean_hooks(rb_hook_list_t *list) } } +static void +exec_hooks_body(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg) +{ + rb_event_hook_t *hook; + + for (hook = list->hooks; hook; hook = hook->next) { + if (!(hook->hook_flags & RUBY_EVENT_HOOK_FLAG_DELETED) && (trace_arg->event & hook->events)) { + if (!(hook->hook_flags & RUBY_EVENT_HOOK_FLAG_RAW_ARG)) { + (*hook->func)(trace_arg->event, hook->data, trace_arg->self, trace_arg->id, trace_arg->klass); + } + else { + (*((rb_event_hook_raw_arg_func_t)hook->func))(hook->data, trace_arg); + } + } + } +} + static int -exec_hooks(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg, int can_clean_hooks) +exec_hooks_precheck(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg) +{ + if ((list->events & trace_arg->event) == 0) return 0; + + if (UNLIKELY(list->need_clean > 0)) { + if (th->vm->trace_running <= 1) { /* only running this hooks */ + clean_hooks(list); + } + } + return 1; +} + +static void +exec_hooks_unprotected(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg) +{ + if (exec_hooks_precheck(th, list, trace_arg) == 0) return; + exec_hooks_body(th, list, trace_arg); +} + +static int +exec_hooks_protected(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg) { int state; volatile int raised; - if (UNLIKELY(list->need_clean > 0) && can_clean_hooks) { - clean_hooks(list); - } + if (exec_hooks_precheck(th, list, trace_arg) == 0) return 0; raised = rb_threadptr_reset_raised(th); @@ -267,18 +302,7 @@ exec_hooks(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_ar TH_PUSH_TAG(th); if ((state = TH_EXEC_TAG()) == 0) { - rb_event_hook_t *hook; - - for (hook = list->hooks; hook; hook = hook->next) { - if (!(hook->hook_flags & RUBY_EVENT_HOOK_FLAG_DELETED) && (trace_arg->event & hook->events)) { - if (!(hook->hook_flags & RUBY_EVENT_HOOK_FLAG_RAW_ARG)) { - (*hook->func)(trace_arg->event, hook->data, trace_arg->self, trace_arg->id, trace_arg->klass); - } - else { - (*((rb_event_hook_raw_arg_func_t)hook->func))(hook->data, trace_arg); - } - } - } + exec_hooks_body(th, list, trace_arg); } TH_POP_TAG(); @@ -293,49 +317,56 @@ 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->errinfo = Qnil; - - 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 (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 */ - list = &th->vm->event_hooks; - if (list->events & trace_arg->event) { - state = exec_hooks(th, list, trace_arg, !vm_tracing); + /* vm global traces */ + state = exec_hooks_protected(th, &th->vm->event_hooks, trace_arg); if (state) goto terminate; + + th->errinfo = errinfo; } - 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; + 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->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); + TH_JUMP_TAG(th, state); } - TH_JUMP_TAG(th, state); + th->state = outer_state; } - th->state = outer_state; } } -- cgit v1.2.3