aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornagachika <nagachika@ruby-lang.org>2020-09-06 11:05:52 +0900
committernagachika <nagachika@ruby-lang.org>2020-09-06 11:05:52 +0900
commit3fef159f81fad6ffb9af5b60f4c8ec867fdb2391 (patch)
tree6b4902e5cc9c7491e02f062a6542aaee0990b112
parente778de2c82478dda930cfc8d795ed4e0e60ea775 (diff)
downloadruby-3fef159f81fad6ffb9af5b60f4c8ec867fdb2391.tar.gz
merge revision(s) 3e02cd518fbe4d91c2aca7fbc3c5aafa387d3cb7: [Backport #17149]
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.def2
-rw-r--r--iseq.c6
-rw-r--r--test/ruby/test_settracefunc.rb14
-rw-r--r--version.h2
4 files changed, 21 insertions, 3 deletions
diff --git a/insns.def b/insns.def
index bd1bffbe02..71b9f44072 100644
--- a/insns.def
+++ b/insns.def
@@ -1508,7 +1508,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;
diff --git a/iseq.c b/iseq.c
index cbf62176bd..9f0f5d04a1 100644
--- a/iseq.c
+++ b/iseq.c
@@ -3094,8 +3094,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 ada7b7596a..e9e22aed8a 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -2279,4 +2279,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
diff --git a/version.h b/version.h
index de0ba11958..eb34c6df10 100644
--- a/version.h
+++ b/version.h
@@ -2,7 +2,7 @@
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
#define RUBY_VERSION_TEENY 1
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 120
+#define RUBY_PATCHLEVEL 121
#define RUBY_RELEASE_YEAR 2020
#define RUBY_RELEASE_MONTH 9