Sasadaさんが2012年に行っていたRuby VM アドベントカレンダーを読んで、
- Kernel.#set_trace_func
- TracePoint
- TracePoint API
- Debug Inspector API
- RubyVM::InstructionSequence
このあたりの内容に興味を持ったので、少し手を動かしてみよう。
バージョンは2.0.0p195 (2013-05-14) [i386-mingw32]
Kernel.#set_trace_func
とりあえずはset_trace_func
。
参考にしたのは
リファレンスマニュアル
Sasadaさんの2012/12/12の記事
takihiroさんの記事
README.EXT.ja
Code Reading Wiki
ひとり勉強会
set_trace_funcの簡単な使い方
trace.rb
1 : set_trace_func lambda { |*args|
2 : p args
3 : }
4 :
5 : class Foo
6 : def bar
7 : p "Hello"
8 : end
9 : end
10:
11: foo = Foo.new
12: foo.bar
# =>
["c-return", "trace.rb", 1, :set_trace_func, #<Binding:0xf6c540>, Kernel]
["line", "trace.rb", 5, nil, #<Binding:0x10cba80>, nil]
["c-call", "trace.rb", 5, :inherited, #<Binding:0x10cb840>, Class]
["c-return", "trace.rb", 5, :inherited, #<Binding:0x10cb600>, Class]
["class", "trace.rb", 5, nil, #<Binding:0x10cb3a8>, nil]
["line", "trace.rb", 6, nil, #<Binding:0x10cb198>, nil]
["c-call", "trace.rb", 6, :method_added, #<Binding:0x10caf88>, Module]
["c-return", "trace.rb", 6, :method_added, #<Binding:0x10cad48>, Module]
["end", "trace.rb", 9, nil, #<Binding:0x10cab20>, nil]
["line", "trace.rb", 11, nil, #<Binding:0x10ca910>, nil]
["c-call", "trace.rb", 11, :new, #<Binding:0x10ca700>, Class]
["c-call", "trace.rb", 11, :initialize, #<Binding:0x10ca4c0>, BasicObject]
["c-return", "trace.rb", 11, :initialize, #<Binding:0x10ca280>, BasicObject]
["c-return", "trace.rb", 11, :new, #<Binding:0x10ca058>, Class]
["line", "trace.rb", 12, nil, #<Binding:0x10c9e30>, nil]
["call", "trace.rb", 6, :bar, #<Binding:0x10c9c08>, Foo]
["line", "trace.rb", 7, :bar, #<Binding:0x10c99e0>, Foo]
["c-call", "trace.rb", 7, :p, #<Binding:0x10c97a0>, Kernel]
["c-call", "trace.rb", 7, :hash, #<Binding:0x10c9560>, Kernel]
["c-return", "trace.rb", 7, :hash, #<Binding:0x10c9338>, Kernel]
["c-call", "trace.rb", 7, :inspect, #<Binding:0x10c9110>, String]
["c-return", "trace.rb", 7, :inspect, #<Binding:0x10c8eb8>, String]
"Hello"
["c-return", "trace.rb", 7, :p, #<Binding:0x10c8bb8>, Kernel]
["return", "trace.rb", 8, :bar, #<Binding:0x10c8990>, Foo]
イベントは
- "line": 式の評価。
- "call": メソッドの呼び出し。
- "return": メソッド呼び出しからのリターン。
- "c-call": Cで記述されたメソッドの呼び出し。
- "c-return": Cで記述されたメソッド呼び出しからのリターン。
- "class": クラス定義、特異クラス定義、モジュール定義への突入。
- "end": クラス定義、特異クラス定義、モジュール定義の終了。
- "raise": 例外の発生。
があり、それぞれが実行される度に設定したproc
が呼ばれます。
args
はそれぞれevent, file, line, id, binding, klass
になっています。
先頭でKernel.#set_trace_func
を呼び出しておけば、それ以降のイベントをフック出来ます。
Ruby標準ライブラリ
リファレンスマニュアルにも書いてあるとおり、
- debug
- tracer
- profile
はset_trace_func
を利用しているそうです。