diff options
author | Koichi Sasada <[email protected]> | 2019-11-07 18:22:08 +0900 |
---|---|---|
committer | Koichi Sasada <[email protected]> | 2019-11-08 09:09:29 +0900 |
commit | e2a45cb984ba75083a577b38ee9643800579a280 (patch) | |
tree | 9e8c56b3c7081b3ffdd8b65ca16c166ba186725e /trace_point.rb | |
parent | 46acd0075d80c2f886498f089fde1e9d795d50c4 (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
Diffstat (limited to 'trace_point.rb')
-rw-r--r-- | trace_point.rb | 348 |
1 files changed, 348 insertions, 0 deletions
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:[email protected]: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 |