mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
use builtin for TracePoint.
Define TracePoint in trace_point.rb and use __builtin_ syntax.
This commit is contained in:
parent
46acd0075d
commit
e2a45cb984
Notes:
git
2019-11-08 09:10:08 +09:00
8 changed files with 527 additions and 438 deletions
|
@ -9,9 +9,10 @@
|
|||
|
||||
# prelude
|
||||
prelude.rb
|
||||
|
||||
rbconfig.rb
|
||||
|
||||
trace_point.rb
|
||||
|
||||
# the lib/ directory (which has its own .document file)
|
||||
lib
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
3
inits.c
3
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
|
||||
|
|
63
prelude.rb
63
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
|
||||
|
|
|
@ -466,6 +466,130 @@ class TestSetTraceFunc < Test::Unit::TestCase
|
|||
trace.disable if trace&.enabled?
|
||||
end
|
||||
|
||||
answer_events = [
|
||||
#
|
||||
[: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],
|
||||
]
|
||||
|
||||
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
|
||||
trace = trace
|
||||
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'
|
||||
3: })
|
||||
4: 1.times{|;_local_var| _local_var = :inner
|
||||
5: tap{}
|
||||
6: }
|
||||
7: class XYZZY
|
||||
8: _local_var = :XYZZY_outer
|
||||
9: def foo
|
||||
10: _local_var = :XYZZY_foo
|
||||
11: bar
|
||||
12: end
|
||||
13: def bar
|
||||
14: _local_var = :XYZZY_bar
|
||||
15: tap{}
|
||||
16: end
|
||||
17: end
|
||||
18: xyzzy = XYZZY.new
|
||||
19: xyzzy.foo
|
||||
20: begin; raise RuntimeError; rescue RuntimeError => raised_exc; end
|
||||
21: set_trace_func(nil)
|
||||
EOF
|
||||
self.class.class_eval{remove_const(:XYZZY)}
|
||||
|
||||
answer_events = [
|
||||
#
|
||||
[:c_return, 1, "xyzzy", TracePoint, :trace, TracePoint, :outer, trace],
|
||||
|
@ -519,79 +643,19 @@ class TestSetTraceFunc < Test::Unit::TestCase
|
|||
[:line, 21, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
|
||||
[:c_call, 21, "xyzzy", TracePoint, :disable, trace, :outer, :nothing],
|
||||
]
|
||||
|
||||
return events, answer_events
|
||||
end
|
||||
|
||||
def trace_by_set_trace_func
|
||||
events = []
|
||||
trace = nil
|
||||
trace = trace
|
||||
xyzzy = nil
|
||||
xyzzy = xyzzy
|
||||
_local_var = :outer
|
||||
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'
|
||||
3: })
|
||||
4: 1.times{|;_local_var| _local_var = :inner
|
||||
5: tap{}
|
||||
6: }
|
||||
7: class XYZZY
|
||||
8: _local_var = :XYZZY_outer
|
||||
9: def foo
|
||||
10: _local_var = :XYZZY_foo
|
||||
11: bar
|
||||
12: end
|
||||
13: def bar
|
||||
14: _local_var = :XYZZY_bar
|
||||
15: tap{}
|
||||
16: end
|
||||
17: end
|
||||
18: xyzzy = XYZZY.new
|
||||
19: xyzzy.foo
|
||||
20: begin; raise RuntimeError; rescue RuntimeError => raised_exc; end
|
||||
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
|
||||
}
|
||||
|
||||
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{}
|
||||
|
|
|
@ -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])
|
||||
|
|
348
trace_point.rb
Normal file
348
trace_point.rb
Normal file
|
@ -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
|
336
vm_trace.c
336
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)
|
||||
{
|
||||
|
@ -1462,6 +1338,12 @@ rb_tracepoint_enabled_p(VALUE tpval)
|
|||
return tp->tracing ? Qtrue : Qfalse;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue