From 59e1fe29d64c41103008605f1a80da7365b5a084 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 27 Feb 2026 10:30:01 +0900 Subject: [PATCH] mrbconf.h: rename MRB_WORDBOX_NO_FLOAT_TRUNCATE to MRB_WORDBOX_NO_INLINE_FLOAT The old name referred to "truncation" of float precision, which no longer happens with rotation encoding. The new name describes the actual behavior: disabling inline float encoding in word boxing. The old name is kept as an obsolete alias for backward compatibility. Co-authored-by: Claude --- doc/internal/boxing.md | 4 ++-- doc/mruby3.1.md | 4 ++-- include/mrbconf.h | 10 ++++++++-- include/mruby/boxing_word.h | 20 ++++++++++---------- mrbgems/mruby-test/driver.c | 2 +- src/etc.c | 8 ++++---- src/gc.c | 4 ++-- 7 files changed, 29 insertions(+), 23 deletions(-) diff --git a/doc/internal/boxing.md b/doc/internal/boxing.md index 1e4956d62..0a7b3ca0d 100644 --- a/doc/internal/boxing.md +++ b/doc/internal/boxing.md @@ -26,8 +26,8 @@ The Word boxing packing bit patterns are like following: | undef | `00000000 00000000 00000000 00010100` | | symbol | `xxxxxxxx xxxxxxxx xxxxxxxx xxxxxx10` | -On 64-bit platforms (unless `MRB_WORDBOX_NO_FLOAT_TRUNCATE`), float values are also packed in the `mrb_value`. In that case, we drop least significant 2 bits from mantissa. -If you need full precision for floating-point numbers, define `MRB_WORDBOX_NO_FLOAT_TRUNCATE`. +On 64-bit platforms (unless `MRB_WORDBOX_NO_INLINE_FLOAT`), float values are also packed in the `mrb_value` using rotation encoding (lossless for exponents in range). +To disable inline float encoding and heap-allocate all floats, define `MRB_WORDBOX_NO_INLINE_FLOAT`. ## NaN Boxing diff --git a/doc/mruby3.1.md b/doc/mruby3.1.md index 7d52e2535..953536198 100644 --- a/doc/mruby3.1.md +++ b/doc/mruby3.1.md @@ -20,7 +20,7 @@ Keyword arguments are basically separated from ordinal arguments. Some configuration macros are available: -- `MRB_WORDBOX_NO_FLOAT_TRUNCATE`: by default, float values are packed in the word if possible, but define this macro to allocate float values in the heap. +- `MRB_WORDBOX_NO_INLINE_FLOAT` (formerly `MRB_WORDBOX_NO_FLOAT_TRUNCATE`): by default, float values are packed in the word if possible, but define this macro to allocate float values in the heap. - `MRB_USE_RO_DATA_P_ETEXT`: define this macro if `_etext` is available on your platform. - `MRB_NO_DEFAULT_RO_DATA_P`: define this macro to avoid using predefined `mrb_ro_data_p()` function @@ -156,7 +156,7 @@ Now takes 2 operands and pushes multiple entries to an array. ### Word Boxing `MRB_WORD_BOXING` now packs floating-point numbers in the word, if the size of `mrb_float` is equal or smaller than the size of `mrb_int` by default. -If the size of `mrb_float` and `mrb_int` are same, the last 2 bits in the `mrb_float` are trimmed and used as flags. If you need full precision, you need to define `MRB_WORDBOX_NO_FLOAT_TRUNCATE` as described above. +If the size of `mrb_float` and `mrb_int` are same, the last 2 bits in the `mrb_float` are trimmed and used as flags. If you need full precision, you need to define `MRB_WORDBOX_NO_INLINE_FLOAT` (formerly `MRB_WORDBOX_NO_FLOAT_TRUNCATE`) as described above. ### NaN Boxing diff --git a/include/mrbconf.h b/include/mrbconf.h index b10f55c8f..ace38d73b 100644 --- a/include/mrbconf.h +++ b/include/mrbconf.h @@ -64,8 +64,14 @@ # define MRB_WORD_BOXING #endif -/* if defined mruby allocates Float objects in the heap to keep full precision if needed */ -//#define MRB_WORDBOX_NO_FLOAT_TRUNCATE +/* if defined mruby does not inline float values in word boxing; + all floats are heap-allocated as RFloat objects */ +//#define MRB_WORDBOX_NO_INLINE_FLOAT + +/* obsolete configuration */ +#if defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE) +# define MRB_WORDBOX_NO_INLINE_FLOAT +#endif /* add -DMRB_INT32 to use 32-bit integer for mrb_int; conflict with MRB_INT64; Default for 32-bit CPU mode. */ diff --git a/include/mruby/boxing_word.h b/include/mruby/boxing_word.h index 4fbbd3b31..ffdd177c8 100644 --- a/include/mruby/boxing_word.h +++ b/include/mruby/boxing_word.h @@ -7,14 +7,14 @@ #ifndef MRUBY_BOXING_WORD_H #define MRUBY_BOXING_WORD_H -#if defined(MRB_32BIT) && !defined(MRB_USE_FLOAT32) && !defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE) -# define MRB_WORDBOX_NO_FLOAT_TRUNCATE +#if defined(MRB_32BIT) && !defined(MRB_USE_FLOAT32) && !defined(MRB_WORDBOX_NO_INLINE_FLOAT) +# define MRB_WORDBOX_NO_INLINE_FLOAT #endif #ifndef MRB_NO_FLOAT struct RFloat { MRB_OBJECT_HEADER; -#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE +#ifdef MRB_WORDBOX_NO_INLINE_FLOAT /* avoid 8-byte alignment on 32-bit; use memcpy-based accessors */ char f[sizeof(mrb_float)]; #else @@ -27,7 +27,7 @@ struct RFloat { static inline mrb_float mrb_rfloat_value(const struct RFloat *p) { -#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE +#ifdef MRB_WORDBOX_NO_INLINE_FLOAT mrb_float f; memcpy(&f, p->f, sizeof(mrb_float)); return f; @@ -39,7 +39,7 @@ mrb_rfloat_value(const struct RFloat *p) static inline void mrb_rfloat_set(struct RFloat *p, mrb_float f) { -#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE +#ifdef MRB_WORDBOX_NO_INLINE_FLOAT memcpy(p->f, &f, sizeof(mrb_float)); #else p->f = f; @@ -79,7 +79,7 @@ enum mrb_special_consts { #define WORDBOX_FIXNUM_FLAG (1 << (WORDBOX_FIXNUM_BIT_POS - 1)) #define WORDBOX_FIXNUM_MASK ((1 << WORDBOX_FIXNUM_BIT_POS) - 1) -#if defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE) || defined(MRB_NO_FLOAT) +#if defined(MRB_WORDBOX_NO_INLINE_FLOAT) || defined(MRB_NO_FLOAT) /* floats are allocated in heaps */ #define WORDBOX_IMMEDIATE_MASK 0x03 #define WORDBOX_SYMBOL_BIT_POS 2 @@ -127,7 +127,7 @@ enum mrb_special_consts { * float : ...FFFF FF10 (float32 shifted left by 2) * (other values same as above) * - * word boxing without inline float (MRB_WORDBOX_NO_FLOAT_TRUNCATE): + * word boxing without inline float (MRB_WORDBOX_NO_INLINE_FLOAT): * nil : ...0000 0000 (all bits are 0) * false : ...0000 0100 (mrb_fixnum(v) != 0) * true : ...0000 1100 @@ -145,7 +145,7 @@ union mrb_value_ { struct RBasic *bp; #ifndef MRB_NO_FLOAT struct RFloat *fp; -#if !defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE) && defined(MRB_USE_FLOAT32) +#if !defined(MRB_WORDBOX_NO_INLINE_FLOAT) && defined(MRB_USE_FLOAT32) mrb_float f; #endif #endif @@ -180,7 +180,7 @@ MRB_API mrb_value mrb_boxing_int_value(struct mrb_state*, mrb_int); #define mrb_ptr(o) mrb_val_union(o).p #define mrb_cptr(o) mrb_val_union(o).vp->p #ifndef MRB_NO_FLOAT -#ifndef MRB_WORDBOX_NO_FLOAT_TRUNCATE +#ifndef MRB_WORDBOX_NO_INLINE_FLOAT MRB_API mrb_float mrb_word_boxing_value_float(mrb_value v); #define mrb_float(o) mrb_word_boxing_value_float(o) #else @@ -205,7 +205,7 @@ mrb_integer_func(mrb_value o) { #define mrb_false_p(o) ((o).w == MRB_Qfalse) #define mrb_true_p(o) ((o).w == MRB_Qtrue) #ifndef MRB_NO_FLOAT -#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE +#ifdef MRB_WORDBOX_NO_INLINE_FLOAT #define mrb_float_p(o) WORDBOX_OBJ_TYPE_P(o, FLOAT) #elif defined(MRB_USE_FLOAT32) && defined(MRB_64BIT) #define mrb_float_p(o) WORDBOX_SHIFT_VALUE_P(o, FLOAT) diff --git a/mrbgems/mruby-test/driver.c b/mrbgems/mruby-test/driver.c index fb7f10cf8..11ccd0d6d 100644 --- a/mrbgems/mruby-test/driver.c +++ b/mrbgems/mruby-test/driver.c @@ -221,7 +221,7 @@ mrb_init_test_driver(mrb_state *mrb, mrb_bool verbose) #ifndef MRB_NO_FLOAT #ifdef MRB_USE_FLOAT32 -#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE +#ifdef MRB_WORDBOX_NO_INLINE_FLOAT mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-5)); #else mrb_define_const(mrb, mrbtest, "FLOAT_TOLERANCE", mrb_float_value(mrb, 1e-4)); diff --git a/src/etc.c b/src/etc.c index c35bf262c..528ce8f4c 100644 --- a/src/etc.c +++ b/src/etc.c @@ -178,7 +178,7 @@ mrb_obj_id(mrb_value obj) #ifndef MRB_NO_FLOAT /* * Boxes a `mrb_float` into an `mrb_value` using word boxing. - * - If `MRB_WORDBOX_NO_FLOAT_TRUNCATE` is defined, it allocates a new + * - If `MRB_WORDBOX_NO_INLINE_FLOAT` is defined, it allocates a new * RFloat object on the heap. * - If `MRB_64BIT` and `MRB_USE_FLOAT32` are defined, it stores the float * in the lower bits of the word, shifted and tagged. @@ -187,7 +187,7 @@ mrb_obj_id(mrb_value obj) * Floats outside the inline range are heap-allocated as RFloat. */ -#if !defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE) && \ +#if !defined(MRB_WORDBOX_NO_INLINE_FLOAT) && \ (!defined(MRB_USE_FLOAT32) || !defined(MRB_64BIT)) /* * Rotation-based float encoding (shared between 64-bit float64 and @@ -286,7 +286,7 @@ mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) { union mrb_value_ v; -#ifdef MRB_WORDBOX_NO_FLOAT_TRUNCATE +#ifdef MRB_WORDBOX_NO_INLINE_FLOAT v.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); mrb_rfloat_set(v.fp, f); v.bp->frozen = 1; @@ -366,7 +366,7 @@ mrb_word_boxing_float_value(mrb_state *mrb, mrb_float f) } -#ifndef MRB_WORDBOX_NO_FLOAT_TRUNCATE +#ifndef MRB_WORDBOX_NO_INLINE_FLOAT /* * Unboxes an `mrb_value` to an `mrb_float`. * - 64-bit + float32: right-shift by 2 to retrieve the float. diff --git a/src/gc.c b/src/gc.c index 69aa89341..0268bf89e 100644 --- a/src/gc.c +++ b/src/gc.c @@ -121,7 +121,7 @@ struct free_obj { struct RVALUE_initializer { MRB_OBJECT_HEADER; -#if defined(MRB_WORD_BOXING) && defined(MRB_32BIT) && defined(MRB_USE_FLOAT32) && !defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE) +#if defined(MRB_WORD_BOXING) && defined(MRB_32BIT) && defined(MRB_USE_FLOAT32) && !defined(MRB_WORDBOX_NO_INLINE_FLOAT) /* inline float word boxing needs 8-byte aligned objects; pad RVALUE to 24 bytes (multiple of 8) on 32-bit */ char padding[sizeof(void*) * 4]; @@ -1680,7 +1680,7 @@ mrb_init_gc(mrb_state *mrb) { struct RClass *gc; -#if defined(MRB_WORD_BOXING) && defined(MRB_32BIT) && defined(MRB_USE_FLOAT32) && !defined(MRB_WORDBOX_NO_FLOAT_TRUNCATE) +#if defined(MRB_WORD_BOXING) && defined(MRB_32BIT) && defined(MRB_USE_FLOAT32) && !defined(MRB_WORDBOX_NO_INLINE_FLOAT) /* 6 words: padded to 8-byte alignment for inline float word boxing */ mrb_static_assert(sizeof(RVALUE) <= sizeof(void*) * 6, "RVALUE size must be within 6 words");