From 553931962a8a6c73ecef770831165070479c8763 Mon Sep 17 00:00:00 2001 From: ko1 Date: Tue, 20 Nov 2012 09:48:24 +0000 Subject: * vm_trace.c: add two methods: (1) TracePoint#return_value which returns return value on the :return and :c_return event. (2) TracePoint#raised_exception which returns raised exception value on the :raise event. Eeach methods raise RuntimeError if it is called at unsupported event. Please review and give us feedback until next preview release (Dec/2012) of Ruby 2.0.0. * insns.def, vm.c, vm_eval.c, vm_insnhelper.c, eval.c, thread.c: ditto. * vm_trace.c, vm_core.h: move definition of rb_trace_arg_t from vm_trace.c to vm_core.h. Caller fills rb_trace_arg_t and pass the pointer of this variable. * test/ruby/test_settracefunc.rb: fix tests to test this change. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37752 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- vm_trace.c | 69 +++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 23 deletions(-) (limited to 'vm_trace.c') diff --git a/vm_trace.c b/vm_trace.c index a1498a8511..cd45b859a4 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -44,15 +44,6 @@ typedef struct rb_event_hook_struct { struct rb_event_hook_struct *next; } rb_event_hook_t; -typedef struct rb_trace_arg_struct { - rb_event_flag_t event; - rb_thread_t *th; - rb_control_frame_t *cfp; - VALUE self; - ID id; - VALUE klass; -} rb_trace_arg_t; - typedef void (*rb_event_hook_raw_arg_func_t)(VALUE data, const rb_trace_arg_t *arg); #define MAX_EVENT_NUM 32 @@ -306,10 +297,11 @@ exec_hooks(rb_thread_t *th, rb_hook_list_t *list, const rb_trace_arg_t *trace_ar } void -rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t event, VALUE self, ID id, VALUE klass) +rb_threadptr_exec_event_hooks(rb_trace_arg_t *targ) { + rb_thread_t *th = targ->th; if (th->trace_running == 0 && - self != rb_mRubyVMFrozenCore /* skip special methods. TODO: remove it. */) { + targ->self != rb_mRubyVMFrozenCore /* skip special methods. TODO: remove it. */) { const int vm_tracing = th->vm->trace_running; int state = 0; int outer_state = th->state; @@ -320,26 +312,18 @@ rb_threadptr_exec_event_hooks(rb_thread_t *th, rb_event_flag_t event, VALUE self { const VALUE errinfo = th->errinfo; rb_hook_list_t *list; - rb_trace_arg_t ta; - - ta.event = event; - ta.th = th; - ta.cfp = th->cfp; - ta.self = self; - ta.id = id; - ta.klass = klass; /* thread local traces */ list = &th->event_hooks; - if (list->events & event) { - state = exec_hooks(th, list, &ta, TRUE); + if (list->events & targ->event) { + state = exec_hooks(th, list, targ, TRUE); if (state) goto terminate; } /* vm global traces */ list = &th->vm->event_hooks; - if (list->events & event) { - state = exec_hooks(th, list, &ta, !vm_tracing); + if (list->events & targ->event) { + state = exec_hooks(th, list, targ, !vm_tracing); if (state) goto terminate; } th->errinfo = errinfo; @@ -774,6 +758,43 @@ tp_attr_self_m(VALUE tpval) return tp->trace_arg->self; } +static VALUE +tp_attr_return_value_m(VALUE tpval) +{ + rb_tp_t *tp = tpptr(tpval); + tp_attr_check_active(tp); + + if (tp->trace_arg->data == Qundef) { + rb_bug("tp_attr_return_value_m: unreachable"); + } + if (tp->trace_arg->event & (RUBY_EVENT_RETURN | RUBY_EVENT_C_RETURN)) { + /* ok */ + } + else { + rb_raise(rb_eRuntimeError, "not supported by this event"); + } + return tp->trace_arg->data; +} + +static VALUE +tp_attr_raised_exception_m(VALUE tpval) +{ + rb_tp_t *tp = tpptr(tpval); + tp_attr_check_active(tp); + + if (tp->trace_arg->data == Qundef) { + rb_bug("tp_attr_raised_exception_m: unreachable"); + } + if (tp->trace_arg->event & (RUBY_EVENT_RAISE)) { + /* ok */ + } + else { + rb_raise(rb_eRuntimeError, "not supported by this event"); + } + return tp->trace_arg->data; +} + + static void tp_call_trace(VALUE tpval, rb_trace_arg_t *trace_arg) { @@ -902,4 +923,6 @@ Init_vm_trace(void) rb_define_method(rb_cTracePoint, "klass", tp_attr_klass_m, 0); rb_define_method(rb_cTracePoint, "binding", tp_attr_binding_m, 0); rb_define_method(rb_cTracePoint, "self", tp_attr_self_m, 0); + rb_define_method(rb_cTracePoint, "return_value", tp_attr_return_value_m, 0); + rb_define_method(rb_cTracePoint, "raised_exception", tp_attr_raised_exception_m, 0); } -- cgit v1.2.3