mruby/mruby — pull request #1660 by xxuejie (2014-01-20 08:58:37+00:00)
Title: Add MRB_PRIMITIVE_BOXING mode

**WARNING**: This is a crazy idea for a pretty stupid problem. So please read this description before jumping into code reviewing(we may need to think about if we want to include this feature indeed).

In some C compilers(clang with le32-unknown-nacl target, used by [emscripten](https://github.com/kripken/emscripten) and [pnacl-clang](https://chromium.googlesource.com/native_client/pnacl-clang/)), `va_arg` cannot be used on aggregate types(e.g. unions or structs). In fact, the LLVM bitcode [does not support](http://llvm.org/docs/LangRef.html#i-va-arg) aggregate types. While some [progress](https://code.google.com/p/nativeclient/issues/detail?id=2381) in pnacl-clang has been made, we are still not having a proper solution for this. Although not confirmed, I wonder there might be more compilers (like those for embedded devices) with this problem.

On the other hand, mruby is [using](https://github.com/mruby/mruby/blob/master/src/vm.c#L299) `va_arg` on `mrb_value`, which is implemented as a struct. Since this is exposed in the mruby public API, it is very unlikely(or it might be possible?) to remove the `va_arg` here so as to solve the problem.

We can encapulate mrb_value using primitive values like `uintptr_t`, this way the problem will be gone. Luckily, we already have NaN-boxing and word boxing mode, which pack `mrb_value` either using `double` or `unsigned long`. However, those 2 boxing modes still represent `mrb_value` using union, which is still counted as aggregated types.

This PR provides a new mode called `MRB_PRIMITIVE_BOXING`. When used together with `MRB_NAN_BOXING` or `MRB_WORD_BOXING` modes, it will pack `mrb_value` using `uint64_t` (for NaN-boxing mode) or `uintptr_t` (for word boxing mode). Bit manipulations will be used to extract values from the primitive types. This way we can have mruby works despite of the restrictions on va_arg.

# Benefits

* mruby is working even though the compiler does not support aggregate types in `va_arg`.
* We will have C99-compatible NaN-boxing mode and word-boxing mode(solves #1299).

# Overheads

* Sophisticated bit manipulations are needed for new modes, which adds burden for maintenance.
* We cannot access fields in `mrb_value` using `value.i`, `value.sym`, etc. We have to use newly defined macros like `mrb_get_attr_i`, `mrb_get_attr_sym` or `mrb_get_word_iflag`, `mrb_get_word_bp_struct` for word boxing mode.

This PR is tested on following OS+compiler combinations. In each combination, all 5 modes (normal mode, `MRB_NAN_BOXING`, `MRB_NAN_BOXING`+`MRB_PRIMITIVE_BOXING`,`MRB_WORD_BOXING`, `MRB_WORD_BOXING`+`MRB_PRIMITIVE_BOXING`) are tested and working correctly.

* Mac OS X 10.9 + Apple LLVM version 5.0 (clang-500.2.79)
* CentOS 6.4(64bit) + gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-4)
* Ubuntu 12.04.3 LTS(64bit) + gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
* Debian GNU/Linux 7(32bit) + gcc (Debian 4.7.2-5) 4.7.2

So what do you guys think? Should we merge and include this new mode? Thanks for reading!