Project

General

Profile

Feature #2565 ยป probes.diff

tenderlovemaking (Aaron Patterson), 11/02/2012 05:07 AM

View differences:

.gitignore
55 55
/exts.mk
56 56
/goruby
57 57
/id.h
58
/probes.h
58 59
/largefile.h
59 60
/lex.c
60 61
/libruby*.*
Makefile.in
147 147
OBJCOPY       = @OBJCOPY@
148 148
VCS           = @VCS@
149 149
VCSUP         = @VCSUP@
150
DTRACE        = @DTRACE@
150 151

  
151 152
OBJEXT        = @OBJEXT@
152 153
ASMEXT        = S
......
263 264
$(srcdir)/configure: $(srcdir)/configure.in
264 265
	$(CHDIR) $(srcdir) && exec $(AUTOCONF)
265 266

  
267
incs: id.h probes.h
268

  
266 269
# Things which should be considered:
267 270
# * with gperf v.s. without gperf
268 271
# * committers may have various versions of gperf
......
318 321
	@$(ECHO) preprocessing $<
319 322
	$(Q) $(CPP) $(warnflags) $(XCFLAGS) $(CPPFLAGS) $(COUTFLAG)$@ -E $< > $@
320 323

  
324
.d.h:
325
	@$(ECHO) translating probes $<
326
	$(Q)if test -n '$(DTRACE)'; then\
327
	  $(DTRACE) -o $@.tmp -h -s $<; \
328
	  sed -e 's/RUBY_/RUBY_DTRACE_/g' $@.tmp | sed -e 's/PROBES_H_TMP/PROBES_H/g' >$@; \
329
	  rm $@.tmp; \
330
	else \
331
	  sed -f $(srcdir)/tool/gen_dummy_probes.sed $< > $@; \
332
	fi
333

  
321 334
clean-local::
322 335
	$(Q)$(RM) ext/extinit.c ext/extinit.$(OBJEXT) ext/ripper/y.output \
323 336
		enc/encinit.c enc/encinit.$(OBJEXT)
array.c
16 16
#include "ruby/st.h"
17 17
#include "ruby/encoding.h"
18 18
#include "internal.h"
19
#include "probes.h"
19 20

  
20 21
#ifndef ARRAY_DEBUG
21 22
# define NDEBUG
......
316 317
}
317 318

  
318 319
static VALUE
320
empty_ary_alloc(VALUE klass)
321
{
322
    if(RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
323
	RUBY_DTRACE_ARRAY_CREATE(0, rb_sourcefile(), rb_sourceline());
324
    }
325

  
326
    return ary_alloc(klass);
327
}
328

  
329
static VALUE
319 330
ary_new(VALUE klass, long capa)
320 331
{
321 332
    VALUE ary;
......
326 337
    if (capa > ARY_MAX_SIZE) {
327 338
	rb_raise(rb_eArgError, "array size too big");
328 339
    }
340

  
341
    if(RUBY_DTRACE_ARRAY_CREATE_ENABLED()) {
342
	RUBY_DTRACE_ARRAY_CREATE(capa, rb_sourcefile(), rb_sourceline());
343
    }
344

  
329 345
    ary = ary_alloc(klass);
330 346
    if (capa > RARRAY_EMBED_LEN_MAX) {
331 347
        FL_UNSET_EMBED(ary);
......
5074 5090
    rb_cArray  = rb_define_class("Array", rb_cObject);
5075 5091
    rb_include_module(rb_cArray, rb_mEnumerable);
5076 5092

  
5077
    rb_define_alloc_func(rb_cArray, ary_alloc);
5093
    rb_define_alloc_func(rb_cArray, empty_ary_alloc);
5078 5094
    rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
5079 5095
    rb_define_singleton_method(rb_cArray, "try_convert", rb_ary_s_try_convert, 1);
5080 5096
    rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
common.mk
2 2
lib: $(LIBRUBY)
3 3
dll: $(LIBRUBY_SO)
4 4

  
5
.SUFFIXES: .inc .h .c .y .i
5
.SUFFIXES: .inc .h .c .y .i .d
6 6

  
7 7
# V=0 quiet, V=1 verbose.  other values don't work.
8 8
V = 0
......
609 609
		     {$(VPATH)}subst.h
610 610
ENCODING_H_INCLUDES= {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
611 611
ID_H_INCLUDES      = {$(VPATH)}id.h
612
PROBES_H_INCLUDES  = {$(VPATH)}probes.h
612 613
VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}thread_$(THREAD_MODEL).h \
613 614
		     {$(VPATH)}node.h {$(VPATH)}method.h {$(VPATH)}atomic.h \
614
		     $(ID_H_INCLUDES)
615
		     $(ID_H_INCLUDES) $(PROBES_H_INCLUDES)
615 616

  
616 617
addr2line.$(OBJEXT): {$(VPATH)}addr2line.c {$(VPATH)}addr2line.h {$(VPATH)}config.h
617 618
array.$(OBJEXT): {$(VPATH)}array.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
618
  $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h
619
  $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES)
619 620
bignum.$(OBJEXT): {$(VPATH)}bignum.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
620 621
  {$(VPATH)}thread.h {$(VPATH)}internal.h
621 622
class.$(OBJEXT): {$(VPATH)}class.c $(RUBY_H_INCLUDES) \
......
648 649
eval.$(OBJEXT): {$(VPATH)}eval.c {$(VPATH)}eval_intern.h {$(VPATH)}vm.h \
649 650
  $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}eval_error.c \
650 651
  {$(VPATH)}eval_jump.c {$(VPATH)}debug.h {$(VPATH)}gc.h {$(VPATH)}iseq.h \
651
  $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h
652
  $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES)
652 653
load.$(OBJEXT): {$(VPATH)}load.c {$(VPATH)}eval_intern.h \
653 654
  {$(VPATH)}util.h $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) \
654 655
  {$(VPATH)}dln.h {$(VPATH)}debug.h \
655
  {$(VPATH)}internal.h
656
  {$(VPATH)}internal.h $(PROBES_H_INCLUDES)
656 657
file.$(OBJEXT): {$(VPATH)}file.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \
657 658
  $(ENCODING_H_INCLUDES) {$(VPATH)}util.h {$(VPATH)}dln.h \
658 659
  {$(VPATH)}internal.h
......
660 661
  {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) $(VM_CORE_H_INCLUDES) \
661 662
  {$(VPATH)}gc.h {$(VPATH)}io.h {$(VPATH)}eval_intern.h {$(VPATH)}util.h \
662 663
  {$(VPATH)}debug.h {$(VPATH)}internal.h {$(VPATH)}constant.h \
663
  {$(VPATH)}thread.h
664
  {$(VPATH)}thread.h $(PROBES_H_INCLUDES)
