static int 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 int exec_hooks(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_arg, int can_clean_hooks) { int state; volatile int raised; if (UNLIKELY(list->need_clean > 0) && can_clean_hooks) { clean_hooks(list); } raised = rb_threadptr_reset_raised(th); /* TODO: Support !RUBY_EVENT_HOOK_FLAG_SAFE hooks */ TH_PUSH_TAG(th); if ((state = TH_EXEC_TAG()) == 0) { rb_event_hook_t *hook; for (hook = list->hooks; hook; hook = hook->next) { if (LIKELY(!(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); } } } } TH_POP_TAG(); if (raised) { rb_threadptr_set_raised(th); } return state; }