summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2019-11-07 18:22:08 +0900
committerKoichi Sasada <ko1@atdot.net>2019-11-08 09:09:29 +0900
commite2a45cb984ba75083a577b38ee9643800579a280 (patch)
tree9e8c56b3c7081b3ffdd8b65ca16c166ba186725e
parent46acd0075d80c2f886498f089fde1e9d795d50c4 (diff)
use builtin for TracePoint.
Define TracePoint in trace_point.rb and use __builtin_ syntax.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/2655
-rw-r--r--.document3
-rw-r--r--common.mk7
-rw-r--r--inits.c3
-rw-r--r--prelude.rb63
-rw-r--r--test/ruby/test_settracefunc.rb138
-rw-r--r--tool/test/testunit/test_parallel.rb3
-rw-r--r--trace_point.rb348
-rw-r--r--vm_trace.c338
8 files changed, 496 insertions, 407 deletions
diff --git a/.document b/.document
index 2116ca6d26..64c56be7ee 100644
--- a/.document
+++ b/.document
@@ -9,9 +9,10 @@
# prelude
prelude.rb
-
rbconfig.rb
+trace_point.rb
+
# the lib/ directory (which has its own .document file)
lib
diff --git a/common.mk b/common.mk
index 42d3223e90..40cef70dda 100644
--- a/common.mk
+++ b/common.mk
@@ -1094,11 +1094,14 @@ preludes: {$(VPATH)}prelude.c
preludes: {$(VPATH)}miniprelude.c
preludes: {$(srcdir)}golf_prelude.c
-BUILTIN_RB_SRCS =
+BUILTIN_RB_SRCS = $(srcdir)/trace_point.rb
builtin_binary.inc: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/tool/mk_builtin_binary.rb
$(Q) $(MINIRUBY) $(srcdir)/tool/mk_builtin_binary.rb
+load_trace_point.inc: $(srcdir)/trace_point.rb $(srcdir)/tool/mk_builtin_loader.rb
+ $(Q) $(BASERUBY) $(srcdir)/tool/mk_builtin_loader.rb $(srcdir)/trace_point.rb
+
$(srcdir)/revision.h:
$(Q)$(gnumake:yes=#) $(RM) $(@F)
$(Q)$(gnumake:yes=#) exit > $@ || exit > $(@F)
@@ -3389,6 +3392,7 @@ vm_trace.$(OBJEXT): $(CCAN_DIR)/str/str.h
vm_trace.$(OBJEXT): $(hdrdir)/ruby.h
vm_trace.$(OBJEXT): $(hdrdir)/ruby/ruby.h
vm_trace.$(OBJEXT): {$(VPATH)}assert.h
+vm_trace.$(OBJEXT): {$(VPATH)}builtin.h
vm_trace.$(OBJEXT): {$(VPATH)}config.h
vm_trace.$(OBJEXT): {$(VPATH)}debug.h
vm_trace.$(OBJEXT): {$(VPATH)}debug_counter.h
@@ -3400,6 +3404,7 @@ vm_trace.$(OBJEXT): {$(VPATH)}intern.h
vm_trace.$(OBJEXT): {$(VPATH)}internal.h
vm_trace.$(OBJEXT): {$(VPATH)}io.h
vm_trace.$(OBJEXT): {$(VPATH)}iseq.h
+vm_trace.$(OBJEXT): {$(VPATH)}load_trace_point.inc
vm_trace.$(OBJEXT): {$(VPATH)}method.h
vm_trace.$(OBJEXT): {$(VPATH)}missing.h
vm_trace.$(OBJEXT): {$(VPATH)}mjit.h
diff --git a/inits.c b/inits.c
index 11b5fa5a7e..8a9789d050 100644
--- a/inits.c
+++ b/inits.c
@@ -65,11 +65,12 @@ rb_call_inits(void)
CALL(Rational);
CALL(Complex);
CALL(version);
- CALL(vm_trace);
CALL(vm_stack_canary);
CALL(ast);
CALL(gc_stress);
CALL(builtin);
+
+ CALL(vm_trace);
}
#undef CALL
diff --git a/prelude.rb b/prelude.rb
index 4e23aba36e..7cc2d260b6 100644
--- a/prelude.rb
+++ b/prelude.rb
@@ -136,69 +136,6 @@ class IO
end
end
-class TracePoint
- # call-seq:
- # trace.enable(target: nil, target_line: nil, target_thread: nil) -> true or false
- # trace.enable(target: nil, target_line: nil, target_thread: nil) { block } -> obj
- #
- # Activates the trace.
- #
- # Returns +true+ if trace was enabled.
- # Returns +false+ if trace was disabled.
- #
- # trace.enabled? #=> false
- # trace.enable #=> false (previous state)
- # # trace is enabled
- # trace.enabled? #=> true
- # trace.enable #=> true (previous state)
- # # trace is still enabled
- #
- # If a block is given, the trace will only be enabled within the scope of the
- # block.
- #
- # trace.enabled?
- # #=> false
- #
- # trace.enable do
- # trace.enabled?
- # # only enabled for this block
- # end
- #
- # trace.enabled?
- # #=> false
- #
- # +target+, +target_line+ and +target_thread+ parameters are used to
- # limit tracing only to specified code objects. +target+ should be a
- # code object for which RubyVM::InstructionSequence.of will return
- # an instruction sequence.
- #
- # t = TracePoint.new(:line) { |tp| p tp }
- #
- # def m1
- # p 1
- # end
- #
- # def m2
- # p 2
- # end
- #
- # t.enable(target: method(:m1))
- #
- # m1
- # # prints #<TracePoint:line@test.rb:5 in `m1'>
- # m2
- # # prints nothing
- #
- # Note: You cannot access event hooks within the +enable+ block.
- #
- # trace.enable { p tp.lineno }
- # #=> RuntimeError: access from outside
- #
- def enable target: nil, target_line: nil, target_thread: nil, &blk
- self.__enable target, target_line, target_thread, &blk
- end
-end
-
class Binding
# :nodoc:
def irb
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 11384273df..dba940b43e 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -468,7 +468,6 @@ class TestSetTraceFunc < Test::Unit::TestCase
answer_events = [
#
- [:c_return, 1, "xyzzy", TracePoint, :trace, TracePoint, :outer, trace],
[:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing],
[:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
@@ -517,12 +516,45 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:c_call, 20, "xyzzy", Module, :===, RuntimeError,:outer, :nothing],
[:c_return,20, "xyzzy", Module, :===, RuntimeError,:outer, true],
[:line, 21, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
- [:c_call, 21, "xyzzy", TracePoint, :disable, trace, :outer, :nothing],
]
return events, answer_events
end
+ def test_tracepoint
+ events1, answer_events = *trace_by_tracepoint(:line, :class, :end, :call, :return, :c_call, :c_return, :raise)
+
+ ms = [events1, answer_events].map{|evs|
+ evs.map{|e|
+ "#{e[0]} - #{e[2]}:#{e[1]} id: #{e[4]}"
+ }
+ }
+
+ if false # show all events
+ printf(" %-60s | %-60s\n", "actual", "expected")
+ ms[0].zip(ms[1]){|a, b|
+ printf("%s%-60s | %-60s\n", a==b ? ' ' : '!', a, b)
+ }
+ end
+
+ mesg = ms[0].zip(ms[1]).map{|a, b|
+ if a != b
+ "actual: #{a} <-> expected: #{b}"
+ end
+ }.compact.join("\n")
+
+ answer_events.zip(events1){|answer, event|
+ assert_equal answer, event, mesg
+ }
+
+ [:line, :class, :end, :call, :return, :c_call, :c_return, :raise].each{|event|
+ events1, answer_events = *trace_by_tracepoint(event)
+ answer_events.find_all{|e| e[0] == event}.zip(events1){|answer_line, event_line|
+ assert_equal answer_line, event_line
+ }
+ }
+ end
+
def trace_by_set_trace_func
events = []
trace = nil
@@ -530,6 +562,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
xyzzy = nil
xyzzy = xyzzy
_local_var = :outer
+ method = :trace_by_set_trace_func
+ raised_exc = nil
+
eval <<-EOF.gsub(/^.*?: /, ""), nil, 'xyzzy'
1: set_trace_func(lambda{|event, file, line, id, binding, klass|
2: events << [event, line, file, klass, id, binding.eval('self'), binding.eval("_local_var")] if file == 'xyzzy'
@@ -554,44 +589,73 @@ class TestSetTraceFunc < Test::Unit::TestCase
21: set_trace_func(nil)
EOF
self.class.class_eval{remove_const(:XYZZY)}
- return events
- end
-
- def test_tracepoint
- events1, answer_events = *trace_by_tracepoint(:line, :class, :end, :call, :return, :c_call, :c_return, :raise)
-
- ms = [events1, answer_events].map{|evs|
- evs.map{|e|
- "#{e[0]} - #{e[2]}:#{e[1]} id: #{e[4]}"
- }
- }
- mesg = ms[0].zip(ms[1]).map{|a, b|
- if a != b
- "#{a} <-> #{b}"
- end
- }.compact.join("\n")
-
- answer_events.zip(events1){|answer, event|
- assert_equal answer, event, mesg
- }
+ answer_events = [
+ #
+ [:c_return, 1, "xyzzy", TracePoint, :trace, TracePoint, :outer, trace],
+ [:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing],
+ [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
+ [:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
+ [:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
+ [:c_call, 5, 'xyzzy', Kernel, :tap, self, :inner, :nothing],
+ [:c_return, 5, "xyzzy", Kernel, :tap, self, :inner, self],
+ [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1],
+ [:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
+ [:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing],
+ [:c_return, 7, "xyzzy", Class, :inherited, Object, :outer, nil],
+ [:class, 7, "xyzzy", nil, nil, xyzzy.class, nil, :nothing],
+ [:line, 8, "xyzzy", nil, nil, xyzzy.class, nil, :nothing],
+ [:line, 9, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing],
+ [:c_call, 9, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, :nothing],
+ [:c_return, 9, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, nil],
+ [:line, 13, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing],
+ [:c_call, 13, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, :nothing],
+ [:c_return,13, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, nil],
+ [:end, 17, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing],
+ [:line, 18, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
+ [:c_call, 18, "xyzzy", Class, :new, xyzzy.class, :outer, :nothing],
+ [:c_call, 18, "xyzzy", BasicObject, :initialize, xyzzy, :outer, :nothing],
+ [:c_return,18, "xyzzy", BasicObject, :initialize, xyzzy, :outer, nil],
+ [:c_return,18, "xyzzy", Class, :new, xyzzy.class, :outer, xyzzy],
+ [:line, 19, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
+ [:call, 9, "xyzzy", xyzzy.class, :foo, xyzzy, nil, :nothing],
+ [:line, 10, "xyzzy", xyzzy.class, :foo, xyzzy, nil, :nothing],
+ [:line, 11, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, :nothing],
+ [:call, 13, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
+ [:line, 14, "xyzzy", xyzzy.class, :bar, xyzzy, nil, :nothing],
+ [:line, 15, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, :nothing],
+ [:c_call, 15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, :nothing],
+ [:c_return,15, "xyzzy", Kernel, :tap, xyzzy, :XYZZY_bar, xyzzy],
+ [:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy],
+ [:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy],
+ [:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
+ [:c_call, 20, "xyzzy", Kernel, :raise, self, :outer, :nothing],
+ [:c_call, 20, "xyzzy", Exception, :exception, RuntimeError, :outer, :nothing],
+ [:c_call, 20, "xyzzy", Exception, :initialize, raised_exc, :outer, :nothing],
+ [:c_return,20, "xyzzy", Exception, :initialize, raised_exc, :outer, raised_exc],
+ [:c_return,20, "xyzzy", Exception, :exception, RuntimeError, :outer, raised_exc],
+ [:c_return,20, "xyzzy", Kernel, :raise, self, :outer, nil],
+ [:c_call, 20, "xyzzy", Exception, :backtrace, raised_exc, :outer, :nothing],
+ [:c_return,20, "xyzzy", Exception, :backtrace, raised_exc, :outer, nil],
+ [:raise, 20, "xyzzy", TestSetTraceFunc, :trace_by_tracepoint, self, :outer, raised_exc],
+ [:c_call, 20, "xyzzy", Module, :===, RuntimeError,:outer, :nothing],
+ [:c_return,20, "xyzzy", Module, :===, RuntimeError,:outer, true],
+ [:line, 21, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
+ [:c_call, 21, "xyzzy", TracePoint, :disable, trace, :outer, :nothing],
+ ]
+ return events, answer_events
+ end
- events2 = trace_by_set_trace_func
- events1.zip(events2){|ev1, ev2|
- ev2[0] = ev2[0].sub('-', '_').to_sym
- assert_equal ev1[0..2], ev2[0..2], ev1.inspect
+ def test_set_trace_func
+ actual_events, expected_events = trace_by_set_trace_func
+ expected_events.zip(actual_events){|e, a|
+ a[0] = a[0].to_s.sub('-', '_').to_sym
+ assert_equal e[0..2], a[0..2], a.inspect
# event, line, file, klass, id, binding.eval('self'), binding.eval("_local_var")
- assert_equal ev1[3].nil?, ev2[3].nil? # klass
- assert_equal ev1[4].nil?, ev2[4].nil? # id
- assert_equal ev1[6], ev2[6] # _local_var
- }
-
- [:line, :class, :end, :call, :return, :c_call, :c_return, :raise].each{|event|
- events1, answer_events = *trace_by_tracepoint(event)
- answer_events.find_all{|e| e[0] == event}.zip(events1){|answer_line, event_line|
- assert_equal answer_line, event_line
- }
+ assert_equal e[3].nil?, a[3].nil? # klass
+ assert_equal e[4].nil?, a[4].nil? # id
+ assert_equal e[6], a[6] # _local_var
}
end
@@ -676,7 +740,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
}
foo
trace.disable
- assert_equal([:foo, :foo], ary)
+ assert_equal([:foo, :disable, :foo, :disable], ary)
assert_equal([], args)
trace = TracePoint.new{}
diff --git a/tool/test/testunit/test_parallel.rb b/tool/test/testunit/test_parallel.rb
index ac4c924eba..24e1f89bcb 100644
--- a/tool/test/testunit/test_parallel.rb
+++ b/tool/test/testunit/test_parallel.rb
@@ -110,9 +110,8 @@ module TestParallel
end
result = Marshal.load($1.chomp.unpack("m")[0])
-
assert_equal(5, result[0])
- assert_equal(17, result[1])
+ assert_equal(12, result[1])
assert_kind_of(Array,result[2])
assert_kind_of(Array,result[3])
assert_kind_of(Array,result[4])
diff --git a/trace_point.rb b/trace_point.rb
new file mode 100644
index 0000000000..9be90506d3
--- /dev/null
+++ b/trace_point.rb
@@ -0,0 +1,348 @@
+# loaded from vm_trace.c
+
+# Document-class: TracePoint
+#
+# A class that provides the functionality of Kernel#set_trace_func in a
+# nice Object-Oriented API.
+#
+# == Example
+#
+# We can use TracePoint to gather information specifically for exceptions:
+#
+# trace = TracePoint.new(:raise) do |tp|
+# p [tp.lineno, tp.event, tp.raised_exception]
+# end
+# #=> #<TracePoint:disabled>
+#
+# trace.enable
+# #=> false
+#
+# 0 / 0
+# #=> [5, :raise, #<ZeroDivisionError: divided by 0>]
+#
+# == Events
+#
+# If you don't specify the type of events you want to listen for,
+# TracePoint will include all available events.
+#
+# *Note* do not depend on current event set, as this list is subject to
+# change. Instead, it is recommended you specify the type of events you
+# want to use.
+#
+# To filter what is traced, you can pass any of the following as +events+:
+#
+# +:line+:: execute code on a new line
+# +:class+:: start a class or module definition
+# +:end+:: finish a class or module definition
+# +:call+:: call a Ruby method
+# +:return+:: return from a Ruby method
+# +:c_call+:: call a C-language routine
+# +:c_return+:: return from a C-language routine
+# +:raise+:: raise an exception
+# +:b_call+:: event hook at block entry
+# +:b_return+:: event hook at block ending
+# +:thread_begin+:: event hook at thread beginning
+# +:thread_end+:: event hook at thread ending
+# +:fiber_switch+:: event hook at fiber switch
+# +:script_compiled+:: new Ruby code compiled (with +eval+, +load+ or +require+)
+#
+class TracePoint
+ # call-seq:
+ # TracePoint.new(*events) { |obj| block } -> obj
+ #
+ # Returns a new TracePoint object, not enabled by default.
+ #
+ # Next, in order to activate the trace, you must use TracePoint#enable
+ #
+ # trace = TracePoint.new(:call) do |tp|
+ # p [tp.lineno, tp.defined_class, tp.method_id, tp.event]
+ # end
+ # #=> #<TracePoint:disabled>
+ #
+ # trace.enable
+ # #=> false
+ #
+ # puts "Hello, TracePoint!"
+ # # ...
+ # # [48, IRB::Notifier::AbstractNotifier, :printf, :call]
+ # # ...
+ #
+ # When you want to deactivate the trace, you must use TracePoint#disable
+ #
+ # trace.disable
+ #
+ # See TracePoint@Events for possible events and more information.
+ #
+ # A block must be given, otherwise an ArgumentError is raised.
+ #
+ # If the trace method isn't included in the given events filter, a
+ # RuntimeError is raised.
+ #
+ # TracePoint.trace(:line) do |tp|
+ # p tp.raised_exception
+ # end
+ # #=> RuntimeError: 'raised_exception' not supported by this event
+ #
+ # If the trace method is called outside block, a RuntimeError is raised.
+ #
+ # TracePoint.trace(:line) do |tp|
+ # $tp = tp
+ # end
+ # $tp.lineno #=> access from outside (RuntimeError)
+ #
+ # Access from other threads is also forbidden.
+ #
+ def self.new(*events)
+ __builtin_tracepoint_new_s(events)
+ end
+
+ # call-seq:
+ # trace.inspect -> string
+ #
+ # Return a string containing a human-readable TracePoint
+ # status.
+ def inspect
+ __builtin_tracepoint_inspect
+ end
+
+ # call-seq:
+ # TracePoint.stat -> obj
+ #
+ # Returns internal information of TracePoint.
+ #
+ # The contents of the returned value are implementation specific.
+ # It may be changed in future.
+ #
+ # This method is only for debugging TracePoint itself.
+ def stat
+ __builtin_tracepoint_stat_s
+ end
+
+ # Document-method: trace
+ #
+ # call-seq:
+ # TracePoint.trace(*events) { |obj| block } -> obj
+ #
+ # A convenience method for TracePoint.new, that activates the trace
+ # automatically.
+ #
+ # trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] }
+ # #=> #<TracePoint:enabled>
+ #
+ # trace.enabled? #=> true
+ #
+ def self.trace(*events)
+ __builtin_tracepoint_trace_s(events)
+ end
+
+ # call-seq:
+ # trace.enable(target: nil, target_line: nil, target_thread: nil) -> true or false
+ # trace.enable(target: nil, target_line: nil, target_thread: nil) { block } -> obj
+ #
+ # Activates the trace.
+ #
+ # Returns +true+ if trace was enabled.
+ # Returns +false+ if trace was disabled.
+ #
+ # trace.enabled? #=> false
+ # trace.enable #=> false (previous state)
+ # # trace is enabled
+ # trace.enabled? #=> true
+ # trace.enable #=> true (previous state)
+ # # trace is still enabled
+ #
+ # If a block is given, the trace will only be enabled within the scope of the
+ # block.
+ #
+ # trace.enabled?
+ # #=> false
+ #
+ # trace.enable do
+ # trace.enabled?
+ # # only enabled for this block
+ # end
+ #
+ # trace.enabled?
+ # #=> false
+ #
+ # +target+, +target_line+ and +target_thread+ parameters are used to
+ # limit tracing only to specified code objects. +target+ should be a
+ # code object for which RubyVM::InstructionSequence.of will return
+ # an instruction sequence.
+ #
+ # t = TracePoint.new(:line) { |tp| p tp }
+ #
+ # def m1
+ # p 1
+ # end
+ #
+ # def m2
+ # p 2
+ # end
+ #
+ # t.enable(target: method(:m1))
+ #
+ # m1
+ # # prints #<TracePoint:line@test.rb:5 in `m1'>
+ # m2
+ # # prints nothing
+ #
+ # Note: You cannot access event hooks within the +enable+ block.
+ #
+ # trace.enable { p tp.lineno }
+ # #=> RuntimeError: access from outside
+ #
+ def enable(target: nil, target_line: nil, target_thread: nil)
+ __builtin_tracepoint_enable_m(target, target_line, target_thread)
+ end
+
+ # call-seq:
+ # trace.disable -> true or false
+ # trace.disable { block } -> obj
+ #
+ # Deactivates the trace
+ #
+ # Return true if trace was enabled.
+ # Return false if trace was disabled.
+ #
+ # trace.enabled? #=> true
+ # trace.disable #=> true (previous status)
+ # trace.enabled? #=> false
+ # trace.disable #=> false
+ #
+ # If a block is given, the trace will only be disable within the scope of the
+ # block.
+ #
+ # trace.enabled?
+ # #=> true
+ #
+ # trace.disable do
+ # trace.enabled?
+ # # only disabled for this block
+ # end
+ #
+ # trace.enabled?
+ # #=> true
+ #
+ # Note: You cannot access event hooks within the block.
+ #
+ # trace.disable { p tp.lineno }
+ # #=> RuntimeError: access from outside
+ def disable
+ __builtin_tracepoint_disable_m
+ end
+
+ # call-seq:
+ # trace.enabled? -> true or false
+ #
+ # The current status of the trace
+ def enabled?
+ __builtin_tracepoint_enabled_p
+ end
+
+ # Type of event
+ #
+ # See TracePoint@Events for more information.
+ def event
+ __builtin_tracepoint_attr_event
+ end
+
+ # Line number of the event
+ def lineno
+ __builtin_tracepoint_attr_lineno
+ end
+
+ # Path of the file being run
+ def path
+ __builtin_tracepoint_attr_path
+ end
+
+ # Return the parameters definition of the method or block that the
+ # current hook belongs to. Format is the same as for Method#parameters
+ def parameters
+ __builtin_tracepoint_attr_parameters
+ end
+
+ # Return the name at the definition of the method being called
+ def method_id
+ __builtin_tracepoint_attr_method_id
+ end
+
+ # Return the called name of the method being called
+ def callee_id
+ __builtin_tracepoint_attr_callee_id
+ end
+
+ # Return class or module of the method being called.
+ #
+ # class C; def foo; end; end
+ # trace = TracePoint.new(:call) do |tp|
+ # p tp.defined_class #=> C
+ # end.enable do
+ # C.new.foo
+ # end
+ #
+ # If method is defined by a module, then that module is returned.
+ #
+ # module M; def foo; end; end
+ # class C; include M; end;
+ # trace = TracePoint.new(:call) do |tp|
+ # p tp.defined_class #=> M
+ # end.enable do
+ # C.new.foo
+ # end
+ #
+ # <b>Note:</b> #defined_class returns singleton class.
+ #
+ # 6th block parameter of Kernel#set_trace_func passes original class
+ # of attached by singleton class.
+ #
+ # <b>This is a difference between Kernel#set_trace_func and TracePoint.</b>
+ #
+ # class C; def self.foo; end; end
+ # trace = TracePoint.new(:call) do |tp|
+ # p tp.defined_class #=> #<Class:C>
+ # end.enable do
+ # C.foo
+ # end
+ def defined_class
+ __builtin_tracepoint_attr_defined_class
+ end
+
+ # Return the generated binding object from event
+ def binding
+ __builtin_tracepoint_attr_binding
+ end
+
+ # Return the trace object during event
+ #
+ # Same as TracePoint#binding:
+ # trace.binding.eval('self')
+ def self
+ __builtin_tracepoint_attr_self
+ end
+
+ # Return value from +:return+, +c_return+, and +b_return+ event
+ def return_value
+ __builtin_tracepoint_attr_return_value
+ end
+
+ # Value from exception raised on the +:raise+ event
+ def raised_exception
+ __builtin_tracepoint_attr_raised_exception
+ end
+
+ # Compiled source code (String) on *eval methods on the +:script_compiled+ event.
+ # If loaded from a file, it will return nil.
+ def eval_script
+ __builtin_tracepoint_attr_eval_script
+ end
+
+ # Compiled instruction sequence represented by a RubyVM::InstructionSequence instance
+ # on the +:script_compiled+ event.
+ #
+ # Note that this method is MRI specific.
+ def instruction_sequence
+ __builtin_tracepoint_attr_instruction_sequence
+ end
+end
diff --git a/vm_trace.c b/vm_trace.c
index eb1c2afa4e..1cb5fd0036 100644
--- a/vm_trace.c
+++ b/vm_trace.c
@@ -28,6 +28,7 @@
#include "mjit.h"
#include "iseq.h"
#include "eval_intern.h"
+#include "builtin.h"
/* (1) trace mechanisms */
@@ -1018,160 +1019,79 @@ rb_tracearg_object(rb_trace_arg_t *trace_arg)
return trace_arg->data;
}
-/*
- * Type of event
- *
- * See TracePoint@Events for more information.
- */
static VALUE
-tracepoint_attr_event(VALUE tpval)
+tracepoint_attr_event(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_event(get_trace_arg());
}
-/*
- * Line number of the event
- */
static VALUE
-tracepoint_attr_lineno(VALUE tpval)
+tracepoint_attr_lineno(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_lineno(get_trace_arg());
}
-
-/*
- * Path of the file being run
- */
static VALUE
-tracepoint_attr_path(VALUE tpval)
+tracepoint_attr_path(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_path(get_trace_arg());
}
-/*
- * Return the parameters definition of the method or block that the
- * current hook belongs to. Format is the same as for Method#parameters
- */
static VALUE
-tracepoint_attr_parameters(VALUE tpval)
+tracepoint_attr_parameters(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_parameters(get_trace_arg());
}
-/*
- * Return the name at the definition of the method being called
- */
static VALUE
-tracepoint_attr_method_id(VALUE tpval)
+tracepoint_attr_method_id(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_method_id(get_trace_arg());
}
-/*
- * Return the called name of the method being called
- */
static VALUE
-tracepoint_attr_callee_id(VALUE tpval)
+tracepoint_attr_callee_id(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_callee_id(get_trace_arg());
}
-/*
- * Return class or module of the method being called.
- *
- * class C; def foo; end; end
- * trace = TracePoint.new(:call) do |tp|
- * p tp.defined_class #=> C
- * end.enable do
- * C.new.foo
- * end
- *
- * If method is defined by a module, then that module is returned.
- *
- * module M; def foo; end; end
- * class C; include M; end;
- * trace = TracePoint.new(:call) do |tp|
- * p tp.defined_class #=> M
- * end.enable do
- * C.new.foo
- * end
- *
- * <b>Note:</b> #defined_class returns singleton class.
- *
- * 6th block parameter of Kernel#set_trace_func passes original class
- * of attached by singleton class.
- *
- * <b>This is a difference between Kernel#set_trace_func and TracePoint.</b>
- *
- * class C; def self.foo; end; end
- * trace = TracePoint.new(:call) do |tp|
- * p tp.defined_class #=> #<Class:C>
- * end.enable do
- * C.foo
- * end
- */
static VALUE
-tracepoint_attr_defined_class(VALUE tpval)
+tracepoint_attr_defined_class(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_defined_class(get_trace_arg());
}
-/*
- * Return the generated binding object from event
- */
static VALUE
-tracepoint_attr_binding(VALUE tpval)
+tracepoint_attr_binding(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_binding(get_trace_arg());
}
-/*
- * Return the trace object during event
- *
- * Same as TracePoint#binding:
- * trace.binding.eval('self')
- */
static VALUE
-tracepoint_attr_self(VALUE tpval)
+tracepoint_attr_self(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_self(get_trace_arg());
}
-/*
- * Return value from +:return+, +c_return+, and +b_return+ event
- */
static VALUE
-tracepoint_attr_return_value(VALUE tpval)
+tracepoint_attr_return_value(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_return_value(get_trace_arg());
}
-/*
- * Value from exception raised on the +:raise+ event
- */
static VALUE
-tracepoint_attr_raised_exception(VALUE tpval)
+tracepoint_attr_raised_exception(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_raised_exception(get_trace_arg());
}
-/*
- * Compiled source code (String) on *eval methods on the +:script_compiled+ event.
- * If loaded from a file, it will return nil.
- */
static VALUE
-tracepoint_attr_eval_script(VALUE tpval)
+tracepoint_attr_eval_script(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_eval_script(get_trace_arg());
}
-/*
- * Compiled instruction sequence represented by a RubyVM::InstructionSequence instance
- * on the +:script_compiled+ event.
- *
- * Note that this method is MRI specific.
- */
static VALUE
-tracepoint_attr_instruction_sequence(VALUE tpval)
+tracepoint_attr_instruction_sequence(rb_execution_context_t *ec, VALUE tpval)
{
return rb_tracearg_instruction_sequence(get_trace_arg());
}
@@ -1352,11 +1272,8 @@ rb_hook_list_remove_tracepoint(rb_hook_list_t *list, VALUE tpval)
list->events = events;
}
-/* :nodoc:
- * Docs for the TracePointe#enable are in prelude.rb
- */
static VALUE
-tracepoint_enable_m(VALUE tpval, VALUE target, VALUE target_line, VALUE target_thread)
+tracepoint_enable_m(rb_execution_context_t *ec, VALUE tpval, VALUE target, VALUE target_line, VALUE target_thread)
{
rb_tp_t *tp = tpptr(tpval);
int previous_tracing = tp->tracing;
@@ -1392,43 +1309,8 @@ tracepoint_enable_m(VALUE tpval, VALUE target, VALUE target_line, VALUE target_t
}
}
-/*
- * call-seq:
- * trace.disable -> true or false
- * trace.disable { block } -> obj
- *
- * Deactivates the trace
- *
- * Return true if trace was enabled.
- * Return false if trace was disabled.
- *
- * trace.enabled? #=> true
- * trace.disable #=> true (previous status)
- * trace.enabled? #=> false
- * trace.disable #=> false
- *
- * If a block is given, the trace will only be disable within the scope of the
- * block.
- *
- * trace.enabled?
- * #=> true
- *
- * trace.disable do
- * trace.enabled?
- * # only disabled for this block
- * end
- *
- * trace.enabled?
- * #=> true
- *
- * Note: You cannot access event hooks within the block.
- *
- * trace.disable { p tp.lineno }
- * #=> RuntimeError: access from outside
- */
-
static VALUE
-tracepoint_disable_m(VALUE tpval)
+tracepoint_disable_m(rb_execution_context_t *ec, VALUE tpval)
{
rb_tp_t *tp = tpptr(tpval);
int previous_tracing = tp->tracing;
@@ -1449,12 +1331,6 @@ tracepoint_disable_m(VALUE tpval)
}
}
-/*
- * call-seq:
- * trace.enabled? -> true or false
- *
- * The current status of the trace
- */
VALUE
rb_tracepoint_enabled_p(VALUE tpval)
{
@@ -1463,6 +1339,12 @@ rb_tracepoint_enabled_p(VALUE tpval)
}
static VALUE
+tracepoint_enabled_p(rb_execution_context_t *ec, VALUE tpval)
+{
+ return rb_tracepoint_enabled_p(tpval);
+}
+
+static VALUE
tracepoint_new(VALUE klass, rb_thread_t *target_th, rb_event_flag_t events, void (func)(VALUE, void*), void *data, VALUE proc)
{
VALUE tpval = tp_alloc(klass);
@@ -1522,63 +1404,17 @@ rb_tracepoint_new(VALUE target_thval, rb_event_flag_t events, void (*func)(VALUE
return tracepoint_new(rb_cTracePoint, target_th, events, func, data, Qundef);
}
-/*
- * call-seq:
- * TracePoint.new(*events) { |obj| block } -> obj
- *
- * Returns a new TracePoint object, not enabled by default.
- *
- * Next, in order to activate the trace, you must use TracePoint#enable
- *
- * trace = TracePoint.new(:call) do |tp|
- * p [tp.lineno, tp.defined_class, tp.method_id, tp.event]
- * end
- * #=> #<TracePoint:disabled>
- *
- * trace.enable
- * #=> false
- *
- * puts "Hello, TracePoint!"
- * # ...
- * # [48, IRB::Notifier::AbstractNotifier, :printf, :call]
- * # ...
- *
- * When you want to deactivate the trace, you must use TracePoint#disable
- *
- * trace.disable
- *
- * See TracePoint@Events for possible events and more information.
- *
- * A block must be given, otherwise an ArgumentError is raised.
- *
- * If the trace method isn't included in the given events filter, a
- * RuntimeError is raised.
- *
- * TracePoint.trace(:line) do |tp|
- * p tp.raised_exception
- * end
- * #=> RuntimeError: 'raised_exception' not supported by this event
- *
- * If the trace method is called outside block, a RuntimeError is raised.
- *
- * TracePoint.trace(:line) do |tp|
- * $tp = tp
- * end
- * $tp.lineno #=> access from outside (RuntimeError)
- *
- * Access from other threads is also forbidden.
- *
- */
static VALUE
-tracepoint_new_s(int argc, VALUE *argv, VALUE self)
+tracepoint_new_s(rb_execution_context_t *ec, VALUE self, VALUE args)
{
rb_event_flag_t events = 0;
- int i;
+ long i;
+ long argc = RARRAY_LEN(args);
if (argc > 0) {
- for (i=0; i<argc; i++) {
- events |= symbol2event_flag(argv[i]);
- }
+ for (i=0; i<argc; i++) {
+ events |= symbol2event_flag(RARRAY_AREF(args, i));
+ }
}
else {
events = RUBY_EVENT_TRACEPOINT_ALL;
@@ -1592,23 +1428,15 @@ tracepoint_new_s(int argc, VALUE *argv, VALUE self)
}
static VALUE
-tracepoint_trace_s(int argc, VALUE *argv, VALUE self)
+tracepoint_trace_s(rb_execution_context_t *ec, VALUE self, VALUE args)
{
- VALUE trace = tracepoint_new_s(argc, argv, self);
+ VALUE trace = tracepoint_new_s(ec, self, args);
rb_tracepoint_enable(trace);
return trace;
}
-/*
- * call-seq:
- * trace.inspect -> string
- *
- * Return a string containing a human-readable TracePoint
- * status.
- */
-
static VALUE
-tracepoint_inspect(VALUE self)
+tracepoint_inspect(rb_execution_context_t *ec, VALUE self)
{
rb_tp_t *tp = tpptr(self);
rb_trace_arg_t *trace_arg = GET_EC()->trace_arg;
@@ -1671,20 +1499,8 @@ tracepoint_stat_event_hooks(VALUE hash, VALUE key, rb_event_hook_t *hook)
rb_hash_aset(hash, key, rb_ary_new3(2, INT2FIX(active), INT2FIX(deleted)));
}
-/*
- * call-seq:
- * TracePoint.stat -> obj
- *
- * Returns internal information of TracePoint.
- *
- * The contents of the returned value are implementation specific.
- * It may be changed in future.
- *
- * This method is only for debugging TracePoint itself.
- */
-
static VALUE
-tracepoint_stat_s(VALUE self)
+tracepoint_stat_s(rb_execution_context_t *ec, VALUE self)
{
rb_vm_t *vm = GET_VM();
VALUE stat = rb_hash_new();
@@ -1695,6 +1511,8 @@ tracepoint_stat_s(VALUE self)
return stat;
}
+#include "load_trace_point.inc"
+
/* This function is called from inits.c */
void
Init_vm_trace(void)
@@ -1704,94 +1522,10 @@ Init_vm_trace(void)
rb_define_method(rb_cThread, "set_trace_func", thread_set_trace_func_m, 1);
rb_define_method(rb_cThread, "add_trace_func", thread_add_trace_func_m, 1);
- /*
- * Document-class: TracePoint
- *
- * A class that provides the functionality of Kernel#set_trace_func in a
- * nice Object-Oriented API.
- *
- * == Example
- *
- * We can use TracePoint to gather information specifically for exceptions:
- *
- * trace = TracePoint.new(:raise) do |tp|
- * p [tp.lineno, tp.event, tp.raised_exception]
- * end
- * #=> #<TracePoint:disabled>
- *
- * trace.enable
- * #=> false
- *
- * 0 / 0
- * #=> [5, :raise, #<ZeroDivisionError: divided by 0>]
- *
- * == Events
- *
- * If you don't specify the type of events you want to listen for,
- * TracePoint will include all available events.
- *
- * *Note* do not depend on current event set, as this list is subject to
- * change. Instead, it is recommended you specify the type of events you
- * want to use.
- *
- * To filter what is traced, you can pass any of the following as +events+:
- *
- * +:line+:: execute code on a new line
- * +:class+:: start a class or module definition
- * +:end+:: finish a class or module definition
- * +:call+:: call a Ruby method
- * +:return+:: return from a Ruby method
- * +:c_call+:: call a C-language routine
- * +:c_return+:: return from a C-language routine
- * +:raise+:: raise an exception
- * +:b_call+:: event hook at block entry
- * +:b_return+:: event hook at block ending
- * +:thread_begin+:: event hook at thread beginning
- * +:thread_end+:: event hook at thread ending
- * +:fiber_switch+:: event hook at fiber switch
- * +:script_compiled+:: new Ruby code compiled (with +eval+, +load+ or +require+)
- *
- */
rb_cTracePoint = rb_define_class("TracePoint", rb_cObject);
rb_undef_alloc_func(rb_cTracePoint);
- rb_define_singleton_method(rb_cTracePoint, "new", tracepoint_new_s, -1);
- /*
- * Document-method: trace
- *
- * call-seq:
- * TracePoint.trace(*events) { |obj| block } -> obj
- *
- * A convenience method for TracePoint.new, that activates the trace
- * automatically.
- *
- * trace = TracePoint.trace(:call) { |tp| [tp.lineno, tp.event] }
- * #=> #<TracePoint:enabled>
- *
- * trace.enabled? #=> true
- */
- rb_define_singleton_method(rb_cTracePoint, "trace", tracepoint_trace_s, -1);
-
- rb_define_method(rb_cTracePoint, "__enable", tracepoint_enable_m, 3);
- rb_define_method(rb_cTracePoint, "disable", tracepoint_disable_m, 0);
- rb_define_method(rb_cTracePoint, "enabled?", rb_tracepoint_enabled_p, 0);
-
- rb_define_method(rb_cTracePoint, "inspect", tracepoint_inspect, 0);
-
- rb_define_method(rb_cTracePoint, "event", tracepoint_attr_event, 0);
- rb_define_method(rb_cTracePoint, "lineno", tracepoint_attr_lineno, 0);
- rb_define_method(rb_cTracePoint, "path", tracepoint_attr_path, 0);
- rb_define_method(rb_cTracePoint, "parameters", tracepoint_attr_parameters, 0);
- rb_define_method(rb_cTracePoint, "method_id", tracepoint_attr_method_id, 0);
- rb_define_method(rb_cTracePoint, "callee_id", tracepoint_attr_callee_id, 0);
- rb_define_method(rb_cTracePoint, "defined_class", tracepoint_attr_defined_class, 0);
- rb_define_method(rb_cTracePoint, "binding", tracepoint_attr_binding, 0);
- rb_define_method(rb_cTracePoint, "self", tracepoint_attr_self, 0);
- rb_define_method(rb_cTracePoint, "return_value", tracepoint_attr_return_value, 0);
- rb_define_method(rb_cTracePoint, "raised_exception", tracepoint_attr_raised_exception, 0);
- rb_define_method(rb_cTracePoint, "eval_script", tracepoint_attr_eval_script, 0);
- rb_define_method(rb_cTracePoint, "instruction_sequence", tracepoint_attr_instruction_sequence, 0);
-
- rb_define_singleton_method(rb_cTracePoint, "stat", tracepoint_stat_s, 0);
+
+ load_trace_point();
}
typedef struct rb_postponed_job_struct {