* trace.h: new file. wraps tracing mechanisms.
* defs/dtrace.d: new file. defined a dtrace provider "ruby". * include/ruby/ruby.h (LIKELY): moved from vm.c. (UNLIKELY): ditto. (OBJSETUP): probe "object-create". (RUBY_EVENT_RESCUE): new event. * vm_exec.c (DEBUG_ENTER_INSN): embeded a probe insn-entry into it. (DEBUG_END_INSN): insn-return. * vm.c (LIKELY): moved into ruby.h. (UNLIKELY): ditto. (Init_BareVM): embeded a probe "raise" into it. * variable.c (rb_class2name_without_alloc): new utility function. * tool/rbinstall.rb (install?(:ext, :arch, :'ext-arch')): installs dtrace.d if necessary. * thread_pthread.c (add_signal_thread_list): probe "raise". (rb_thread_create_timer_thread): ditto. * thread.c (rb_thread_schedule_rec): probes "thread-enter" and "thread-leave", (thread_start_func_2): ditto. (thread_cleanup_func): probe "thread-term" * lib/mkmf.rb: supports dtrace postprocessor on making an extension. * iseq.c (rb_vm_insn_name): new utility function. (rb_vm_insn_len): ditto. * insns.def (hook): probes "method-etnry", "method-return", "line", and "rescue". * compile.c (iseq_compile_each): adds a trace op for "rescue" probe. * gc.c (garbage_collect): probes "gc-begin" and "gc-end". (obj_free): probe "object-free" (garbage_collect_with_gvl): probe "raise" (negative_size_allocation_error): ditto. (rb_memerror): ditto. * eval.c (rb_rescue2): probe "rescue" (rb_longjmp): probe "raise" * ext/probe/probe.c: new extension for application defined probes. * ext/probe/extconf.rb: ditto. * configure.in (--with-tracing-model): new option to choose a tracing mechanism. (DTRACE): new substitution. name of dtrace(1). (RUBY_TRACING_MODEL): new substitution. (DTRACE_OBJ): ditto. (MINIDTRACE_OBJ): ditto. (GOLFDTRACE_OBJ): ditto. (LIBRUBY_DTRACE_OBJ): ditto. (RUBY_DTRACE_POSTPROCESS): new macro. checks whether the dtrace on the system needs postprocessing. (RUBY_DTRACE_BSD_BROKEN): new macro. checks whether the dtrace supports USDT. * Makefile.in: (DTRACE): new variable. name of dtrace(1). (TRACING_MODEL): new variable. name of the chosen tracing mechanism. (DTRACE_OBJ): same as the one in configure.in. (MINIDTRACE_OBJ): ditto. (GOLFDTRACE_OBJ): ditto. (LIBRUBY_DTRACE_OBJ): ditto. (CPPOUTFILE): new substitution. necessary for generating dtrace.d (trace_none.h): new target for TRACING_MODEL=none (RUBY_H_INCLUDES): appended a header for tracing. (distclean-local): also removes preprocessed version of dtrace.d ($(LIBRUBY_A)): needs $(LIBRUBY_DTRACE_OBJ) if dtrace needs postprocessing. ($(PROGRAM)): ditto. (golf): ditto. (miniruby): ditto. ($(arch_hdrdir)/ruby/dtrace.d): new target. preprocessed verson of defs/dtrace.d. generated if necessary. ($(arch_hdrdir)/ruby/trace_dtrace.h): new target. definition of probes. ($(LIBRUBY_DTRACE_OBJ)): new target. generated if dtrace needs postprocessing. ($(DTRACE_OBJ)): ditto. ($(MINIDTRACE_OBJ)): ditto. ($(GOLFDTRACE_OBJ)): ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26235 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0e8fae89ab
commit
72b199940d
93
ChangeLog
93
ChangeLog
@ -1,3 +1,96 @@
|
|||||||
|
Sun Jan 3 23:54:51 2010 Yuki Sonoda (Yugui) <yugui@yugui.jp>
|
||||||
|
|
||||||
|
* trace.h: new file. wraps tracing mechanisms.
|
||||||
|
|
||||||
|
* defs/dtrace.d: new file. defined a dtrace provider "ruby".
|
||||||
|
|
||||||
|
* include/ruby/ruby.h (LIKELY): moved from vm.c.
|
||||||
|
(UNLIKELY): ditto.
|
||||||
|
(OBJSETUP): probe "object-create".
|
||||||
|
(RUBY_EVENT_RESCUE): new event.
|
||||||
|
|
||||||
|
* vm_exec.c (DEBUG_ENTER_INSN): embeded a probe insn-entry into it.
|
||||||
|
(DEBUG_END_INSN): insn-return.
|
||||||
|
|
||||||
|
* vm.c (LIKELY): moved into ruby.h.
|
||||||
|
(UNLIKELY): ditto.
|
||||||
|
(Init_BareVM): embeded a probe "raise" into it.
|
||||||
|
|
||||||
|
* variable.c (rb_class2name_without_alloc): new utility function.
|
||||||
|
|
||||||
|
* tool/rbinstall.rb (install?(:ext, :arch, :'ext-arch')): installs
|
||||||
|
dtrace.d if necessary.
|
||||||
|
|
||||||
|
* thread_pthread.c (add_signal_thread_list): probe "raise".
|
||||||
|
(rb_thread_create_timer_thread): ditto.
|
||||||
|
|
||||||
|
* thread.c (rb_thread_schedule_rec): probes "thread-enter" and
|
||||||
|
"thread-leave",
|
||||||
|
(thread_start_func_2): ditto.
|
||||||
|
(thread_cleanup_func): probe "thread-term"
|
||||||
|
|
||||||
|
* lib/mkmf.rb: supports dtrace postprocessor on making an extension.
|
||||||
|
|
||||||
|
* iseq.c (rb_vm_insn_name): new utility function.
|
||||||
|
(rb_vm_insn_len): ditto.
|
||||||
|
|
||||||
|
* insns.def (hook): probes "method-etnry", "method-return", "line",
|
||||||
|
and "rescue".
|
||||||
|
|
||||||
|
* compile.c (iseq_compile_each): adds a trace op for "rescue" probe.
|
||||||
|
|
||||||
|
* gc.c (garbage_collect): probes "gc-begin" and "gc-end".
|
||||||
|
(obj_free): probe "object-free"
|
||||||
|
(garbage_collect_with_gvl): probe "raise"
|
||||||
|
(negative_size_allocation_error): ditto.
|
||||||
|
(rb_memerror): ditto.
|
||||||
|
|
||||||
|
* eval.c (rb_rescue2): probe "rescue"
|
||||||
|
(rb_longjmp): probe "raise"
|
||||||
|
|
||||||
|
* ext/probe/probe.c: new extension for application defined probes.
|
||||||
|
|
||||||
|
* ext/probe/extconf.rb: ditto.
|
||||||
|
|
||||||
|
* configure.in (--with-tracing-model): new option to choose a tracing
|
||||||
|
mechanism.
|
||||||
|
(DTRACE): new substitution. name of dtrace(1).
|
||||||
|
(RUBY_TRACING_MODEL): new substitution.
|
||||||
|
(DTRACE_OBJ): ditto.
|
||||||
|
(MINIDTRACE_OBJ): ditto.
|
||||||
|
(GOLFDTRACE_OBJ): ditto.
|
||||||
|
(LIBRUBY_DTRACE_OBJ): ditto.
|
||||||
|
(RUBY_DTRACE_POSTPROCESS): new macro. checks whether the dtrace on
|
||||||
|
the system needs postprocessing.
|
||||||
|
(RUBY_DTRACE_BSD_BROKEN): new macro. checks whether the dtrace
|
||||||
|
supports USDT.
|
||||||
|
|
||||||
|
* Makefile.in:
|
||||||
|
(DTRACE): new variable. name of dtrace(1).
|
||||||
|
(TRACING_MODEL): new variable. name of the chosen tracing mechanism.
|
||||||
|
(DTRACE_OBJ): same as the one in configure.in.
|
||||||
|
(MINIDTRACE_OBJ): ditto.
|
||||||
|
(GOLFDTRACE_OBJ): ditto.
|
||||||
|
(LIBRUBY_DTRACE_OBJ): ditto.
|
||||||
|
(CPPOUTFILE): new substitution. necessary for generating dtrace.d
|
||||||
|
(trace_none.h): new target for TRACING_MODEL=none
|
||||||
|
(RUBY_H_INCLUDES): appended a header for tracing.
|
||||||
|
(distclean-local): also removes preprocessed version of dtrace.d
|
||||||
|
($(LIBRUBY_A)): needs $(LIBRUBY_DTRACE_OBJ) if dtrace needs
|
||||||
|
postprocessing.
|
||||||
|
($(PROGRAM)): ditto.
|
||||||
|
(golf): ditto.
|
||||||
|
(miniruby): ditto.
|
||||||
|
($(arch_hdrdir)/ruby/dtrace.d): new target. preprocessed verson
|
||||||
|
of defs/dtrace.d. generated if necessary.
|
||||||
|
($(arch_hdrdir)/ruby/trace_dtrace.h): new target.
|
||||||
|
definition of probes.
|
||||||
|
($(LIBRUBY_DTRACE_OBJ)): new target. generated if dtrace needs
|
||||||
|
postprocessing.
|
||||||
|
($(DTRACE_OBJ)): ditto.
|
||||||
|
($(MINIDTRACE_OBJ)): ditto.
|
||||||
|
($(GOLFDTRACE_OBJ)): ditto.
|
||||||
|
|
||||||
Sun Jan 3 15:34:19 2010 Yuki Sonoda (Yugui) <yugui@yugui.jp>
|
Sun Jan 3 15:34:19 2010 Yuki Sonoda (Yugui) <yugui@yugui.jp>
|
||||||
|
|
||||||
* lib/rexml/text.rb: String no longer has #each.
|
* lib/rexml/text.rb: String no longer has #each.
|
||||||
|
41
Makefile.in
41
Makefile.in
@ -52,6 +52,7 @@ debugflags = @debugflags@
|
|||||||
warnflags = @warnflags@
|
warnflags = @warnflags@
|
||||||
XCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) @XCFLAGS@
|
XCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) @XCFLAGS@
|
||||||
CPPFLAGS = @CPPFLAGS@
|
CPPFLAGS = @CPPFLAGS@
|
||||||
|
CPPOUTFILE = @CPPOUTFILE@
|
||||||
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
|
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
|
||||||
EXTLDFLAGS =
|
EXTLDFLAGS =
|
||||||
XLDFLAGS = @XLDFLAGS@ $(EXTLDFLAGS)
|
XLDFLAGS = @XLDFLAGS@ $(EXTLDFLAGS)
|
||||||
@ -66,6 +67,10 @@ ARCHMINIOBJS = @MINIOBJS@
|
|||||||
BUILTIN_ENCOBJS = @BUILTIN_ENCOBJS@
|
BUILTIN_ENCOBJS = @BUILTIN_ENCOBJS@
|
||||||
BUILTIN_TRANSSRCS = @BUILTIN_TRANSSRCS@
|
BUILTIN_TRANSSRCS = @BUILTIN_TRANSSRCS@
|
||||||
BUILTIN_TRANSOBJS = @BUILTIN_TRANSOBJS@
|
BUILTIN_TRANSOBJS = @BUILTIN_TRANSOBJS@
|
||||||
|
DTRACE_OBJ = @DTRACE_OBJ@
|
||||||
|
MINIDTRACE_OBJ = @MINIDTRACE_OBJ@
|
||||||
|
GOLFDTRACE_OBJ = @GOLFDTRACE_OBJ@
|
||||||
|
LIBRUBY_DTRACE_OBJ = @LIBRUBY_DTRACE_OBJ@
|
||||||
|
|
||||||
RUBY_BASE_NAME=@RUBY_BASE_NAME@
|
RUBY_BASE_NAME=@RUBY_BASE_NAME@
|
||||||
RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
|
RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
|
||||||
@ -92,6 +97,7 @@ LIBRUBYARG_STATIC = @LIBRUBYARG_STATIC@
|
|||||||
LIBRUBYARG_SHARED = @LIBRUBYARG_SHARED@
|
LIBRUBYARG_SHARED = @LIBRUBYARG_SHARED@
|
||||||
|
|
||||||
THREAD_MODEL = @THREAD_MODEL@
|
THREAD_MODEL = @THREAD_MODEL@
|
||||||
|
TRACING_MODEL = @TRACING_MODEL@
|
||||||
|
|
||||||
PREP = @PREP@
|
PREP = @PREP@
|
||||||
ARCHFILE = @ARCHFILE@
|
ARCHFILE = @ARCHFILE@
|
||||||
@ -115,8 +121,10 @@ IFCHANGE = $(srcdir)/tool/ifchange
|
|||||||
SET_LC_MESSAGES = env LC_MESSAGES=C
|
SET_LC_MESSAGES = env LC_MESSAGES=C
|
||||||
OBJDUMP = @OBJDUMP@
|
OBJDUMP = @OBJDUMP@
|
||||||
OBJCOPY = @OBJCOPY@
|
OBJCOPY = @OBJCOPY@
|
||||||
|
DTRACE = @DTRACE@
|
||||||
VCS = @VCS@
|
VCS = @VCS@
|
||||||
VCSUP = @VCSUP@
|
VCSUP = @VCSUP@
|
||||||
|
DOXYGEN = @DOXYGEN@
|
||||||
|
|
||||||
OBJEXT = @OBJEXT@
|
OBJEXT = @OBJEXT@
|
||||||
ASMEXT = S
|
ASMEXT = S
|
||||||
@ -139,28 +147,37 @@ all:
|
|||||||
|
|
||||||
miniruby$(EXEEXT):
|
miniruby$(EXEEXT):
|
||||||
@-if test -f $@; then $(MV) -f $@ $@.old; $(RM) $@.old; fi
|
@-if test -f $@; then $(MV) -f $@ $@.old; $(RM) $@.old; fi
|
||||||
$(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT) $(LIBS) $(OUTFLAG)$@
|
$(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT) $(MINIDTRACE_OBJ) $(LIBS) $(OUTFLAG)$@
|
||||||
|
$(MINIDTRACE_OBJ): $(arch_hdrdir)/ruby/dtrace.d $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT)
|
||||||
|
$(DTRACE) -G -o $@ -s $(arch_hdrdir)/ruby/dtrace.d $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT)
|
||||||
|
|
||||||
$(PROGRAM):
|
$(PROGRAM):
|
||||||
@$(RM) $@
|
@$(RM) $@
|
||||||
$(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) $(OUTFLAG)$@
|
$(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(EXTOBJS) $(DTRACE_OBJ) $(LIBRUBYARG) $(LIBS) $(OUTFLAG)$@
|
||||||
|
$(DTRACE_OBJ): $(arch_hdrdir)/ruby/dtrace.d $(MAINOBJ) $(EXTOBJS)
|
||||||
|
$(DTRACE) -G -o $@ -s $(arch_hdrdir)/ruby/dtrace.d $(MAINOBJ) $(EXTOBJS)
|
||||||
|
$(GOLFDTRACE_OBJ): $(arch_hdrdir)/ruby/dtrace.d $(GOLFOBJS) $(EXTOBJS)
|
||||||
|
$(DTRACE) -G -o $@ -s $(arch_hdrdir)/ruby/dtrace.d $(GOLFOBJS) $(EXTOBJS)
|
||||||
|
|
||||||
# We must `rm' the library each time this rule is invoked because "updating" a
|
# We must `rm' the library each time this rule is invoked because "updating" a
|
||||||
# MAB library on Apple/NeXT (see --enable-fat-binary in configure) is not
|
# MAB library on Apple/NeXT (see --enable-fat-binary in configure) is not
|
||||||
# supported.
|
# supported.
|
||||||
$(LIBRUBY_A):
|
$(LIBRUBY_A):
|
||||||
@$(RM) $@
|
@$(RM) $@
|
||||||
$(AR) $(ARFLAGS) $@ $(OBJS) $(DMYEXT)
|
$(AR) $(ARFLAGS) $@ $(OBJS) $(DMYEXT) $(LIBRUBY_DTRACE_OBJ)
|
||||||
@-$(RANLIB) $@ 2> /dev/null || true
|
@-$(RANLIB) $@ 2> /dev/null || true
|
||||||
|
|
||||||
$(LIBRUBY_SO):
|
$(LIBRUBY_SO):
|
||||||
@-$(PRE_LIBRUBY_UPDATE)
|
@-$(PRE_LIBRUBY_UPDATE)
|
||||||
$(LDSHARED) $(DLDFLAGS) $(OBJS) $(DLDOBJS) $(SOLIBS) $(OUTFLAG)$@
|
$(LDSHARED) $(DLDFLAGS) $(OBJS) $(DLDOBJS) $(LIBRUBY_DTRACE_OBJ) $(SOLIBS) $(OUTFLAG)$@
|
||||||
-$(OBJCOPY) -w -L '@EXPORT_PREFIX@Init_*' -L '@EXPORT_PREFIX@*_threadptr_*' $@
|
-$(OBJCOPY) -w -L '@EXPORT_PREFIX@Init_*' -L '@EXPORT_PREFIX@*_threadptr_*' $@
|
||||||
@-$(MINIRUBY) -e 'ARGV.each{|link| File.delete link if File.exist? link; \
|
@-$(MINIRUBY) -e 'ARGV.each{|link| File.delete link if File.exist? link; \
|
||||||
File.symlink "$(LIBRUBY_SO)", link}' \
|
File.symlink "$(LIBRUBY_SO)", link}' \
|
||||||
$(LIBRUBY_ALIASES) || true
|
$(LIBRUBY_ALIASES) || true
|
||||||
|
|
||||||
|
$(LIBRUBY_DTRACE_OBJ): $(arch_hdrdir)/ruby/dtrace.d $(OBJS) $(DMYEXT)
|
||||||
|
$(DTRACE) -G -o $@ -s $(arch_hdrdir)/ruby/dtrace.d $(OBJS) $(DMYEXT)
|
||||||
|
|
||||||
fake: $(arch)-fake.rb
|
fake: $(arch)-fake.rb
|
||||||
$(arch)-fake.rb: config.status
|
$(arch)-fake.rb: config.status
|
||||||
@./config.status --file=$@:$(srcdir)/template/fake.rb.in
|
@./config.status --file=$@:$(srcdir)/template/fake.rb.in
|
||||||
@ -188,6 +205,22 @@ $(srcdir)/configure: $(srcdir)/configure.in
|
|||||||
|
|
||||||
incs: id.h
|
incs: id.h
|
||||||
|
|
||||||
|
$(arch_hdrdir)/ruby/trace_dtrace.h: $(arch_hdrdir)/ruby/dtrace.d
|
||||||
|
$(DTRACE) -h -o $@ -s $(arch_hdrdir)/ruby/dtrace.d
|
||||||
|
|
||||||
|
# NOTE: dtrace is not used on cross compiling
|
||||||
|
$(arch_hdrdir)/ruby/dtrace.d: $(srcdir)/defs/dtrace.d
|
||||||
|
@echo '#include <limits.h>' > conftest.c
|
||||||
|
@echo '#define RUBY_TRACE_H' >> conftest.c
|
||||||
|
@echo '#include "ruby/ruby.h"' >> conftest.c
|
||||||
|
@echo 'int main(){ printf("%d", SIZEOF_VALUE * CHAR_BIT); return 0; }' >> conftest.c
|
||||||
|
@$(CC) $(CFLAGS) $(XCFLAGS) $(CPPFLAGS) -c $(COUTFLAG)conftest.o conftest.c
|
||||||
|
$(CC) $(LDFLAGS) $(XLDFLAGS) conftest.o $(LIBS) $(OUTFLAG)conftest
|
||||||
|
@$(CP) $(srcdir)/defs/dtrace.d dtrace.c
|
||||||
|
$(CPP) $(CPPFLAGS) -DBITSIZE_OF_VALUE=`./conftest` dtrace.c $(CPPOUTFILE)
|
||||||
|
$(MV) conftest.i $@
|
||||||
|
@$(RM) conftest conftest.[co] dtrace.c
|
||||||
|
|
||||||
# Things which should be considered:
|
# Things which should be considered:
|
||||||
# * with gperf v.s. without gperf
|
# * with gperf v.s. without gperf
|
||||||
# * committers may have various versions of gperf
|
# * committers may have various versions of gperf
|
||||||
|
14
NEWS
14
NEWS
@ -217,6 +217,10 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
* Pathname#realdirpath
|
* Pathname#realdirpath
|
||||||
* Pathname#each_child
|
* Pathname#each_child
|
||||||
|
|
||||||
|
* probe
|
||||||
|
new library.
|
||||||
|
* Kernel#fire_probe
|
||||||
|
|
||||||
* Readline
|
* Readline
|
||||||
* new methods:
|
* new methods:
|
||||||
* Readline.set_screen_size
|
* Readline.set_screen_size
|
||||||
@ -261,6 +265,14 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
Unicode semantics
|
Unicode semantics
|
||||||
* $: no longer includes the current directory, use require_relative
|
* $: no longer includes the current directory, use require_relative
|
||||||
|
|
||||||
|
=== Tracing (experimental)
|
||||||
|
|
||||||
|
* Runtime tracing is supported. Currently implemented on top of dtrace.
|
||||||
|
You can trace a ruby program without any modification if your platform
|
||||||
|
supports dtrace USDT.
|
||||||
|
|
||||||
|
This feature is experimental. The semantics of probes will possibly change.
|
||||||
|
|
||||||
=== Compilation options
|
=== Compilation options
|
||||||
|
|
||||||
* --program-prefix and --program-suffix no longer act on the shared object
|
* --program-prefix and --program-suffix no longer act on the shared object
|
||||||
@ -272,6 +284,8 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
* --with-arch is added for universal binary, instead of
|
* --with-arch is added for universal binary, instead of
|
||||||
--enable-fat-binary option.
|
--enable-fat-binary option.
|
||||||
|
|
||||||
|
* --with-tracing-model is added for choosing a particular tracing mechanism.
|
||||||
|
|
||||||
=== Compatibility issues (excluding feature bug fixes)
|
=== Compatibility issues (excluding feature bug fixes)
|
||||||
|
|
||||||
* Enumerator#rewind
|
* Enumerator#rewind
|
||||||
|
17
common.mk
17
common.mk
@ -142,11 +142,11 @@ loadpath: $(PREP) PHONY
|
|||||||
|
|
||||||
$(PREP): $(MKFILES)
|
$(PREP): $(MKFILES)
|
||||||
|
|
||||||
miniruby$(EXEEXT): config.status $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT) $(ARCHFILE)
|
miniruby$(EXEEXT): config.status $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(DMYEXT) $(ARCHFILE) $(MINIDTRACE_OBJ)
|
||||||
|
|
||||||
GORUBY = go$(RUBY_INSTALL_NAME)
|
GORUBY = go$(RUBY_INSTALL_NAME)
|
||||||
golf: $(LIBRUBY) $(GOLFOBJS) PHONY
|
golf: $(LIBRUBY) $(GOLFOBJS) $(GOLFDTRACE_OBJ) PHONY
|
||||||
$(MAKE) $(MFLAGS) MAINOBJ="$(GOLFOBJS)" PROGRAM=$(GORUBY)$(EXEEXT) program
|
$(MAKE) $(MFLAGS) MAINOBJ="$(GOLFOBJS)" DTRACE_OBJ="$(GOLFDTRACE_OBJ)" PROGRAM=$(GORUBY)$(EXEEXT) program
|
||||||
capi: Doxyfile PHONY $(PREP)
|
capi: Doxyfile PHONY $(PREP)
|
||||||
@$(MAKEDIRS) doc/capi
|
@$(MAKEDIRS) doc/capi
|
||||||
@$(DOXYGEN)
|
@$(DOXYGEN)
|
||||||
@ -157,9 +157,9 @@ Doxyfile: $(srcdir)/template/Doxyfile.tmpl $(PREP) $(srcdir)/tool/generic_erb.rb
|
|||||||
|
|
||||||
program: $(PROGRAM)
|
program: $(PROGRAM)
|
||||||
|
|
||||||
$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP)
|
$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(DTRACE_OBJ) $(SETUP) $(PREP)
|
||||||
|
|
||||||
$(LIBRUBY_A): $(OBJS) $(DMYEXT) $(ARCHFILE)
|
$(LIBRUBY_A): $(OBJS) $(DMYEXT) $(LIBRUBY_DTRACE_OBJ) $(ARCHFILE)
|
||||||
|
|
||||||
$(LIBRUBY_SO): $(OBJS) $(DLDOBJS) $(LIBRUBY_A) $(PREP) $(LIBRUBY_SO_UPDATE) $(BUILTIN_ENCOBJS)
|
$(LIBRUBY_SO): $(OBJS) $(DLDOBJS) $(LIBRUBY_A) $(PREP) $(LIBRUBY_SO_UPDATE) $(BUILTIN_ENCOBJS)
|
||||||
|
|
||||||
@ -385,6 +385,7 @@ distclean: distclean-ext distclean-local distclean-enc distclean-golf distclean-
|
|||||||
distclean-local:: clean-local
|
distclean-local:: clean-local
|
||||||
@$(RM) $(MKFILES) rbconfig.rb yasmdata.rb encdb.h
|
@$(RM) $(MKFILES) rbconfig.rb yasmdata.rb encdb.h
|
||||||
@$(RM) config.cache config.log config.status config.status.lineno $(PRELUDES)
|
@$(RM) config.cache config.log config.status config.status.lineno $(PRELUDES)
|
||||||
|
@$(RM) $(arch_hdrdir)/ruby/dtrace.d
|
||||||
@$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP)
|
@$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP)
|
||||||
distclean-ext:: PHONY
|
distclean-ext:: PHONY
|
||||||
distclean-golf: clean-golf
|
distclean-golf: clean-golf
|
||||||
@ -511,7 +512,8 @@ win32.$(OBJEXT): {$(VPATH)}win32.c $(RUBY_H_INCLUDES)
|
|||||||
###
|
###
|
||||||
|
|
||||||
RUBY_H_INCLUDES = {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \
|
RUBY_H_INCLUDES = {$(VPATH)}ruby.h {$(VPATH)}config.h {$(VPATH)}defines.h \
|
||||||
{$(VPATH)}intern.h {$(VPATH)}missing.h {$(VPATH)}st.h
|
{$(VPATH)}intern.h {$(VPATH)}missing.h {$(VPATH)}st.h \
|
||||||
|
{$(VPATH)}trace.h {$(VPATH)}trace_$(TRACING_MODEL).h
|
||||||
ENCODING_H_INCLUDES= {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
|
ENCODING_H_INCLUDES= {$(VPATH)}encoding.h {$(VPATH)}oniguruma.h
|
||||||
ID_H_INCLUDES = {$(VPATH)}id.h
|
ID_H_INCLUDES = {$(VPATH)}id.h
|
||||||
VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}vm_opts.h \
|
VM_CORE_H_INCLUDES = {$(VPATH)}vm_core.h {$(VPATH)}vm_opts.h \
|
||||||
@ -678,6 +680,9 @@ newline.$(OBJEXT): {$(VPATH)}newline.c {$(VPATH)}defines.h \
|
|||||||
{$(VPATH)}intern.h {$(VPATH)}missing.h {$(VPATH)}st.h \
|
{$(VPATH)}intern.h {$(VPATH)}missing.h {$(VPATH)}st.h \
|
||||||
{$(VPATH)}transcode_data.h {$(VPATH)}ruby.h {$(VPATH)}config.h
|
{$(VPATH)}transcode_data.h {$(VPATH)}ruby.h {$(VPATH)}config.h
|
||||||
|
|
||||||
|
trace_none.h:
|
||||||
|
echo > $@
|
||||||
|
|
||||||
INSNS2VMOPT = --srcdir="$(srcdir)"
|
INSNS2VMOPT = --srcdir="$(srcdir)"
|
||||||
|
|
||||||
{$(VPATH)}minsns.inc: $(srcdir)/template/minsns.inc.tmpl
|
{$(VPATH)}minsns.inc: $(srcdir)/template/minsns.inc.tmpl
|
||||||
|
@ -3569,6 +3569,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||||||
}
|
}
|
||||||
ADD_INSNL(ret, nd_line(node), jump, label_miss);
|
ADD_INSNL(ret, nd_line(node), jump, label_miss);
|
||||||
ADD_LABEL(ret, label_hit);
|
ADD_LABEL(ret, label_hit);
|
||||||
|
ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RESCUE);
|
||||||
COMPILE(ret, "resbody body", resq->nd_body);
|
COMPILE(ret, "resbody body", resq->nd_body);
|
||||||
if (iseq->compile_data->option->tailcall_optimization) {
|
if (iseq->compile_data->option->tailcall_optimization) {
|
||||||
ADD_INSN(ret, nd_line(node), nop);
|
ADD_INSN(ret, nd_line(node), nop);
|
||||||
|
95
configure.in
95
configure.in
@ -357,6 +357,51 @@ fi
|
|||||||
MAKEDIRS="$MKDIR_P"
|
MAKEDIRS="$MKDIR_P"
|
||||||
AC_SUBST(MAKEDIRS)
|
AC_SUBST(MAKEDIRS)
|
||||||
|
|
||||||
|
AC_DEFUN([RUBY_DTRACE_POSTPROCESS],
|
||||||
|
[AC_CACHE_CHECK(whether $DTRACE needs post processing, rb_cv_prog_dtrace_g,
|
||||||
|
[
|
||||||
|
echo "int main(void){ return 0; }" > conftest.c
|
||||||
|
echo "provider conftest{};" > conftest_provider.d
|
||||||
|
$CC $CFLAGS -c -o conftest.o conftest.c
|
||||||
|
if $DTRACE -G -s conftest_provider.d conftest.o 2>/dev/null; then
|
||||||
|
rb_cv_prog_dtrace_g=yes
|
||||||
|
$1
|
||||||
|
else
|
||||||
|
rb_cv_prog_dtrace_g=no
|
||||||
|
$2
|
||||||
|
fi
|
||||||
|
rm -f conftest.o conftest.c conftest_provider.d conftest_provider.o
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([RUBY_DTRACE_BSD_BROKEN],
|
||||||
|
[AC_CACHE_CHECK(whether dtrace USDT is broken, rb_cv_dtrace_bsd_broken,
|
||||||
|
[
|
||||||
|
cat <<EOF > conftest.c
|
||||||
|
#define _DTRACE_VERSION 1
|
||||||
|
#include "conftest_provider.h"
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
if (CONFTEST_FIRE_ENABLED()) CONFTEST_FIRE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo "provider conftest{ probe fire(); };" > conftest_provider.d
|
||||||
|
$DTRACE -h -o conftest_provider.h -s conftest_provider.d
|
||||||
|
$CC $CFLAGS -c -o conftest.o conftest.c
|
||||||
|
if $DTRACE -G -o conftest_provider.o -s conftest_provider.d conftest.o >/dev/null 2>/dev/null; then
|
||||||
|
rb_cv_dtrace_bsd_broken=no
|
||||||
|
$2
|
||||||
|
else
|
||||||
|
rb_cv_dtrace_bsd_broken=yes
|
||||||
|
$1
|
||||||
|
fi
|
||||||
|
rm -f conftest.[co] conftest_provider.[dho]
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_CHECK_TOOL(DTRACE, dtrace)
|
||||||
|
|
||||||
AC_CHECK_TOOL(DOT, dot)
|
AC_CHECK_TOOL(DOT, dot)
|
||||||
AC_CHECK_TOOL(DOXYGEN, doxygen)
|
AC_CHECK_TOOL(DOXYGEN, doxygen)
|
||||||
if test x"$DOXYGEN" = x; then
|
if test x"$DOXYGEN" = x; then
|
||||||
@ -1023,6 +1068,7 @@ AC_CHECK_HEADERS(limits.h sys/file.h sys/ioctl.h sys/syscall.h\
|
|||||||
ucontext.h intrinsics.h langinfo.h locale.h sys/sendfile.h time.h \
|
ucontext.h intrinsics.h langinfo.h locale.h sys/sendfile.h time.h \
|
||||||
net/socket.h sys/socket.h)
|
net/socket.h sys/socket.h)
|
||||||
|
|
||||||
|
|
||||||
dnl Check additional types.
|
dnl Check additional types.
|
||||||
RUBY_CHECK_SIZEOF(rlim_t, [int long "long long"], [], [
|
RUBY_CHECK_SIZEOF(rlim_t, [int long "long long"], [], [
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
@ -2065,6 +2111,54 @@ case "$target_os" in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
AC_ARG_WITH(tracing-model,
|
||||||
|
AS_HELP_STRING([--with-tracing-model=MODEL], [use MODEL for tracing ruby's internal. [[auto]] (none|dtrace|auto)]),
|
||||||
|
[TRACING_MODEL=$withval], [TRACING_MODEL=auto])
|
||||||
|
|
||||||
|
if test "${TRACING_MODEL}" = "auto"; then
|
||||||
|
if test x"$DTRACE" != x -a x"$cross_compiling" != xyes; then
|
||||||
|
RUBY_DTRACE_POSTPROCESS()
|
||||||
|
if test "$rb_cv_prog_dtrace_g" = 'yes'; then
|
||||||
|
RUBY_DTRACE_BSD_BROKEN([TRACING_MODEL=none], [TRACING_MODEL=dtrace])
|
||||||
|
else
|
||||||
|
TRACING_MODEL=dtrace
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
TRACING_MODEL=none
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "${TRACING_MODEL}" in
|
||||||
|
when(none)
|
||||||
|
AC_DEFINE(RUBY_TRACING_MODEL, RUBY_TRACING_MODEL_NONE, [none])
|
||||||
|
;;
|
||||||
|
when(dtrace)
|
||||||
|
if test -z "$DTRACE"; then
|
||||||
|
AC_MSG_ERROR([dtrace(1) is missing])
|
||||||
|
elif test "$cross_compiling" = yes; then
|
||||||
|
AC_MSG_ERROR([--with-tracing-model=dtrace, however, cross compiling])
|
||||||
|
else
|
||||||
|
RUBY_DTRACE_POSTPROCESS()
|
||||||
|
if test "$rb_cv_prog_dtrace_g" = 'yes'; then
|
||||||
|
RUBY_DTRACE_BSD_BROKEN([AC_MSG_ERROR([--with-tracing-model=dtrace, however, USDT is broken])], [])
|
||||||
|
DTRACE_OBJ='dtrace.$(OBJEXT)'
|
||||||
|
MINIDTRACE_OBJ='minidtrace.$(OBJEXT)'
|
||||||
|
GOLFDTRACE_OBJ='golfdtrace.$(OBJEXT)'
|
||||||
|
LIBRUBY_DTRACE_OBJ='libruby_dtrace.$(OBJEXT)'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
AC_DEFINE(RUBY_TRACING_MODEL, RUBY_TRACING_MODEL_DTRACE, [dtrace])
|
||||||
|
AC_SUBST(DTRACE_OBJ)
|
||||||
|
AC_SUBST(MINIDTRACE_OBJ)
|
||||||
|
AC_SUBST(GOLFDTRACE_OBJ)
|
||||||
|
AC_SUBST(LIBRUBY_DTRACE_OBJ)
|
||||||
|
;;
|
||||||
|
when(*)
|
||||||
|
AC_MSG_ERROR([unknown tracing model: ${TRACING_MODEL}])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
AC_SUBST(TRACING_MODEL)
|
||||||
|
|
||||||
AC_ARG_WITH(soname,
|
AC_ARG_WITH(soname,
|
||||||
AS_HELP_STRING([--with-soname=SONAME], [base name of shared library]),
|
AS_HELP_STRING([--with-soname=SONAME], [base name of shared library]),
|
||||||
[RUBY_SO_NAME=$withval], [RUBY_SO_NAME='$(RUBY_BASE_NAME)'])
|
[RUBY_SO_NAME=$withval], [RUBY_SO_NAME='$(RUBY_BASE_NAME)'])
|
||||||
@ -2712,4 +2806,5 @@ AC_CONFIG_FILES(Makefile, [{
|
|||||||
[EXEEXT=$EXEEXT gnumake=$gnumake])
|
[EXEEXT=$EXEEXT gnumake=$gnumake])
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
dnl }
|
dnl }
|
||||||
|
|
||||||
dnl }
|
dnl }
|
||||||
|
41
defs/dtrace.d
Normal file
41
defs/dtrace.d
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifdef BITSIZE_OF_VALUE
|
||||||
|
#define DO_DEFINE_VALUE(sz) typedef uint ## sz ## _t VALUE
|
||||||
|
#define DEFINE_VALUE(sz) DO_DEFINE_VALUE(sz)
|
||||||
|
DEFINE_VALUE(BITSIZE_OF_VALUE);
|
||||||
|
#else
|
||||||
|
# error BITSIZE_OF_VALUE is not defined.
|
||||||
|
#endif
|
||||||
|
provider ruby {
|
||||||
|
probe method__entry(VALUE receiver, char *classname, char *methodname, char *sourcefile, int sourceline);
|
||||||
|
probe method__return(VALUE receiver, char *classname, char *methodname, char *sourcefile, int sourceline);
|
||||||
|
probe raise(VALUE exception, char *classname, char *sourcefile, int sourceline);
|
||||||
|
probe rescue(VALUE exception, char *classname, char *sourcefile, int sourceline);
|
||||||
|
probe line(char* sourcefile, int sourceline);
|
||||||
|
|
||||||
|
/* gc probes */
|
||||||
|
probe gc__begin();
|
||||||
|
probe gc__end();
|
||||||
|
|
||||||
|
/* threads and fibers */
|
||||||
|
probe thread__init(VALUE thread, char *sourcefile, int sourceline);
|
||||||
|
probe thread__term(VALUE thread, char *sourcefile, int sourceline);
|
||||||
|
probe thread__enter(VALUE thread, char *sourcefile, int sourceline);
|
||||||
|
probe thread__leave(VALUE thread, char *sourcefile, int sourceline);
|
||||||
|
|
||||||
|
/* Some initial memory type probes */
|
||||||
|
probe object__create(VALUE obj, char *classname, char *sourcefile, int sourceline);
|
||||||
|
probe object__free(VALUE obj);
|
||||||
|
|
||||||
|
/* VM proves */
|
||||||
|
probe insn__entry(char *insnname, VALUE *operands, char *sourcefile, int sourceline);
|
||||||
|
probe insn__return(char *insnname, VALUE *operands, char *sourcefile, int sourceline);
|
||||||
|
|
||||||
|
probe ruby__probe(char *name, char *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma D attributes Evolving/Evolving/Common provider ruby provider
|
||||||
|
#pragma D attributes Private/Private/Unknown provider ruby module
|
||||||
|
#pragma D attributes Private/Private/Unknown provider ruby function
|
||||||
|
#pragma D attributes Evolving/Evolving/Unknown provider ruby name
|
||||||
|
#pragma D attributes Evolving/Evolving/Unknown provider ruby args
|
||||||
|
|
9
eval.c
9
eval.c
@ -424,9 +424,13 @@ rb_longjmp(int tag, volatile VALUE mesg)
|
|||||||
|
|
||||||
rb_trap_restore_mask();
|
rb_trap_restore_mask();
|
||||||
|
|
||||||
if (tag != TAG_FATAL) {
|
if (tag == TAG_FATAL) {
|
||||||
|
if (UNLIKELY(TRACE_RAISE_ENABLED())) FIRE_RAISE(0, (char*)"fatal", (char*)file, line);
|
||||||
|
}
|
||||||
|
else {
|
||||||
EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self,
|
EXEC_EVENT_HOOK(th, RUBY_EVENT_RAISE, th->cfp->self,
|
||||||
0 /* TODO: id */, 0 /* TODO: klass */);
|
0 /* TODO: id */, 0 /* TODO: klass */);
|
||||||
|
if (UNLIKELY(TRACE_RAISE_ENABLED())) FIRE_RAISE(mesg, (char*)rb_class2name(CLASS_OF(mesg)), (char*)file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_thread_raised_clear(th);
|
rb_thread_raised_clear(th);
|
||||||
@ -633,6 +637,9 @@ rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1,
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
if (handle) {
|
if (handle) {
|
||||||
|
if (UNLIKELY(TRACE_RESCUE_ENABLED())) {
|
||||||
|
FIRE_RESCUE(th->errinfo, (char*)rb_class2name(CLASS_OF(th->errinfo)), (char*)"<unknown>", 0);
|
||||||
|
}
|
||||||
if (r_proc) {
|
if (r_proc) {
|
||||||
PUSH_TAG();
|
PUSH_TAG();
|
||||||
if ((state = EXEC_TAG()) == 0) {
|
if ((state = EXEC_TAG()) == 0) {
|
||||||
|
3
ext/probe/extconf.rb
Normal file
3
ext/probe/extconf.rb
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
require 'mkmf'
|
||||||
|
create_makefile('probe')
|
||||||
|
|
47
ext/probe/probe.c
Normal file
47
ext/probe/probe.c
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/**
|
||||||
|
* probe.c -
|
||||||
|
*
|
||||||
|
* $Author$
|
||||||
|
*
|
||||||
|
* Based on the patch for Ruby 1.8.6 by Joyent Inc.
|
||||||
|
*
|
||||||
|
* Copyright 2007 Joyent Inc.
|
||||||
|
* Copyright 2009 Yuki Sonoda (Yugui).
|
||||||
|
*/
|
||||||
|
#include "ruby/ruby.h"
|
||||||
|
|
||||||
|
#define FIRE_WITH_SUFFIXED_MSG(probe_name, probe_data, suffix) \
|
||||||
|
if (TRACE_RUBY_PROBE_ENABLED()) { \
|
||||||
|
char *msg = ALLOCA_N(char, strlen(probe_name) + strlen("-" #suffix) ); \
|
||||||
|
sprintf(msg, "%s%s", probe_name, "-" #suffix); \
|
||||||
|
FIRE_RUBY_PROBE(msg, (char*)probe_data); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
probe_fire(int argc, VALUE *argv, VALUE klass)
|
||||||
|
{
|
||||||
|
int args;
|
||||||
|
VALUE name, data, ret;
|
||||||
|
const char *probe_data;
|
||||||
|
char *probe_name;
|
||||||
|
|
||||||
|
args = rb_scan_args(argc, argv, "11", &name, &data);
|
||||||
|
probe_data = args == 2 ? StringValuePtr(data) : "";
|
||||||
|
probe_name = StringValuePtr(name);
|
||||||
|
|
||||||
|
if (rb_block_given_p()) {
|
||||||
|
FIRE_WITH_SUFFIXED_MSG(probe_name, probe_data, start);
|
||||||
|
ret = rb_yield(Qnil);
|
||||||
|
FIRE_WITH_SUFFIXED_MSG(probe_name, probe_data, end);
|
||||||
|
} else {
|
||||||
|
if (TRACE_RUBY_PROBE_ENABLED())
|
||||||
|
FIRE_RUBY_PROBE(probe_name, (char*)probe_data);
|
||||||
|
ret = Qnil;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init_probe()
|
||||||
|
{
|
||||||
|
rb_define_global_function("fire_probe", probe_fire, -1);
|
||||||
|
}
|
8
gc.c
8
gc.c
@ -460,6 +460,7 @@ ruby_memerror(void)
|
|||||||
else {
|
else {
|
||||||
/* no ruby thread */
|
/* no ruby thread */
|
||||||
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
||||||
|
if (UNLIKELY(TRACE_RAISE_ENABLED())) FIRE_RAISE_FATAL();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,6 +473,7 @@ rb_memerror(void)
|
|||||||
if (!nomem_error ||
|
if (!nomem_error ||
|
||||||
(rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) {
|
(rb_thread_raised_p(th, RAISED_NOMEMORY) && rb_safe_level() < 4)) {
|
||||||
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
||||||
|
if (UNLIKELY(TRACE_RAISE_ENABLED())) FIRE_RAISE_FATAL();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (rb_thread_raised_p(th, RAISED_NOMEMORY)) {
|
if (rb_thread_raised_p(th, RAISED_NOMEMORY)) {
|
||||||
@ -604,6 +606,7 @@ negative_size_allocation_error(const char *msg)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fprintf(stderr, "[FATAL] %s\n", msg);
|
fprintf(stderr, "[FATAL] %s\n", msg);
|
||||||
|
if (UNLIKELY(TRACE_RAISE_ENABLED())) FIRE_RAISE_FATAL();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -629,6 +632,7 @@ garbage_collect_with_gvl(rb_objspace_t *objspace)
|
|||||||
else {
|
else {
|
||||||
/* no ruby thread */
|
/* no ruby thread */
|
||||||
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
||||||
|
if (UNLIKELY(TRACE_RAISE_ENABLED())) FIRE_RAISE_FATAL();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1973,6 +1977,8 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TRACE_OBJECT_FREE_ENABLED()) FIRE_OBJECT_FREE(rb_obj_id(obj));
|
||||||
|
|
||||||
if (FL_TEST(obj, FL_EXIVAR)) {
|
if (FL_TEST(obj, FL_EXIVAR)) {
|
||||||
rb_free_generic_ivar((VALUE)obj);
|
rb_free_generic_ivar((VALUE)obj);
|
||||||
FL_UNSET(obj, FL_EXIVAR);
|
FL_UNSET(obj, FL_EXIVAR);
|
||||||
@ -2153,6 +2159,7 @@ garbage_collect(rb_objspace_t *objspace)
|
|||||||
during_gc++;
|
during_gc++;
|
||||||
objspace->count++;
|
objspace->count++;
|
||||||
|
|
||||||
|
if (TRACE_GC_BEGIN_ENABLED()) FIRE_GC_BEGIN();
|
||||||
GC_PROF_TIMER_START;
|
GC_PROF_TIMER_START;
|
||||||
GC_PROF_MARK_TIMER_START;
|
GC_PROF_MARK_TIMER_START;
|
||||||
SET_STACK_END;
|
SET_STACK_END;
|
||||||
@ -2201,6 +2208,7 @@ garbage_collect(rb_objspace_t *objspace)
|
|||||||
GC_PROF_SWEEP_TIMER_STOP;
|
GC_PROF_SWEEP_TIMER_STOP;
|
||||||
|
|
||||||
GC_PROF_TIMER_STOP;
|
GC_PROF_TIMER_STOP;
|
||||||
|
if (TRACE_GC_END_ENABLED()) FIRE_GC_END();
|
||||||
if (GC_NOTIFY) printf("end garbage_collect()\n");
|
if (GC_NOTIFY) printf("end garbage_collect()\n");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -40,10 +40,19 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#define PRINTF_ARGS(decl, string_index, first_to_check) \
|
# define PRINTF_ARGS(decl, string_index, first_to_check) \
|
||||||
decl __attribute__((format(printf, string_index, first_to_check)))
|
decl __attribute__((format(printf, string_index, first_to_check)))
|
||||||
|
# if __GNUC__ >= 3
|
||||||
|
# define LIKELY(x) (__builtin_expect((x), 1))
|
||||||
|
# define UNLIKELY(x) (__builtin_expect((x), 0))
|
||||||
|
# else
|
||||||
|
# define LIKELY(x) (x)
|
||||||
|
# define UNLIKELY(x) (x)
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
#define PRINTF_ARGS(decl, string_index, first_to_check) decl
|
# define PRINTF_ARGS(decl, string_index, first_to_check) decl
|
||||||
|
# define LIKELY(x) (x)
|
||||||
|
# define UNLIKELY(x) (x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_STDLIB_H
|
#ifdef HAVE_STDLIB_H
|
||||||
@ -516,12 +525,17 @@ double rb_num2dbl(VALUE);
|
|||||||
VALUE rb_uint2big(VALUE);
|
VALUE rb_uint2big(VALUE);
|
||||||
VALUE rb_int2big(SIGNED_VALUE);
|
VALUE rb_int2big(SIGNED_VALUE);
|
||||||
|
|
||||||
|
#include "ruby/trace.h"
|
||||||
|
|
||||||
VALUE rb_newobj(void);
|
VALUE rb_newobj(void);
|
||||||
#define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
|
#define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
|
||||||
#define OBJSETUP(obj,c,t) do {\
|
#define OBJSETUP(obj,c,t) do {\
|
||||||
RBASIC(obj)->flags = (t);\
|
RBASIC(obj)->flags = (t);\
|
||||||
RBASIC(obj)->klass = (c);\
|
RBASIC(obj)->klass = (c);\
|
||||||
if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT | FL_UNTRUSTED);\
|
if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT | FL_UNTRUSTED);\
|
||||||
|
if (UNLIKELY(TRACE_OBJECT_CREATE_ENABLED())) { \
|
||||||
|
FIRE_OBJECT_CREATE((VALUE)(obj), rb_class2name((c)), rb_sourcefile(), rb_sourceline()); \
|
||||||
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define CLONESETUP(clone,obj) do {\
|
#define CLONESETUP(clone,obj) do {\
|
||||||
OBJSETUP(clone,rb_singleton_class_clone((VALUE)obj),RBASIC(obj)->flags);\
|
OBJSETUP(clone,rb_singleton_class_clone((VALUE)obj),RBASIC(obj)->flags);\
|
||||||
@ -1325,6 +1339,7 @@ int ruby_native_thread_p(void);
|
|||||||
#define RUBY_EVENT_C_CALL 0x0020
|
#define RUBY_EVENT_C_CALL 0x0020
|
||||||
#define RUBY_EVENT_C_RETURN 0x0040
|
#define RUBY_EVENT_C_RETURN 0x0040
|
||||||
#define RUBY_EVENT_RAISE 0x0080
|
#define RUBY_EVENT_RAISE 0x0080
|
||||||
|
#define RUBY_EVENT_RESCUE 0x0100
|
||||||
#define RUBY_EVENT_ALL 0xffff
|
#define RUBY_EVENT_ALL 0xffff
|
||||||
#define RUBY_EVENT_VM 0x10000
|
#define RUBY_EVENT_VM 0x10000
|
||||||
#define RUBY_EVENT_SWITCH 0x20000
|
#define RUBY_EVENT_SWITCH 0x20000
|
||||||
|
105
include/ruby/trace.h
Normal file
105
include/ruby/trace.h
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
/**********************************************************************
|
||||||
|
|
||||||
|
trace.h -
|
||||||
|
|
||||||
|
$Author$
|
||||||
|
|
||||||
|
Copyright (C) 2009 Yuki Sonoda (Yugui)
|
||||||
|
|
||||||
|
**********************************************************************/
|
||||||
|
|
||||||
|
#ifndef RUBY_TRACE_H
|
||||||
|
#define RUBY_TRACE_H
|
||||||
|
|
||||||
|
#define RUBY_TRACING_MODEL_NONE 0
|
||||||
|
#define RUBY_TRACING_MODEL_DTRACE 1
|
||||||
|
|
||||||
|
#if RUBY_TRACING_MODEL == RUBY_TRACING_MODEL_NONE
|
||||||
|
# define TRACE_METHOD_ENTRY_ENABLED() 0
|
||||||
|
# define TRACE_METHOD_RETURN_ENABLED() 0
|
||||||
|
# define TRACE_RAISE_ENABLED() 0
|
||||||
|
# define TRACE_RESCUE_ENABLED() 0
|
||||||
|
# define TRACE_LINE_ENABLED() 0
|
||||||
|
# define TRACE_GC_BEGIN_ENABLED() 0
|
||||||
|
# define TRACE_GC_END_ENABLED() 0
|
||||||
|
# define TRACE_THREAD_INIT_ENABLED() 0
|
||||||
|
# define TRACE_THREAD_TERM_ENABLED() 0
|
||||||
|
# define TRACE_THREAD_LEAVE_ENABLED() 0
|
||||||
|
# define TRACE_THREAD_ENTER_ENABLED() 0
|
||||||
|
# define TRACE_OBJECT_CREATE_ENABLED() 0
|
||||||
|
# define TRACE_OBJECT_FREE_ENABLED() 0
|
||||||
|
# define TRACE_INSN_ENTRY_ENABLED() 0
|
||||||
|
# define TRACE_INSN_RETURN_ENABLED() 0
|
||||||
|
# define TRACE_RUBY_PROBE_ENABLED() 0
|
||||||
|
|
||||||
|
# define FIRE_METHOD_ENTRY(receiver, classname, methodname, sourcefile, sourceline) ((void)0)
|
||||||
|
# define FIRE_METHOD_RETURN(receiver, classname, methodname, sourcefile, sourceline) ((void)0)
|
||||||
|
# define FIRE_RAISE(exception, classname, sourcename, sourceline) ((void)0)
|
||||||
|
# define FIRE_RESCUE(exception, classname, sourcename, sourceline) ((void)0)
|
||||||
|
# define FIRE_LINE(sourcename, sourceline) ((void)0)
|
||||||
|
# define FIRE_GC_BEGIN() ((void)0)
|
||||||
|
# define FIRE_GC_END() ((void)0)
|
||||||
|
# define FIRE_THREAD_INIT(th, sourcefile, sourceline) ((void)0)
|
||||||
|
# define FIRE_THREAD_TERM(th, sourcefile, sourceline) ((void)0)
|
||||||
|
# define FIRE_THREAD_LEAVE(th, sourcefile, sourceline) ((void)0)
|
||||||
|
# define FIRE_THREAD_ENTER(th, sourcefile, sourceline) ((void)0)
|
||||||
|
# define FIRE_OBJECT_CREATE(obj, classname, sourcefile, sourceline) ((void)0)
|
||||||
|
# define FIRE_OBJECT_FREE(obj) ((void)0)
|
||||||
|
# define FIRE_INSN_ENTRY(insnname, operands, sourcename, sourceline) ((void)0)
|
||||||
|
# define FIRE_INSN_RETURN(insnname, operands, sourcename, sourceline) ((void)0)
|
||||||
|
# define FIRE_RUBY_PROBE(name, data) ((void)0)
|
||||||
|
|
||||||
|
#elif RUBY_TRACING_MODEL == RUBY_TRACING_MODEL_DTRACE
|
||||||
|
# include "ruby/trace_dtrace.h"
|
||||||
|
# define TRACE_METHOD_ENTRY_ENABLED() RUBY_METHOD_ENTRY_ENABLED()
|
||||||
|
# define TRACE_METHOD_RETURN_ENABLED() RUBY_METHOD_RETURN_ENABLED()
|
||||||
|
# define TRACE_RAISE_ENABLED() RUBY_RAISE_ENABLED()
|
||||||
|
# define TRACE_RESCUE_ENABLED() RUBY_RESCUE_ENABLED()
|
||||||
|
# define TRACE_LINE_ENABLED() RUBY_LINE_ENABLED()
|
||||||
|
# define TRACE_GC_BEGIN_ENABLED() RUBY_GC_BEGIN_ENABLED()
|
||||||
|
# define TRACE_GC_END_ENABLED() RUBY_GC_END_ENABLED()
|
||||||
|
# define TRACE_THREAD_INIT_ENABLED() RUBY_THREAD_INIT_ENABLED()
|
||||||
|
# define TRACE_THREAD_TERM_ENABLED() RUBY_THREAD_TERM_ENABLED()
|
||||||
|
# define TRACE_THREAD_LEAVE_ENABLED() RUBY_THREAD_LEAVE_ENABLED()
|
||||||
|
# define TRACE_THREAD_ENTER_ENABLED() RUBY_THREAD_ENTER_ENABLED()
|
||||||
|
# define TRACE_OBJECT_CREATE_ENABLED() RUBY_OBJECT_CREATE_ENABLED()
|
||||||
|
# define TRACE_OBJECT_FREE_ENABLED() RUBY_OBJECT_FREE_ENABLED()
|
||||||
|
# define TRACE_INSN_ENTRY_ENABLED() RUBY_INSN_ENTRY_ENABLED()
|
||||||
|
# define TRACE_INSN_RETURN_ENABLED() RUBY_INSN_RETURN_ENABLED()
|
||||||
|
# define TRACE_RUBY_PROBE_ENABLED() RUBY_RUBY_PROBE_ENABLED()
|
||||||
|
|
||||||
|
# define FIRE_METHOD_ENTRY(receiver, classname, methodname, sourcefile, sourceline) \
|
||||||
|
RUBY_METHOD_ENTRY(receiver, classname, methodname, sourcefile, sourceline)
|
||||||
|
# define FIRE_METHOD_RETURN(receiver, classname, methodname, sourcefile, sourceline) \
|
||||||
|
RUBY_METHOD_RETURN(receiver, classname, methodname, sourcefile, sourceline)
|
||||||
|
# define FIRE_RAISE(exception, classname, sourcename, sourceline) \
|
||||||
|
RUBY_RAISE(exception, classname, sourcename, sourceline)
|
||||||
|
# define FIRE_RESCUE(exception, classname, sourcename, sourceline) \
|
||||||
|
RUBY_RESCUE(exception, classname, sourcename, sourceline)
|
||||||
|
# define FIRE_LINE(sourcename, sourceline) \
|
||||||
|
RUBY_LINE(sourcename, sourceline)
|
||||||
|
# define FIRE_GC_BEGIN() RUBY_GC_BEGIN()
|
||||||
|
# define FIRE_GC_END() RUBY_GC_END()
|
||||||
|
# define FIRE_THREAD_INIT(th, sourcefile, sourceline) \
|
||||||
|
RUBY_THREAD_INIT(th, (char*)sourcefile, sourceline)
|
||||||
|
# define FIRE_THREAD_TERM(th, sourcefile, sourceline) \
|
||||||
|
RUBY_THREAD_TERM(th, (char*)sourcefile, sourceline)
|
||||||
|
# define FIRE_THREAD_LEAVE(th, sourcefile, sourceline) \
|
||||||
|
RUBY_THREAD_LEAVE(th, (char*)sourcefile, sourceline)
|
||||||
|
# define FIRE_THREAD_ENTER(th, sourcefile, sourceline) \
|
||||||
|
RUBY_THREAD_ENTER(th, (char*)sourcefile, sourceline)
|
||||||
|
# define FIRE_OBJECT_CREATE(obj, classname, sourcefile, sourceline) \
|
||||||
|
RUBY_OBJECT_CREATE(obj, (char*)classname, (char*)sourcefile, sourceline)
|
||||||
|
# define FIRE_OBJECT_FREE(obj) \
|
||||||
|
RUBY_OBJECT_FREE(obj)
|
||||||
|
# define FIRE_INSN_ENTRY(insnname, operands, sourcename, sourceline) \
|
||||||
|
RUBY_INSN_ENTRY(insnname, operands, sourcename, sourceline)
|
||||||
|
# define FIRE_INSN_RETURN(insnname, operands, sourcename, sourceline) \
|
||||||
|
RUBY_INSN_RETURN(insnname, operands, sourcename, sourceline)
|
||||||
|
# define FIRE_RUBY_PROBE(name, data) \
|
||||||
|
RUBY_RUBY_PROBE(name, data)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define FIRE_RAISE_FATAL() FIRE_RAISE(0, (char*)"fatal", (char*)"<unknown>", 0)
|
||||||
|
|
||||||
|
#endif
|
24
insns.def
24
insns.def
@ -859,6 +859,30 @@ trace
|
|||||||
rb_event_flag_t flag = (rb_event_flag_t)nf;
|
rb_event_flag_t flag = (rb_event_flag_t)nf;
|
||||||
|
|
||||||
EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */);
|
EXEC_EVENT_HOOK(th, flag, GET_SELF(), 0, 0 /* TODO: id, klass */);
|
||||||
|
if (UNLIKELY(TRACE_METHOD_ENTRY_ENABLED()
|
||||||
|
| TRACE_METHOD_RETURN_ENABLED()
|
||||||
|
| TRACE_LINE_ENABLED()
|
||||||
|
| TRACE_RESCUE_ENABLED())) {
|
||||||
|
if (UNLIKELY(TRACE_METHOD_ENTRY_ENABLED()) && (flag & RUBY_EVENT_CALL) ) {
|
||||||
|
VALUE self = GET_SELF(), klass;
|
||||||
|
ID id;
|
||||||
|
rb_thread_method_id_and_class(GET_THREAD(), &id, &klass);
|
||||||
|
FIRE_METHOD_ENTRY(self, (char*)rb_class2name(klass), (char*)rb_id2name(id), (char*)rb_sourcefile(), rb_sourceline());
|
||||||
|
}
|
||||||
|
if (UNLIKELY(TRACE_METHOD_RETURN_ENABLED()) && (flag & RUBY_EVENT_RETURN) ) {
|
||||||
|
VALUE self = GET_SELF(), klass;
|
||||||
|
ID id;
|
||||||
|
rb_thread_method_id_and_class(GET_THREAD(), &id, &klass);
|
||||||
|
FIRE_METHOD_RETURN(self, (char*)rb_class2name(klass), (char*)rb_id2name(id), (char*)rb_sourcefile(), rb_sourceline());
|
||||||
|
}
|
||||||
|
if (UNLIKELY(TRACE_RESCUE_ENABLED()) && (flag & RUBY_EVENT_RESCUE) ) {
|
||||||
|
VALUE ex = GET_DFP()[-2];
|
||||||
|
FIRE_RESCUE(ex, (char*)rb_class2name(CLASS_OF(ex)), (char*)rb_sourcefile(), rb_sourceline());
|
||||||
|
}
|
||||||
|
if (UNLIKELY(TRACE_LINE_ENABLED()) && (flag & RUBY_EVENT_LINE) ) {
|
||||||
|
FIRE_LINE((char*)rb_sourcefile(), rb_sourceline());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************/
|
/**********************************************************/
|
||||||
|
21
iseq.c
21
iseq.c
@ -1473,6 +1473,27 @@ rb_iseq_build_for_ruby2cext(
|
|||||||
return iseqval;
|
return iseqval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
rb_vm_insn_name(int insn)
|
||||||
|
{
|
||||||
|
if (insn < VM_INSTRUCTION_SIZE) {
|
||||||
|
return insn_name(insn);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rb_vm_insn_len(int insn)
|
||||||
|
{
|
||||||
|
if (insn < VM_INSTRUCTION_SIZE) {
|
||||||
|
return insn_len(insn);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Init_ISeq(void)
|
Init_ISeq(void)
|
||||||
{
|
{
|
||||||
|
21
lib/mkmf.rb
21
lib/mkmf.rb
@ -69,6 +69,8 @@ $solaris = /solaris/ =~ RUBY_PLATFORM
|
|||||||
$universal = /universal/ =~ RUBY_PLATFORM
|
$universal = /universal/ =~ RUBY_PLATFORM
|
||||||
$dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
|
$dest_prefix_pattern = (File::PATH_SEPARATOR == ';' ? /\A([[:alpha:]]:)?/ : /\A/)
|
||||||
|
|
||||||
|
$dtrace_postprocess = (CONFIG['DTRACE_OBJ'] and /^\s*$/ !~ CONFIG['DTRACE_OBJ'])
|
||||||
|
|
||||||
# :stopdoc:
|
# :stopdoc:
|
||||||
|
|
||||||
def config_string(key, config = CONFIG)
|
def config_string(key, config = CONFIG)
|
||||||
@ -1450,6 +1452,7 @@ VPATH = #{vpath.join(CONFIG['PATH_SEPARATOR'])}
|
|||||||
mk << %{
|
mk << %{
|
||||||
CC = #{CONFIG['CC']}
|
CC = #{CONFIG['CC']}
|
||||||
CXX = #{CONFIG['CXX']}
|
CXX = #{CONFIG['CXX']}
|
||||||
|
DTRACE = #{CONFIG['DTRACE']}
|
||||||
LIBRUBY = #{CONFIG['LIBRUBY']}
|
LIBRUBY = #{CONFIG['LIBRUBY']}
|
||||||
LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
|
LIBRUBY_A = #{CONFIG['LIBRUBY_A']}
|
||||||
LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
|
LIBRUBYARG_SHARED = #$LIBRUBYARG_SHARED
|
||||||
@ -1719,6 +1722,7 @@ LOCAL_LIBS = #{$LOCAL_LIBS}
|
|||||||
LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
|
LIBS = #{$LIBRUBYARG} #{$libs} #{$LIBS}
|
||||||
SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
|
SRCS = #{srcs.collect(&File.method(:basename)).join(' ')}
|
||||||
OBJS = #{$objs.join(" ")}
|
OBJS = #{$objs.join(" ")}
|
||||||
|
DTRACE_OBJ = #{$dtrace_postprocess ? "$(TARGET)_dtrace.#{$OBJEXT}" : ''}
|
||||||
TARGET = #{target}
|
TARGET = #{target}
|
||||||
DLLIB = #{dllib}
|
DLLIB = #{dllib}
|
||||||
EXTSTATIC = #{$static || ""}
|
EXTSTATIC = #{$static || ""}
|
||||||
@ -1739,6 +1743,12 @@ static: $(STATIC_LIB)#{$extout ? " install-rb" : ""}
|
|||||||
.PHONY: clean clean-so clean-rb
|
.PHONY: clean clean-so clean-rb
|
||||||
"
|
"
|
||||||
mfile.print CLEANINGS
|
mfile.print CLEANINGS
|
||||||
|
|
||||||
|
if $dtrace_postprocess
|
||||||
|
mfile.print "$(DTRACE_OBJ): $(OBJS)\n"
|
||||||
|
mfile.print "\t$(DTRACE) -G -o $@ -s $(arch_hdrdir)/ruby/dtrace.d $(OBJS)\n"
|
||||||
|
end
|
||||||
|
|
||||||
fsep = config_string('BUILD_FILE_SEPARATOR') {|s| s unless s == "/"}
|
fsep = config_string('BUILD_FILE_SEPARATOR') {|s| s unless s == "/"}
|
||||||
if fsep
|
if fsep
|
||||||
sep = ":/=#{fsep}"
|
sep = ":/=#{fsep}"
|
||||||
@ -1841,7 +1851,7 @@ site-install-rb: install-rb
|
|||||||
mfile.print "$(RUBYARCHDIR)/" if $extout
|
mfile.print "$(RUBYARCHDIR)/" if $extout
|
||||||
mfile.print "$(DLLIB): "
|
mfile.print "$(DLLIB): "
|
||||||
mfile.print "$(DEFFILE) " if makedef
|
mfile.print "$(DEFFILE) " if makedef
|
||||||
mfile.print "$(OBJS) Makefile\n"
|
mfile.print "$(OBJS) $(DTRACE_OBJ) Makefile\n"
|
||||||
mfile.print "\t@-$(RM) $(@#{sep})\n"
|
mfile.print "\t@-$(RM) $(@#{sep})\n"
|
||||||
mfile.print "\t@-$(MAKEDIRS) $(@D)\n" if $extout
|
mfile.print "\t@-$(MAKEDIRS) $(@D)\n" if $extout
|
||||||
link_so = LINK_SO.gsub(/^/, "\t")
|
link_so = LINK_SO.gsub(/^/, "\t")
|
||||||
@ -1850,8 +1860,8 @@ site-install-rb: install-rb
|
|||||||
end
|
end
|
||||||
mfile.print link_so, "\n\n"
|
mfile.print link_so, "\n\n"
|
||||||
unless $static.nil?
|
unless $static.nil?
|
||||||
mfile.print "$(STATIC_LIB): $(OBJS)\n\t@-$(RM) $(@#{sep})\n\t"
|
mfile.print "$(STATIC_LIB): $(OBJS) $(DTRACE_OBJ)\n\t@-$(RM) $(@#{sep})\n\t"
|
||||||
mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS)"
|
mfile.print "$(AR) #{config_string('ARFLAGS') || 'cru '}$@ $(OBJS) $(DTRACE_OBJ)"
|
||||||
config_string('RANLIB') do |ranlib|
|
config_string('RANLIB') do |ranlib|
|
||||||
mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true"
|
mfile.print "\n\t@-#{ranlib} $(DLLIB) 2> /dev/null || true"
|
||||||
end
|
end
|
||||||
@ -1872,6 +1882,7 @@ site-install-rb: install-rb
|
|||||||
end
|
end
|
||||||
headers << $config_h
|
headers << $config_h
|
||||||
headers << '$(RUBY_EXTCONF_H)' if $extconf_h
|
headers << '$(RUBY_EXTCONF_H)' if $extconf_h
|
||||||
|
headers << '$(arch_hdrdir)/ruby/dtrace.d' if $dtrace_postprocess
|
||||||
mfile.print "$(OBJS): ", headers.join(' '), "\n"
|
mfile.print "$(OBJS): ", headers.join(' '), "\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2004,9 +2015,9 @@ TRY_LINK = config_string('TRY_LINK') ||
|
|||||||
"$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
|
"$(CFLAGS) $(src) $(LIBPATH) $(LDFLAGS) $(ARCH_FLAG) $(LOCAL_LIBS) $(LIBS)"
|
||||||
LINK_SO = config_string('LINK_SO') ||
|
LINK_SO = config_string('LINK_SO') ||
|
||||||
if CONFIG["DLEXT"] == $OBJEXT
|
if CONFIG["DLEXT"] == $OBJEXT
|
||||||
"ld $(DLDFLAGS) -r -o $@ $(OBJS)\n"
|
"ld $(DLDFLAGS) -r -o $@ $(OBJS) $(DTRACE_OBJ)\n"
|
||||||
else
|
else
|
||||||
"$(LDSHARED) #{OUTFLAG}$@ $(OBJS) " \
|
"$(LDSHARED) #{OUTFLAG}$@ $(OBJS) $(DTRACE_OBJ) " \
|
||||||
"$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
|
"$(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)"
|
||||||
end
|
end
|
||||||
LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
|
LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L"%s"'
|
||||||
|
12
thread.c
12
thread.c
@ -376,6 +376,8 @@ thread_cleanup_func(void *th_ptr)
|
|||||||
{
|
{
|
||||||
rb_thread_t *th = th_ptr;
|
rb_thread_t *th = th_ptr;
|
||||||
|
|
||||||
|
if (TRACE_THREAD_TERM_ENABLED()) FIRE_THREAD_TERM(th->self, rb_sourcefile(), rb_sourceline());
|
||||||
|
|
||||||
/* unlock all locking mutexes */
|
/* unlock all locking mutexes */
|
||||||
if (th->keeping_mutexes) {
|
if (th->keeping_mutexes) {
|
||||||
rb_mutex_unlock_all(th->keeping_mutexes, th);
|
rb_mutex_unlock_all(th->keeping_mutexes, th);
|
||||||
@ -427,10 +429,16 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s
|
|||||||
th->errinfo = Qnil;
|
th->errinfo = Qnil;
|
||||||
th->local_lfp = proc->block.lfp;
|
th->local_lfp = proc->block.lfp;
|
||||||
th->local_svar = Qnil;
|
th->local_svar = Qnil;
|
||||||
|
if (TRACE_THREAD_ENTER_ENABLED()) {
|
||||||
|
VALUE filename = proc->block.iseq->filename;
|
||||||
|
int lineno = proc->block.iseq->line_no;
|
||||||
|
FIRE_THREAD_ENTER(th->self, (TYPE(filename) == T_STRING ? RSTRING_PTR(filename) : 0), lineno);
|
||||||
|
}
|
||||||
th->value = rb_vm_invoke_proc(th, proc, proc->block.self,
|
th->value = rb_vm_invoke_proc(th, proc, proc->block.self,
|
||||||
(int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
|
(int)RARRAY_LEN(args), RARRAY_PTR(args), 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (TRACE_THREAD_ENTER_ENABLED()) FIRE_THREAD_ENTER(th->self, 0, 0);
|
||||||
th->value = (*th->first_func)((void *)args);
|
th->value = (*th->first_func)((void *)args);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -461,6 +469,7 @@ thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_s
|
|||||||
|
|
||||||
th->status = THREAD_KILLED;
|
th->status = THREAD_KILLED;
|
||||||
thread_debug("thread end: %p\n", (void *)th);
|
thread_debug("thread end: %p\n", (void *)th);
|
||||||
|
if (TRACE_THREAD_LEAVE_ENABLED()) FIRE_THREAD_LEAVE(th->self, 0, 0);
|
||||||
|
|
||||||
main_th = th->vm->main_thread;
|
main_th = th->vm->main_thread;
|
||||||
if (th != main_th) {
|
if (th != main_th) {
|
||||||
@ -533,6 +542,7 @@ thread_create_core(VALUE thval, VALUE args, VALUE (*fn)(ANYARGS))
|
|||||||
native_mutex_initialize(&th->interrupt_lock);
|
native_mutex_initialize(&th->interrupt_lock);
|
||||||
/* kick thread */
|
/* kick thread */
|
||||||
st_insert(th->vm->living_threads, thval, (st_data_t) th->thread_id);
|
st_insert(th->vm->living_threads, thval, (st_data_t) th->thread_id);
|
||||||
|
if (TRACE_THREAD_INIT_ENABLED()) FIRE_THREAD_INIT(th->self, rb_sourcefile(), rb_sourceline());
|
||||||
err = native_thread_create(th);
|
err = native_thread_create(th);
|
||||||
if (err) {
|
if (err) {
|
||||||
st_delete_wrap(th->vm->living_threads, th->self);
|
st_delete_wrap(th->vm->living_threads, th->self);
|
||||||
@ -982,6 +992,7 @@ rb_thread_schedule_rec(int sched_depth)
|
|||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
|
||||||
thread_debug("rb_thread_schedule/switch start\n");
|
thread_debug("rb_thread_schedule/switch start\n");
|
||||||
|
if (TRACE_THREAD_LEAVE_ENABLED()) FIRE_THREAD_LEAVE(th->self, rb_sourcefile(), rb_sourceline());
|
||||||
|
|
||||||
RB_GC_SAVE_MACHINE_CONTEXT(th);
|
RB_GC_SAVE_MACHINE_CONTEXT(th);
|
||||||
native_mutex_unlock(&th->vm->global_vm_lock);
|
native_mutex_unlock(&th->vm->global_vm_lock);
|
||||||
@ -992,6 +1003,7 @@ rb_thread_schedule_rec(int sched_depth)
|
|||||||
|
|
||||||
rb_thread_set_current(th);
|
rb_thread_set_current(th);
|
||||||
thread_debug("rb_thread_schedule/switch done\n");
|
thread_debug("rb_thread_schedule/switch done\n");
|
||||||
|
if (TRACE_THREAD_ENTER_ENABLED()) FIRE_THREAD_ENTER(th->self, rb_sourcefile(), rb_sourceline());
|
||||||
|
|
||||||
if (!sched_depth && UNLIKELY(GET_THREAD()->interrupt_flag)) {
|
if (!sched_depth && UNLIKELY(GET_THREAD()->interrupt_flag)) {
|
||||||
rb_threadptr_execute_interrupts_rec(GET_THREAD(), sched_depth+1);
|
rb_threadptr_execute_interrupts_rec(GET_THREAD(), sched_depth+1);
|
||||||
|
@ -694,6 +694,7 @@ add_signal_thread_list(rb_thread_t *th)
|
|||||||
|
|
||||||
if (list == 0) {
|
if (list == 0) {
|
||||||
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
||||||
|
if (UNLIKELY(TRACE_RAISE_ENABLED())) FIRE_RAISE_FATAL();
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -805,6 +806,7 @@ rb_thread_create_timer_thread(void)
|
|||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
native_mutex_unlock(&timer_thread_lock);
|
native_mutex_unlock(&timer_thread_lock);
|
||||||
fprintf(stderr, "[FATAL] Failed to create timer thread (errno: %d)\n", err);
|
fprintf(stderr, "[FATAL] Failed to create timer thread (errno: %d)\n", err);
|
||||||
|
if (UNLIKELY(TRACE_RAISE_ENABLED())) FIRE_RAISE_FATAL();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
native_cond_wait(&timer_thread_cond, &timer_thread_lock);
|
native_cond_wait(&timer_thread_cond, &timer_thread_lock);
|
||||||
|
@ -346,7 +346,7 @@ install?(:ext, :arch, :'ext-arch') do
|
|||||||
end
|
end
|
||||||
install?(:ext, :arch, :'ext-arch') do
|
install?(:ext, :arch, :'ext-arch') do
|
||||||
prepare "extension headers", archhdrdir
|
prepare "extension headers", archhdrdir
|
||||||
install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "*.h", :mode => $data_mode)
|
install_recursive("#{$extout}/include/#{CONFIG['arch']}", archhdrdir, :glob => "*.[dh]", :mode => $data_mode)
|
||||||
end
|
end
|
||||||
install?(:ext, :comm, :'ext-comm') do
|
install?(:ext, :comm, :'ext-comm') do
|
||||||
prepare "extension scripts", rubylibdir
|
prepare "extension scripts", rubylibdir
|
||||||
|
21
variable.c
21
variable.c
@ -313,6 +313,27 @@ rb_class2name(VALUE klass)
|
|||||||
return RSTRING_PTR(rb_class_name(klass));
|
return RSTRING_PTR(rb_class_name(klass));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* \internal
|
||||||
|
* Same as rb_class2name but safe if during GC
|
||||||
|
*
|
||||||
|
* \post the returned pointer points a string. not NULL.
|
||||||
|
*/
|
||||||
|
const char *
|
||||||
|
rb_class2name_without_alloc(VALUE klass)
|
||||||
|
{
|
||||||
|
if (RCLASS_IV_TBL(klass)) {
|
||||||
|
st_data_t n;
|
||||||
|
if (st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classpath, &n) ||
|
||||||
|
st_lookup(RCLASS_IV_TBL(klass), (st_data_t)classid, &n) ||
|
||||||
|
st_lookup(RCLASS_IV_TBL(klass), (st_data_t)tmp_classpath, &n)) {
|
||||||
|
if (TYPE(n) != T_STRING) rb_bug("class path is not set properly");
|
||||||
|
return RSTRING_PTR(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "(anonymous)";
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
rb_obj_classname(VALUE obj)
|
rb_obj_classname(VALUE obj)
|
||||||
{
|
{
|
||||||
|
1
vm.c
1
vm.c
@ -2072,6 +2072,7 @@ Init_BareVM(void)
|
|||||||
rb_thread_t * th = malloc(sizeof(*th));
|
rb_thread_t * th = malloc(sizeof(*th));
|
||||||
if (!vm || !th) {
|
if (!vm || !th) {
|
||||||
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
fprintf(stderr, "[FATAL] failed to allocate memory\n");
|
||||||
|
if (TRACE_RAISE_ENABLED()) FIRE_RAISE_FATAL();
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
MEMZERO(th, rb_thread_t, 1);
|
MEMZERO(th, rb_thread_t, 1);
|
||||||
|
@ -97,15 +97,6 @@
|
|||||||
#endif /* OPT_STACK_CACHING */
|
#endif /* OPT_STACK_CACHING */
|
||||||
#endif /* OPT_CALL_THREADED_CODE */
|
#endif /* OPT_CALL_THREADED_CODE */
|
||||||
|
|
||||||
/* likely */
|
|
||||||
#if __GNUC__ >= 3
|
|
||||||
#define LIKELY(x) (__builtin_expect((x), 1))
|
|
||||||
#define UNLIKELY(x) (__builtin_expect((x), 0))
|
|
||||||
#else /* __GNUC__ >= 3 */
|
|
||||||
#define LIKELY(x) (x)
|
|
||||||
#define UNLIKELY(x) (x)
|
|
||||||
#endif /* __GNUC__ >= 3 */
|
|
||||||
|
|
||||||
typedef unsigned long rb_num_t;
|
typedef unsigned long rb_num_t;
|
||||||
|
|
||||||
/* iseq data type */
|
/* iseq data type */
|
||||||
|
35
vm_exec.h
35
vm_exec.h
@ -52,8 +52,39 @@ typedef rb_iseq_t *ISEQ;
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
#define debugs
|
#define debugs
|
||||||
#define DEBUG_ENTER_INSN(insn)
|
extern const char *rb_vm_insn_name(int);
|
||||||
#define DEBUG_END_INSN()
|
#define DEBUG_ENTER_INSN(insn) \
|
||||||
|
do { \
|
||||||
|
if (UNLIKELY(TRACE_INSN_ENTRY_ENABLED())) { \
|
||||||
|
rb_control_frame_t *cfp = GET_CFP(); \
|
||||||
|
rb_iseq_t *iseq = cfp->iseq; \
|
||||||
|
if (iseq != NULL && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_FINISH) { \
|
||||||
|
VALUE *seq = iseq->iseq; \
|
||||||
|
int pc = cfp->pc - iseq->iseq_encoded; \
|
||||||
|
FIRE_INSN_ENTRY((char *)rb_vm_insn_name(seq[pc]), \
|
||||||
|
seq+1, \
|
||||||
|
(char *)rb_sourcefile(), \
|
||||||
|
rb_sourceline()); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
|
#define DEBUG_END_INSN() \
|
||||||
|
do { \
|
||||||
|
if (UNLIKELY(TRACE_INSN_RETURN_ENABLED())) { \
|
||||||
|
rb_control_frame_t *cfp = GET_CFP(); \
|
||||||
|
rb_iseq_t *iseq = cfp->iseq; \
|
||||||
|
if (iseq != NULL && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_FINISH) { \
|
||||||
|
VALUE *seq = iseq->iseq; \
|
||||||
|
int pc = cfp->pc - iseq->iseq_encoded; \
|
||||||
|
FIRE_INSN_RETURN((char *)rb_vm_insn_name(seq[pc]), \
|
||||||
|
seq+1, \
|
||||||
|
(char *)rb_sourcefile(), \
|
||||||
|
rb_sourceline()); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define throwdebug if(0)printf
|
#define throwdebug if(0)printf
|
||||||
|
Loading…
x
Reference in New Issue
Block a user