diff options
author | ngoto <ngoto@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-11-05 14:49:04 +0000 |
---|---|---|
committer | ngoto <ngoto@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-11-05 14:49:04 +0000 |
commit | da4a5ef141a7d78f8e72567fc46db2de820833f7 (patch) | |
tree | 303a0397fa5c642c0d6a272961dd278a7a7ab236 /compile.c | |
parent | f4c848e158e469e031aa29a503526345e97cab75 (diff) | |
download | ruby-da4a5ef141a7d78f8e72567fc46db2de820833f7.tar.gz |
* compile.c (compile_data_alloc): add padding when strict alignment
is required for memory access. Currently, the padding is enabled
only when the CPU is 32-bit SPARC and the compiler is GCC.
[Bug #9681] [ruby-core:61715]
* compile.c (STRICT_ALIGNMENT): defined if strict alignment is required
* compile.c (ALIGNMENT_SIZE, ALIGNMENT_SIZE_MASK, PADDING_SIZE_MAX):
new macros for alignemnt word size, bit mask, max size of padding.
* compile.c (calc_padding): new function to calculate padding size.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48288 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 67 |
1 files changed, 64 insertions, 3 deletions
@@ -625,18 +625,72 @@ rb_iseq_original_iseq(rb_iseq_t *iseq) /* cold path */ /* definition of data structure for compiler */ /*********************************************/ +/* + * On 32-bit SPARC, GCC by default generates SPARC V7 code that may require + * 8-byte word alignment. On the other hand, Oracle Solaris Studio seems to + * generate SPARCV8PLUS code with unaligned memory accesss instructions. + * That is why the STRICT_ALIGNMENT is defined only with GCC. + */ +#if defined(__sparc) && SIZEOF_VOIDP == 4 && defined(__GNUC__) + #define STRICT_ALIGNMENT +#endif + +#ifdef STRICT_ALIGNMENT + #if defined(HAVE_TRUE_LONG_LONG) && SIZEOF_LONG_LONG > SIZEOF_VALUE + #define ALIGNMENT_SIZE SIZEOF_LONG_LONG + #else + #define ALIGNMENT_SIZE SIZEOF_VALUE + #endif + #define PADDING_SIZE_MAX ((size_t)((ALIGNMENT_SIZE) - 1)) + #define ALIGNMENT_SIZE_MASK PADDING_SIZE_MAX + /* Note: ALIGNMENT_SIZE == (2 ** N) is expected. */ +#else + #define PADDING_SIZE_MAX 0 +#endif /* STRICT_ALIGNMENT */ + +#ifdef STRICT_ALIGNMENT +/* calculate padding size for aligned memory access */ +static size_t +calc_padding(void *ptr, size_t size) +{ + size_t mis; + size_t padding = 0; + + mis = (size_t)ptr & ALIGNMENT_SIZE_MASK; + if (mis > 0) { + padding = ALIGNMENT_SIZE - mis; + } +/* + * On 32-bit sparc or equivalents, when a single VALUE is requested + * and padding == sizeof(VALUE), it is clear that no padding is needed. + */ +#if ALIGNMENT_SIZE > SIZEOF_VALUE + if (size == sizeof(VALUE) && padding == sizeof(VALUE)) { + padding = 0; + } +#endif + + return padding; +} +#endif /* STRICT_ALIGNMENT */ + static void * compile_data_alloc(rb_iseq_t *iseq, size_t size) { void *ptr = 0; struct iseq_compile_data_storage *storage = iseq->compile_data->storage_current; +#ifdef STRICT_ALIGNMENT + size_t padding = calc_padding((void *)&storage->buff[storage->pos], size); +#else + const size_t padding = 0; /* expected to be optimized by compiler */ +#endif /* STRICT_ALIGNMENT */ - if (size >= INT_MAX) rb_memerror(); - if (storage->pos + size > storage->size) { + if (size >= INT_MAX - padding) rb_memerror(); + if (storage->pos + size + padding > storage->size) { unsigned int alloc_size = storage->size; - while (alloc_size < size) { + while (alloc_size < size + PADDING_SIZE_MAX) { if (alloc_size >= INT_MAX / 2) rb_memerror(); alloc_size *= 2; } @@ -646,8 +700,15 @@ compile_data_alloc(rb_iseq_t *iseq, size_t size) storage->next = 0; storage->pos = 0; storage->size = alloc_size; +#ifdef STRICT_ALIGNMENT + padding = calc_padding((void *)&storage->buff[storage->pos], size); +#endif /* STRICT_ALIGNMENT */ } +#ifdef STRICT_ALIGNMENT + storage->pos += (int)padding; +#endif /* STRICT_ALIGNMENT */ + ptr = (void *)&storage->buff[storage->pos]; storage->pos += (int)size; return ptr; |