aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-01-15 02:35:16 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-01-15 02:35:16 +0000
commitf089a52865bd82a327fe9ef460cecdb812dcb56c (patch)
treefd2ebe09327942662defac756ae752d0a9134e00
parent630ab3b925cd8b6e3c94250bb7c970d80604dcdc (diff)
downloadruby-f089a52865bd82a327fe9ef460cecdb812dcb56c.tar.gz
__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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61827 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--compile.c2
-rw-r--r--configure.ac26
-rw-r--r--include/ruby/defines.h4
-rw-r--r--include/ruby/ruby.h17
-rw-r--r--win32/Makefile.sub1
5 files changed, 39 insertions, 11 deletions
diff --git a/compile.c b/compile.c
index f4ae64bacc..98004b65a0 100644
--- a/compile.c
+++ b/compile.c
@@ -8077,7 +8077,7 @@ struct ibf_dump {
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, ...] */
diff --git a/configure.ac b/configure.ac
index 81efb0bbc1..f7707b761d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1743,6 +1743,30 @@ EOH
])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_params)[ x]}
${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
@%:@define x struct conftest_attribute_check {int i;}
])
])
-
RUBY_FUNC_ATTRIBUTE(__const__, CONSTFUNC)
RUBY_FUNC_ATTRIBUTE(__pure__, PUREFUNC)
RUBY_FUNC_ATTRIBUTE(__noreturn__, NORETURN)
diff --git a/include/ruby/defines.h b/include/ruby/defines.h
index 2c72a7cb8a..da2ba24109 100644
--- a/include/ruby/defines.h
+++ b/include/ruby/defines.h
@@ -376,6 +376,10 @@ void rb_ia64_flushrs(void);
# endif
#endif
+#ifndef RUBY_ALIGNAS
+#define RUBY_ALIGNAS(x) y
+#endif
+
RUBY_SYMBOL_EXPORT_END
#if defined(__cplusplus)
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 6d84a6b06e..fe0ecf4622 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -853,14 +853,10 @@ enum ruby_fl_type {
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 {
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 {
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) ? \
diff --git a/win32/Makefile.sub b/win32/Makefile.sub
index 944573f1bb..a3ac277dd2 100644
--- a/win32/Makefile.sub
+++ b/win32/Makefile.sub
@@ -636,6 +636,7 @@ $(CONFIG_H): $(MKFILES) $(srcdir)/win32/Makefile.sub $(win_srcdir)/Makefile.sub
#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