664 665
hash.$(OBJEXT): {$(VPATH)}hash.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
665
  $(ENCODING_H_INCLUDES)
666
  $(ENCODING_H_INCLUDES) $(PROBES_H_INCLUDES)
666 667
inits.$(OBJEXT): {$(VPATH)}inits.c $(RUBY_H_INCLUDES) \
667 668
  {$(VPATH)}internal.h
668 669
io.$(OBJEXT): {$(VPATH)}io.c $(RUBY_H_INCLUDES) {$(VPATH)}io.h \
......
679 680
numeric.$(OBJEXT): {$(VPATH)}numeric.c $(RUBY_H_INCLUDES) \
680 681
  {$(VPATH)}util.h $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h
681 682
object.$(OBJEXT): {$(VPATH)}object.c $(RUBY_H_INCLUDES) {$(VPATH)}util.h \
682
  {$(VPATH)}internal.h {$(VPATH)}constant.h $(ENCODING_H_INCLUDES)
683
  {$(VPATH)}internal.h {$(VPATH)}constant.h $(ENCODING_H_INCLUDES) $(PROBES_H_INCLUDES)
683 684
pack.$(OBJEXT): {$(VPATH)}pack.c $(RUBY_H_INCLUDES) {$(VPATH)}encoding.h \
684 685
  {$(VPATH)}oniguruma.h
685 686
parse.$(OBJEXT): {$(VPATH)}parse.c $(RUBY_H_INCLUDES) {$(VPATH)}node.h \
......
729 730
strftime.$(OBJEXT): {$(VPATH)}strftime.c $(RUBY_H_INCLUDES) \
730 731
  {$(VPATH)}timev.h $(ENCODING_H_INCLUDES)
731 732
string.$(OBJEXT): {$(VPATH)}string.c $(RUBY_H_INCLUDES) {$(VPATH)}re.h \
732
  {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h
733
  {$(VPATH)}regex.h $(ENCODING_H_INCLUDES) {$(VPATH)}internal.h $(PROBES_H_INCLUDES)
733 734
struct.$(OBJEXT): {$(VPATH)}struct.c $(RUBY_H_INCLUDES) {$(VPATH)}internal.h
734 735
thread.$(OBJEXT): {$(VPATH)}thread.c {$(VPATH)}eval_intern.h \
735 736
  $(RUBY_H_INCLUDES) {$(VPATH)}gc.h $(VM_CORE_H_INCLUDES) \
......
760 761
iseq.$(OBJEXT): {$(VPATH)}iseq.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \
761 762
  $(RUBY_H_INCLUDES) $(VM_CORE_H_INCLUDES) {$(VPATH)}insns.inc \
762 763
  {$(VPATH)}insns_info.inc {$(VPATH)}node_name.inc {$(VPATH)}debug.h {$(VPATH)}internal.h
764
{$(VPATH)}vm_insnhelper.c:$(PROBES_H_INCLUDES)
763 765
vm.$(OBJEXT): {$(VPATH)}vm.c {$(VPATH)}gc.h {$(VPATH)}iseq.h \
764 766
  {$(VPATH)}eval_intern.h $(RUBY_H_INCLUDES) $(ENCODING_H_INCLUDES) \
765 767
  $(VM_CORE_H_INCLUDES) {$(VPATH)}vm_method.c {$(VPATH)}vm_eval.c \
766 768
  {$(VPATH)}vm_insnhelper.c {$(VPATH)}vm_insnhelper.h {$(VPATH)}vm_exec.c \
767 769
  {$(VPATH)}vm_exec.h {$(VPATH)}insns.def {$(VPATH)}vmtc.inc \
768 770
  {$(VPATH)}vm.inc {$(VPATH)}insns.inc {$(VPATH)}debug.h \
769
  {$(VPATH)}internal.h {$(VPATH)}vm.h {$(VPATH)}constant.h
771
  {$(VPATH)}internal.h {$(VPATH)}vm.h {$(VPATH)}constant.h $(PROBES_H_INCLUDES)
770 772
vm_dump.$(OBJEXT): {$(VPATH)}vm_dump.c $(RUBY_H_INCLUDES) \
771 773
  $(VM_CORE_H_INCLUDES) {$(VPATH)}debug.h {$(VPATH)}addr2line.h \
772 774
  {$(VPATH)}internal.h
compile.c
5348 5348
    printf("---------------------\n");
5349 5349
}
5350 5350

  
5351
const char *
5352
rb_insns_name(int i)
5353
{
5354
    return insn_name_info[i];
5355
}
5356

  
5351 5357
VALUE
5352 5358
rb_insns_name_array(void)
5353 5359
{
configure.in
372 372
if test x"${build}" != x"${host}"; then
373 373
  AC_CHECK_TOOL(CC, gcc)
374 374
fi
375

  
376
AC_CHECK_TOOL(DTRACE, dtrace)
377

  
375 378
AC_PROG_CC
376 379
AC_PROG_CXX
377 380
RUBY_MINGW32
eval.c
18 18
#include "ruby/encoding.h"
19 19
#include "internal.h"
20 20
#include "vm_core.h"
21
#include "probes.h"
21 22

  
22 23
#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
23 24

  
......
499 500
    }
500 501

  
501 502
    if (tag != TAG_FATAL) {
503
	if(RUBY_DTRACE_RAISE_ENABLED()) {
504
	    RUBY_DTRACE_RAISE(rb_obj_classname(th->errinfo),
505
		    rb_sourcefile(),
506
		    rb_sourceline());
507
	}
502 508
	EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self, 0, 0);
503 509
    }
504 510
}
gc.c
23 23
#include "gc.h"
24 24
#include "constant.h"
25 25
#include "atomic.h"
26
#include "probes.h"
26 27
#include <stdio.h>
27 28
#include <setjmp.h>
28 29
#include <sys/types.h>
......
141 142
#endif
142 143
} gc_profile_record;
143 144

  
144

  
145 145
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
146 146
#pragma pack(push, 1) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
147 147
#endif
......
1323 1323
	rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
1324 1324
		 rb_obj_classname(block));
1325 1325
    }
1326

  
1326 1327
    return define_final0(obj, block);
1327 1328
}
1328 1329

  
......
3047 3048
    during_gc++;
3048 3049
    gc_marks(objspace);
3049 3050

  
3051
    if (RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED()) {
3052
	RUBY_DTRACE_GC_SWEEP_BEGIN();
3053
    }
3050 3054
    gc_prof_sweep_timer_start(objspace);
3051 3055
    gc_sweep(objspace);
3052 3056
    gc_prof_sweep_timer_stop(objspace);
