diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2021-10-26 23:39:43 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2021-10-27 02:05:06 +0900 |
commit | e3a783b14191fef175c9a59996afdc744c8edc4c (patch) | |
tree | 33e1fa96535433dc67e7b8fac63c738e32e88b0c | |
parent | afdca0e780760e008e26f4c9fc7262a0a4fe56bb (diff) | |
download | ruby-e3a783b14191fef175c9a59996afdc744c8edc4c.tar.gz |
Align `RFloat` at VALUE boundary
-rw-r--r-- | gc.c | 11 | ||||
-rw-r--r-- | internal/numeric.h | 27 | ||||
-rw-r--r-- | numeric.c | 8 |
3 files changed, 27 insertions, 19 deletions
@@ -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 } @@ -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; |