diff options
author | shyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-01-15 02:35:16 +0000 |
---|---|---|
committer | shyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-01-15 02:35:16 +0000 |
commit | f089a52865bd82a327fe9ef460cecdb812dcb56c (patch) | |
tree | fd2ebe09327942662defac756ae752d0a9134e00 /include/ruby | |
parent | 630ab3b925cd8b6e3c94250bb7c970d80604dcdc (diff) | |
download | ruby-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
Diffstat (limited to 'include/ruby')
-rw-r--r-- | include/ruby/defines.h | 4 | ||||
-rw-r--r-- | include/ruby/ruby.h | 17 |
2 files changed, 12 insertions, 9 deletions
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) ? \ |