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

ruby-changes:61609

From: =E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3 <ko1@a...>
Date: Tue, 9 Jun 2020 09:53:06 +0900 (JST)
Subject: [ruby-changes:61609] 8f3d4090f0 (master): rb_equal_opt: fully static call data

https://git.ruby-lang.org/ruby.git/commit/?id=8f3d4090f0

From 8f3d4090f037ae35fc9ba6380ee284aec837201f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=9C=E9=83=A8=E6=98=8C=E5=B9=B3?=
 <shyouhei@r...>
Date: Fri, 29 May 2020 16:04:53 +0900
Subject: rb_equal_opt: fully static call data

This changeset reduces the generated binary of rb_equal_opt from 129 bytes
to 17 bytes on my machine, according to nm(1).

diff --git a/vm.c b/vm.c
index f2c45f3..7a3ba4a 100644
--- a/vm.c
+++ b/vm.c
@@ -386,7 +386,13 @@ rb_serial_t ruby_vm_global_method_state = 1; https://github.com/ruby/ruby/blob/trunk/vm.c#L386
 rb_serial_t ruby_vm_global_constant_state = 1;
 rb_serial_t ruby_vm_class_serial = 1;
 
-static const struct rb_callcache *vm_empty_cc;
+static const struct rb_callcache vm_empty_cc = {
+    .flags = (T_IMEMO | (imemo_callcache << FL_USHIFT) | VM_CALLCACHE_UNMARKABLE),
+    .klass = Qfalse,
+    .cme_ = NULL,
+    .call_ = vm_call_general,
+    .aux_.v = 0,
+};
 
 static void thread_free(void *ptr);
 
@@ -3424,10 +3430,6 @@ Init_vm_objects(void) https://github.com/ruby/ruby/blob/trunk/vm.c#L3430
     vm->frozen_strings = st_init_table_with_size(&rb_fstring_hash_type, 10000);
 
     rb_objspace_gc_enable(vm->objspace);
-
-    vm_empty_cc = vm_cc_new(0, NULL, vm_call_general);
-    FL_SET_RAW((VALUE)vm_empty_cc, VM_CALLCACHE_UNMARKABLE);
-    rb_gc_register_mark_object((VALUE)vm_empty_cc);
 }
 
 /* top self */
@@ -3799,7 +3801,7 @@ vm_collect_usage_register(int reg, int isset) https://github.com/ruby/ruby/blob/trunk/vm.c#L3801
 MJIT_FUNC_EXPORTED const struct rb_callcache *
 rb_vm_empty_cc(void)
 {
-    return vm_empty_cc;
+    return &vm_empty_cc;
 }
 
 #endif /* #ifndef MJIT_HEADER */
diff --git a/vm_callinfo.h b/vm_callinfo.h
index 14027fc..7c73194 100644
--- a/vm_callinfo.h
+++ b/vm_callinfo.h
@@ -180,15 +180,20 @@ vm_ci_dump(const struct rb_callinfo *ci) https://github.com/ruby/ruby/blob/trunk/vm_callinfo.h#L180
 #define vm_ci_new(mid, flag, argc, kwarg) vm_ci_new_(mid, flag, argc, kwarg, __FILE__, __LINE__)
 #define vm_ci_new_runtime(mid, flag, argc, kwarg) vm_ci_new_runtime_(mid, flag, argc, kwarg, __FILE__, __LINE__)
 
+#/* This is passed to STATIC_ASSERT.  Cannot be an inline function. */
+#define VM_CI_EMBEDDABLE_P(mid, flag, argc, kwarg) \
+    (((mid ) & ~CI_EMBED_ID_MASK)   ? false :      \
+     ((flag) & ~CI_EMBED_FLAG_MASK) ? false :      \
+     ((argc) & ~CI_EMBED_ARGC_MASK) ? false :      \
+      (kwarg)                       ? false : true)
+
 static inline const struct rb_callinfo *
 vm_ci_new_(ID mid, unsigned int flag, unsigned int argc, const struct rb_callinfo_kwarg *kwarg, const char *file, int line)
 {
 #if USE_EMBED_CI
-    if ((mid & ~CI_EMBED_ID_MASK) == 0 &&
-        (argc & ~CI_EMBED_ARGC_MASK) == 0 &&
-        kwarg == NULL) {
+    if (VM_CI_EMBEDDABLE_P(mid, flag, argc, kwarg)) {
         VALUE embed_ci =
-          1L                                  |
+          RUBY_FIXNUM_FLAG                    |
           ((VALUE)argc << CI_EMBED_ARGC_SHFT) |
           ((VALUE)flag << CI_EMBED_FLAG_SHFT) |
           ((VALUE)mid  << CI_EMBED_ID_SHFT);
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 25b5db8..5cb7f16 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -37,7 +37,7 @@ extern VALUE rb_make_no_method_exception(VALUE exc, VALUE format, VALUE obj, https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L37
                                          int argc, const VALUE *argv, int priv);
 
 #ifndef MJIT_HEADER
-static const struct rb_callcache *vm_empty_cc;
+static const struct rb_callcache vm_empty_cc;
 #endif
 
 /* control stack frame */
@@ -1571,8 +1571,8 @@ vm_search_cc(VALUE klass, const struct rb_callinfo *ci) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1571
 
     if (cme == NULL) {
         // undef or not found: can't cache the information
-        VM_ASSERT(vm_cc_cme(vm_empty_cc) == NULL);
-        return vm_empty_cc;
+        VM_ASSERT(vm_cc_cme(&vm_empty_cc) == NULL);
+        return &vm_empty_cc;
     }
     else {
         const struct rb_callcache *cc = vm_cc_new(klass, cme, vm_call_general);
@@ -1636,7 +1636,7 @@ vm_search_method_fastpath(VALUE cd_owner, struct rb_call_data *cd, VALUE klass) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1636
 #ifdef MJIT_HEADER
             rb_vm_empty_cc();
 #else
-            vm_empty_cc;
+            &vm_empty_cc;
 #endif
         RB_DEBUG_COUNTER_INC(mc_inline_miss_invalidated);
     }
@@ -1776,20 +1776,26 @@ opt_equality(const rb_iseq_t *cd_owner, VALUE recv, VALUE obj, CALL_DATA cd) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1776
 
 #undef EQ_UNREDEFINED_P
 
+#ifndef MJIT_HEADER
+
 #define vm_ci_new_id(mid) vm_ci_new_runtime(mid, 0, 0, NULL)
+#define VM_CI_NEW_ID(mid) \
+    ((const struct rb_callinfo *)\
+     ((((VALUE)(mid)) << CI_EMBED_ID_SHFT) | RUBY_FIXNUM_FLAG))
 
 VALUE
 rb_equal_opt(VALUE obj1, VALUE obj2)
 {
-    static const struct rb_callinfo *ci = NULL;
-    if (ci == NULL) {
-        ci = vm_ci_new_id(idEq);
-        rb_gc_register_mark_object((VALUE)ci);
-    }
+    STATIC_ASSERT(idEq_is_embeddable, VM_CI_EMBEDDABLE_P(idEq, 0, 1, 0));
+
+    static struct rb_call_data cd = {
+        .ci = VM_CI_NEW_ID(idEq),
+        .cc = &vm_empty_cc,
+    };
 
-    struct rb_call_data cd = { .ci = ci, .cc = vm_cc_empty() };
     return opt_equality(NULL, obj1, obj2, &cd);
 }
+#endif
 
 VALUE
 rb_eql_opt(VALUE obj1, VALUE obj2)
-- 
cgit v0.10.2


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

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