......
3931 3935
static inline void
3932 3936
gc_prof_mark_timer_start(rb_objspace_t *objspace)
3933 3937
{
3938
    if (RUBY_DTRACE_GC_MARK_BEGIN_ENABLED()) {
3939
	RUBY_DTRACE_GC_MARK_BEGIN();
3940
    }
3934 3941
}
3935 3942

  
3936 3943
static inline void
3937 3944
gc_prof_mark_timer_stop(rb_objspace_t *objspace)
3938 3945
{
3946
    if (RUBY_DTRACE_GC_MARK_END_ENABLED()) {
3947
	RUBY_DTRACE_GC_MARK_END();
3948
    }
3939 3949
}
3940 3950

  
3941 3951
static inline void
3942 3952
gc_prof_sweep_timer_start(rb_objspace_t *objspace)
3943 3953
{
3954
    if (RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED()) {
3955
	RUBY_DTRACE_GC_SWEEP_BEGIN();
3956
    }
3944 3957
}
3945 3958

  
3946 3959
static inline void
3947 3960
gc_prof_sweep_timer_stop(rb_objspace_t *objspace)
3948 3961
{
3962
    if (RUBY_DTRACE_GC_SWEEP_END_ENABLED()) {
3963
	RUBY_DTRACE_GC_SWEEP_END();
3964
    }
3949 3965
}
3950 3966

  
3951 3967
static inline void
......
3979 3995
static inline void
3980 3996
gc_prof_mark_timer_start(rb_objspace_t *objspace)
3981 3997
{
3998
    if (RUBY_DTRACE_GC_MARK_BEGIN_ENABLED()) {
3999
	RUBY_DTRACE_GC_MARK_BEGIN();
4000
    }
3982 4001
    if (objspace->profile.run) {
3983 4002
        size_t count = objspace->profile.count;
3984 4003

  
......
3989 4008
static inline void
3990 4009
gc_prof_mark_timer_stop(rb_objspace_t *objspace)
3991 4010
{
4011
    if (RUBY_DTRACE_GC_MARK_END_ENABLED()) {
4012
	RUBY_DTRACE_GC_MARK_END();
4013
    }
3992 4014
    if (objspace->profile.run) {
3993 4015
        double mark_time = 0;
3994 4016
        size_t count = objspace->profile.count;
......
4003 4025
static inline void
4004 4026
gc_prof_sweep_timer_start(rb_objspace_t *objspace)
4005 4027
{
4028
    if (RUBY_DTRACE_GC_SWEEP_BEGIN_ENABLED()) {
4029
	RUBY_DTRACE_GC_SWEEP_BEGIN();
4030
    }
4006 4031
    if (objspace->profile.run) {
4007 4032
        size_t count = objspace->profile.count;
4008 4033

  
......
4013 4038
static inline void
4014 4039
gc_prof_sweep_timer_stop(rb_objspace_t *objspace)
4015 4040
{
4041
    if (RUBY_DTRACE_GC_SWEEP_END_ENABLED()) {
4042
	RUBY_DTRACE_GC_SWEEP_END();
4043
    }
4016 4044
    if (objspace->profile.run) {
4017 4045
        double sweep_time = 0;
4018 4046
        size_t count = objspace->profile.count;
hash.c
16 16
#include "ruby/util.h"
17 17
#include "ruby/encoding.h"
18 18
#include <errno.h>
19
#include "probes.h"
19 20

  
20 21
#ifdef __APPLE__
21 22
#include <crt_externs.h>
......
214 215
    return (VALUE)hash;
215 216
}
216 217

  
218
static VALUE
219
empty_hash_alloc(VALUE klass)
220
{
221
    if(RUBY_DTRACE_HASH_CREATE_ENABLED()) {
222
	RUBY_DTRACE_HASH_CREATE(0, rb_sourcefile(), rb_sourceline());
223
    }
224

  
225
    return hash_alloc(klass);
226
}
227

  
217 228
VALUE
218 229
rb_hash_new(void)
219 230
{
......
3381 3392

  
3382 3393
    rb_include_module(rb_cHash, rb_mEnumerable);
3383 3394

  
3384
    rb_define_alloc_func(rb_cHash, hash_alloc);
3395
    rb_define_alloc_func(rb_cHash, empty_hash_alloc);
3385 3396
    rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
3386 3397
    rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
3387 3398
    rb_define_method(rb_cHash,"initialize", rb_hash_initialize, -1);
insns.def
524 524
(VALUE val) // inc += 1 - num;
525 525
{
526 526
    rb_num_t i;
527

  
528
    if(RUBY_DTRACE_HASH_CREATE_ENABLED()) {
529
	RUBY_DTRACE_HASH_CREATE(num, rb_sourcefile(), rb_sourceline());
530
    }
531

  
527 532
    val = rb_hash_new();
528 533

  
529 534
    for (i = num; i > 0; i -= 2) {
......
838 843
{
839 844
    rb_event_flag_t flag = (rb_event_flag_t)nf;
840 845

  
846
    if (RUBY_DTRACE_FUNCTION_ENTRY_ENABLED()) {
847
        if (flag == RUBY_EVENT_CALL || flag == RUBY_EVENT_C_CALL) {
848
          VALUE klass;
849
          ID called_id;
850

  
851
          rb_thread_method_id_and_class(th, &called_id, &klass);
852

  
853
          RUBY_DTRACE_FUNCTION_ENTRY(
854
                  RSTRING_PTR(rb_inspect(klass)),
855
                  rb_id2name(called_id),
856
                  rb_sourcefile(),
857
                  rb_sourceline());
858
        }
859
    }
860
    if (RUBY_DTRACE_FUNCTION_RETURN_ENABLED()) {
861
        if (flag == RUBY_EVENT_RETURN || flag == RUBY_EVENT_C_RETURN) {
862
          VALUE klass;
863
          ID called_id;
864

  
865
          rb_thread_method_id_and_class(th, &called_id, &klass);
866

  
867
          RUBY_DTRACE_FUNCTION_RETURN(
868
                  RSTRING_PTR(rb_inspect(klass)),
869
                  rb_id2name(called_id),
870
                  rb_sourcefile(),
871
                  rb_sourceline());
872
        }
873
    }
841 874
    EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */);
842 875
}
843 876

  
internal.h
69 69
int rb_local_defined(ID);
70 70
int rb_parse_in_eval(void);
71 71
int rb_parse_in_main(void);
72
const char * rb_insns_name(int i);
72 73
VALUE rb_insns_name_array(void);
73 74

  
74 75
/* cont.c */
load.c
7 7
#include "internal.h"
8 8
#include "dln.h"
9 9
#include "eval_intern.h"
10
#include "probes.h"
10 11

  
11 12
VALUE ruby_dln_librefs;
12 13

  
......
376 377
    VALUE fname, wrap, path;
377 378

  
378 379
    rb_scan_args(argc, argv, "11", &fname, &wrap);
380

  
381
    if(RUBY_DTRACE_LOAD_ENTRY_ENABLED()) {
382
      RUBY_DTRACE_LOAD_ENTRY(
383
          StringValuePtr(fname),
384
          rb_sourcefile(),
385
          rb_sourceline());
386
    }
387

  
379 388
    path = rb_find_file(FilePathValue(fname));
380 389
    if (!path) {
381 390
	if (!rb_file_load_ok(RSTRING_PTR(fname)))
......
383 392
	path = fname;
384 393
    }
385 394
    rb_load_internal(path, RTEST(wrap));
395

  
396
    if(RUBY_DTRACE_LOAD_RETURN_ENABLED()) {
397
      RUBY_DTRACE_LOAD_RETURN(StringValuePtr(fname));
398
    }
399

  
386 400
    return Qtrue;
387 401
}
388 402

  
......
616 630
    } volatile saved;
617 631
    char *volatile ftptr = 0;
618 632

  
633
    if(RUBY_DTRACE_REQUIRE_ENTRY_ENABLED()) {
634
      RUBY_DTRACE_REQUIRE_ENTRY(
635
          StringValuePtr(fname),
636
          rb_sourcefile(),
637
          rb_sourceline());
638
    }
639

  
619 640
    PUSH_TAG();
620 641
    saved.safe = rb_safe_level();
621 642
    if ((state = EXEC_TAG()) == 0) {
......
626 647
	rb_set_safe_level_force(safe);
627 648
	FilePathValue(fname);
628 649
	rb_set_safe_level_force(0);
650

  
651
	if(RUBY_DTRACE_FIND_REQUIRE_ENTRY_ENABLED()) {
652
	    RUBY_DTRACE_FIND_REQUIRE_ENTRY(
653
		    StringValuePtr(fname),
654
		    rb_sourcefile(),
655
		    rb_sourceline());
656
	}
657

  
629 658
	found = search_required(fname, &path, safe);
659

  
660
	if(RUBY_DTRACE_FIND_REQUIRE_RETURN_ENABLED()) {
661
	    RUBY_DTRACE_FIND_REQUIRE_RETURN(
662
		    StringValuePtr(fname),
663
		    rb_sourcefile(),
664
		    rb_sourceline());
665
	}
630 666
	if (found) {
631 667
	    if (!path || !(ftptr = load_lock(RSTRING_PTR(path)))) {
632 668
		result = Qfalse;
......
662 698

  
663 699
    th->errinfo = errinfo;
664 700

  
701
    if(RUBY_DTRACE_REQUIRE_RETURN_ENABLED()) {
702
      RUBY_DTRACE_REQUIRE_RETURN(StringValuePtr(fname));
703
    }
704

  
665 705
    return result;
666 706
}
667 707

  
object.c
22 22
#include <float.h>
23 23
#include "constant.h"
24 24
#include "internal.h"
25
#include "probes.h"
25 26

  
26 27
VALUE rb_cBasicObject;
27 28
VALUE rb_mKernel;
......
1669 1670
		 klass);
1670 1671
    }
1671 1672

  
1673
    if (RUBY_DTRACE_OBJECT_CREATE_ENABLED()) {
1674
        const char * file = rb_sourcefile();
1675
        RUBY_DTRACE_OBJECT_CREATE(rb_class2name(klass),
1676
                                 file ? file : "",
1677
                                 rb_sourceline());
1678
    }
1679

  
1672 1680
    obj = (*allocator)(klass);
1681

  
1673 1682
    if (rb_obj_class(obj) != rb_class_real(klass)) {
1674 1683
	rb_raise(rb_eTypeError, "wrong instance allocation");
1675 1684
    }
parse.y
29 29
#include <stdio.h>
30 30
#include <errno.h>
31 31
#include <ctype.h>
32
#include "probes.h"
32 33

  
33 34
#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
34 35

  
......
5310 5311
#ifndef RIPPER
5311 5312
    parser->parser_token_info_enabled = !compile_for_eval && RTEST(ruby_verbose);
5312 5313
#endif
5314
#ifndef RIPPER
5315
    if(RUBY_DTRACE_PARSE_BEGIN_ENABLED()) {
5316
	RUBY_DTRACE_PARSE_BEGIN(parser->parser_ruby_sourcefile,
5317
		parser->parser_ruby_sourceline);
5318
    }
5319
#endif
5313 5320
    n = yyparse((void*)parser);
5321
#ifndef RIPPER
5322
    if(RUBY_DTRACE_PARSE_END_ENABLED()) {
5323
	RUBY_DTRACE_PARSE_END(parser->parser_ruby_sourcefile,
5324
		parser->parser_ruby_sourceline);
5325
    }
5326
#endif
5314 5327
    ruby_debug_lines = 0;
5315 5328
    ruby_coverage = 0;
5316 5329
    compile_for_eval = 0;
probes.d
1
provider ruby {
2
  probe function__entry(const char *, const char *, const char *, int);
3
  probe function__return(const char *, const char *, const char *, int);
4

  
5
  probe require__entry(const char *, const char *, int);
6
  probe require__return(const char *);
7

  
8
  probe find__require__entry(const char *, const char *, int);
9
  probe find__require__return(const char *, const char *, int);
10

  
11
  probe load__entry(const char *, const char *, int);
12
  probe load__return(const char *);
13

  
14
  probe raise(const char *, const char *, int);
15

  
16
  probe object__create(const char *, const char *, int);
17
  probe array__create(long, const char *, int);
18
  probe hash__create(long, const char *, int);
19
  probe string__create(long, const char *, int);
20

  
21
  probe parse__begin(const char *, int);
22
  probe parse__end(const char *, int);
23

  
24
  probe insn(const char *);
25
  probe insn__operand(const char *, const char *);
26

  
27
  probe gc__mark__begin();
28
  probe gc__mark__end();
29
  probe gc__sweep__begin();
30
  probe gc__sweep__end();
31
};
32

  
33
#pragma D attributes Stable/Evolving/Common provider ruby provider
34
#pragma D attributes Stable/Evolving/Common provider ruby module
35
#pragma D attributes Stable/Evolving/Common provider ruby function
36
#pragma D attributes Evolving/Evolving/Common provider ruby name
37
#pragma D attributes Evolving/Evolving/Common provider ruby args
string.c
15 15
#include "ruby/re.h"
16 16
#include "ruby/encoding.h"
17 17
#include "internal.h"
18
#include "probes.h"
18 19
#include <assert.h>
19 20

  
20 21
#define BEG(no) (regs->beg[(no)])
......
379 380
    return (VALUE)str;
380 381
}
381 382

  
383
static inline VALUE
384
empty_str_alloc(VALUE klass)
385
{
386
    if(RUBY_DTRACE_STRING_CREATE_ENABLED()) {
387
	RUBY_DTRACE_STRING_CREATE(0, rb_sourcefile(), rb_sourceline());
388
    }
389
    return str_alloc(klass);
390
}
391

  
382 392
static VALUE
383 393
str_new(VALUE klass, const char *ptr, long len)
384 394
{
......
388 398
	rb_raise(rb_eArgError, "negative string size (or size too big)");
389 399
    }
390 400

  
401
    if(RUBY_DTRACE_STRING_CREATE_ENABLED()) {
402
	RUBY_DTRACE_STRING_CREATE(len, rb_sourcefile(), rb_sourceline());
403
    }
404

  
391 405
    str = str_alloc(klass);
392 406
    if (len > RSTRING_EMBED_LEN_MAX) {
393 407
	RSTRING(str)->as.heap.aux.capa = len;
......
910 924
VALUE
911 925
rb_str_resurrect(VALUE str)
912 926
{
927
    if(RUBY_DTRACE_STRING_CREATE_ENABLED()) {
928
	RUBY_DTRACE_STRING_CREATE(
929
            RSTRING_LEN(str), rb_sourcefile(), rb_sourceline());
930
    }
913 931
    return str_replace(str_alloc(rb_cString), str);
914 932
}
915 933

  
......
7867 7885

  
7868 7886
    rb_cString  = rb_define_class("String", rb_cObject);
7869 7887
    rb_include_module(rb_cString, rb_mComparable);
7870
    rb_define_alloc_func(rb_cString, str_alloc);
7888
    rb_define_alloc_func(rb_cString, empty_str_alloc);
7871 7889
    rb_define_singleton_method(rb_cString, "try_convert", rb_str_s_try_convert, 1);
7872 7890
    rb_define_method(rb_cString, "initialize", rb_str_init, -1);
7873 7891
    rb_define_method(rb_cString, "initialize_copy", rb_str_replace, 1);
test/dtrace/dummy.rb
1
# this is a dummy file used by test/dtrace/test_require.rb
test/dtrace/helper.rb
1
require 'minitest/autorun'
2
require 'tempfile'
3

  
4
module DTrace
5
  class TestCase < MiniTest::Unit::TestCase
6
    INCLUDE = File.expand_path(File.join(File.dirname(__FILE__), '..'))
7

  
8
    def setup
9
      skip "must be setuid 0 to run dtrace tests" unless Process.euid == 0
10
    end
11

  
12
    def trap_probe d_program, ruby_program
13
      d = Tempfile.new('probe.d')
14
      d.write d_program
15
      d.flush
16

  
17
      rb = Tempfile.new('probed.rb')
18
      rb.write ruby_program
19
      rb.flush
20

  
21
      d_path  = d.path
22
      rb_path = rb.path
23

  
24
      cmd = "dtrace -q -s #{d_path} -c '#{Gem.ruby} -I#{INCLUDE} #{rb_path}'"
25
      probes = IO.popen(cmd) do |io|
26
        io.readlines
27
      end
28
      d.close(true)
29
      rb.close(true)
30
      yield(d_path, rb_path, probes)
31
    end
32
  end
33
end
test/dtrace/test_array_create.rb
1
require 'dtrace/helper'
2

  
3
module DTrace
4
  class TestArrayCreate < TestCase
5
    def test_lit
6
      trap_probe(probe, '[]') { |_,rbfile,saw|
7
        saw = saw.map(&:split).find_all { |num, file, line|
8
          file == rbfile && num == '0'
9
        }
10
        assert_equal([rbfile], saw.map { |line| line[1] })
11
        assert_equal(['1'], saw.map { |line| line[2] })
12
      }
13
    end
14

  
15
    def test_many_lit
16
      trap_probe(probe, '[1,2,3,4]') { |_,rbfile,saw|
17
        saw = saw.map(&:split).find_all { |num, file, line|
18
          file == rbfile && num == '4' && line == '1'
19
        }
20
        assert_operator saw.length, :>, 0
21
      }
22
    end
23

  
24
    private
25
    def probe type = 'array'
26
      <<-eoprobe
27
ruby$target:::#{type}-create
28
/arg1/
29
{
30
  printf("%d %s %d\\n", arg0, copyinstr(arg1), arg2);
31
}
32
      eoprobe
33
    end
34
  end
35
end
test/dtrace/test_function_entry.rb
1
require 'dtrace/helper'
2

  
3
module DTrace
4
  class TestFunctionEntry < TestCase
5
    def test_function_entry
6
      probe = <<-eoprobe
7
ruby$target:::function-entry
8
/arg0 && arg1 && arg2/
9
{
10
  printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
11
}
12
      eoprobe
13

  
14
      trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
15
	foo_calls = probes.map { |line| line.split }.find_all { |row|
16
	  row.first == 'Foo'  && row[1] == 'foo'
17
	}
18

  
19
	assert_equal 10, foo_calls.length
20
	line = '2'
21
	foo_calls.each { |f| assert_equal line, f[3] }
22
	foo_calls.each { |f| assert_equal rb_file, f[2] }
23
      }
24
    end
25

  
26
    def test_function_return
27
      probe = <<-eoprobe
28
ruby$target:::function-return
29
/arg0 && arg1 && arg2/
30
{
31
  printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
32
}
33
      eoprobe
34

  
35
      trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
36
	foo_calls = probes.map { |line| line.split }.find_all { |row|
37
	  row.first == 'Foo'  && row[1] == 'foo'
38
	}
39

  
40
	assert_equal 10, foo_calls.length
41
	line = '2'
42
	foo_calls.each { |f| assert_equal line, f[3] }
43
	foo_calls.each { |f| assert_equal rb_file, f[2] }
44
      }
45
    end
46

  
47
    private
48
    def ruby_program
49
      <<-eoruby
50
      class Foo
51
	def foo; end
52
      end
53
      x = Foo.new
54
      10.times { x.foo }
55
      eoruby
56
    end
57
  end
58
end
test/dtrace/test_gc.rb
1
require 'dtrace/helper'
2

  
3
module DTrace
4
  class TestGC < TestCase
5
    %w{
6
      gc-mark-begin
7
      gc-mark-end
8
      gc-sweep-begin
9
      gc-sweep-end
10
    }.each do |probe_name|
11
      define_method(:"test_#{probe_name.gsub(/-/, '_')}") do
12
	probe = "ruby$target:::#{probe_name} { printf(\"#{probe_name}\\n\"); }"
13

  
14
	trap_probe(probe, ruby_program) { |_, _, saw|
15
	  assert_operator saw.length, :>, 0
16
	}
17

  
18
      end
19
    end
20

  
21
    private
22
    def ruby_program
23
      "100000.times { Object.new }"
24
    end
25
  end
26
end
test/dtrace/test_hash_create.rb
1
require 'dtrace/helper'
2

  
3
module DTrace
4
  class TestHashCreate < TestCase
5
    def test_hash_new
6
      trap_probe(probe, 'Hash.new') { |_,rbfile,saw|
7
        saw = saw.map(&:split).find_all { |num, file, line|
8
          file == rbfile && num == '0'
9
        }
10
        assert_operator saw.length, :>, 0
11
      }
12
    end
13

  
14
    def test_hash_lit
15
      trap_probe(probe, '{}') { |_,rbfile,saw|
16
        saw = saw.map(&:split).find_all { |num, file, line|
17
          file == rbfile && num == '0'
18
        }
19
        assert_operator saw.length, :>, 0
20
      }
21
    end
22

  
23
    def test_hash_lit_elements
24
      trap_probe(probe, '{ :foo => :bar }') { |_,rbfile,saw|
25
        saw = saw.map(&:split).find_all { |num, file, line|
26
          file == rbfile && num == '2'
27
        }
28
        assert_operator saw.length, :>, 0
29
      }
30
    end
31

  
32
    def test_hash_lit_elements_string
33
      trap_probe(probe, '{ :foo => :bar, :bar => "baz" }') { |_,rbfile,saw|
34
        saw = saw.map(&:split).find_all { |num, file, line|
35
          file == rbfile && num == '4'
36
        }
37
        assert_operator saw.length, :>, 0
38
      }
39
    end
40

  
41
    private
42
    def probe
43
      <<-eoprobe
44
ruby$target:::hash-create
45
/arg1/
46
{
47
  printf("%d %s %d\\n", arg0, copyinstr(arg1), arg2);
48
}
49
      eoprobe
50
    end
51
  end
52
end
test/dtrace/test_load.rb
1
require 'dtrace/helper'
2
require 'tempfile'
3

  
4
module DTrace
5
  class TestLoad < TestCase
6
    def setup
7
      super
8
      @rbfile = Tempfile.new(['omg', 'rb'])
9
      @rbfile.write 'x = 10'
10
    end
11

  
12
    def teardown
13
      super
14
      @rbfile.close(true) if @rbfile
15
    end
16

  
17
    def test_load_entry
18
      probe = <<-eoprobe
19
ruby$target:::load-entry
20
{
21
  printf("%s %s %d\\n", copyinstr(arg0), copyinstr(arg1), arg2);
22
}
23
      eoprobe
24
      trap_probe(probe, program) { |dpath, rbpath, saw|
25
	saw = saw.map(&:split).find_all { |loaded, _, _|
26
	  loaded == @rbfile.path
27
	}
28
	assert_equal 10, saw.length
29
      }
30
    end
31

  
32
    def test_load_return
33
      probe = <<-eoprobe
34
ruby$target:::load-return
35
{
36
  printf("%s\\n", copyinstr(arg0));
37
}
38
      eoprobe
39
      trap_probe(probe, program) { |dpath, rbpath, saw|
40
	saw = saw.map(&:split).find_all { |loaded, _, _|
41
	  loaded == @rbfile.path
42
	}
43
	assert_equal 10, saw.length
44
      }
45
    end
46

  
47
    private
48
    def program
49
      "10.times { load '#{@rbfile.path}' }"
50
    end
51
  end
52
end
test/dtrace/test_object_create_start.rb
1
require 'dtrace/helper'
2

  
3
module DTrace
4
  class TestObjectCreateStart < TestCase
5
    def test_object_create_start
6
      trap_probe(probe, '10.times { Object.new }') { |_,rbfile,saw|
7
        saw = saw.map(&:split).find_all { |_, file, _|
8
          file == rbfile
9
        }
10
        assert_equal 10, saw.length
11
      }
12
    end
13

  
14
    def test_object_create_start_name
15
      trap_probe(probe, 'Hash.new') { |_,rbfile,saw|
16
        saw = saw.map(&:split).find_all { |klass, file, line|
17
          file == rbfile
18
        }
19
        assert_equal(%w{ Hash }, saw.map(&:first))
20
        assert_equal([rbfile], saw.map { |line| line[1] })
21
        assert_equal(['1'], saw.map { |line| line[2] })
22
      }
23
    end
24

  
25
    def test_object_create_start_string_lit
26
      trap_probe(probe, '"omg"') { |_,rbfile,saw|
27
        saw = saw.map(&:split).find_all { |klass, file, line|
28
          file == rbfile
29
        }
30
        assert_equal(%w{ String }, saw.map(&:first))
31
        assert_equal([rbfile], saw.map { |line| line[1] })
32
        assert_equal(['1'], saw.map { |line| line[2] })
33
      }
34
    end
35

  
36
    private
37
    def probe type = "object"
38
      <<-eoprobe
39
ruby$target:::#{type}-create
40
{
41
  printf("%s %s %d\\n", copyinstr(arg0), copyinstr(arg1), arg2);
42
}
43
      eoprobe
44
    end
45
  end
46
end
test/dtrace/test_raise.rb
1
require 'dtrace/helper'
2

  
3
module DTrace
4
  class TestRaise < TestCase
5
    def test_raise
6
      probe = <<-eoprobe
7
ruby$target:::raise
8
{
9
  printf("%s %s %d\\n", copyinstr(arg0), copyinstr(arg1), arg2);
10
}
11
      eoprobe
12
      trap_probe(probe, program) { |dpath, rbpath, saw|
13
	saw = saw.map(&:split).find_all { |_, source_file, _|
14
	  source_file == rbpath
15
	}
16
	assert_equal 10, saw.length
17
	saw.each do |klass, _, source_line|
18
	  assert_equal 'RuntimeError', klass
19
	  assert_equal '1', source_line
20
	end
21
      }
22
    end
23

  
24
    private
25
    def program
26
      '10.times { raise rescue nil }'
27
    end
28
  end
29
end
test/dtrace/test_require.rb
1
require 'dtrace/helper'
2

  
3
module DTrace
4
  class TestRequire < TestCase
5
    def test_require_entry
6
      probe = <<-eoprobe
7
ruby$target:::require-entry
8
{
9
  printf("%s %s %d\\n", copyinstr(arg0), copyinstr(arg1), arg2);
10
}
11
      eoprobe
12
      trap_probe(probe, ruby_program) { |d_file, rb_file, saw|
13
	required = saw.map { |s| s.split }.find_all do |(required, _)|
14
	  required == 'dtrace/dummy'
15
	end
16
	assert_equal 10, required.length
17
      }
18
    end
19

  
20
    def test_require_return
21
      probe = <<-eoprobe
22
ruby$target:::require-return
23
{
24
  printf("%s\\n", copyinstr(arg0));
25
}
26
      eoprobe
27
    end
28

  
29
    private
30
    def ruby_program
31
      "10.times { require 'dtrace/dummy' }"
32
    end
33
  end
34
end
test/dtrace/test_singleton_function.rb
1
require 'dtrace/helper'
2

  
3
module DTrace
4
  class TestSingletonFunctionEntry < TestCase
5
    def test_entry
6
      probe = <<-eoprobe
7
ruby$target:::function-entry
8
/strstr(copyinstr(arg0), "Foo") != NULL/
9
{
10
  printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
11
}
12
      eoprobe
13

  
14
      trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
15
	foo_calls = probes.map { |line| line.split }.find_all { |row|
16
	  row.first == '#<Class:Foo>'  && row[1] == 'foo'
17
	}
18

  
19
	assert_equal 10, foo_calls.length
20
	line = '2'
21
	foo_calls.each { |f| assert_equal line, f[3] }
22
	foo_calls.each { |f| assert_equal rb_file, f[2] }
23
      }
24
    end
25

  
26
    def test_exit
27
      probe = <<-eoprobe
28
ruby$target:::function-return
29
{
30
  printf("%s %s %s %d\\n", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3);
31
}
32
      eoprobe
33

  
34
      trap_probe(probe, ruby_program) { |d_file, rb_file, probes|
35
	foo_calls = probes.map { |line| line.split }.find_all { |row|
36
	  row.first == '#<Class:Foo>'  && row[1] == 'foo'
37
	}
38

  
39
	assert_equal 10, foo_calls.length
40
	line = '2'
41
	foo_calls.each { |f| assert_equal line, f[3] }
42
	foo_calls.each { |f| assert_equal rb_file, f[2] }
43
      }
44
    end
45

  
46
    def ruby_program
47
      <<-eoruby
48
      class Foo
49
	def self.foo; end
50
      end
51
      10.times { Foo.foo }
52
      eoruby
53
    end
54
  end
55
end
tool/gen_dummy_probes.sed
1

  
2
# upper case everything
3
y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
4

  
5
# remove the pragma declarations
6
s/^#PRAGMA.*$//
7

  
8
# replace the provider section with the start of the header file
9
s/PROVIDER RUBY {/#ifndef	_PROBES_H\
10
#define	_PROBES_H/
11

  
12
# finish up the #ifndef sandwich
13
s/};/#endif	\/* _PROBES_H *\//
14

  
15
s/__/_/g
16

  
17
s/([^,)]\{1,\})/(arg0)/
18
s/([^,)]\{1,\},[^,)]\{1,\})/(arg0, arg1)/
19
s/([^,)]\{1,\},[^,)]\{1,\},[^,)]\{1,\})/(arg0, arg1, arg2)/
20
s/([^,)]\{1,\},[^,)]\{1,\},[^,)]\{1,\},[^,)]\{1,\})/(arg0, arg1, arg2, arg3)/
21
s/([^,)]\{1,\},[^,)]\{1,\},[^,)]\{1,\},[^,)]\{1,\},[^,)]\{1,\})/(arg0, arg1, arg2, arg3, arg4)/
22

  
23
s/[ ]*PROBE[ ]\([^\(]*\)\(([^\)]*)\);/#define RUBY_DTRACE_\1_ENABLED() 0\
24
#define RUBY_DTRACE_\1\2\ do \{ \} while\(0\)/
vm.c
18 18
#include "vm_core.h"
19 19
#include "iseq.h"
20 20
#include "eval_intern.h"
21
#include "probes.h"
21 22

  
22 23
static inline VALUE *
23 24
VM_EP_LEP(VALUE *ep)
......
65 66
#define VM_COLLECT_USAGE_DETAILS 0
66 67
#endif
67 68

  
68
#if VM_COLLECT_USAGE_DETAILS
69 69
static void vm_collect_usage_operand(int insn, int n, VALUE op);
70 70
static void vm_collect_usage_register(int reg, int isset);
71 71
static void vm_collect_usage_insn(int insn);
72
#endif
73 72

  
74 73
static VALUE
75 74
vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self, VALUE defined_class,
......
1174 1173
	    if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
