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

ruby-changes:49710

From: shyouhei <ko1@a...>
Date: Mon, 15 Jan 2018 11:35:20 +0900 (JST)
Subject: [ruby-changes:49710] shyouhei:r61827 (trunk): __attibute__((__aligned__)) for RSTRING_PTR()

shyouhei	2018-01-15 11:35:16 +0900 (Mon, 15 Jan 2018)

  New Revision: 61827

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61827

  Log:
    __attibute__((__aligned__)) for RSTRING_PTR()
    
    For instance array.c:rb_ary_product() uses RSTRING_PTR() as an
    array of int. So to avoid misaligned memory access RSTRING_PTR()
    must at least be sizeof(int)-aligned.  However the type of
    RSTRING_PTR() is char*, which of course can expect alignment as
    much as 1.  This is a problem.
    
    The reality is, there is no misaligned memory access because the
    memory region behind RSTRING_PTR() is allocated using malloc().
    Memory regions returned from malloc() are always aligned
    appropriately.  So let's tell the compiler about this information.
    It seems GCC, clang, and MSVC have such feature.

  Modified files:
    trunk/compile.c
    trunk/configure.ac
    trunk/include/ruby/defines.h
    trunk/include/ruby/ruby.h
    trunk/win32/Makefile.sub
Index: include/ruby/defines.h
===================================================================
--- include/ruby/defines.h	(revision 61826)
+++ include/ruby/defines.h	(revision 61827)
@@ -376,6 +376,10 @@ void rb_ia64_flushrs(void); https://github.com/ruby/ruby/blob/trunk/include/ruby/defines.h#L376
 # endif
 #endif
 
+#ifndef RUBY_ALIGNAS
+#define RUBY_ALIGNAS(x) y
+#endif
+
 RUBY_SYMBOL_EXPORT_END
 
 #if defined(__cplusplus)
Index: include/ruby/ruby.h
===================================================================
--- include/ruby/ruby.h	(revision 61826)
+++ include/ruby/ruby.h	(revision 61827)
@@ -853,14 +853,10 @@ enum ruby_fl_type { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L853
     RUBY_FL_SINGLETON = RUBY_FL_USER0
 };
 
-struct RBasic {
+struct RUBY_ALIGNAS(sizeof(VALUE)) RBasic {
     VALUE flags;
     const VALUE klass;
-}
-#ifdef __GNUC__
-    __attribute__((aligned(sizeof(VALUE))))
-#endif
-;
+};
 
 VALUE rb_obj_hide(VALUE obj);
 VALUE rb_obj_reveal(VALUE obj, VALUE klass); /* do not use this API to change klass information */
@@ -953,18 +949,21 @@ enum ruby_rstring_flags { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L949
 
     RSTRING_ENUM_END
 };
+
+typedef RUBY_ALIGNAS(sizeof(VALUE)) char ruby_aligned_char;
+
 struct RString {
     struct RBasic basic;
     union {
 	struct {
 	    long len;
-	    char *ptr;
+	    ruby_aligned_char *ptr;
 	    union {
 		long capa;
 		VALUE shared;
 	    } aux;
 	} heap;
-	char ary[RSTRING_EMBED_LEN_MAX + 1];
+	char RUBY_ALIGNAS(sizeof(VALUE)) ary[RSTRING_EMBED_LEN_MAX + 1];
     } as;
 };
 #define RSTRING_EMBED_LEN(str) \
