summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-11-06 08:36:10 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-11-06 08:36:10 +0000
commitfd25950ec7234ea48fc98da064cbe43b7701237c (patch)
treee4077744823689c1b1746e99b72e423b14baf24b
parentfb9df41221bfe285227537e04cb822b28188501e (diff)
* 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
-rw-r--r--ChangeLog14
-rw-r--r--compile.c65
-rw-r--r--version.h6
3 files changed, 80 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 935912e530..fb47fef8b7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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>
* vm_insnhelper.c (unknown_keyword_error): delete expected keywords
diff --git a/compile.c b/compile.c
index c7d19d143c..7dba662466 100644
--- a/compile.c
+++ b/compile.c
@@ -581,18 +581,72 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
/* 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 (storage->pos + size > storage->size) {
+ if (storage->pos + size + padding > storage->size) {
unsigned long alloc_size = storage->size * 2;
retry:
- if (alloc_size < size) {
+ if (alloc_size < size + PADDING_SIZE_MAX) {
alloc_size *= 2;
goto retry;
}
@@ -604,8 +658,15 @@ compile_data_alloc(rb_iseq_t *iseq, size_t size)
storage->pos = 0;
storage->size = alloc_size;
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];
storage->pos += size;
return ptr;
diff --git a/version.h b/version.h
index a0e3aae8c5..9e10b4337d 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "2.0.0"
-#define RUBY_RELEASE_DATE "2014-11-05"
-#define RUBY_PATCHLEVEL 596
+#define RUBY_RELEASE_DATE "2014-11-06"
+#define RUBY_PATCHLEVEL 597
#define RUBY_RELEASE_YEAR 2014
#define RUBY_RELEASE_MONTH 11
-#define RUBY_RELEASE_DAY 5
+#define RUBY_RELEASE_DAY 6
#include "ruby/version.h"