1175 1174
		const rb_method_entry_t *me = th->cfp->me;
1176 1175
		EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass);
1176
		RUBY_DTRACE_FUNC_RETURN_HOOK(me->klass, me->called_id);
1177 1177
	    }
1178 1178
	    th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
1179 1179
	}
......
1973 1973
    VALUE hash = rb_hash_new();
1974 1974
    int i;
1975 1975

  
1976
    if(RUBY_DTRACE_HASH_CREATE_ENABLED()) {
1977
	RUBY_DTRACE_HASH_CREATE(RARRAY_LEN(ary), rb_sourcefile(), rb_sourceline());
1978
    }
1979

  
1976 1980
    for (i=0; i<RARRAY_LEN(ary); i+=2) {
1977 1981
	rb_hash_aset(hash, RARRAY_PTR(ary)[i], RARRAY_PTR(ary)[i+1]);
1978 1982
    }
......
2298 2302
    return ruby_vm_debug_ptr(GET_VM());
2299 2303
}
2300 2304

  
2305
/* iseq.c */
2306
VALUE insn_operand_intern(rb_iseq_t *iseq,
2307
			  VALUE insn, int op_no, VALUE op,
2308
			  int len, size_t pos, VALUE *pnop, VALUE child);
2309

  
2301 2310
#if VM_COLLECT_USAGE_DETAILS
2302 2311

  
2303 2312
#define HASH_ASET(h, k, v) st_insert(RHASH_TBL(h), (st_data_t)(k), (st_data_t)(v))
......
2355 2364
    prev_insn = insn;
