* 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/branches/ruby_2_0_0@48296 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
usa 2014-11-06 08:36:10 +00:00
parent fb9df41221
commit fd25950ec7
3 changed files with 80 additions and 5 deletions

View file

@ -1,3 +1,17 @@
Thu Nov 6 17:31:51 2014 Naohisa Goto <ngotogenome@gmail.com>
* 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
Wed Nov 5 18:26:49 2014 NAKAMURA Usaku <usa@ruby-lang.org> Wed Nov 5 18:26:49 2014 NAKAMURA Usaku <usa@ruby-lang.org>
* vm_insnhelper.c (unknown_keyword_error): delete expected keywords * vm_insnhelper.c (unknown_keyword_error): delete expected keywords

View file

@ -581,18 +581,72 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
/* definition of data structure for compiler */ /* 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 * static void *
compile_data_alloc(rb_iseq_t *iseq, size_t size) compile_data_alloc(rb_iseq_t *iseq, size_t size)
{ {
void *ptr = 0; void *ptr = 0;
struct iseq_compile_data_storage *storage = struct iseq_compile_data_storage *storage =
iseq->compile_data->storage_current; 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 (storage->pos + size > storage->size) { if (storage->pos + size + padding > storage->size) {
unsigned long alloc_size = storage->size * 2; unsigned long alloc_size = storage->size * 2;
retry: retry:
if (alloc_size < size) { if (alloc_size < size + PADDING_SIZE_MAX) {
alloc_size *= 2; alloc_size *= 2;
goto retry; goto retry;
} }
@ -604,8 +658,15 @@ compile_data_alloc(rb_iseq_t *iseq, size_t size)
storage->pos = 0; storage->pos = 0;
storage->size = alloc_size; storage->size = alloc_size;
storage->buff = (char *)(&storage->buff + 1); storage->buff = (char *)(&storage->buff + 1);
#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]; ptr = (void *)&storage->buff[storage->pos];
storage->pos += size; storage->pos += size;
return ptr; return ptr;

View file

@ -1,10 +1,10 @@
#define RUBY_VERSION "2.0.0" #define RUBY_VERSION "2.0.0"
#define RUBY_RELEASE_DATE "2014-11-05" #define RUBY_RELEASE_DATE "2014-11-06"
#define RUBY_PATCHLEVEL 596 #define RUBY_PATCHLEVEL 597
#define RUBY_RELEASE_YEAR 2014 #define RUBY_RELEASE_YEAR 2014
#define RUBY_RELEASE_MONTH 11 #define RUBY_RELEASE_MONTH 11
#define RUBY_RELEASE_DAY 5 #define RUBY_RELEASE_DAY 6
#include "ruby/version.h" #include "ruby/version.h"