From 680f0b5ba4eb4ba4f542ebc8d1204da61b71eb92 Mon Sep 17 00:00:00 2001 From: ko1 Date: Mon, 27 May 2013 00:21:02 +0000 Subject: * include/ruby/ruby.h, gc.c, vm_trace.c: add internal events. * RUBY_INTERNAL_EVENT_NEWOBJ: object created. * RUBY_INTERNAL_EVENT_FREE: object freeed. * RUBY_INTERNAL_EVENT_GC_START: GC started. And rename `RUBY_EVENT_SWITCH' to `RUBY_INTERNAL_EVENT_SWITCH'. Internal events can not invoke any Ruby program because the tracing timing may be critical (under huge restriction). These events can be hooked only by C-extensions. We recommend to use rb_potponed_job_register() API to call Ruby program safely. This change is mostly written by Aman Gupta (tmm1). https://bugs.ruby-lang.org/issues/8107#note-12 [Feature #8107] * include/ruby/debug.h, vm_trace.c: added two new APIs. * rb_tracearg_event_flag() returns rb_event_flag_t of this event. * rb_tracearg_object() returns created/freeed object. * ext/-test-/tracepoint/extconf.rb, ext/-test-/tracepoint/tracepoint.c, test/-ext-/tracepoint/test_tracepoint.rb: add a test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40946 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ext/-test-/tracepoint/extconf.rb | 1 + ext/-test-/tracepoint/tracepoint.c | 65 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 ext/-test-/tracepoint/extconf.rb create mode 100644 ext/-test-/tracepoint/tracepoint.c (limited to 'ext/-test-/tracepoint') diff --git a/ext/-test-/tracepoint/extconf.rb b/ext/-test-/tracepoint/extconf.rb new file mode 100644 index 0000000000..c0c2399eb4 --- /dev/null +++ b/ext/-test-/tracepoint/extconf.rb @@ -0,0 +1 @@ +create_makefile("-test-/tracepoint") diff --git a/ext/-test-/tracepoint/tracepoint.c b/ext/-test-/tracepoint/tracepoint.c new file mode 100644 index 0000000000..220280c951 --- /dev/null +++ b/ext/-test-/tracepoint/tracepoint.c @@ -0,0 +1,65 @@ +#include "ruby/ruby.h" +#include "ruby/debug.h" + +static size_t newobj_count; +static size_t free_count; +static size_t gc_start_count; +static size_t objects_count; +static VALUE objects[10]; + +void +tracepoint_track_objspace_events_i(VALUE tpval, void *data) +{ + rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval); + switch (rb_tracearg_event_flag(tparg)) { + case RUBY_INTERNAL_EVENT_NEWOBJ: + { + VALUE obj = rb_tracearg_object(tparg); + if (objects_count < sizeof(objects)/sizeof(VALUE)) objects[objects_count++] = obj; + newobj_count++; + break; + } + case RUBY_INTERNAL_EVENT_FREE: + { + free_count++; + break; + } + case RUBY_INTERNAL_EVENT_GC_START: + { + gc_start_count++; + break; + } + default: + rb_raise(rb_eRuntimeError, "unknown event"); + } +} + +VALUE +tracepoint_track_objspace_events(VALUE self) +{ + VALUE tpval = rb_tracepoint_new(0, RUBY_INTERNAL_EVENT_NEWOBJ | RUBY_INTERNAL_EVENT_FREE | RUBY_INTERNAL_EVENT_GC_START, tracepoint_track_objspace_events_i, 0); + VALUE result = rb_ary_new(); + int i; + + newobj_count = free_count = gc_start_count = objects_count = 0; + + rb_tracepoint_enable(tpval); + rb_yield(Qundef); + rb_tracepoint_disable(tpval); + + rb_ary_push(result, SIZET2NUM(newobj_count)); + rb_ary_push(result, SIZET2NUM(free_count)); + rb_ary_push(result, SIZET2NUM(gc_start_count)); + for (i=0; i