2356 2365
}
2357 2366

  
2358
/* iseq.c */
2359
VALUE insn_operand_intern(rb_iseq_t *iseq,
2360
			  VALUE insn, int op_no, VALUE op,
2361
			  int len, size_t pos, VALUE *pnop, VALUE child);
2362

  
2363 2367
static void
2364 2368
vm_analysis_operand(int insn, int n, VALUE op)
2365 2369
{
......
2466 2470
    return Qnil;
2467 2471
}
2468 2472

  
2473
#else
2474

  
2475
void (*ruby_vm_collect_usage_func_insn)(int insn) = NULL;
2476
void (*ruby_vm_collect_usage_func_operand)(int insn, int n, VALUE op) = NULL;
2477
void (*ruby_vm_collect_usage_func_register)(int reg, int isset) = NULL;
2478

  
2479
#endif
2480

  
2469 2481
/* @param insn instruction number */
2470 2482
static void
2471 2483
vm_collect_usage_insn(int insn)
2472 2484
{
2485
    if (RUBY_DTRACE_INSN_ENABLED()) {
2486
	RUBY_DTRACE_INSN(rb_insns_name(insn));
2487
    }
2473 2488
    if (ruby_vm_collect_usage_func_insn)
2474 2489
      (*ruby_vm_collect_usage_func_insn)(insn);
2475 2490
}
......
2481 2496
static void
2482 2497
vm_collect_usage_operand(int insn, int n, VALUE op)
2483 2498
{
2499
    if (RUBY_DTRACE_INSN_OPERAND_ENABLED()) {
2500
	VALUE valstr;
2501

  
2502
	valstr = insn_operand_intern(GET_THREAD()->cfp->iseq, insn, n, op, 0, 0, 0, 0);
2503

  
2504
	RUBY_DTRACE_INSN_OPERAND(RSTRING_PTR(valstr), rb_insns_name(insn));
2505
    }
2484 2506
    if (ruby_vm_collect_usage_func_operand)
2485 2507
      (*ruby_vm_collect_usage_func_operand)(insn, n, op);
2486 2508
}
......
2494 2516
      (*ruby_vm_collect_usage_func_register)(reg, isset);