@@ -976,7 +975,7 @@ struct RString { https://github.com/ruby/ruby/blob/trunk/include/ruby/ruby.h#L975
      RSTRING(str)->as.heap.len)
 #define RSTRING_PTR(str) \
     (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \
-     RSTRING(str)->as.ary : \
+     (ruby_aligned_char *)RSTRING(str)->as.ary : \
      RSTRING(str)->as.heap.ptr)
 #define RSTRING_END(str) \
     (!(RBASIC(str)->flags & RSTRING_NOEMBED) ? \
Index: win32/Makefile.sub
===================================================================
--- win32/Makefile.sub	(revision 61826)
+++ win32/Makefile.sub	(revision 61827)
@@ -636,6 +636,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/ https://github.com/ruby/ruby/blob/trunk/win32/Makefile.sub#L636
 #define PACKED_STRUCT_UNALIGNED(x) x
 !endif
 #define RUBY_EXTERN extern __declspec(dllimport)
+#define RUBY_ALIGNAS(n) __declspec(align(n))
 #define HAVE_DECL_SYS_NERR 1
 #define HAVE_LIMITS_H 1
 #define HAVE_FCNTL_H 1
Index: compile.c
===================================================================
--- compile.c	(revision 61826)
+++ compile.c	(revision 61827)
@@ -8077,7 +8077,7 @@ struct ibf_dump { https://github.com/ruby/ruby/blob/trunk/compile.c#L8077
 rb_iseq_t * iseq_alloc(void);
 
 struct ibf_load {
-    const char *buff;
+    const RUBY_ALIGNAS(sizeof(VALUE)) char *buff;
     const struct ibf_header *header;
     ID *id_list;     /* [id0, ...] */
     VALUE iseq_list; /* [iseq0, ...] */
Index: configure.ac
===================================================================
--- configure.ac	(revision 61826)
+++ configure.ac	(revision 61827)
@@ -1743,6 +1743,30 @@ EOH https://github.com/ruby/ruby/blob/trunk/configure.ac#L1743
 ])dnl
 ])dnl
 
+AC_CACHE_CHECK([for alignas() syntax], rb_cv_have_alignas, [
+rb_cv_have_alignas=no
+RUBY_WERROR_FLAG([
+for attr in \
+    "_Alignas(x)" \
+    "alignas(x)" \
+    "@<:@@<:@alignas(x)@:>@@:>@" \
+    "__declspec(aligned(x))" \
+    "__attribute__((__aligned__(x)))" \
+;
+do
+    # C11 _Alignas and GCC __attribute__((__aligned__)) behave
+    # slightly differently.  What we want is GCC's.  Check that
+    # here by something C11 does not allow (`struct ALIGNAS ...`)
+    AC_TRY_COMPILE(
+	[@%:@define ALIGNAS(x) $attr
+	struct ALIGNAS(128) conftest_tag { int foo; } foo; ], [],
+        [rb_cv_have_alignas="$attr"; break], [])
+done
+])])
+AS_IF([test "$rb_cv_have_alignas" != no], [
+    AC_DEFINE_UNQUOTED([RUBY_ALIGNAS(x)], $rb_cv_have_alignas)
+])
+
 dnl RUBY_DECL_ATTRIBUTE(attrib, macroname, cachevar, condition, type, code)
 AC_DEFUN([RUBY_DECL_ATTRIBUTE], [dnl
 m4_ifval([$2], dnl
@@ -1773,6 +1797,7 @@ ${rbcv_cond+[@%:@define ]attrib[](attrib https://github.com/ruby/ruby/blob/trunk/configure.ac#L1797
 ${rbcv_cond+[@%:@endif]})
 $6
 @%:@define mesg ("")
+@%:@define n (32768)
     attrib[](attrib_params)[;], [],
     [rbcv="$mac"; break])
 done
@@ -1801,7 +1826,6 @@ AC_DEFUN([RUBY_TYPE_ATTRIBUTE], [dnl https://github.com/ruby/ruby/blob/trunk/configure.ac#L1826
 @%:@define x struct conftest_attribute_check {int i;}
 ])
 ])
-
 RUBY_FUNC_ATTRIBUTE(__const__, CONSTFUNC)
 RUBY_FUNC_ATTRIBUTE(__pure__, PUREFUNC)
 RUBY_FUNC_ATTRIBUTE(__noreturn__, NORETURN)

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

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