Hey, I wrote one of those too :P I went the route of compiling to java source code rather than bytecode though. I'll definitely give this a look through when I get some free time, glad to see others want it to happen (though as you allude to jvmci / truffle / sulong and friends are kind of a game changer).
* https://github.com/wrmsr/wava - be forewarned though I never got around to giving it any polish and it's based on a dated version of wasm
Nice! I too thought about transpiling to it (as I have in other projects transpiling to things like Go) but I wanted to see how close to the bytecode I could get some of the translations.
I see what it is and I think I understand what it does, at least as far as the high level description goes. I am re-working some C++ code to work when built with emscripten as asm.js and I have a passing familiarity with web assembly.
But why does this webassembly to JVM bytecode converter exist?
Is this some kind of research project? If so, great no more explanation someone wanted to see their limits and learn in the process, great.
Is this for some professional purpose? If so then I am much more curious. Who has a need to convert stuff in the browser to JVM code, and what benefit do they gain?
It is theoretically possible though not likely that you could get better performance on the JVM than a static compiler due to runtime optimizations on hot code paths.
It's not about converting stuff in the browser to the jvm, it's about converting existing c and c++ (and others) to the jvm via an intermediate format primarily (but not exclusively) designed for the browser. There are real reasons to 'rewrite-it-in-java' beyond just NIH, to the degree that even without this automatic transpiling it's frequently done (grpc-c vs grpc-java, all jdbc drivers, etc):
- Native transitions are expensive - not just through register saving and gc machinery but also because native code is opaque to the optimizer. Runtime virtual inlining is probably the single most important optimization hotspot does and the more frequently code it can't work with is called the worse everything gets. While it's almost certainly nothing to worry about with coarse-grained syscalls, and probably not too much to worry about with things like opengl calls, I'd be very skeptical of using, say, a native database driver involving native transitions to retrieve every field of every row of every query in a db-heavy app. This is much the same way pypy is usually much happier with pure-python code than with native code - the more your vm does for you the less happy it is when it can't do it. Furthermore, as these binaries are the compiled results of clang and llvm (just with a different backend) the normal static analysis and optimization passes are run on the c source and ir, it just gets compiled down to a simpler instruction set than most modern physical machines.
- Native deps are anathema to most clean java projects. Our de-facto dep system, maven (and compatibles), is entirely jar-centric. The 'accepted' solution for distributing something like sqlite is some poor person having compiled the native libraries on (win|lin|osx)(32|64), zipped them all up into a big ol jar, and put that single blob on maven. On boot it sees what platform its on, extracts the lib to a temp dir, loads it, then imports a jni binding for it. Inelegant to say the least, especially when java people tend to be spoiled by the notion of there being no difference between an osx or linux build or binary.
- Debugging is worlds nicer when everything's in the jvm, even before stackmaps. You only need one debugger, it's nice and graphical, you can run it remotely with no such thing as a 'debug build', it basically never segfaults, et cetera.
Might this be useful for incorporating C or C++ code in an Android app without having to use the NDK, compile for multiple architectures, and have to use JNI to bridge to the Dalvik/ART world?
Probably not without some considerable effort. I touched on this in the README FAQ, but basically to use Emscripten-compiled code with this, a runtime layer will need to be written which I haven't done yet.
> Everyone is focused on targeting WASM with several languages but is missing the big problem: lack of a standard library
I'm not so sure that's a problem that would benefit WASM to solve. Right now the imports Emscripten provide are the defacto standard lib, which does shape how other projects approach WASM.
I feel a large reason behind seeing so many interesting toy projects that use WASM (and it's quick cross browser adoption) is due to it having such a small scope. Define a portable, easily optimizable VM.
The big challenge there is to support higher level concepts like GC, you need to make that work at a machine level, not a standard library level.
Agreed it is not for WASM to solve. I'm just stating the ecosystem issue because everyone thinks compiling their favorite language to WASM provides immediate interoperability.
When I was working on it the accepted solution was to compile as linux and statically link musl into the wasm binary, leaving mostly __syscallN symbols unresolved. As such it's a matter of implementing those on an as-needed basis (in javascript for emscripten and in java here). I at least successfully got sqlite opening a database in a pure java transpile that way. While it's a possibly inelegant approach on the face of it linux does at least have an aggressive 'dont break userspace' attitude and there is longstanding prior art for this on freebsd.
19 comments
[ 3.9 ms ] story [ 52.3 ms ] threadI don't quite get the joke...
* https://github.com/wrmsr/wava - be forewarned though I never got around to giving it any polish and it's based on a dated version of wasm
But why does this webassembly to JVM bytecode converter exist?
Is this some kind of research project? If so, great no more explanation someone wanted to see their limits and learn in the process, great.
Is this for some professional purpose? If so then I am much more curious. Who has a need to convert stuff in the browser to JVM code, and what benefit do they gain?
Also, it's not "convert stuff in the browser", WebAssembly has non-web goals [0]. There can be benefit in libraries sharing a common bytecode.
0 - http://webassembly.org/docs/non-web/
I was unaware of the non-web goals of WebAssembly, Thank you.
- Native transitions are expensive - not just through register saving and gc machinery but also because native code is opaque to the optimizer. Runtime virtual inlining is probably the single most important optimization hotspot does and the more frequently code it can't work with is called the worse everything gets. While it's almost certainly nothing to worry about with coarse-grained syscalls, and probably not too much to worry about with things like opengl calls, I'd be very skeptical of using, say, a native database driver involving native transitions to retrieve every field of every row of every query in a db-heavy app. This is much the same way pypy is usually much happier with pure-python code than with native code - the more your vm does for you the less happy it is when it can't do it. Furthermore, as these binaries are the compiled results of clang and llvm (just with a different backend) the normal static analysis and optimization passes are run on the c source and ir, it just gets compiled down to a simpler instruction set than most modern physical machines.
- Native deps are anathema to most clean java projects. Our de-facto dep system, maven (and compatibles), is entirely jar-centric. The 'accepted' solution for distributing something like sqlite is some poor person having compiled the native libraries on (win|lin|osx)(32|64), zipped them all up into a big ol jar, and put that single blob on maven. On boot it sees what platform its on, extracts the lib to a temp dir, loads it, then imports a jni binding for it. Inelegant to say the least, especially when java people tend to be spoiled by the notion of there being no difference between an osx or linux build or binary.
- Debugging is worlds nicer when everything's in the jvm, even before stackmaps. You only need one debugger, it's nice and graphical, you can run it remotely with no such thing as a 'debug build', it basically never segfaults, et cetera.
[1] https://github.com/konsoletyper/teavm
I'm not so sure that's a problem that would benefit WASM to solve. Right now the imports Emscripten provide are the defacto standard lib, which does shape how other projects approach WASM.
I feel a large reason behind seeing so many interesting toy projects that use WASM (and it's quick cross browser adoption) is due to it having such a small scope. Define a portable, easily optimizable VM.
The big challenge there is to support higher level concepts like GC, you need to make that work at a machine level, not a standard library level.
see: https://github.com/kripken/emscripten/blob/6dc4ac5f9e4d8484e...