--- inits.c.old 2009-03-02 15:12:41.000000000 -0800 +++ inits.c 2009-03-02 15:13:13.000000000 -0800 @@ -46,6 +46,7 @@ void Init_Time _((void)); void Init_var_tables _((void)); void Init_version _((void)); +void Init_DTracer _((void)); void rb_call_inits() @@ -83,4 +84,5 @@ Init_Enumerator(); Init_marshal(); Init_version(); + Init_DTracer(); } --- object.c.old 2009-03-02 15:12:46.000000000 -0800 +++ object.c 2009-03-02 15:13:13.000000000 -0800 @@ -20,6 +20,12 @@ #include <ctype.h> #include <math.h> +#ifdef ENABLE_DTRACE +#include "dtrace.h" +#include "node.h" +extern NODE* ruby_current_node; +#endif + VALUE rb_mKernel; VALUE rb_cObject; VALUE rb_cModule; @@ -1603,7 +1609,25 @@ if (FL_TEST(klass, FL_SINGLETON)) { rb_raise(rb_eTypeError, "can't create instance of virtual class"); } + + #ifdef ENABLE_DTRACE + if (RUBY_OBJECT_CREATE_START_ENABLED()) { + char *file = ruby_current_node == NULL ? "" : ruby_current_node->nd_file; + int line = ruby_current_node == NULL ? 0 : nd_line(ruby_current_node); + RUBY_OBJECT_CREATE_START(rb_class2name(klass), file, line); + } + #endif + obj = rb_funcall(klass, ID_ALLOCATOR, 0, 0); + + #ifdef ENABLE_DTRACE + if (RUBY_OBJECT_CREATE_DONE_ENABLED()) { + char *file = ruby_current_node == NULL ? "" : ruby_current_node->nd_file; + int line = ruby_current_node == NULL ? 0 : nd_line(ruby_current_node); + RUBY_OBJECT_CREATE_DONE(rb_class2name(klass), file, line); + } + #endif + if (rb_obj_class(obj) != rb_class_real(klass)) { rb_raise(rb_eTypeError, "wrong instance allocation"); } Index: tracer.c =================================================================== --- tracer.c (revision 0) +++ tracer.c (revision 77) @@ -0,0 +1,47 @@ +#include "ruby.h" + +#ifdef ENABLE_DTRACE +#include "dtrace.h" +#endif + +VALUE rb_mDtrace; + +static VALUE +ruby_dtrace_probe(int argc, VALUE *argv, unsigned check_only) +{ +#ifdef ENABLE_DTRACE + if (check_only) { + return RUBY_RUBY_PROBE_ENABLED() ? Qtrue : Qfalse; + } + else { + VALUE name, data; + char *probe_data; + + rb_scan_args(argc, argv, "11", &name, &data); + probe_data = NIL_P(data) ? "" : StringValuePtr(data); + + RUBY_RUBY_PROBE(StringValuePtr(name), probe_data); + } +#endif + return Qnil; +} + +static VALUE +ruby_dtrace_fire(int argc, VALUE *argv, VALUE klass) +{ + return ruby_dtrace_probe(argc, argv, 0); +} + +static VALUE +ruby_dtrace_enabled(VALUE klass) +{ + return ruby_dtrace_probe(0, NULL, 1); +} + +void Init_DTracer() +{ + rb_mDtrace = rb_define_module("DTracer"); + rb_define_module_function(rb_mDtrace, "fire", ruby_dtrace_fire, -1); + rb_define_module_function(rb_mDtrace, "enabled?", ruby_dtrace_enabled, 0); +} + --- common.mk.old 2009-03-02 15:12:09.000000000 -0800 +++ common.mk 2009-03-02 15:19:53.000000000 -0800 @@ -55,6 +55,7 @@ string.$(OBJEXT) \ struct.$(OBJEXT) \ time.$(OBJEXT) \ + tracer.$(OBJEXT) \ util.$(OBJEXT) \ variable.$(OBJEXT) \ version.$(OBJEXT) \ @@ -84,9 +85,9 @@ miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) $(MINIOBJS) $(OBJS) $(DMYEXT) -$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP) +$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(DTRACE_OBJS) $(SETUP) $(PREP) -$(LIBRUBY_A): $(OBJS) $(DMYEXT) $(ARCHFILE) +$(LIBRUBY_A): $(OBJS) $(DMYEXT) $(ARCHFILE) $(DTRACE_OBJS) $(LIBRUBY_SO): $(OBJS) $(DLDOBJS) $(LIBRUBY_A) $(PREP) $(LIBRUBY_SO_UPDATE) @@ -279,7 +280,7 @@ clean: clean-ext clean-local clean-local:: - @$(RM) $(OBJS) $(MINIOBJS) $(MAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES) + @$(RM) $(OBJS) $(DTRACE_OBJS) $(MINIOBJS) $(MAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES) @$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) $(ARCHFILE) .*.time @$(RM) y.tab.c y.output clean-ext: --- eval.c.old 2009-03-02 15:12:55.000000000 -0800 +++ eval.c 2009-03-02 15:21:04.000000000 -0800 @@ -215,6 +215,10 @@ #include <sys/stat.h> +#ifdef ENABLE_DTRACE +#include "dtrace.h" +#endif + VALUE rb_cProc; VALUE rb_cBinding; static VALUE proc_invoke _((VALUE,VALUE,VALUE,VALUE)); @@ -3045,12 +3049,22 @@ case NODE_IF: if (RTEST(rb_eval(self, node->nd_cond))) { +#ifdef ENABLE_DTRACE + if (RUBY_LINE_ENABLED()) + if (ruby_current_node && ruby_current_node->nd_file) + RUBY_LINE(ruby_current_node->nd_file, nd_line(ruby_current_node)); +#endif EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, ruby_frame->last_func, ruby_frame->last_class); node = node->nd_body; } else { +#ifdef ENABLE_DTRACE + if (RUBY_LINE_ENABLED()) + if (ruby_current_node && ruby_current_node->nd_file) + RUBY_LINE(ruby_current_node->nd_file, nd_line(ruby_current_node)); +#endif EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, ruby_frame->last_func, ruby_frame->last_class); @@ -3065,6 +3079,11 @@ if (nd_type(node) != NODE_WHEN) goto again; tag = node->nd_head; while (tag) { + #ifdef ENABLE_DTRACE + if (RUBY_LINE_ENABLED()) + if (ruby_current_node && ruby_current_node->nd_file) + RUBY_LINE(ruby_current_node->nd_file, nd_line(ruby_current_node)); + #endif EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self, ruby_frame->last_func, ruby_frame->last_class); @@ -3106,6 +3125,11 @@ } tag = node->nd_head; while (tag) { + #ifdef ENABLE_DTRACE + if (RUBY_LINE_ENABLED()) + if (ruby_current_node && ruby_current_node->nd_file) + RUBY_LINE(ruby_current_node->nd_file, nd_line(ruby_current_node)); + #endif EXEC_EVENT_HOOK(RUBY_EVENT_LINE, tag, self, ruby_frame->last_func, ruby_frame->last_class); @@ -3326,6 +3350,11 @@ rescuing = -1; while (resq) { ruby_current_node = resq; + #ifdef ENABLE_DTRACE + if (RUBY_RESCUE_ENABLED()) + if (ruby_current_node && ruby_current_node->nd_file) + RUBY_RESCUE(ruby_current_node->nd_file, nd_line(ruby_current_node)); + #endif if (handle_rescue(self, resq)) { state = 0; rescuing = 1; @@ -4144,6 +4173,11 @@ break; case NODE_NEWLINE: + #ifdef ENABLE_DTRACE + if (RUBY_LINE_ENABLED()) + if (ruby_current_node && ruby_current_node->nd_file) + RUBY_LINE(ruby_current_node->nd_file, nd_line(ruby_current_node)); + #endif EXEC_EVENT_HOOK(RUBY_EVENT_LINE, node, self, ruby_frame->last_func, ruby_frame->last_class); @@ -4622,6 +4656,10 @@ rb_trap_restore_mask(); if (tag != TAG_FATAL) { + #ifdef ENABLE_DTRACE + if (RUBY_RAISE_ENABLED()) + RUBY_RAISE(rb_obj_classname(ruby_errinfo), ruby_sourcefile, ruby_sourceline); + #endif EXEC_EVENT_HOOK(RUBY_EVENT_RAISE, ruby_current_node, ruby_frame->self, ruby_frame->last_func, @@ -5885,6 +5923,13 @@ rb_bug("bad argc (%d) specified for `%s(%s)'", len, rb_class2name(klass), rb_id2name(id)); } + #ifdef ENABLE_DTRACE + if (RUBY_FUNCTION_ENTRY_ENABLED()) { + char *classname = rb_class2name(klass), *methodname = rb_id2name(id); + if (ruby_current_node && ruby_current_node->nd_file && classname && methodname) + RUBY_FUNCTION_ENTRY(classname, methodname, ruby_current_node->nd_file, nd_line(ruby_current_node)); + } + #endif if (event_hooks) { int state; @@ -5903,6 +5948,13 @@ else { result = call_cfunc(body->nd_cfnc, recv, len, argc, argv); } + #ifdef ENABLE_DTRACE + if (RUBY_FUNCTION_RETURN_ENABLED()) { + char *classname = rb_class2name(klass), *methodname = rb_id2name(id); + if (ruby_current_node && ruby_current_node->nd_file && classname && methodname) + RUBY_FUNCTION_RETURN(classname, methodname, ruby_current_node->nd_file, nd_line(ruby_current_node)); + } + #endif } break; @@ -5930,12 +5982,26 @@ case NODE_BMETHOD: ruby_frame->flags |= FRAME_DMETH; + #ifdef ENABLE_DTRACE + if (RUBY_FUNCTION_ENTRY_ENABLED()) { + char *classname = rb_class2name(klass), *methodname = rb_id2name(id); + if (ruby_current_node && ruby_current_node->nd_file && classname && methodname) + RUBY_FUNCTION_ENTRY(classname, methodname, ruby_current_node->nd_file, nd_line(ruby_current_node)); + } + #endif if (event_hooks) { struct BLOCK *data; Data_Get_Struct(body->nd_cval, struct BLOCK, data); EXEC_EVENT_HOOK(RUBY_EVENT_CALL, data->body, recv, id, klass); } result = proc_invoke(body->nd_cval, rb_ary_new4(argc, argv), recv, klass); + #ifdef ENABLE_DTRACE + if (RUBY_FUNCTION_RETURN_ENABLED()) { + char *classname = rb_class2name(klass), *methodname = rb_id2name(id); + if (ruby_current_node && ruby_current_node->nd_file && classname && methodname) + RUBY_FUNCTION_RETURN(classname, methodname, ruby_current_node->nd_file, nd_line(ruby_current_node)); + } + #endif if (event_hooks) { EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, ruby_current_node, recv, id, klass); } @@ -6049,6 +6115,13 @@ } ruby_frame->argc = i; } + #ifdef ENABLE_DTRACE + if (RUBY_FUNCTION_ENTRY_ENABLED()) { + char *classname = rb_class2name(klass), *methodname = rb_id2name(id); + if (ruby_current_node && ruby_current_node->nd_file && classname && methodname) + RUBY_FUNCTION_ENTRY(classname, methodname, ruby_current_node->nd_file, nd_line(ruby_current_node)); + } + #endif if (event_hooks) { EXEC_EVENT_HOOK(RUBY_EVENT_CALL, b2, recv, id, klass); } @@ -6059,6 +6132,13 @@ state = 0; } POP_TAG(); + #ifdef ENABLE_DTRACE + if (RUBY_FUNCTION_RETURN_ENABLED()) { + char *classname = rb_class2name(klass), *methodname = rb_id2name(id); + if (ruby_current_node && ruby_current_node->nd_file && classname && methodname) + RUBY_FUNCTION_RETURN(classname, methodname, ruby_current_node->nd_file, nd_line(ruby_current_node)); + } + #endif if (event_hooks) { EXEC_EVENT_HOOK(RUBY_EVENT_RETURN, ruby_current_node, recv, id, klass); } --- gc.c.old 2009-03-02 15:13:00.000000000 -0800 +++ gc.c 2009-03-02 15:13:13.000000000 -0800 @@ -30,6 +30,12 @@ #include <sys/resource.h> #endif +#ifdef ENABLE_DTRACE +#include <sys/sdt.h> +#include "dtrace.h" +#endif + + #if defined _WIN32 || defined __CYGWIN__ #include <windows.h> #endif @@ -1214,6 +1220,15 @@ break; } + #ifdef ENABLE_DTRACE + if (RUBY_OBJECT_FREE_ENABLED()) + { + char *classname = rb_obj_classname(obj); + if (classname) + RUBY_OBJECT_FREE(classname); + } + #endif + if (FL_TEST(obj, FL_EXIVAR)) { rb_free_generic_ivar((VALUE)obj); } @@ -1374,6 +1389,12 @@ { struct gc_list *list; struct FRAME * volatile frame; /* gcc 2.7.2.3 -O2 bug?? */ + + #ifdef ENABLE_DTRACE + if (RUBY_GC_BEGIN_ENABLED()) + RUBY_GC_BEGIN(); + #endif + jmp_buf save_regs_gc_mark; SET_STACK_END; @@ -1466,6 +1487,11 @@ } while (!MARK_STACK_EMPTY); gc_sweep(); + + #ifdef ENABLE_DTRACE + if (RUBY_GC_END_ENABLED()) + RUBY_GC_END(); + #endif } void