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

ruby-changes:66350

From: Alan <ko1@a...>
Date: Sat, 29 May 2021 01:34:32 +0900 (JST)
Subject: [ruby-changes:66350] 5ada23ac12 (master): compile.c: Emit send for === calls in when statements

https://git.ruby-lang.org/ruby.git/commit/?id=5ada23ac12

From 5ada23ac1265a1da5d7ef82e1c71f14c40dddc26 Mon Sep 17 00:00:00 2001
From: Alan Wu <XrXr@u...>
Date: Wed, 26 May 2021 11:50:37 -0400
Subject: compile.c: Emit send for === calls in when statements

The checkmatch instruction with VM_CHECKMATCH_TYPE_CASE calls
=== without a call cache. Emit a send instruction to make the call
instead. It includes a call cache.

The call cache improves throughput of using when statements to check the
class of a given object. This is useful for say, JSON serialization.

Use of a regular send instead of checkmatch also avoids taking the VM
lock every time, which is good for multi-ractor workloads.

    Calculating -------------------------------------
                             master        post
         vm_case_classes    11.013M     16.172M i/s -      6.000M times in 0.544795s 0.371009s
             vm_case_lit      2.296       2.263 i/s -       1.000 times in 0.435606s 0.441826s
                 vm_case    74.098M     64.338M i/s -      6.000M times in 0.080974s 0.093257s

    Comparison:
                      vm_case_classes
                    post:  16172114.4 i/s
                  master:  11013316.9 i/s - 1.47x  slower

                          vm_case_lit
                  master:         2.3 i/s
                    post:         2.3 i/s - 1.01x  slower

                              vm_case
                  master:  74097858.6 i/s
                    post:  64338333.9 i/s - 1.15x  slower

The vm_case benchmark is a bit slower post patch, possibily due to the
larger instruction sequence. The benchmark dispatches using
opt_case_dispatch so was not running checkmatch and does not make the
=== call post patch.
---
 benchmark/vm_case_classes.yml | 9 +++++++++
 compile.c                     | 6 +++---
 test/ruby/test_jit.rb         | 2 +-
 3 files changed, 13 insertions(+), 4 deletions(-)
 create mode 100644 benchmark/vm_case_classes.yml

diff --git a/benchmark/vm_case_classes.yml b/benchmark/vm_case_classes.yml
new file mode 100644
index 0000000..cacc4f0
--- /dev/null
+++ b/benchmark/vm_case_classes.yml
@@ -0,0 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/benchmark/vm_case_classes.yml#L1
+benchmark:
+  vm_case_classes: |
+    case :foo
+    when Hash
+      raise
+    when Array
+      raise
+    end
+loop_count: 6000000
diff --git a/compile.c b/compile.c
index e8d5d05..b03e815 100644
--- a/compile.c
+++ b/compile.c
@@ -4572,8 +4572,6 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, https://github.com/ruby/ruby/blob/trunk/compile.c#L4572
             rb_hash_aset(literals, lit, (VALUE)(l1) | 1);
 	}
 
-	ADD_INSN(cond_seq, val, dup); /* dup target */
-
 	if (nd_type(val) == NODE_STR) {
 	    debugp_param("nd_lit", val->nd_lit);
 	    lit = rb_fstring(val->nd_lit);
@@ -4584,7 +4582,9 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, https://github.com/ruby/ruby/blob/trunk/compile.c#L4582
 	    if (!COMPILE(cond_seq, "when cond", val)) return -1;
 	}
 
-	ADD_INSN1(cond_seq, vals, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE));
+        // Emit patern === target
+        ADD_INSN1(cond_seq, vals, topn, INT2FIX(1));
+        ADD_CALL(cond_seq, vals, idEqq, INT2FIX(1));
 	ADD_INSNL(cond_seq, val, branchif, l1);
 	vals = vals->nd_next;
     }
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
index 55922b2..5b79f8c 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -497,7 +497,7 @@ class TestJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_jit.rb#L497
   end
 
   def test_compile_insn_checkmatch_opt_case_dispatch
-    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[checkmatch opt_case_dispatch])
+    assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[opt_case_dispatch])
     begin;
       case 'hello'
       when 'hello'
-- 
cgit v1.1


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

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