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/