2495 2517
}
2496 2518

  
2497
#endif
vm_core.h
23 23
#include "id.h"
24 24
#include "method.h"
25 25
#include "atomic.h"
26
#include "probes.h"
26 27

  
27 28
#if   defined(_WIN32)
28 29
#include "thread_win32.h"
......
894 895
    } \
895 896
} while (0)
896 897

  
898
#define RUBY_DTRACE_FUNC_ENTRY_HOOK(klass, id) \
899
    if (RUBY_DTRACE_FUNCTION_ENTRY_ENABLED()) { \
900
	const char * classname  = rb_class2name((klass)); \
901
	const char * methodname = rb_id2name((id)); \
902
	const char * filename   = rb_sourcefile(); \
903
	if (classname && methodname && filename) { \
904
	    RUBY_DTRACE_FUNCTION_ENTRY( \
905
		    classname, \
906
		    methodname, \
907
		    filename, \
908
		    rb_sourceline()); \
909
	} \
910
    } \
911

  
912
#define RUBY_DTRACE_FUNC_RETURN_HOOK(klass, id) \
913
    if (RUBY_DTRACE_FUNCTION_RETURN_ENABLED()) { \
914
	const char * classname  = rb_class2name((klass)); \
915
	const char * methodname = rb_id2name((id)); \
916
	const char * filename   = rb_sourcefile(); \
917
	if (classname && methodname && filename) { \
918
	    RUBY_DTRACE_FUNCTION_RETURN( \
919
		    classname, \
920
		    methodname, \
921
		    filename, \
922
		    rb_sourceline()); \
923
	} \
924
    } \
