With my Hadoop paper submitted last Friday, I can spend more time playing with mruby. Now after several days' hacking, I finally manage to make all mruby tests pass in a browser or in node.js.
Now it's time to keep a note on how to make these tests passed.
As this Issue is resolved(Thanks to Alon Zakai for his super fast commit to fix this!), the mruby source code can be compiled using
emcc successfully, the sample
main.c file also works. But there are still 5 tests left that are not passed: 2 of them failed, while the other 3 caused node.js to crash. These 5 tests are:
- Tests for
To be honest, the result is quite good, since only 5 of the 489 tests got problems. I guess
emscripten really has reached a pretty mature status thanks to Alon. Most of the fixes here are resolved from commits to
emscripten directly. However, there are also annoying ones. Anyway, I will explain how to make each of them pass.
Honestly, this is the first time that I heard about these two functions. They reside in the
math.h header file of standard C library. The
erf function is used to calculate the error function of a value
x. While the 'erfc' function calculates the complementary error function of
emscripten does not come with an implementation for this function. However, there is an implementation in
mruby for MSVC, which does not provide
erf/erfc functions. It was originally take from here:
What's worth noting is that the original
mruby implementation contains a bug which will give wrong results for negative values. The original post from digitalmars also has a fix for this problem. It was just the case that the original commiter uses the earlier version without the fix. Hence a simple commit to the
erf/erfc test would then pass.
This is an interesting and easy one. The test code resides at here. Actually all the round tests give the correct result, what went the wrong is that
== is used to test equality for two floating point values. A small commit fixes this, easy one.
This is also related floating point value. The code is at here.
b should be assigned to
123456789.0, when using
check_float to compare
123456789.0, they should be treated as equality. Funny thing is that node.js would give the result of
1.4901161193848e-08 as the difference between the two values, while
check_float would only consider two values to be the same if they are within
Simply changing Line #328 to
123456789 instead of
123456789.0 would give the correct result, but this is a very bad fix for this problem and does not really solve it. Basically there may be two reasons:
emscripten, the code does not treat the floating point value well.
v8does not provide that many precisions for floating point value.
It is still unknown which is the cause for this problem. What I choose to do now is to let
mruby use float instead of double. When using float,
check_float would accept two values within
1E-5, for which the current result of
1.4901161193848e-08 will be enough. Anyway, I will come back to this later, maybe a dig into the
v8 issue list can bring some insight into this.
Exception 14 and
LABEL_DEBUG option in
emscripten proves to be a huge help here(thanks again, Alon!). Finally the problem turns out to be the need for stack manipulation setjmp/longjmp. I prepared a gist describing this problem:
The original gist also comes with logs running this natively or via
emscripten. With a stack manipulating setjmp/longjmp, the longjmp would erase the stack for level 1 calling of
stack_manipulate_func. The program would only call the exiting printf once. However, with the current implementation of setjmp/longjmp in
emscripten, the stack is not changed, the exiting printf will be call by both the level 0 and level 1 version of
mruby. But wait, does this sound similar? Didn't I just come up with a solution a few days earlier? Well, it is just in my first post on
mruby. I created a patch to use C++ exception instead of setjmp/longjmp and then found out that our simple
main.c file does not need this to run. Well, now we do. So I have to bring it back. This is really bad news for a pathetic C99 lover to find that the dependency for a C++ compiler returns-_-
Quick Update: Actually Alon confirms that this is just a bug and it is fixed. So maybe we can still have a C99 solution on this problem. Interesting, I will take a look at this later. I really feel sick about using a C++ compiler, that may bring a lot of evil stuff when working on the later parts involving more C code, such as C function calling interface.
Anyway, now all the tests have passed. Not only in node.js but also in browsers. However, the time to run tests differ greatly:
- Chrome 23: 1.682s
- Firefox Aurora 18: 5.294s
- Safari 6: 0.394s
This is interesting. Safari is so fast that one can think something went wrong for the other two.