diff options
author | Takashi Kokubun <takashikkbn@gmail.com> | 2020-06-23 23:41:57 -0700 |
---|---|---|
committer | Takashi Kokubun <takashikkbn@gmail.com> | 2020-06-23 23:42:38 -0700 |
commit | 3e02cd518fbe4d91c2aca7fbc3c5aafa387d3cb7 (patch) | |
tree | eee79b71a547956ea23d19cc5799fee46938d12c | |
parent | fbb32b1f483925987d225b4dc08efd197775bcae (diff) |
Trace :return of builtin methods
using opt_invokebuiltin_delegate_leave insn.
Since Ruby 2.7, :return of methods using builtin have not been traced properly.
-rw-r--r-- | insns.def | 2 | ||||
-rw-r--r-- | iseq.c | 6 | ||||
-rw-r--r-- | test/ruby/test_settracefunc.rb | 14 |
3 files changed, 20 insertions, 2 deletions
@@ -1509,7 +1509,7 @@ opt_invokebuiltin_delegate_leave val = vm_invoke_builtin_delegate(ec, reg_cfp, bf, (unsigned int)index); /* leave fastpath */ - /* TracePoint/return should fallback this insn to opt_invokebuiltin_delegate */ + /* TracePoint/return fallbacks this insn to opt_invokebuiltin_delegate */ if (vm_pop_frame(ec, GET_CFP(), GET_EP())) { #if OPT_CALL_THREADED_CODE rb_ec_thread_ptr(ec)->retval = val; @@ -3125,8 +3125,12 @@ rb_vm_encoded_insn_data_table_init(void) encoded_insn_data = st_init_numtable_with_size(VM_INSTRUCTION_SIZE / 2); for (insn = 0; insn < VM_INSTRUCTION_SIZE/2; insn++) { + int traced_insn = insn; + if (traced_insn == BIN(opt_invokebuiltin_delegate_leave)) { + traced_insn = BIN(opt_invokebuiltin_delegate); // to dispatch :return from leave + } st_data_t key1 = (st_data_t)INSN_CODE(insn); - st_data_t key2 = (st_data_t)INSN_CODE(insn + VM_INSTRUCTION_SIZE/2); + st_data_t key2 = (st_data_t)INSN_CODE(traced_insn + VM_INSTRUCTION_SIZE/2); insn_data[insn].insn = (int)insn; insn_data[insn].insn_len = insn_len(insn); diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb index 300033ae7e..80490204ca 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -2292,4 +2292,18 @@ class TestSetTraceFunc < Test::Unit::TestCase def test_stat_exists assert_instance_of Hash, TracePoint.stat end + + def test_tracepoint_opt_invokebuiltin_delegate_leave + code = 'puts RubyVM::InstructionSequence.of("\x00".method(:unpack)).disasm' + out, _err, _status = EnvUtil.invoke_ruby(['-e', code], '', true) + assert_match /^0000 opt_invokebuiltin_delegate_leave /, out + + events = [] + TracePoint.new(:return) do |tp| + events << [tp.event, tp.method_id] + end.enable do + "\x00".unpack("c") + end + assert_equal [[:return, :unpack]], events + end end |