925

  
926

  
897 927
#if defined __GNUC__ && __GNUC__ >= 4
898 928
#pragma GCC visibility push(default)
899 929
#endif
vm_dump.c
13 13
#include "addr2line.h"
14 14
#include "vm_core.h"
15 15
#include "internal.h"
16
#include "probes.h"
16 17

  
17 18
/* see vm_insnhelper.h for the values */
18 19
#ifndef VMDEBUG
vm_eval.c
55 55
{
56 56
    VALUE val;
57 57

  
58
    RUBY_DTRACE_FUNC_ENTRY_HOOK(ci->defined_class, ci->mid);
58 59
    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, ci->recv, ci->mid, ci->defined_class);
59 60
    {
60 61
	rb_control_frame_t *reg_cfp = th->cfp;
......
84 85
	}
85 86
    }
86 87
    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, ci->recv, ci->mid, ci->defined_class);
88
    RUBY_DTRACE_FUNC_RETURN_HOOK(ci->defined_class, ci->mid);
87 89

  
88 90
    return val;
89 91
}
......
93 95
{
94 96
    VALUE val;
95 97

  
98
    RUBY_DTRACE_FUNC_ENTRY_HOOK(ci->defined_class, ci->mid);
96 99
    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, ci->recv, ci->mid, ci->defined_class);
