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

ruby-changes:69504

From: Yusuke <ko1@a...>
Date: Fri, 29 Oct 2021 10:57:57 +0900 (JST)
Subject: [ruby-changes:69504] c1228f833c (master): vm_core.h: Avoid unaligned access to ic_serial on 32-bit machine

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

From c1228f833c5925c01b2aed1544d9c7fc2421e79b Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Fri, 29 Oct 2021 01:58:15 +0900
Subject: vm_core.h: Avoid unaligned access to ic_serial on 32-bit machine

This caused Bus error on 32 bit Solaris
---
 .../ruby_vm/views/_mjit_compile_getinlinecache.erb |  4 +--
 vm_core.h                                          | 41 +++++++++++++++++++---
 vm_insnhelper.c                                    |  4 +--
 yjit_codegen.c                                     |  2 +-
 4 files changed, 42 insertions(+), 9 deletions(-)

diff --git a/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb b/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb
index 1acfdb7f0b8..d4eb4977a47 100644
--- a/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb
+++ b/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb
@@ -13,9 +13,9 @@ https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/views/_mjit_compile_getinlinecache.erb#L13
 
 % # compiler: Capture IC values, locking getinlinecache
     struct iseq_inline_constant_cache_entry *ice = ic->entry;
-    if (ice != NULL && ice->ic_serial && !status->compile_info->disable_const_cache) {
+    if (ice != NULL && GET_IC_SERIAL(ice) && !status->compile_info->disable_const_cache) {
 %       # JIT: Inline everything in IC, and cancel the slow path
-        fprintf(f, "    if (vm_inlined_ic_hit_p(0x%"PRIxVALUE", 0x%"PRIxVALUE", (const rb_cref_t *)0x%"PRIxVALUE", %"PRI_SERIALT_PREFIX"u, reg_cfp->ep)) {", ice->flags, ice->value, (VALUE)ice->ic_cref, ice->ic_serial);
+        fprintf(f, "    if (vm_inlined_ic_hit_p(0x%"PRIxVALUE", 0x%"PRIxVALUE", (const rb_cref_t *)0x%"PRIxVALUE", %"PRI_SERIALT_PREFIX"u, reg_cfp->ep)) {", ice->flags, ice->value, (VALUE)ice->ic_cref, GET_IC_SERIAL(ice));
         fprintf(f, "        stack[%d] = 0x%"PRIxVALUE";\n", b->stack_size, ice->value);
         fprintf(f, "        goto label_%d;\n", pos + insn_len(insn) + (int)dst);
         fprintf(f, "    }");
diff --git a/vm_core.h b/vm_core.h
index a696a1af39e..96437ff5599 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -219,21 +219,54 @@ struct rb_control_frame_struct; https://github.com/ruby/ruby/blob/trunk/vm_core.h#L219
 /* iseq data type */
 typedef struct rb_compile_option_struct rb_compile_option_t;
 
+union ic_serial_entry {
+    rb_serial_t raw;
+    VALUE data[2];
+};
+
 // imemo_constcache
 struct iseq_inline_constant_cache_entry {
     VALUE flags;
 
     VALUE value;              // v0
-    rb_serial_t ic_serial;    // v1
-#if (SIZEOF_SERIAL_T < 2 * SIZEOF_VOIDP)
-    VALUE ic_padding;         // v2
-#endif
+    union ic_serial_entry ic_serial; // v1, v2
     const rb_cref_t *ic_cref; // v3
 };
 STATIC_ASSERT(sizeof_iseq_inline_constant_cache_entry,
               (offsetof(struct iseq_inline_constant_cache_entry, ic_cref) +
 	       sizeof(const rb_cref_t *)) <= sizeof(struct RObject));
 
+#if SIZEOF_SERIAL_T <= SIZEOF_VALUE
+
+#define GET_IC_SERIAL(ice) (ice)->ic_serial.raw
+#define SET_IC_SERIAL(ice, v) (ice)->ic_serial.raw = (v)
+
+#else
+
+static inline rb_serial_t
+get_ic_serial(const struct iseq_inline_constant_cache_entry *ice)
+{
+    union ic_serial_entry tmp;
+    tmp.data[0] = ice->ic_serial.data[0];
+    tmp.data[1] = ice->ic_serial.data[1];
+    return tmp.raw;
+}
+
+#define GET_IC_SERIAL(ice) get_ic_serial(ice)
+
+static inline void
+set_ic_serial(struct iseq_inline_constant_cache_entry *ice, rb_serial_t v)
+{
+    union ic_serial_entry tmp;
+    tmp.raw = v;
+    ice->ic_serial.data[0] = tmp.data[0];
+    ice->ic_serial.data[1] = tmp.data[1];
+}
+
+#define SET_IC_SERIAL(ice, v) set_ic_serial((ice), (v))
+
+#endif
+
 struct iseq_inline_constant_cache {
     struct iseq_inline_constant_cache_entry *entry;
     // For YJIT: the index to the opt_getinlinecache instruction in the same iseq.
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 048ed63aed9..86bdfd2fb6f 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -4781,7 +4781,7 @@ static bool https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L4781
 vm_ic_hit_p(const struct iseq_inline_constant_cache_entry *ice, const VALUE *reg_ep)
 {
     VM_ASSERT(IMEMO_TYPE_P(ice, imemo_constcache));
-    return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, ice->ic_serial, reg_ep);
+    return vm_inlined_ic_hit_p(ice->flags, ice->value, ice->ic_cref, GET_IC_SERIAL(ice), reg_ep);
 }
 
 // YJIT needs this function to never allocate and never raise
@@ -4798,7 +4798,7 @@ vm_ic_update(const rb_iseq_t *iseq, IC ic, VALUE val, const VALUE *reg_ep) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L4798
     struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)rb_imemo_new(imemo_constcache, 0, 0, 0, 0);
     RB_OBJ_WRITE(ice, &ice->value, val);
     ice->ic_cref = vm_get_const_key_cref(reg_ep);
-    ice->ic_serial = GET_GLOBAL_CONSTANT_STATE() - ruby_vm_const_missing_count;
+    SET_IC_SERIAL(ice, GET_GLOBAL_CONSTANT_STATE() - ruby_vm_const_missing_count);
     if (rb_ractor_shareable_p(val)) ice->flags |= IMEMO_CONST_CACHE_SHAREABLE;
     ruby_vm_const_missing_count = 0;
     RB_OBJ_WRITE(iseq, &ic->entry, ice);
diff --git a/yjit_codegen.c b/yjit_codegen.c
index b0d799c0132..d438970cf23 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -4364,7 +4364,7 @@ gen_opt_getinlinecache(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L4364
     // See vm_ic_hit_p(). The same conditions are checked in yjit_constant_ic_update().
     struct iseq_inline_constant_cache_entry *ice = ic->entry;
     if (!ice || // cache not filled
-        ice->ic_serial != ruby_vm_global_constant_state /* cache out of date */) {
+        GET_IC_SERIAL(ice) != ruby_vm_global_constant_state /* cache out of date */) {
         // In these cases, leave a block that unconditionally side exits
         // for the interpreter to invalidate.
         return YJIT_CANT_COMPILE;
-- 
cgit v1.2.1


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

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