diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-05-27 00:21:02 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-05-27 00:21:02 +0000 |
commit | 680f0b5ba4eb4ba4f542ebc8d1204da61b71eb92 (patch) | |
tree | 8b49f2f3f6fe57d5d5738402089c792ef4368bc2 /ext/-test-/tracepoint/tracepoint.c | |
parent | dc7522f835937152cd3f7a410886d6f8ed8a7ea0 (diff) |
* 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
Diffstat (limited to 'ext/-test-/tracepoint/tracepoint.c')
-rw-r--r-- | ext/-test-/tracepoint/tracepoint.c | 65 |
1 files changed, 65 insertions, 0 deletions
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<objects_count; i++) { + rb_ary_push(result, objects[i]); + } + + return result; +} + +void +Init_tracepoint(void) +{ + VALUE mBug = rb_define_module("Bug"); + rb_define_module_function(mBug, "tracepoint_track_objspace_events", tracepoint_track_objspace_events, 0); +} |