[#25636] [Oniguruma 3.X] reggnu.c — "K.Kosako" <sndgk393@...>

さっき気がついたのですが、元々は

15 messages 2005/02/05

[#25655] openssl binding for SSL_CTX_set_default_verify_paths and X509_STORE_set_default_paths — Tanaka Akira <akr@...17n.org>

open-uri で https を扱うことを考えていろいろと調べていた所、openssl で、

9 messages 2005/02/08
[#25670] Re: openssl binding for SSL_CTX_set_default_verify_paths and X509_STORE_set_default_paths — GOTOU Yuuzou <gotoyuzo@...> 2005/02/10

In message <876513vce0.fsf@serein.a02.aist.go.jp>,

[#25713] pthread trouble on sighandler — Hidetoshi NAGAI <nagai@...>

永井@知能.九工大です.

17 messages 2005/02/18
[#25714] Re: pthread trouble on sighandler — Yukihiro Matsumoto <matz@...> 2005/02/18

まつもと ゆきひろです

[#25755] I/O operation differs signal handler — Minero Aoki <aamine@...>

青木です。

14 messages 2005/02/24
[#25756] Re: I/O operation differs signal handler — Tanaka Akira <akr@...17n.org> 2005/02/24

In article <20050224091450P.aamine@loveruby.net>,

[ruby-dev:25647] C level set_trace_func

From: Shugo Maeda <shugo@...>
Date: 2005-02-07 02:46:45 UTC
List: ruby-dev #25647
前田です。

今Cでプロファイラを書いているのですが、Cレベルでset_trace_funcのような
ことができるようにしていただけないでしょうか。

今考えているのは、

static void
prof_event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE
klass)
{
    ...
}

のような関数を用意しておいて、

    rb_set_event_hook(prof_event_hook,
                      RUBY_EVENT_CALL | RUBY_EVENT_RETURN |
                      RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN);

とすると、rb_set_event_hook()の第二引数で指定したイベントだけフック
できる、というものです。
パッチを添付していますが、オーバーへッドはほとんどないと思います。
ちなみに、このパッチではset_trace_funcも上記の機能で実現しています。

-- 
前田 修吾

Attachments (1)

ruby-event-hook.diff (7.91 KB, text/x-diff)
Index: eval.c
===================================================================
RCS file: /src/ruby/eval.c,v
retrieving revision 1.748
diff -u -r1.748 eval.c
--- eval.c	5 Jan 2005 03:49:50 -0000	1.748
+++ eval.c	5 Feb 2005 15:47:36 -0000
@@ -1017,9 +1017,18 @@
 static VALUE massign _((VALUE,NODE*,VALUE,int));
 static void assign _((VALUE,NODE*,VALUE,int));
 
+static rb_event_t hooked_events;
+static rb_event_hook_t event_hook;
+
+#define EXEC_EVENT_HOOK(event, node, self, id, klass) \
+    do { \
+	if (hooked_events & event) \
+	    (*event_hook)(event, node, self, id, klass); \
+    } while (0)
+
 static VALUE trace_func = 0;
 static int tracing = 0;
-static void call_trace_func _((char*,NODE*,VALUE,ID,VALUE));
+static void call_trace_func _((rb_event_t,NODE*,VALUE,ID,VALUE));
 
 #if 0
 #define SET_CURRENT_SOURCE() (ruby_sourcefile = ruby_current_node->nd_file, \
@@ -2370,6 +2379,18 @@
     return Qfalse;
 }
 
+void
+rb_set_event_hook(rb_event_hook_t hook, rb_event_t events)
+{
+    event_hook = hook;
+    if (event_hook == 0) {
+	hooked_events = RUBY_EVENT_NONE;
+    }
+    else {
+	hooked_events = events;
+    }
+}
+
 /*
  *  call-seq:
  *     set_trace_func(proc)    => proc
@@ -2420,17 +2441,45 @@
 {
     if (NIL_P(trace)) {
 	trace_func = 0;
+	rb_set_event_hook(0, RUBY_EVENT_NONE);
 	return Qnil;
     }
     if (!rb_obj_is_proc(trace)) {
 	rb_raise(rb_eTypeError, "trace_func needs to be Proc");
     }
-    return trace_func = trace;
+    trace_func = trace;
+    rb_set_event_hook(call_trace_func, RUBY_EVENT_ALL);
+    return trace;
+}
+
+static char *
+get_event_name(rb_event_t event)
+{
+    switch (event) {
+    case RUBY_EVENT_LINE:
+	return "line";
+    case RUBY_EVENT_CLASS:
+	return "class";
+    case RUBY_EVENT_END:
+	return "end";
+    case RUBY_EVENT_CALL:
+	return "call";
+    case RUBY_EVENT_RETURN:
+	return "return";
+    case RUBY_EVENT_C_CALL:
+	return "c-call";
+    case RUBY_EVENT_C_RETURN:
+	return "c-return";
+    case RUBY_EVENT_RAISE:
+	return "raise";
+    default:
+	return "unknown";
+    }
 }
 
 static void
 call_trace_func(event, node, self, id, klass)
-    char *event;
+    rb_event_t event;
     NODE *node;
     VALUE self;
     ID id;
@@ -2440,6 +2489,7 @@
     struct FRAME *prev;
     NODE *node_save;
     VALUE srcfile;
+    char *event_name;
 
     if (!trace_func) return;
     if (tracing) return;
@@ -2474,7 +2524,8 @@
     raised = thread_reset_raised();
     if ((state = EXEC_TAG()) == 0) {
 	srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)");
-	proc_invoke(trace_func, rb_ary_new3(6, rb_str_new2(event),
+	event_name = get_event_name(event);
+	proc_invoke(trace_func, rb_ary_new3(6, rb_str_new2(event_name),
 					    srcfile,
 					    INT2FIX(ruby_sourceline),
 					    id?ID2SYM(id):Qnil,
@@ -2641,8 +2692,8 @@
     if (!node) RETURN(Qnil);
 
     ruby_current_node = node;
-    if (trace_func && (node->flags & NODE_NEWLINE)) {
-	call_trace_func("line", node, self,
+    if (node->flags & NODE_NEWLINE) {
+	EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, 
 			ruby_frame->last_func,
 			ruby_frame->last_class);
     }
@@ -2738,11 +2789,9 @@
 	RETURN(ruby_errinfo);
 
       case NODE_IF:
-	if (trace_func) {
-	    call_trace_func("line", node, self,
-			    ruby_frame->last_func,
-			    ruby_frame->last_class);
-	}
+	EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self,
+			ruby_frame->last_func,
+			ruby_frame->last_class);
 	if (RTEST(rb_eval(self, node->nd_cond))) {
 	    node = node->nd_body;
 	}
@@ -2758,11 +2807,9 @@
 	    if (nd_type(node) != NODE_WHEN) goto again;
 	    tag = node->nd_head;
 	    while (tag) {
-		if (trace_func) {
-		    call_trace_func("line", tag, self,
-				    ruby_frame->last_func,
-				    ruby_frame->last_class);
-		}
+		EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
+				ruby_frame->last_func,
+				ruby_frame->last_class);
 		if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
 		    VALUE v = rb_eval(self, tag->nd_head->nd_head);
 		    long i;
@@ -2801,11 +2848,9 @@
 		}
 		tag = node->nd_head;
 		while (tag) {
-		    if (trace_func) {
-			call_trace_func("line", tag, self,
-					ruby_frame->last_func,
-					ruby_frame->last_class);
-		    }
+		    EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self,
+				    ruby_frame->last_func,
+				    ruby_frame->last_class);
 		    if (tag->nd_head && nd_type(tag->nd_head) == NODE_WHEN) {
 			VALUE v = rb_eval(self, tag->nd_head->nd_head);
 			long i;
@@ -3911,9 +3956,7 @@
     PUSH_CREF(module);
     PUSH_TAG(PROT_NONE);
     if ((state = EXEC_TAG()) == 0) {
-	if (trace_func) {
-	    call_trace_func("class", n, ruby_cbase, ruby_frame->last_func, ruby_frame->last_class);
-	}
+	EXEC_EVENT_HOOK(RUBY_EVENT_CLASS, n, ruby_cbase, ruby_frame->last_func, ruby_frame->last_class);
 	result = rb_eval(ruby_cbase, node->nd_next);
     }
     POP_TAG();
@@ -3923,9 +3966,7 @@
     POP_CLASS();
 
     ruby_frame = frame.tmp;
-    if (trace_func) {
-	call_trace_func("end", n, 0, ruby_frame->last_func, ruby_frame->last_class);
-    }
+    EXEC_EVENT_HOOK(RUBY_EVENT_END, n, 0, ruby_frame->last_func, ruby_frame->last_class);
     if (state) JUMP_TAG(state);
 
     return result;
@@ -4320,8 +4361,8 @@
     }
 
     rb_trap_restore_mask();
-    if (trace_func && tag != TAG_FATAL) {
-	call_trace_func("raise", ruby_current_node,
+    if (tag != TAG_FATAL) {
+	EXEC_EVENT_HOOK(RUBY_EVENT_RAISE, ruby_current_node,
 			ruby_frame->self,
 			ruby_frame->last_func,
 			ruby_frame->last_class);
@@ -4541,10 +4582,9 @@
 	{ 
 	    tt->dst = (VALUE)tt->frame->uniq;
 	    tt->retval = retval;
-	    if (trace_func) {
-		struct FRAME *f = tt->frame;
-		call_trace_func("return", f->node, f->self, f->last_func, f->last_class);
-	    }
+	    EXEC_EVENT_HOOK(RUBY_EVENT_RETURN,
+			    tt->frame->node, tt->frame->self,
+			    tt->frame->last_func, tt->frame->last_class);
 	    JUMP_TAG(TAG_RETURN);
 	}
 	if (tt->tag == PROT_THREAD) {
@@ -5542,17 +5582,19 @@
 		rb_bug("bad argc(%d) specified for `%s(%s)'",
 		       len, rb_class2name(klass), rb_id2name(id));
 	    }
-	    if (trace_func) {
+	    if (hooked_events & (RUBY_EVENT_C_CALL | RUBY_EVENT_C_RETURN)) {
 		int state;
 
-		call_trace_func("c-call", ruby_current_node, recv, id, klass);
+		EXEC_EVENT_HOOK(RUBY_EVENT_C_CALL, ruby_current_node,
+				recv, id, klass);
 		PUSH_TAG(PROT_FUNC);
 		if ((state = EXEC_TAG()) == 0) {
 		    result = call_cfunc(body->nd_cfnc, recv, len, argc, argv);
 		}
 		POP_TAG();
 		ruby_current_node = ruby_frame->node;
-		call_trace_func("c-return", ruby_current_node, recv, id, klass);
+		EXEC_EVENT_HOOK(RUBY_EVENT_C_RETURN, ruby_current_node,
+				recv, id, klass);
 		if (state) JUMP_TAG(state);
 	    }
 	    else {
@@ -5682,13 +5724,9 @@
 		    ruby_frame->argc = -(ruby_frame->argc - argc)-1;
 		}
 
-		if (trace_func) {
-		    call_trace_func("call", b2, recv, id, klass);
-		}
+		EXEC_EVENT_HOOK(RUBY_EVENT_CALL, b2, recv, id, klass);
 		result = rb_eval(recv, body);
-		if (trace_func) {
-		    call_trace_func("return", body, recv, id, klass);
-		}
+		EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, body, recv, id, klass);
 	    }
 	    else if (state == TAG_RETURN && TAG_DST()) {
 		result = prot_tag->retval;
Index: node.h
===================================================================
RCS file: /src/ruby/node.h,v
retrieving revision 1.61
diff -u -r1.61 node.h
--- node.h	16 Dec 2004 15:01:49 -0000	1.61
+++ node.h	5 Feb 2005 15:47:36 -0000
@@ -364,6 +364,22 @@
 VALUE rb_gvar_set _((struct global_entry *, VALUE));
 VALUE rb_gvar_defined _((struct global_entry *));
 
+typedef unsigned int rb_event_t;
+
+#define RUBY_EVENT_NONE     0x00
+#define RUBY_EVENT_LINE     0x01
+#define RUBY_EVENT_CLASS    0x02
+#define RUBY_EVENT_END      0x04
+#define RUBY_EVENT_CALL     0x08
+#define RUBY_EVENT_RETURN   0x10
+#define RUBY_EVENT_C_CALL   0x20
+#define RUBY_EVENT_C_RETURN 0x40
+#define RUBY_EVENT_RAISE    0x80
+#define RUBY_EVENT_ALL      0xff
+
+typedef void (*rb_event_hook_t)_((rb_event_t,NODE*,VALUE,ID,VALUE));
+void rb_set_event_hook(rb_event_hook_t,rb_event_t);
+
 #if defined(__cplusplus)
 }  /* extern "C" { */
 #endif

In This Thread

Prev Next