[前][次][番号順一覧][スレッド一覧]

ruby-changes:62179

From: Takashi <ko1@a...>
Date: Fri, 10 Jul 2020 16:46:24 +0900 (JST)
Subject: [ruby-changes:62179] 7fa3c71bec (master): Make sure vm_call_cfunc uses inlined cc

https://git.ruby-lang.org/ruby.git/commit/?id=7fa3c71bec

From 7fa3c71becd6d9b11d1574b3537a3b2993a7046c Mon Sep 17 00:00:00 2001
From: Takashi Kokubun <takashikkbn@g...>
Date: Fri, 10 Jul 2020 00:42:43 -0700
Subject: Make sure vm_call_cfunc uses inlined cc

which is checked by the first guard. When JIT-inlined cc and operand
cd->cc are different, the JIT-ed code might wrongly dispatch cd->cc even
while class check is done with another cc inlined by JIT.

This fixes SEGV on railsbench.

diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
index 08093a5..c1f2f7a 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -793,6 +793,22 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L793
     end;
   end
 
+  def test_inlined_c_method
+    assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 2, recompile_count: 1, min_calls: 2)
+    begin;
+      def test(obj, recursive: nil)
+        if recursive
+          test(recursive)
+        end
+        obj.to_s
+      end
+
+      print(test('a')) # set #to_s cc to String#to_s (expecting C method)
+      print(test('a')) # JIT with #to_s cc: String#to_s
+      print(test('a', recursive: :foo)) # update #to_s cd->cc to Symbol#to_s, then go through inlined #to_s cc with Symbol#to_s
+    end;
+  end
+
   def test_inlined_exivar
     assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 3, recompile_count: 1, min_calls: 2)
     begin;
diff --git a/tool/ruby_vm/views/_mjit_compile_send.erb b/tool/ruby_vm/views/_mjit_compile_send.erb
index 6b271d4..2dff016 100644
--- a/tool/ruby_vm/views/_mjit_compile_send.erb
+++ b/tool/ruby_vm/views/_mjit_compile_send.erb
@@ -75,8 +75,8 @@ https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/views/_mjit_compile_send.erb#L75
 
             if (vm_cc_cme(captured_cc)->def->type == VM_METHOD_TYPE_CFUNC) {
 %               # TODO: optimize this more
-                fprintf(f, "        CALL_DATA cd = (CALL_DATA)0x%"PRIxVALUE";\n", operands[0]);
-                fprintf(f, "        val = vm_call_cfunc_with_frame(ec, reg_cfp, &calling, cd);\n");
+                fprintf(f, "        struct rb_call_data cc_cd = { .ci = (CALL_INFO)0x%"PRIxVALUE", .cc = cc };\n", (VALUE)ci); // creating local cd here because operand's cd->cc may not be the same as inlined cc.
+                fprintf(f, "        val = vm_call_cfunc_with_frame(ec, reg_cfp, &calling, &cc_cd);\n");
             }
             else { // VM_METHOD_TYPE_ISEQ
 %               # fastpath_applied_iseq_p checks rb_simple_iseq_p, which ensures has_opt == FALSE
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]