summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNobuyoshi Nakada <nobu@ruby-lang.org>2021-10-26 23:39:43 +0900
committerNobuyoshi Nakada <nobu@ruby-lang.org>2021-10-27 02:05:06 +0900
commite3a783b14191fef175c9a59996afdc744c8edc4c (patch)
tree33e1fa96535433dc67e7b8fac63c738e32e88b0c
parentafdca0e780760e008e26f4c9fc7262a0a4fe56bb (diff)
downloadruby-e3a783b14191fef175c9a59996afdc744c8edc4c.tar.gz
Align `RFloat` at VALUE boundary
-rw-r--r--gc.c11
-rw-r--r--internal/numeric.h27
-rw-r--r--numeric.c8
3 files changed, 27 insertions, 19 deletions
diff --git a/gc.c b/gc.c
index 0c739ba709..bd3915fb47 100644
--- a/gc.c
+++ b/gc.c
@@ -565,10 +565,6 @@ struct RMoved {
#define RMOVED(obj) ((struct RMoved *)(obj))
-#if (SIZEOF_DOUBLE > SIZEOF_VALUE) && (defined(_MSC_VER) || defined(__CYGWIN__))
-#pragma pack(push, 4) /* == SIZEOF_VALUE: magic for reducing sizeof(RVALUE): 24 -> 20 */
-#endif
-
typedef struct RVALUE {
union {
struct {
@@ -618,9 +614,12 @@ typedef struct RVALUE {
#endif
} RVALUE;
-#if (SIZEOF_DOUBLE > SIZEOF_VALUE) && (defined(_MSC_VER) || defined(__CYGWIN__))
-#pragma pack(pop)
+#if GC_DEBUG
+STATIC_ASSERT(sizeof_rvalue, offsetof(RVALUE, file) == SIZEOF_VALUE * 5);
+#else
+STATIC_ASSERT(sizeof_rvalue, sizeof(RVALUE) == SIZEOF_VALUE * 5);
#endif
+STATIC_ASSERT(alignof_rvalue, RUBY_ALIGNOF(RVALUE) == SIZEOF_VALUE);
typedef uintptr_t bits_t;
enum {
diff --git a/internal/numeric.h b/internal/numeric.h
index 3d88845a16..440bef1671 100644
--- a/internal/numeric.h
+++ b/internal/numeric.h
@@ -35,9 +35,18 @@ enum ruby_num_rounding_mode {
RUBY_NUM_ROUND_DEFAULT = ROUND_DEFAULT,
};
+#if SIZEOF_DOUBLE < SIZEOF_VALUE
+typedef double rb_float_value_type;
+#else
+typedef struct {
+ VALUE values[(SIZEOF_DOUBLE + SIZEOF_VALUE - 1) / SIZEOF_VALUE];
+ /* roomof() needs internal.h, and the order of some macros may matter */
+} rb_float_value_type;
+#endif
+
struct RFloat {
struct RBasic basic;
- double float_value;
+ rb_float_value_type float_value;
};
#define RFLOAT(obj) ((struct RFloat *)(obj))
@@ -206,21 +215,17 @@ rb_float_flonum_value(VALUE v)
return 0.0;
}
-#if SIZEOF_VALUE >= SIZEOF_DOUBLE || defined(UNALIGNED_WORD_ACCESS)
-# define UNALIGNED_DOUBLE_ACCESS 1
-#else
-# define UNALIGNED_DOUBLE_ACCESS 0
-#endif
-
static inline double
rb_float_noflonum_value(VALUE v)
{
-#if UNALIGNED_DOUBLE_ACCESS
+#if SIZEOF_DOUBLE < SIZEOF_VALUE
return RFLOAT(v)->float_value;
#else
- double d;
- memcpy(&d, &RFLOAT(v)->float_value, sizeof(double));
- return d;
+ union {
+ rb_float_value_type v;
+ double d;
+ } u = {RFLOAT(v)->float_value};
+ return u.d;
#endif
}
diff --git a/numeric.c b/numeric.c
index e12bcce5b8..3ee98343a7 100644
--- a/numeric.c
+++ b/numeric.c
@@ -951,10 +951,14 @@ rb_float_new_in_heap(double d)
{
NEWOBJ_OF(flt, struct RFloat, rb_cFloat, T_FLOAT | (RGENGC_WB_PROTECTED_FLOAT ? FL_WB_PROTECTED : 0));
-#if UNALIGNED_DOUBLE_ACCESS
+#if SIZEOF_DOUBLE < SIZEOF_VALUE
flt->float_value = d;
#else
- memcpy(&flt->float_value, &d, sizeof(double));
+ union {
+ double d;
+ rb_float_value_type v;
+ } u = {d};
+ flt->float_value = u.v;
#endif
OBJ_FREEZE((VALUE)flt);
return (VALUE)flt;