Skip to content
Permalink
Browse files

add simple object events to tracepoint api (c-api only)

  • Loading branch information
tmm1 committed Mar 19, 2013
1 parent 4ea96ec commit bffaecd560e83d4818130fa162b86dca6155f93b
Showing with 94 additions and 0 deletions.
  1. +1 −0 ext/-test-/tracepoint/extconf.rb
  2. +37 −0 ext/-test-/tracepoint/obj.c
  3. +7 −0 gc.c
  4. +1 −0 include/ruby/debug.h
  5. +6 −0 include/ruby/ruby.h
  6. +24 −0 test/-ext-/tracepoint/test_obj.rb
  7. +18 −0 vm_trace.c
@@ -0,0 +1 @@
create_makefile("-test-/tracepoint")
@@ -0,0 +1,37 @@
#include "ruby.h"
#include "ruby/debug.h"

static size_t count;
static VALUE objects[10];

void
newobj_callback(VALUE tpval, void *data)
{
rb_trace_arg_t *tparg = rb_tracearg_from_tracepoint(tpval);
VALUE obj = rb_tracearg_object(tparg);

if (count < sizeof(objects))
objects[count++] = obj;
}

VALUE
tracepoint_track_newobj(VALUE self)
{
VALUE tpval = rb_tracepoint_new(0, RUBY_EVENT_OBJ_NEW, newobj_callback, 0);

count = 0;
memset(objects, (VALUE)Qnil, sizeof(objects));

rb_tracepoint_enable(tpval);
rb_yield(Qundef);
rb_tracepoint_disable(tpval);

return rb_ary_new4(count, objects);
}

void
Init_tracepoint(void)
{
VALUE mBug = rb_define_module("Bug");
rb_define_module_function(mBug, "tracepoint_track_newobj", tracepoint_track_newobj, 0);
}
7 gc.c
@@ -687,9 +687,11 @@ VALUE
rb_newobj_of(VALUE klass, VALUE flags)
{
VALUE obj;
rb_thread_t *th = GET_THREAD();

obj = newobj(klass, flags);
OBJSETUP(obj, klass, flags);
EXEC_EVENT_HOOK(th, RUBY_EVENT_OBJ_NEW, th->self, 0, 0, obj);

return obj;
}
@@ -907,6 +909,7 @@ make_io_deferred(RVALUE *p)
static int
obj_free(rb_objspace_t *objspace, VALUE obj)
{
rb_thread_t *th = GET_THREAD();
switch (BUILTIN_TYPE(obj)) {
case T_NIL:
case T_FIXNUM:
@@ -916,6 +919,8 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
}

EXEC_EVENT_HOOK(th, RUBY_EVENT_OBJ_FREE, th->self, 0, 0, obj);

if (FL_TEST(obj, FL_EXIVAR)) {
rb_free_generic_ivar((VALUE)obj);
FL_UNSET(obj, FL_EXIVAR);
@@ -2559,8 +2564,10 @@ static int
gc_mark_ptr(rb_objspace_t *objspace, VALUE ptr)
{
register uintptr_t *bits = GET_HEAP_BITMAP(ptr);
rb_thread_t *th = GET_THREAD();
if (MARKED_IN_BITMAP(bits, ptr)) return 0;
MARK_IN_BITMAP(bits, ptr);
EXEC_EVENT_HOOK(th, RUBY_EVENT_OBJ_MARK, th->self, 0, 0, ptr);
objspace->heap.marked_num++;
return 1;
}
@@ -67,6 +67,7 @@ VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg);
VALUE rb_tracearg_object(rb_trace_arg_t *trace_arg);

/* undocumented advanced tracing APIs */

@@ -1599,6 +1599,12 @@ int ruby_native_thread_p(void);
#define RUBY_EVENT_SWITCH 0x20000
#define RUBY_EVENT_COVERAGE 0x40000

/* GC events (c-api only) */
#define RUBY_EVENT_OBJ_NEW 0x100000
#define RUBY_EVENT_OBJ_MARK 0x200000
#define RUBY_EVENT_OBJ_FREE 0x400000
#define RUBY_EVENT_OBJ_ALL 0xF00000

typedef unsigned long rb_event_flag_t;
typedef void (*rb_event_hook_func_t)(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass);

@@ -0,0 +1,24 @@
require 'test/unit'
require '-test-/tracepoint'

class TestTracepointObj < Test::Unit::TestCase
def test_not_available_from_ruby
assert_raises ArgumentError do
TracePoint.trace(:obj_new){}
end
end

def test_tracks_newly_created_objects
newobjs = Bug.tracepoint_track_newobj{
99
'abc'
v="foobar"
Object.new
nil
}

assert_equal 2, newobjs.size
assert_equal 'foobar', newobjs[0]
assert_equal Object, newobjs[1].class
end
end
@@ -556,6 +556,9 @@ get_event_id(rb_event_flag_t event)
C(thread_begin, THREAD_BEGIN);
C(thread_end, THREAD_END);
C(specified_line, SPECIFIED_LINE);
C(obj_new, OBJ_NEW);
C(obj_mark, OBJ_MARK);
C(obj_free, OBJ_FREE);
case RUBY_EVENT_LINE | RUBY_EVENT_SPECIFIED_LINE: CONST_ID(id, "line"); return id;
#undef C
default:
@@ -813,6 +816,21 @@ rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg)
return trace_arg->data;
}

VALUE
rb_tracearg_object(rb_trace_arg_t *trace_arg)
{
if (trace_arg->event & (RUBY_EVENT_OBJ_ALL)) {
/* ok */
}
else {
rb_raise(rb_eRuntimeError, "not supported by this event");
}
if (trace_arg->data == Qundef) {
rb_bug("tp_attr_raised_exception_m: unreachable");
}
return trace_arg->data;
}

/*
* Type of event
*

0 comments on commit bffaecd

Please sign in to comment.
You can’t perform that action at this time.