[前][次][番号順一覧][スレッド一覧]

ruby-changes:31776

From: ko1 <ko1@a...>
Date: Tue, 26 Nov 2013 18:42:14 +0900 (JST)
Subject: [ruby-changes:31776] ko1:r43855 (trunk): * vm_trace.c: skip "exception check" and "reentrant check (only normal

ko1	2013-11-26 18:42:04 +0900 (Tue, 26 Nov 2013)

  New Revision: 43855

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=43855

  Log:
    * vm_trace.c: skip "exception check" and "reentrant check (only normal
      events)  for internal events.
      Reentrant check for internal events are remaining.

  Modified files:
    trunk/ChangeLog
    trunk/vm_trace.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 43854)
+++ ChangeLog	(revision 43855)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Nov 26 18:12:13 2013  Koichi Sasada  <ko1@a...>
+
+	* vm_trace.c: skip "exception check" and "reentrant check (only normal
+	  events)  for internal events.
+
+	  Reentrant check for internal events are remaining.
+
 Tue Nov 26 17:38:16 2013  Koichi Sasada  <ko1@a...>
 
 	* vm_trace.c: prohibit to specify normal events and internal events
Index: vm_trace.c
===================================================================
--- vm_trace.c	(revision 43854)
+++ vm_trace.c	(revision 43855)
@@ -251,15 +251,50 @@ clean_hooks(rb_hook_list_t *list) https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L251
     }
 }
 
+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 https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L302
 
     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 https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L317
 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;
     }
 }
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]