diff --git a/doc/internal/boxing.md b/doc/internal/boxing.md index 0a7b3ca0d..33dcbd860 100644 --- a/doc/internal/boxing.md +++ b/doc/internal/boxing.md @@ -26,8 +26,30 @@ 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_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`. +### Inline Float (64-bit) + +On 64-bit platforms, `double` values are packed into the word using +rotation encoding. The IEEE 754 exponent field is rotated so that +common exponent values (those not colliding with the pointer/tag +patterns above) fit directly in a word. This encoding is lossless +for most float values; only a small set of exotic exponents require +heap allocation as `RFloat`. + +To disable inline float and heap-allocate all floats, define +`MRB_WORDBOX_NO_INLINE_FLOAT`. + +### 32-bit Considerations + +On 32-bit platforms with 64-bit `double` (the common case), +`MRB_WORDBOX_NO_INLINE_FLOAT` is automatically defined because a +64-bit double cannot fit in a 32-bit word. All floats are +heap-allocated as `RFloat` objects. + +The `RFloat` struct uses a `char[]` buffer instead of a `double` +field to avoid alignment issues, since GC heap slots (RVALUE) on +32-bit have only 4-byte alignment but `double` requires 8-byte. +Accessor functions `mrb_rfloat_value()` and `mrb_rfloat_set()` use +`memcpy` for safe access. ## NaN Boxing @@ -52,3 +74,23 @@ The object values appear far more frequently than floating-point numbers, so we ## No Boxing No boxing represents `mrb_value` by the C struct with `type` and the value union. This is the most portable (but inefficient) representation. No boxing can be specified by `MRB_NO_BOXING`, and it's default for debugging configuration (e.g. `host-debug`). + +## Comparison + +| Property | Word Boxing | NaN Boxing | No Boxing | +| ---------------------- | ------------------ | ------------------ | -------------------- | +| `mrb_value` size | 1 word (4/8 byte) | 8 bytes | 2 words (8/16 bytes) | +| Default on | most platforms | (manual opt-in) | `host-debug` | +| Macro | `MRB_WORD_BOXING` | `MRB_NAN_BOXING` | `MRB_NO_BOXING` | +| Inline integers | yes (31/63 bit) | yes (32 bit) | yes (full width) | +| Inline floats (64-bit) | yes (rotation) | yes (native) | yes (struct field) | +| Inline floats (32-bit) | no (heap RFloat) | yes (native) | yes (struct field) | +| Pointer size limit | none | 48 bits | none | +| Debugger friendly | no | no | yes | + +## ABI Compatibility + +The boxing mode changes the layout of `mrb_value`. Code compiled with +one boxing mode **cannot** be linked against a library built with a +different mode. Always use `mruby-config --cflags` to get the correct +compiler flags.