New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compiling a JVM to run Java programs with emscripten #3342
Comments
JIT could actually be done - see pypy.js, which can do JIT compilation. There is experimental threading support in progress in browsers and in emscripten, see https://blog.mozilla.org/javascript/2015/02/26/the-path-to-parallel-javascript/ There is also the emterpreter option in emscripten, which can pause and resume the execution state. That could implement switching between "threads", but not the speedup of multiple cores. |
Thank you for the blog article link and your hint to Emterpreter! (An interpreter (JVM) within an interpreter (Emterpreter)... that's fancy! :D ) Is there an API for the thread scheduling in Emterpreter, because JamVM and the GNU Classpath build their threading on top of pthreads and we would now need to have an API to replace pthreads in order to guide Emterpreter in its decisions about when to create, pause and resume/restore execution of a particular "thread". This would be needed if we talk about translating the whole JamVM and GNU Classpath to the Bytecode suited for Emterpreter and let it then handle multithreading as guided by Emterpreter's API invocations in JamVM and GNU Classpath. Again, thanks for your suggestions! |
The SharedArrayBuffer project is implementing the pthreads API. In principle we could also hook up the emterpreter to those. |
Do you know the status of that project? I googled for it but all I found was some blog discussions. |
@httpdigest : you can try out pthreads using the branch from the pull request #3266 . See also the associated branch to LLVM in the comments of that pr. |
Thank you all for your help and hints to the documentation! Helps me alot. Now, I first started slowly with test compiling Classpath and JamVM using a default GCC 4.8.2 for x86_64 target and it worked very nicely without any manual source or config/Makefile changes or quirks. (happens quite seldomly with C projects :) ) Currently, I am on to compiling juj's 'pthreads' branch of 'emscripten-fastcomp' repository from source together with kripken's 'master' branch of 'emscripten-fastcomp-clang', as I did not find a 'pthreads' branch in juj's 'emscripten-fastcomp-clang' repository and it seems to be heavily out of date compared to kripken's 'emscripten-fastcomp-clang' repository (tens of thousands of commits behind). Is this the correct way of doing? EDIT: Compiling fastcomp and fastcomp-clang worked but executing emcc now prints: But I guess that's okay, since I am using the pthreads branch. |
There were no changes needed to the emscripten-fastcomp-clang repository for pthreads so you can just use the latest Note that these branches are in quite a flux, since there is a lot of code coming in upstream, and I frequently rebase the |
Running a simple single-threaded printf "Hello, World!" program in latest firefox-trunk resulted in the error "TypeError: invalid object argument" in line:
I used firefox-trunk from the repository ppa:ubuntu-mozilla-daily/ppa via apt-get. The current version is 40.0a1 (2015-04-13). |
Not sure about different derivative repositories... Try checking in the browser page console if it does have the object
More info at https://developer.mozilla.org/en-US/docs/Simple_Firefox_build |
The conditional
in the emscripten-generated code seems to have succeeded (evaluated to true, I mean) and then the next line
failed. EDIT: Just some info: Just tried on the current Firefox Nightly download for Windows 7 x64, which is 40.0a1 (2015-04-14). |
The global function SharedInt8Array does exist in both browser variants (Ubuntu and Windows), but the constructor function seems to take 3 arguments (EDIT: okay, that's just due to optional byte 'offset' and 'length' parameters). If I do this, it works:
but the little-endianness check after that fails. :( So, I first create a SharedArrayBuffer on an ArrayBuffer and then the typed views on the SharedArrayBuffer. EDIT: Just found a hint in the documentation https://docs.google.com/document/d/1NDGA_gZJ7M7w1Bh8S0AoDyEqwDdRh4uSoTPSNn77PFk/edit#heading=h.a6o4dubw5qla (end of Page 2) that the constructor of SharedArrayBuffer can only get an int as parameter and anything else will throw a TypeError. Funny thing is if, according to the "specs", I do this:
Nightly hangs on the last call indefinitely. :) |
Okay, that "hanging" of Nightly was just due to the Debugger trying to get the values of all the memory locations of the big SharedArrayBuffer when mouse-hovering over the variable holding the SharedArrayBuffer. So, the code setup with:
works for me now using a small test (putting and getting 8 and 32 bit ints here and there and testing for equality with expected values) on the current Windows 7 x64 Firefox Nightly. Without altering the code, I get the aforementioned "TypeError". BIG EDIT: I always totally forgot to specify "-s USE_PTHREADS=1" when invoking emcc. facepalm There is just one thing. Now I am getting "ReferenceError: PThread is not defined" at "PThread.terminateAllThreads();" in the "exit" function. |
I would close this issue, since in principle with the support of pthreads in Emscripten it seems to be possible. Another important thing would be atomics. Currently JamVM has very little architecture-specific assembler scripts that do cmpxchg. |
The pthreads branch does support atomics, both as GCC intrinsics ( https://github.com/juj/emscripten/blob/pthreads/tests/pthread/test_pthread_gcc_atomic_op_and_fetch.cpp ) and as custom API that matches 1:1 with JS function calls ( https://github.com/juj/emscripten/blob/pthreads/system/include/emscripten/threading.h ). C++11 atomics should also work, but haven't gotten around to testing that yet. It is not worthwhile to attempt to shove .S files through Emscripten, but generally its just better to ifdef those out. If JamVM has been written smartly, the whole codebase has one global spot where it defines those ops, so #ifdeffing them for GCC or Emscripten specific atomics to avoid the assembly should only be a few lines of change. |
Yes, luckily the codebase of JamVM is small and clean. I just saw those are not .S files as originally assumed, but are few inline asm in one specific header file, which I would use. This is src/arch/i386.h. |
Empty asm blocks are often used as a compiler reordering barrier, see http://stackoverflow.com/questions/12183311/difference-in-mfence-and-asm-volatile-memory . Emscripten does support such empty asm blocks for the same purpose. Note though that it doesn't serve as a full memory barrier. |
Yay! The repository for all this can be found here: https://github.com/httpdigest/gnu-classpath |
Ahh... just found out about Browser.asyncLoad and FS.createDataFile which completely answered all my current questions on how I would go about loading .jar and .class files from the user-supplied classpath over the web into the virtual file system for the JVM to read via libc/stdio. |
We are experimenting with ways to do that, but they would only work in workers (which have synchronous IO access in some ways). Overall, in general you do just need to load that 10MB into the head. But 10MB isn't so bad ;) |
Thanks for the info. I am planning on having the "main" thread of the JVM just be a worker thread, which the browser thread of the site just bootstraps and kicks off via some "java.js" file. So nothing is done in the browser thread except to load this small "java.js" starter script, which then does a |
@juj Will |
Nice! I added the function Regarding the signature in |
Thank you for implementing that! |
Oh, I recommend using |
Do you manage to do it ? Can we think of java to javasscript ? |
@httpdigest What was the outcome of this work? Very interested in if you have a JVM running with emscripten. |
I've also tried to do what @httpdigest did (after I unsuccessfully tried to compile openjdk) and needed to make similar changes to the ones he made (to jamvm and classpath). https://github.com/vilie/javify (work in progress, cannot run a .class file in it yet) Other than that, I do not understand why I always get
They seem to be defined in emscripten. Any thoughts about that? |
We don't support those because we can't control the native stack size - it's an unobservable property of the JS engine. But perhaps the codebase works with those calls removed? |
These two functions actually only control getters and setters for the "thread creation attributes" struct that controls the behavior of how threads are spawned, so we could support them even in non-threaded builds. (after a thread is spawned, the pthread_attr_t struct can be discarded). Although it might be a bit silly, since why would any code manipulate a structure that is used for creating threads when threads can't be created anyways. If you build with pthreads enabled with |
@httpdigest @vilie What is the current status on this? However, it does generate a .js file which does run! and gives me usage and version information. I have tried various ways to get past this without luck. |
I just noticed the internal buffer is not shared So, perhaps I do not have pthreads correct? |
Hello, I suspect the java file and the classpath.zip need to be preloaded by using --preload-file - see ./experiments/IO Feel free to open a bug there (I may have time to look at this issue in the following weeks). |
@httpdigest DoppioJVM is "a Java virtual machine written in 100% JavaScript". The research project was published in 2014 and continues evolving. |
Hi there,
since with clang and emscripten it is now possible to run arbitrary C/C++ code via asm.js on the browser, I was curious whether anyone thought about compiling a simple JVM with emscripten to be able to run Java programs?
I thought about JamVM with GNU Classpath.
Of course, only interpretation would be possible and not JIT. Or at least the JIT compiler would need to emit JavaScript code and not native code.
Another thing would be threading. Since JavaScript does not support native threads with shared memory (only web worker threads without shared memory), the JVM would have to implement "green threads" with some cooperative mode, for example have the main "thread" invoke GC and system/IO calls at some safepoint bytecode instructions.
Is there anything in progress right now that tries to accomplish this?
Otherwise I am keen on looking into that experimentally.
The text was updated successfully, but these errors were encountered: