ruby-changes:25950
From: ko1 <ko1@a...>
Date: Fri, 30 Nov 2012 07:43:38 +0900 (JST)
Subject: [ruby-changes:25950] ko1:r38007 (trunk): [EXPERIMENTAL: NEED DISCUSS]
ko1 2012-11-30 07:28:16 +0900 (Fri, 30 Nov 2012) New Revision: 38007 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=38007 Log: [EXPERIMENTAL: NEED DISCUSS] * vm_trace.c: add events * :thread_begin - hook at thread beggining. * :thead_end - hook at thread ending. * :b_call - hook at block enter. * :b_return - hook at block leave. This change slow down block invocation. Please try and give us feedback until 2.0 code freeze. * include/ruby/ruby.h: ditto. * compile.c (rb_iseq_compile_node): ditto. * insns.def: ditto. * thread.c: ditto. * vm.c: ditto. * include/ruby/debug.h: add a comment. * test/ruby/test_settracefunc.rb: add a tests. Modified files: trunk/ChangeLog trunk/compile.c trunk/include/ruby/debug.h trunk/include/ruby/ruby.h trunk/insns.def trunk/test/ruby/test_settracefunc.rb trunk/thread.c trunk/vm.c trunk/vm_trace.c Index: include/ruby/ruby.h =================================================================== --- include/ruby/ruby.h (revision 38006) +++ include/ruby/ruby.h (revision 38007) @@ -1574,6 +1574,13 @@ #define RUBY_EVENT_SWITCH 0x20000 #define RUBY_EVENT_COVERAGE 0x40000 +/* for TracePoint extended events */ +#define RUBY_EVENT_B_CALL 0x0100 +#define RUBY_EVENT_B_RETURN 0x0200 +#define RUBY_EVENT_THREAD_BEGIN 0x0400 +#define RUBY_EVENT_THREAD_END 0x0800 +#define RUBY_EVENT_TRACEPOINT_ALL 0xFFFF + typedef unsigned int rb_event_flag_t; typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass); Index: include/ruby/debug.h =================================================================== --- include/ruby/debug.h (revision 38006) +++ include/ruby/debug.h (revision 38007) @@ -38,8 +38,10 @@ /* Old style set_trace_func APIs */ +/* duplicated def of include/ruby/ruby.h */ void rb_add_event_hook(rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); int rb_remove_event_hook(rb_event_hook_func_t func); + int rb_remove_event_hook_with_data(rb_event_hook_func_t func, VALUE data); void rb_thread_add_event_hook(VALUE thval, rb_event_hook_func_t func, rb_event_flag_t events, VALUE data); int rb_thread_remove_event_hook(VALUE thval, rb_event_hook_func_t func); Index: ChangeLog =================================================================== --- ChangeLog (revision 38006) +++ ChangeLog (revision 38007) @@ -1,3 +1,28 @@ +Fri Nov 30 07:21:33 2012 Koichi Sasada <ko1@a...> + + [EXPERIMENTAL: NEED DISCUSS] + * vm_trace.c: add events + * :thread_begin - hook at thread beggining. + * :thead_end - hook at thread ending. + * :b_call - hook at block enter. + * :b_return - hook at block leave. + This change slow down block invocation. + Please try and give us feedback until 2.0 code freeze. + + * include/ruby/ruby.h: ditto. + + * compile.c (rb_iseq_compile_node): ditto. + + * insns.def: ditto. + + * thread.c: ditto. + + * vm.c: ditto. + + * include/ruby/debug.h: add a comment. + + * test/ruby/test_settracefunc.rb: add a tests. + Fri Nov 30 06:56:30 2012 Ryan Davis <ryand-ruby@z...> * test/minitest/*: Imported minitest 4.3.2 (r8027) Index: insns.def =================================================================== --- insns.def (revision 38006) +++ insns.def (revision 38007) @@ -871,8 +871,9 @@ rb_sourceline()); } } + EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* id and klass are resolved at callee */, - flag & RUBY_EVENT_RETURN ? TOPN(0) : Qundef); + (flag & RUBY_EVENT_RETURN | RUBY_EVENT_B_RETURN) ? TOPN(0) : Qundef); } /**********************************************************/ Index: compile.c =================================================================== --- compile.c (revision 38006) +++ compile.c (revision 38007) @@ -475,31 +475,36 @@ iseq_set_arguments(iseq, ret, node->nd_args); switch (iseq->type) { - case ISEQ_TYPE_BLOCK: { - LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0); - LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0); + case ISEQ_TYPE_BLOCK: + { + LABEL *start = iseq->compile_data->start_label = NEW_LABEL(0); + LABEL *end = iseq->compile_data->end_label = NEW_LABEL(0); - ADD_LABEL(ret, start); - COMPILE(ret, "block body", node->nd_body); - ADD_LABEL(ret, end); + ADD_LABEL(ret, start); + ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_B_CALL); + COMPILE(ret, "block body", node->nd_body); + ADD_TRACE(ret, nd_line(node), RUBY_EVENT_B_RETURN); + ADD_LABEL(ret, end); - /* wide range catch handler must put at last */ - ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start); - ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end); - break; - } - case ISEQ_TYPE_CLASS: { - ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CLASS); - COMPILE(ret, "scoped node", node->nd_body); - ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END); - break; - } - case ISEQ_TYPE_METHOD: { - ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CALL); - COMPILE(ret, "scoped node", node->nd_body); - ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN); - break; - } + /* wide range catch handler must put at last */ + ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start); + ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end); + break; + } + case ISEQ_TYPE_CLASS: + { + ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CLASS); + COMPILE(ret, "scoped node", node->nd_body); + ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END); + break; + } + case ISEQ_TYPE_METHOD: + { + ADD_TRACE(ret, FIX2INT(iseq->location.first_lineno), RUBY_EVENT_CALL); + COMPILE(ret, "scoped node", node->nd_body); + ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN); + break; + } default: { COMPILE(ret, "scoped node", node->nd_body); break; Index: thread.c =================================================================== --- thread.c (revision 38006) +++ thread.c (revision 38007) @@ -478,8 +478,9 @@ th->errinfo = Qnil; th->root_lep = rb_vm_ep_local_ep(proc->block.ep); th->root_svar = Qnil; - th->value = rb_vm_invoke_proc(th, proc, - (int)RARRAY_LEN(args), RARRAY_PTR(args), 0); + EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_BEGIN, proc->block.self, 0, 0, th->self); + th->value = rb_vm_invoke_proc(th, proc, (int)RARRAY_LEN(args), RARRAY_PTR(args), 0); + EXEC_EVENT_HOOK(th, RUBY_EVENT_THREAD_END, proc->block.self, 0, 0, th->self); } else { th->value = (*th->first_func)((void *)args); Index: vm_trace.c =================================================================== --- vm_trace.c (revision 38006) +++ vm_trace.c (revision 38007) @@ -507,6 +507,10 @@ C(c_call, C_CALL); C(c_return, C_RETURN); C(raise, RAISE); + C(b_call, B_CALL); + C(b_return, B_RETURN); + C(thread_begin, THREAD_BEGIN); + C(thread_end, THREAD_END); #undef C default: return 0; @@ -610,6 +614,10 @@ C(c_call, C_CALL); C(c_return, C_RETURN); C(raise, RAISE); + C(b_call, B_CALL); + C(b_return, B_RETURN); + C(thread_begin, THREAD_BEGIN); + C(thread_end, THREAD_END); #undef C rb_raise(rb_eArgError, "unknown event: %s", rb_id2name(SYM2ID(sym))); } @@ -736,7 +744,7 @@ VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg) { - if (trace_arg->event & (RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN)) { + if (trace_arg->event & (RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN | RUBY_EVENT_B_RETURN)) { /* ok */ } else { @@ -975,7 +983,7 @@ } } else { - events = RUBY_EVENT_ALL; + events = RUBY_EVENT_TRACEPOINT_ALL; } if (!rb_block_given_p()) { Index: vm.c =================================================================== --- vm.c (revision 38006) +++ vm.c (revision 38007) @@ -1353,6 +1353,9 @@ RUBY_DTRACE_METHOD_RETURN_HOOK(th, 0, 0) EXEC_EVENT_HOOK(th, RUBY_EVENT_RETURN, th->cfp->self, 0, 0, Qnil); break; + case VM_FRAME_MAGIC_BLOCK: + EXEC_EVENT_HOOK(th, RUBY_EVENT_B_RETURN, th->cfp->self, 0, 0, Qnil); + break; case VM_FRAME_MAGIC_CLASS: EXEC_EVENT_HOOK(th, RUBY_EVENT_END, th->cfp->self, 0, 0, Qnil); break; Index: test/ruby/test_settracefunc.rb =================================================================== --- test/ruby/test_settracefunc.rb (revision 38006) +++ test/ruby/test_settracefunc.rb (revision 38007) @@ -532,9 +532,14 @@ end def test_tracepoint - events1, answer_events = *trace_by_tracepoint() + events1, answer_events = *trace_by_tracepoint(:line, :class, :end, :call, :return, :c_call, :c_return, :raise) mesg = events1.map{|e| + if false + p [:event, e[0]] + p [:line_file, e[1], e[2]] + p [:id, e[4]] + end "#{e[0]} - #{e[2]}:#{e[1]} id: #{e[4]}" }.join("\n") answer_events.zip(events1){|answer, event| @@ -682,4 +687,54 @@ end } end + + def method_for_test_tracepoint_block + yield + end + + def test_tracepoint_block + events = [] + TracePoint.new(:call, :return, :c_call, :b_call, :c_return, :b_return){|tp| + events << [ + tp.event, tp.method_id, tp.defined_class, tp.self.class, + /return/ =~ tp.event ? tp.return_value : nil + ] + }.enable{ + 1.times{ + 3 + } + method_for_test_tracepoint_block{ + 4 + } + } + # pp events + expected_events = + [[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil], + [:c_call, :times, Integer, Fixnum, nil], + [:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil], + [:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 3], + [:c_return, :times, Integer, Fixnum, 1], + [:call, :method_for_test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil], + [:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil], + [:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4], + [:return, :method_for_test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4], + [:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4] + ].zip(events){|expected, actual| + assert_equal(expected, actual) + } + end + + def test_tracepoint_thread + events = [] + created_thread = nil + TracePoint.new(:thread_begin, :thread_end){|tp| + events << [Thread.current, tp.event, tp.self] + }.enable{ + created_thread = Thread.new{} + created_thread.join + } + assert_equal([created_thread, :thread_begin, self], events[0]) + assert_equal([created_thread, :thread_end, self], events[1]) + assert_equal(2, events.size) + end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/