97 100
    {
98 101
	rb_control_frame_t *reg_cfp = th->cfp;
......
116 119
	vm_pop_frame(th);
117 120
    }
118 121
    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, ci->recv, ci->mid, ci->defined_class);
122
    RUBY_DTRACE_FUNC_RETURN_HOOK(ci->defined_class, ci->mid);
119 123

  
120 124
    return val;
121 125
}
......
290 294
{
291 295
    VALUE defined_class;
292 296
    rb_method_entry_t *me = rb_search_method_entry(recv, mid, &defined_class);
297

  
293 298
    rb_thread_t *th = GET_THREAD();
294 299
    int call_status = rb_method_call_status(th, me, scope, self);
295 300

  
......
986 991
		    if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) {
987 992
			const rb_method_entry_t *me = th->cfp->me;
988 993
			EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass);
994
			RUBY_DTRACE_FUNC_RETURN_HOOK(me->klass, me->called_id);
989 995
		    }
990 996

  
991 997
		    th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
vm_exec.c
11 11

  
12 12
#include <math.h>
13 13

  
14
void vm_analysis_insn(int insn);
15

  
14 16
#if VMDEBUG > 0
15 17
#define DECL_SC_REG(type, r, reg) register type reg_##r
16 18

  
vm_insnhelper.c
13 13
#include <math.h>
14 14
#include "constant.h"
15 15
#include "internal.h"
16
#include "probes.h"
16 17

  
17 18
/* control stack frame */
18 19

  
......
1430 1431
    int len = cfunc->argc;
1431 1432
    VALUE recv = ci->recv;
1432 1433

  
1434
    RUBY_DTRACE_FUNC_ENTRY_HOOK(me->klass, me->called_id);
1433 1435
    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass);
1434 1436

  
1435 1437
    vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, ci->defined_class,
......
1448 1450
    vm_pop_frame(th);
1449 1451

  
1450 1452
    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, me->called_id, me->klass);
1453
    RUBY_DTRACE_FUNC_RETURN_HOOK(me->klass, me->called_id);
1451 1454

  
1452 1455
    return val;
1453 1456
}
......
1495 1498

  
1496 1499
    if (len >= 0) rb_check_arity(ci->argc, len, len);
1497 1500

  
1501
    RUBY_DTRACE_FUNC_ENTRY_HOOK(me->klass, me->called_id);
1498 1502
    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass);
1499 1503

  
1500 1504
    if (!(ci->me->flag & NOEX_PROTECTED) &&
......
1504 1508
    val = vm_call_cfunc_latter(th, reg_cfp, ci);
1505 1509

  
1506 1510
    EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, me->called_id, me->klass);
1511
    RUBY_DTRACE_FUNC_RETURN_HOOK(me->klass, me->called_id);
1507 1512

  
1508 1513
    return val;
1509 1514
}
... This diff was truncated because it exceeds the maximum size that can be displayed.